diff --git a/.eslintrc.yml b/.eslintrc.yml deleted file mode 100644 index a9ca1a804..000000000 --- a/.eslintrc.yml +++ /dev/null @@ -1 +0,0 @@ -root: true \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml index c0c12448a..d19f135e6 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,10 +8,10 @@ updates: - package-ecosystem: "github-actions" directory: "/" schedule: - interval: "weekly" - open-pull-requests-limit: 5 + interval: "daily" + open-pull-requests-limit: 15 - package-ecosystem: "docker" directory: "/docker" schedule: - interval: "weekly" + interval: "daily" open-pull-requests-limit: 5 diff --git a/.github/workflows/flow-deploy-release-artifact.yaml b/.github/workflows/flow-deploy-release-artifact.yaml index 7c689b732..16c574cd9 100644 --- a/.github/workflows/flow-deploy-release-artifact.yaml +++ b/.github/workflows/flow-deploy-release-artifact.yaml @@ -259,44 +259,12 @@ jobs: with: node-version: 18 - - name: Setup JFrog CLI - uses: jfrog/setup-jfrog-cli@8fc3d0018a8721b9a797cd7fd97c8e4833f5a3d1 # v3.5.3 - env: - JF_URL: ${{ vars.JF_URL }} - JF_ACCESS_TOKEN: ${{ secrets.JF_ACCESS_TOKEN }} - - - name: Show JFrog Config - run: jfrog config show - - - name: Verify JFrog Connectivity - run: jfrog rt ping - - - name: Setup JFrog NPM Repository - working-directory: solo - run: | - jf npmc --server-id-resolve setup-jfrog-cli-server --server-id-deploy setup-jfrog-cli-server --repo-resolve solo-npm-release --repo-deploy solo-npm-release - echo "::group::JFrog NPM Repository Configuration" - cat .jfrog/projects/npm.yaml - echo "::endgroup::" - - name: Install Semantic Release run: | npm install -g semantic-release@21.0.7 @semantic-release/git@10.0.1 @semantic-release/exec@6.0.3 gradle-semantic-release-plugin@1.7.6 npm install -g conventional-changelog-conventionalcommits@6.1.0 @commitlint/cli@17.6.6 @commitlint/config-conventional@17.6.6 npm install -g marked-mangle@1.0.1 marked-gfm-heading-id@3.0.4 semantic-release-conventional-commits@3.0.0 - - name: Install Dependencies - working-directory: solo - run: jf npm ci - - - name: Setup NPM Authentication - working-directory: solo - run: | - # create .npmrc file to publish solo to Github NPM registry - rm -f .npmrc || true - echo '//registry.npmjs.org/:_authToken=${NPM_TOKEN}' > ".npmrc" - echo '@hashgraph:registry=https://registry.npmjs.org/' >> ".npmrc" - - name: Publish Semantic Release env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} @@ -307,8 +275,3 @@ jobs: GIT_COMMITTER_EMAIL: ${{ secrets.GIT_USER_EMAIL }} if: ${{ github.event.inputs.dry-run-enabled != 'true' && !cancelled() && !failure() }} run: npx semantic-release - - - name: Deploy to JFrog Registry - working-directory: solo - if: ${{ github.event.inputs.dry-run-enabled != 'true' && !cancelled() && !failure() }} - run: jf npm publish diff --git a/.github/workflows/flow-pull-request-checks.yaml b/.github/workflows/flow-pull-request-checks.yaml index d110e5846..d8fff8618 100644 --- a/.github/workflows/flow-pull-request-checks.yaml +++ b/.github/workflows/flow-pull-request-checks.yaml @@ -65,12 +65,6 @@ jobs: with: custom-job-label: Standard - solo-tests: - name: FS Network Manager Tests - uses: ./.github/workflows/zxc-solo-tests.yaml - with: - custom-job-label: Standard - codecov: name: CodeCov uses: ./.github/workflows/zxc-code-analysis.yaml diff --git a/.github/workflows/zxc-solo-tests.yaml b/.github/workflows/zxc-solo-tests.yaml deleted file mode 100644 index a49cfb51b..000000000 --- a/.github/workflows/zxc-solo-tests.yaml +++ /dev/null @@ -1,168 +0,0 @@ -## -# Copyright (C) 2023-2024 Hedera Hashgraph, LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -## - -name: "ZXC: FS Network Manager Tests" -# The purpose of this reusable workflow is to compile the code and run the unit tests on every PR and commit. -# This reusable component is called by the following workflows: -# - .github/workflows/flow-pull-request-checks.yaml - -on: - workflow_call: - inputs: - custom-job-label: - description: "Custom Job Label:" - type: string - required: false - default: "solo Test" - node-version: - description: "NodeJS Version:" - type: string - required: false - default: "18" - java-distribution: - description: "Java JDK Distribution:" - type: string - required: false - default: "temurin" - java-version: - description: "Java JDK Version:" - type: string - required: false - default: "21.0.1" - -defaults: - run: - shell: bash - -permissions: - id-token: write - contents: read - actions: read - pull-requests: write - checks: write - statuses: write - -jobs: - test: - name: ${{ inputs.custom-job-label || 'solo Test' }} - runs-on: [ self-hosted, Linux, medium, ephemeral ] - steps: - - name: Get related changed files - id: changed-files - uses: tj-actions/changed-files@90a06d6ba9543371ab4df8eeca0be07ca6054959 #v42.0.2 - with: - files: | - solo/** - - - name: List all related changed files - id: check-changed-files - run: | - echo "Modified files" - echo "-------------------------------------------------------------------" - for file in ${{ steps.changed-files.outputs.all_changed_files }}; do - echo " - ${file} was changed" - done - echo "" - if [ "${{ steps.changed-files.outputs.any_changed }}" == "true" ]; then - echo "run-tests=true" >> "${GITHUB_OUTPUT}" - echo "Scheduled solo tests...." - else - echo ">> No relevant files are changed. No need to run solo tests" - fi - - - name: Checkout Code - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - if: ${{ steps.check-changed-files.outputs.run-tests && !cancelled() && !failure() }} - with: - # the fetch depth defaults to only the commit that triggered the workflow unless the spotless check was enabled - fetch-depth: ${{ inputs.enable-spotless-check && '0' || '' }} - - - name: Setup Java - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0 - if: ${{ !inputs.enable-nodejs-tests && !cancelled() && !failure() }} - with: - distribution: ${{ inputs.java-distribution }} - java-version: ${{ inputs.java-version }} - - - name: Setup Node - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 - if: ${{ steps.check-changed-files.outputs.run-tests && !cancelled() && !failure() }} - with: - node-version: ${{ inputs.node-version }} - - - name: Docker Prune - id: docker-prune - if: ${{ steps.check-changed-files.outputs.run-tests && !cancelled() && !failure() }} - run: | - docker info - docker ps -a - docker system prune -f - docker image prune -f - - - name: Setup Kind - uses: helm/kind-action@dda0770415bac9fc20092cacbc54aa298604d140 # v1.8.0 - if: ${{ steps.check-changed-files.outputs.run-tests && !cancelled() && !failure() }} - with: - node_image: kindest/node:v1.27.3@sha256:3966ac761ae0136263ffdb6cfd4db23ef8a83cba8a463690e98317add2c9ba72 - config: dev/dev-cluster.yaml - version: v0.20.0 - verbosity: 3 - wait: 120s - - - name: Setup Helm - uses: azure/setup-helm@5119fcb9089d432beecbf79bb2c7915207344b78 # v3.5 - if: ${{ steps.check-changed-files.outputs.run-tests && !cancelled() && !failure() }} - with: - version: "v3.12.3" # helm version - - # Technically, this step is not required for the unit tests to run, but it is useful for debugging setup issues. - - name: Kubernetes Cluster Info - if: ${{ steps.check-changed-files.outputs.run-tests && !cancelled() && !failure() }} - run: | - kubectl config get-contexts - kubectl get crd - kubectl get node --show-labels - - - name: NodeJS CLI Unit Tests - id: nodejs-test - working-directory: solo - if: ${{ steps.check-changed-files.outputs.run-tests && !cancelled() && !failure() }} - run: | - which npm - which bash - npm -v - npm i - npm test - - - name: NodeJS CLI E2E Tests - id: nodejs-test-e2e - working-directory: solo - if: ${{ steps.check-changed-files.outputs.run-tests && !cancelled() && !failure() }} - run: | - npm i - npm link - kind delete cluster -n chart-testing || true - docker image pull kindest/node:v1.27.3@sha256:3966ac761ae0136263ffdb6cfd4db23ef8a83cba8a463690e98317add2c9ba72 - docker image ls - ./test/e2e/setup-e2e.sh - npm run test-e2e - - - name: Output logs - id: nodejs-test-e2e-logs - working-directory: solo - if: ${{ steps.check-changed-files.outputs.run-tests && !cancelled() }} - run: | - cat ~/.solo/logs/solo.log diff --git a/.gitignore b/.gitignore index 8d5d26bfa..3200bc170 100644 --- a/.gitignore +++ b/.gitignore @@ -514,8 +514,6 @@ dev/local-node/config.txt dev/temp/.env charts/deleteme.yaml node_modules -solo/coverage dev/resources/nmt/version.properties -solo/test/scripts/backup fullstack-network-manager/test/data/tmp *.pfx diff --git a/.releaserc b/.releaserc index 7cf17893b..99e97fe85 100644 --- a/.releaserc +++ b/.releaserc @@ -7,12 +7,6 @@ "preset": "conventionalcommits" } ], - [ - "@semantic-release/npm", - { - "pkgRoot": "solo" - } - ], "@semantic-release/git", "@semantic-release/github" ], @@ -27,21 +21,13 @@ "@semantic-release/exec", { "cmd": "./gradlew versionAsSpecified --scan -PnewVersion=${nextRelease.version}" } ], - [ - "@semantic-release/npm", - { - "pkgRoot": "solo" - } - ], [ "@semantic-release/git", { "assets": [ "gradle.properties", "charts/fullstack-deployment/Chart.yaml", - "charts/fullstack-cluster-setup/Chart.yaml", - "solo/package.json", - "solo/package-lock.json" + "charts/fullstack-cluster-setup/Chart.yaml" ] } ] diff --git a/build-logic/project-plugins/src/main/kotlin/Utils.kt b/build-logic/project-plugins/src/main/kotlin/Utils.kt index fb1dad65c..c5a8a9e5b 100644 --- a/build-logic/project-plugins/src/main/kotlin/Utils.kt +++ b/build-logic/project-plugins/src/main/kotlin/Utils.kt @@ -46,12 +46,6 @@ class Utils { } } - @JvmStatic - fun updateSoloVersion(project: Project, newVersion: SemVer) { - val manifestFile = File(project.rootProject.projectDir, "solo/package.json") - updateStringInFile(manifestFile, "\"version\":", " \"version\": \"${newVersion}\",") - } - @JvmStatic fun updateHelmChartAppVersion(project: Project, newVersion: SemVer) { updateHelmCharts(project) {chart -> diff --git a/build-logic/project-plugins/src/main/kotlin/com.hedera.fullstack.aggregate-reports.gradle.kts b/build-logic/project-plugins/src/main/kotlin/com.hedera.fullstack.aggregate-reports.gradle.kts index 0dfab23bb..a4db18ef4 100644 --- a/build-logic/project-plugins/src/main/kotlin/com.hedera.fullstack.aggregate-reports.gradle.kts +++ b/build-logic/project-plugins/src/main/kotlin/com.hedera.fullstack.aggregate-reports.gradle.kts @@ -60,7 +60,6 @@ tasks.register("versionAsSpecified") { val newVer = SemVer.parse(verStr) Utils.updateHelmChartVersion(project, newVer) Utils.updateHelmChartAppVersion(project, newVer) - Utils.updateSoloVersion(project, newVer) Utils.updateVersion(project, newVer) } } @@ -73,7 +72,6 @@ tasks.register("versionAsSnapshot") { Utils.updateHelmChartVersion(project, newVer) Utils.updateHelmChartAppVersion(project, newVer) - Utils.updateSoloVersion(project, newVer) Utils.updateVersion(project, newVer) } } diff --git a/solo/.eslintrc.yml b/solo/.eslintrc.yml deleted file mode 100644 index fd12b9363..000000000 --- a/solo/.eslintrc.yml +++ /dev/null @@ -1,33 +0,0 @@ -env: - browser: true - es2021: true -extends: standard -parserOptions: - ecmaVersion: latest - sourceType: module -rules: - headers/header-format: - - error - - source: "string" - variables: - year: "2024" - content: | - Copyright (C) {year} Hedera Hashgraph, LLC - - Licensed under the Apache License, Version 2.0 (the ""License""); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an ""AS IS"" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -plugins: ["headers"] -overrides: - - files: ["*.mjs"] - parserOptions: - ecmaVersion: latest - sourceType: module \ No newline at end of file diff --git a/solo/.npmignore b/solo/.npmignore deleted file mode 100644 index e19255845..000000000 --- a/solo/.npmignore +++ /dev/null @@ -1 +0,0 @@ -test/* \ No newline at end of file diff --git a/solo/.remarkrc.yml b/solo/.remarkrc.yml deleted file mode 100644 index 737365955..000000000 --- a/solo/.remarkrc.yml +++ /dev/null @@ -1,8 +0,0 @@ -plugins: - # Check that markdown is consistent. - - remark-preset-lint-consistent - # Few recommended rules. - - remark-preset-lint-recommended - # list item indentation should be space - - - remark-lint-list-item-indent - - space diff --git a/solo/CONTRIBUTE.md b/solo/CONTRIBUTE.md deleted file mode 100644 index 3d93db9d6..000000000 --- a/solo/CONTRIBUTE.md +++ /dev/null @@ -1,28 +0,0 @@ -# Contribute - -Below we describe how you can set up local environment and contribute to `solo`. - -## Developer instructions - -* Clone the repo -* In order to support ES6 modules with `jest`, set an env - variable `export NODE_OPTIONS=--experimental-vm-modules >> ~/.zshrc` - * If you are using Intellij and would like to use debugger tools, you will need to - enable `--experimental-vm-modules` for `Jest`. - * `Run->Edit Configurations->Edit Configuration Templates->Jest` and then set `--experimental-vm-modules` - in `Node Options`. -* Run `npm i` to install the required packages -* Run `npm link` to install `solo` as the CLI - * Note: you need to do it once. If `solo` already exists in your path, you will need to remove it first. - * Alternative way would be to run `npm run solo -- ` -* Run `npm test` or `npm run test` to run the unit tests -* Run `solo` to access the CLI. -* Note that debug logs are stored at `$HOME/.solo/logs/solo.log`. So you may use `tail -f $HOME/.solo/logs/solo.log | jq - ` in a separate terminal to keep an eye on the logs. -* Before making a commit run `npm run format` - -## E2E tests - -* In order to run E2E test, we need to set up cluster and install the chart. - * Run `./test/e2e/setup-e2e.sh` - * Run `npm run test-e2e` diff --git a/solo/README.md b/solo/README.md deleted file mode 100644 index 395797f4a..000000000 --- a/solo/README.md +++ /dev/null @@ -1,413 +0,0 @@ -# Solo - -An opinionated CLI tool to deploy and manage private Hedera Networks. - -## Requirements - -* Node(^v18.19.0) (*lts/hydrogen*) -* Helm(^v3.12.3) -* Kubectl(^v1.28.2) - -## Setup - -* Install [Node](https://nodejs.org/en/download). You may also use [nvm](https://github.com/nvm-sh/nvm) to manage different Node versions locally: - -``` -$ nvm install lts/hydrogen -$ nvm use lts/hydrogen -``` - -* Install [kubectl](https://kubernetes.io/docs/tasks/tools/) -* Install [helm](https://helm.sh/docs/intro/install/) -* Useful tools (Optional) - * Install [kind](https://kind.sigs.k8s.io/) - * Install [k9s](https://k9scli.io/) - * Install [kubectx](https://github.com/ahmetb/kubectx) - -## Install Solo - -* Run `npm install -g @hashgraph/solo` - -## Setup Kubernetes cluster - -* You may use remote kubernetes cluster. In this case, ensure kubernetes context is set up correctly. - Check and select appropriate kubernetes context using `kubectx` command as below: - -``` -$ kubectx -``` - -* For a local cluster, you may use [kind](https://kind.sigs.k8s.io/) and [kubectl](https://kubernetes.io/docs/tasks/tools/) to create a cluster and namespace as below. - * In this case, ensure your Docker engine has enough resources (e.g. Memory >=8Gb, CPU: >=4). - -``` -$ export SOLO_CLUSTER_NAME=solo -$ export SOLO_NAMESPACE=solo -$ export SOLO_CLUSTER_SETUP_NAMESPACE=solo-cluster -$ kind create cluster -n "${SOLO_CLUSTER_NAME}" -$ kubectl create ns "${SOLO_NAMESPACE}" -$ kubectl create ns "${SOLO_CLUSTER_SETUP_NAMESPACE}" - -Creating cluster "solo" ... - βœ“ Ensuring node image (kindest/node:v1.27.3) πŸ–Ό - βœ“ Preparing nodes πŸ“¦ - βœ“ Writing configuration πŸ“œ - βœ“ Starting control-plane πŸ•ΉοΈ - βœ“ Installing CNI πŸ”Œ - βœ“ Installing StorageClass πŸ’Ύ -Set kubectl context to "kind-solo" -You can now use your cluster with: - -kubectl cluster-info --context kind-solo - -Have a nice day! πŸ‘‹ -namespace/solo created -``` - -You may now view pods in your cluster using `k9s -A` as below: - -``` - Context: kind-solo <0> all Attac… ____ __.________ - Cluster: kind-solo <1> default Delete| |/ _/ __ \______ - User: kind-solo Descri| < \____ / ___/ - K9s Rev: v0.27.4 ⚑️v0.31.7 Edit | | \ / /\___ \ - K8s Rev: v1.27.3 Help |____|__ \ /____//____ > - CPU: n/a Kill \/ \/ - MEM: n/a -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ Pods(all)[9] ─────────────────────────────────────────────┐ -β”‚ NAMESPACE↑ NAME PF READY RESTARTS STATUS IP β”‚ -β”‚ kube-system coredns-5d78c9869d-8x4zm ● 1/1 0 Running 10.244.0.4 β”‚ -β”‚ kube-system coredns-5d78c9869d-64lm6 ● 1/1 0 Running 10.244.0.3 β”‚ -β”‚ kube-system etcd-solo-control-plane ● 1/1 0 Running 172.18.0.2 β”‚ -β”‚ kube-system kindnet-6cng4 ● 1/1 0 Running 172.18.0.2 β”‚ -β”‚ kube-system kube-apiserver-solo-control-plane ● 1/1 0 Running 172.18.0.2 β”‚ -β”‚ kube-system kube-controller-manager-solo-control-plane ● 1/1 0 Running 172.18.0.2 β”‚ -β”‚ kube-system kube-proxy-sg88w ● 1/1 0 Running 172.18.0.2 β”‚ -β”‚ kube-system kube-scheduler-solo-control-plane ● 1/1 0 Running 172.18.0.2 β”‚ -β”‚ local-path-storage local-path-provisioner-6bc4bddd6b-7cv7c ● 1/1 0 Running 10.244.0.2 β”‚ -β”‚ -``` - -## Generate Node Keys - -### Legacy keys (.pfx file) - -All Hedera platform versions support the legacy `.pfx` formatted key files. - -Unfortunately `solo` is not able to generate legacy `PFX` formatted keys. However, if `curl`, `keytool` and `openssl` -are installed, you may run the following command to generate the pfx formatted gossip keys in the default -cache directory (`$HOME/.solo/cache/keys`): - -``` -# Option - 1: Generate keys for default node IDs: node0,node1,node2 -/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/hashgraph/full-stack-testing/main/solo/test/scripts/gen-legacy-keys.sh)" - -# Option - 2: Generate keys for custom node IDs -curl https://raw.githubusercontent.com/hashgraph/full-stack-testing/main/solo/test/scripts/gen-legacy-keys.sh -o gen-legacy-keys.sh -chmod +x gen-legacy-keys.sh -./gen-legacy-keys.sh alice,bob,carol -``` - -### Standard keys (.pem file) - -These keys are supported by Hedera platform >=`0.47.0-alpha.0`. -You may run `solo node keys --gossip-keys --tls-keys --key-format pem -i node0,node1,node2` command to generate the required node keys. - -# Examples - -## Example - 1: Deploy a private Hedera network (version `0.42.5`) - -* Initialize `solo` with tag `v0.42.5` and list of node names `node0,node1,node2`: - -``` -$ solo init -t v0.42.5 -i node0,node1,node2 -n "${SOLO_NAMESPACE}" -s "${SOLO_CLUSTER_SETUP_NAMESPACE}" - -******************************* Solo ********************************************* -Version : 0.19.1 -Kubernetes Context : kind-solo -Kubernetes Cluster : kind-solo -Kubernetes Namespace : solo -********************************************************************************** -βœ” Setup home directory and cache -βœ” Setup config manager -βœ” Check dependencies - βœ” Check dependency: helm -βœ” Setup chart manager [1s] -``` - -* Generate `pfx` node keys (You will need `curl`, `keytool` and `openssl`) - -``` -$ curl https://raw.githubusercontent.com/hashgraph/full-stack-testing/main/solo/test/scripts/gen-legacy-keys.sh -o gen-legacy-keys.sh -$ chmod +x gen-legacy-keys.sh -$ ./gen-legacy-keys.sh node0,node1,node2 - -# view the list of generated keys in the cache folder -$ ls ~/.solo/cache/keys -hedera-node0.crt hedera-node1.crt hedera-node2.crt private-node0.pfx private-node2.pfx -hedera-node0.key hedera-node1.key hedera-node2.key private-node1.pfx public.pfx - -``` - -* Setup cluster with shared components - * In a separate terminal, you may run `k9s` to view the pod status. - -``` -$ solo cluster setup - -******************************* Solo ********************************************* -Version : 0.19.1 -Kubernetes Context : kind-solo -Kubernetes Cluster : kind-solo -Kubernetes Namespace : solo -********************************************************************************** -βœ” Initialize -βœ” Prepare chart values -βœ” Install 'fullstack-cluster-setup' chart [1s] - -``` - -* Deploy helm chart with Hedera network components - * It may take a while (5~15 minutes depending on your internet speed) to download various docker images and get the pods started. - * If it fails, ensure you have enough resources allocated for Docker and restart. - -``` -$ solo network deploy - -******************************* Solo ********************************************* -Version : 0.19.1 -Kubernetes Context : kind-solo -Kubernetes Cluster : kind-solo -Kubernetes Namespace : solo -********************************************************************************** -βœ” Initialize -βœ” Install chart 'fullstack-deployment' [3s] -βœ” Waiting for network pods to be ready [8m54s] - βœ” Node: node0 (Pod: network-node0-0) [8m54s] - βœ” Node: node1 (Pod: network-node1-0) - βœ” Node: node2 (Pod: network-node2-0) - -``` - -* Setup node with Hedera platform software. - * It may take a while as it download the hedera platform code from - -``` -$ solo node setup - -******************************* Solo ********************************************* -Version : 0.19.1 -Kubernetes Context : kind-solo -Kubernetes Cluster : kind-solo -Kubernetes Namespace : solo -********************************************************************************** -βœ” Initialize -βœ” Identify network pods - βœ” Check network pod: node0 - βœ” Check network pod: node1 - βœ” Check network pod: node2 -βœ” Fetch platform software -↓ Generate Gossip keys -↓ Generate gRPC TLS keys -βœ” Prepare staging directory - βœ” Copy default files and templates - βœ” Copy Gossip keys to staging - βœ” Copy gRPC TLS keys to staging - βœ” Prepare config.txt for the network -βœ” Upload platform software into network nodes [5s] - βœ” Node: node0 [1s] - βœ” Node: node1 [1s] - βœ” Node: node2 [1s] -βœ” Setup network nodes [1s] - βœ” Node: node0 [1s] - βœ” Copy Gossip keys [0.3s] - βœ” Copy TLS keys [0.3s] - βœ” Copy configuration files [0.8s] - βœ” Set file permissions - βœ” Node: node1 [1s] - βœ” Copy Gossip keys [0.2s] - βœ” Copy TLS keys [0.3s] - βœ” Copy configuration files [0.8s] - βœ” Set file permissions [0.1s] - βœ” Node: node2 [1s] - βœ” Copy Gossip keys [0.2s] - βœ” Copy TLS keys [0.3s] - βœ” Copy configuration files [0.8s] - βœ” Set file permissions [0.1s] - -``` - -* Start the nodes - -``` -$ solo node start - -******************************* Solo ********************************************* -Version : 0.19.1 -Kubernetes Context : kind-solo -Kubernetes Cluster : kind-solo -Kubernetes Namespace : solo -********************************************************************************** -βœ” Initialize -βœ” Identify network pods - βœ” Check network pod: node0 - βœ” Check network pod: node1 - βœ” Check network pod: node2 -βœ” Starting nodes - βœ” Start node: node0 - βœ” Start node: node1 - βœ” Start node: node2 -βœ” Check nodes are ACTIVE [23s] - βœ” Check node: node0 [23s] - βœ” Check node: node1 [0.1s] - βœ” Check node: node2 [0.1s] - -``` - -You may view the list of pods using `k9s` as below: - -``` - Context: kind-solo ✏️ <0> all Attach Logs Show PortForward ____ __.________ - Cluster: kind-solo <1> default Delete

Logs Previous Transfer | |/ _/ __ \______ - User: kind-solo Describe Port-Forward YAML | < \____ / ___/ - K9s Rev: v0.31.7 Edit Sanitize | | \ / /\___ \ - K8s Rev: v1.27.3 Help Shell |____|__ \ /____//____ > - CPU: n/a Kill Show Node \/ \/ - MEM: n/a -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ Pods(all)[27] ──────────────────────────────────────────────────────────────────────────────────────────────────┐ -β”‚ NAMESPACE↑ NAME PF READY STATUS RESTARTS IP NODE AGE β”‚ -β”‚ kube-system coredns-5d78c9869d-5ds5h ● 1/1 Running 0 10.244.0.4 solo-control-plane 26m β”‚ -β”‚ kube-system coredns-5d78c9869d-m99rt ● 1/1 Running 0 10.244.0.3 solo-control-plane 26m β”‚ -β”‚ kube-system etcd-solo-control-plane ● 1/1 Running 0 172.18.0.2 solo-control-plane 26m β”‚ -β”‚ kube-system kindnet-bh2cv ● 1/1 Running 0 172.18.0.2 solo-control-plane 26m β”‚ -β”‚ kube-system kube-apiserver-solo-control-plane ● 1/1 Running 0 172.18.0.2 solo-control-plane 26m β”‚ -β”‚ kube-system kube-controller-manager-solo-control-plane ● 1/1 Running 0 172.18.0.2 solo-control-plane 26m β”‚ -β”‚ kube-system kube-proxy-tj9cf ● 1/1 Running 0 172.18.0.2 solo-control-plane 26m β”‚ -β”‚ kube-system kube-scheduler-solo-control-plane ● 1/1 Running 0 172.18.0.2 solo-control-plane 26m β”‚ -β”‚ local-path-storage local-path-provisioner-6bc4bddd6b-n4xbj ● 1/1 Running 0 10.244.0.2 solo-control-plane 26m β”‚ -β”‚ solo envoy-proxy-node0-84947f844f-bh6nw ● 1/1 Running 0 10.244.0.14 solo-control-plane 6m4s β”‚ -β”‚ solo envoy-proxy-node1-65f8879dcc-p6m2l ● 1/1 Running 0 10.244.0.10 solo-control-plane 6m4s β”‚ -β”‚ solo envoy-proxy-node2-667f848689-fwlmz ● 1/1 Running 0 10.244.0.13 solo-control-plane 6m4s β”‚ -β”‚ solo fullstack-deployment-grpc-69f9cc5666-z62r2 ● 1/1 Running 0 10.244.0.19 solo-control-plane 6m4s β”‚ -β”‚ solo fullstack-deployment-hedera-explorer-79f79b7df4-6z284 ● 1/1 Running 0 10.244.0.15 solo-control-plane 6m4s β”‚ -β”‚ solo fullstack-deployment-importer-6bb8547f5b-g9m4x ● 1/1 Running 0 10.244.0.16 solo-control-plane 6m4s β”‚ -β”‚ solo fullstack-deployment-postgres-postgresql-0 ● 1/1 Running 0 10.244.0.24 solo-control-plane 6m4s β”‚ -β”‚ solo fullstack-deployment-rest-584f5cb6bb-4h6m5 ● 1/1 Running 0 10.244.0.17 solo-control-plane 6m4s β”‚ -β”‚ solo fullstack-deployment-web3-69dcdfc4fb-89pkm ● 1/1 Running 0 10.244.0.23 solo-control-plane 6m3s β”‚ -β”‚ solo haproxy-node0-96f8df6d-zq9tw ● 1/1 Running 0 10.244.0.9 solo-control-plane 6m4s β”‚ -β”‚ solo haproxy-node1-845fb68f48-rrlb5 ● 1/1 Running 0 10.244.0.12 solo-control-plane 6m4s β”‚ -β”‚ solo haproxy-node2-867656ff6-7fwgv ● 1/1 Running 0 10.244.0.11 solo-control-plane 6m4s β”‚ -β”‚ solo minio-pool-1-0 ● 2/2 Running 0 10.244.0.26 solo-control-plane 5m58s β”‚ -β”‚ solo network-node0-0 ● 6/6 Running 0 10.244.0.18 solo-control-plane 6m4s β”‚ -β”‚ solo network-node1-0 ● 6/6 Running 0 10.244.0.21 solo-control-plane 6m4s β”‚ -β”‚ solo network-node2-0 ● 6/6 Running 0 10.244.0.20 solo-control-plane 6m4s β”‚ -β”‚ solo-cluster console-557956d575-wkx5v ● 1/1 Running 0 10.244.0.8 solo-control-plane 7m31s β”‚ -β”‚ solo-cluster minio-operator-7d575c5f84-jwrjn ● 1/1 Running 0 10.244.0.7 solo-control-plane 7m31s β”‚ -β”‚ β”‚ -``` - -### Access Hedera Network services - -Once the nodes are up, you may now expose various services (using `k9s` (shift-f) or `kubectl port-forward`) and access. Below are most used services that you may expose. - -* Node services: `network--svc` -* HAProxy: `haproxy--svc` -* Envoy Proxy: `envoy-proxy--svc` -* Hedera explorer: `fullstack-deployment-hedera-explorer` - -``` -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ Services(all)[24] ────────────────────────────────────────────────────────────────────────────────────────────────┐ -β”‚ NAMESPACE↑ NAME TYPE CLUSTER-IP EXTERNAL-IP PORTS AGE β”‚ -β”‚ default kubernetes ClusterIP 10.96.0.1 https:443β–Ί0 27m β”‚ -β”‚ kube-system kube-dns ClusterIP 10.96.0.10 dns:53β–Ί0β•±UDP dns-tcp:53β–Ί0 metrics:9153β–Ί0 27m β”‚ -β”‚ solo envoy-proxy-node0-svc ClusterIP 10.96.190.57 hedera-grpc-web:8080β–Ί0 prometheus:9090β–Ί0 7m1s β”‚ -β”‚ solo envoy-proxy-node1-svc ClusterIP 10.96.200.55 hedera-grpc-web:8080β–Ί0 prometheus:9090β–Ί0 7m1s β”‚ -β”‚ solo envoy-proxy-node2-svc ClusterIP 10.96.127.86 hedera-grpc-web:8080β–Ί0 prometheus:9090β–Ί0 7m1s β”‚ -β”‚ solo fullstack-deployment-grpc ClusterIP 10.96.130.194 grpc:5600β–Ί0 http:80β–Ί0 7m1s β”‚ -β”‚ solo fullstack-deployment-hedera-explorer ClusterIP 10.96.239.23 http:80β–Ί0 7m1s β”‚ -β”‚ solo fullstack-deployment-postgres-pgpool ClusterIP 10.96.113.9 postgresql:5432β–Ί0 7m1s β”‚ -β”‚ solo fullstack-deployment-postgres-postgresql ClusterIP 10.96.149.174 postgresql:5432β–Ί0 7m1s β”‚ -β”‚ solo fullstack-deployment-postgres-postgresql-headless ClusterIP postgresql:5432β–Ί0 7m1s β”‚ -β”‚ solo fullstack-deployment-rest ClusterIP 10.96.212.206 http:80β–Ί0 7m1s β”‚ -β”‚ solo fullstack-deployment-web3 ClusterIP 10.96.9.179 http:80β–Ί0 7m1s β”‚ -β”‚ solo haproxy-node0-svc LoadBalancer 10.96.181.106 non-tls-grpc-client-port:50211β–Ί31438 tls-grpc-client-port:50212β–Ί30630 prometheus:9090β–Ί30474 7m1s β”‚ -β”‚ solo haproxy-node1-svc LoadBalancer 10.96.26.200 non-tls-grpc-client-port:50211β–Ί30989 tls-grpc-client-port:50212β–Ί30683 prometheus:9090β–Ί30243 7m1s β”‚ -β”‚ solo haproxy-node2-svc LoadBalancer 10.96.46.132 non-tls-grpc-client-port:50211β–Ί30306 tls-grpc-client-port:50212β–Ί31995 prometheus:9090β–Ί32545 7m1s β”‚ -β”‚ solo minio ClusterIP 10.96.57.196 http-minio:80β–Ί0 6m56s β”‚ -β”‚ solo minio-console ClusterIP 10.96.90.42 http-console:9090β–Ί0 6m56s β”‚ -β”‚ solo minio-hl ClusterIP http-minio:9000β–Ί0 6m56s β”‚ -β”‚ solo network-node0-svc ClusterIP 10.96.162.219 gossip:50111β–Ί0 grpc-non-tls:50211β–Ί0 grpc-tls:50212β–Ί0 prometheus:9090β–Ί0 7m1s β”‚ -β”‚ solo network-node1-svc ClusterIP 10.96.144.87 gossip:50111β–Ί0 grpc-non-tls:50211β–Ί0 grpc-tls:50212β–Ί0 prometheus:9090β–Ί0 7m1s β”‚ -β”‚ solo network-node2-svc ClusterIP 10.96.35.210 gossip:50111β–Ί0 grpc-non-tls:50211β–Ί0 grpc-tls:50212β–Ί0 prometheus:9090β–Ί0 7m1s β”‚ -β”‚ solo-cluster console ClusterIP 10.96.184.207 http:9090β–Ί0 https:9443β–Ί0 8m28s β”‚ -β”‚ solo-cluster operator ClusterIP 10.96.250.178 http:4221β–Ί0 8m28s β”‚ -β”‚ solo-cluster sts ClusterIP 10.96.19.237 https:4223β–Ί0 8m28s β”‚ -β”‚ β”‚ -``` - -## Example - 2: Deploy a private Hedera network (version `0.47.0-alpha.0`) - -* Initialize `solo` with tag `v0.47.0-alpha.0` and list of node names `n0,n1,n2`: - -``` -$ solo init -t v0.47.0-alpha.0 -i n0,n1,n2 -n "${SOLO_NAMESPACE}" -s "${SOLO_CLUSTER_SETUP_NAMESPACE}" - -# output is similar as example-1 -``` - -* Generate `pem` formatted node keys - -``` -$ solo node keys --gossip-keys --tls-keys --key-format pem - -******************************* Solo ********************************************* -Version : 0.19.1 -Kubernetes Context : kind-solo -Kubernetes Cluster : kind-solo -Kubernetes Namespace : solo -********************************************************************************** -βœ” Initialize -βœ” Generate gossip keys -βœ” Generate gRPC TLS keys - -$ ls ~/.solo/cache/keys -a-private-n0.pem a-private-n2.pem a-public-n1.pem hedera-n0.crt hedera-n1.crt hedera-n2.crt s-private-n0.pem s-private-n2.pem s-public-n1.pem -a-private-n1.pem a-public-n0.pem a-public-n2.pem hedera-n0.key hedera-n1.key hedera-n2.key s-private-n1.pem s-public-n0.pem s-public-n2.pem - -``` - -* Setup cluster with shared components - -``` -$ solo cluster setup - -# output is similar to example-1 -``` - -In a separate terminal, you may run `k9s` to view the pod status. - -* Deploy helm chart with Hedera network components - -``` -$ solo network deploy - -# output is similar to example-1 -``` - -* Setup node with Hedera platform. - * It may take a while (~10 minutes depending on your internet speed) to download various docker images and get the - pods started. - -``` -$ solo node setup - -# output is similar to example-1 -``` - -* Start the nodes - -``` -$ solo node start - -# output is similar to example-1 -``` diff --git a/solo/jest.config.mjs b/solo/jest.config.mjs deleted file mode 100644 index 3cb258013..000000000 --- a/solo/jest.config.mjs +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -const config = { - moduleFileExtensions: ['js', 'mjs'], - verbose: true, - testSequencer: './test/e2e/jestCustomSequencer.cjs', - projects: [ - { - rootDir: '/test/e2e', - displayName: 'end-to-end', - testMatch: ['/**/*.test.mjs'] - }, - { - rootDir: '/test/unit', - displayName: 'unit', - testMatch: ['/**/*.test.mjs'] - } - ] -} -export default config diff --git a/solo/package-lock.json b/solo/package-lock.json deleted file mode 100644 index f8094ad6d..000000000 --- a/solo/package-lock.json +++ /dev/null @@ -1,13887 +0,0 @@ -{ - "name": "@hashgraph/solo", - "version": "0.21.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "@hashgraph/solo", - "version": "0.21.0", - "license": "Apache2.0", - "os": [ - "darwin", - "linux" - ], - "dependencies": { - "@hashgraph/sdk": "^2.40.0", - "@kubernetes/client-node": "^0.20.0", - "@listr2/prompt-adapter-enquirer": "^1.0.2", - "@peculiar/x509": "^1.9.5", - "adm-zip": "^0.5.10", - "chalk": "^5.3.0", - "dotenv": "^16.3.1", - "enquirer": "^2.4.1", - "esm": "^3.2.25", - "figlet": "^1.7.0", - "got": "^13.0.0", - "inquirer": "^9.2.12", - "listr2": "^7.0.2", - "tar": "^6.2.0", - "uuid": "^9.0.1", - "winston": "^3.11.0", - "yaml": "^2.3.4", - "yargs": "^17.7.2" - }, - "bin": { - "solo": "solo.mjs" - }, - "devDependencies": { - "@jest/globals": "^29.7.0", - "@jest/test-sequencer": "^29.7.0", - "eslint": "^8.53.0", - "eslint-config-standard": "^17.1.0", - "eslint-plugin-headers": "^1.1.0", - "eslint-plugin-import": "^2.29.0", - "eslint-plugin-n": "^16.3.1", - "eslint-plugin-promise": "^6.1.1", - "jest": "^29.7.0", - "remark-cli": "^12.0.0", - "remark-lint-list-item-indent": "^3.1.2", - "remark-preset-lint-consistent": "^5.1.2", - "remark-preset-lint-recommended": "^6.1.3" - }, - "engines": { - "node": ">=18.18.2", - "npm": ">=9.8.1" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", - "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", - "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", - "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.2", - "@babel/parser": "^7.23.0", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@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.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", - "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@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.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", - "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/@colors/colors": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", - "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@dabh/diagnostics": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", - "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", - "dependencies": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", - "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.53.0.tgz", - "integrity": "sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@ethersproject/abi": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", - "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/abstract-provider": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", - "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0" - } - }, - "node_modules/@ethersproject/abstract-signer": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", - "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0" - } - }, - "node_modules/@ethersproject/address": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", - "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/rlp": "^5.7.0" - } - }, - "node_modules/@ethersproject/base64": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", - "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0" - } - }, - "node_modules/@ethersproject/bignumber": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", - "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "bn.js": "^5.2.1" - } - }, - "node_modules/@ethersproject/bytes": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", - "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/constants": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", - "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0" - } - }, - "node_modules/@ethersproject/hash": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", - "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/keccak256": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", - "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "js-sha3": "0.8.0" - } - }, - "node_modules/@ethersproject/logger": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", - "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ] - }, - "node_modules/@ethersproject/networks": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", - "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/properties": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", - "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/rlp": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", - "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/signing-key": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", - "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "bn.js": "^5.2.1", - "elliptic": "6.5.4", - "hash.js": "1.1.7" - } - }, - "node_modules/@ethersproject/strings": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", - "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/transactions": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", - "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0" - } - }, - "node_modules/@ethersproject/web": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", - "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@grpc/grpc-js": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.2.tgz", - "integrity": "sha512-5cqCjUvDKJWHGeu1prlrFOUmjuML0NequZKJ38PsCkfwIqPnZq4Q9burPP3It7/+46wpl0KsqVN3s6Te3B9Qtw==", - "dependencies": { - "@grpc/proto-loader": "^0.7.0", - "@types/node": ">=12.12.47" - }, - "engines": { - "node": "^8.13.0 || >=10.10.0" - } - }, - "node_modules/@grpc/proto-loader": { - "version": "0.7.10", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.10.tgz", - "integrity": "sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==", - "dependencies": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.2.4", - "yargs": "^17.7.2" - }, - "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@grpc/proto-loader/node_modules/long": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" - }, - "node_modules/@hashgraph/cryptography": { - "version": "1.4.8-beta.5", - "resolved": "https://registry.npmjs.org/@hashgraph/cryptography/-/cryptography-1.4.8-beta.5.tgz", - "integrity": "sha512-soq2vGLRkdl2Evr+gIvIjCXJjqA1hOAjysBGG+dhP6tKx2PEgEjb3hON/sMbxm3Q4qQdkML/vEthdAV707+flw==", - "dependencies": { - "asn1js": "^3.0.5", - "bignumber.js": "^9.1.1", - "bn.js": "^5.2.1", - "buffer": "^6.0.3", - "crypto-js": "^4.2.0", - "elliptic": "^6.5.4", - "js-base64": "^3.7.4", - "node-forge": "^1.3.1", - "spark-md5": "^3.0.2", - "tweetnacl": "^1.0.3", - "utf8": "^3.0.0" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "expo": "^49.0.16", - "expo-crypto": "^10.1.2", - "expo-random": "^12.1.2" - }, - "peerDependenciesMeta": { - "expo": { - "optional": true - }, - "expo-crypto": { - "optional": true - }, - "expo-random": { - "optional": true - } - } - }, - "node_modules/@hashgraph/cryptography/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/@hashgraph/proto": { - "version": "2.14.0-beta.3", - "resolved": "https://registry.npmjs.org/@hashgraph/proto/-/proto-2.14.0-beta.3.tgz", - "integrity": "sha512-y2DYFXpXZN0ywULaPycRmmryaUBzSDQ2+UAAYdE1jQr8NPcIL2gv8wB5GKBBQqz1HihRNXiyJgYSGoNSeq9qsg==", - "dependencies": { - "long": "^4.0.0", - "protobufjs": "^7.2.5" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@hashgraph/sdk": { - "version": "2.40.0", - "resolved": "https://registry.npmjs.org/@hashgraph/sdk/-/sdk-2.40.0.tgz", - "integrity": "sha512-wgkjCsOldSPbWZY3sKd7vGHqfcR5yQL/YNIbW7O1cihGN0G4nTzvYLjNLoNNIsA+XWMb0zkxWpQ0PAZaeQJgcw==", - "dependencies": { - "@ethersproject/abi": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@grpc/grpc-js": "1.8.2", - "@hashgraph/cryptography": "1.4.8-beta.5", - "@hashgraph/proto": "2.14.0-beta.3", - "axios": "^1.6.4", - "bignumber.js": "^9.1.1", - "bn.js": "^5.1.1", - "crypto-js": "^4.2.0", - "js-base64": "^3.7.4", - "long": "^4.0.0", - "pino": "^8.14.1", - "pino-pretty": "^10.0.0", - "protobufjs": "^7.2.5", - "rfc4648": "^1.5.3", - "utf8": "^3.0.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "expo": "^49.0.16" - }, - "peerDependenciesMeta": { - "expo": { - "optional": true - } - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", - "dev": true - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "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/console/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/@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/core/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/@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/reporters/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/@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/transform/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/@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/@jest/types/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/@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.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@kubernetes/client-node": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@kubernetes/client-node/-/client-node-0.20.0.tgz", - "integrity": "sha512-xxlv5GLX4FVR/dDKEsmi4SPeuB49aRc35stndyxcC73XnUEEwF39vXbROpHOirmDse8WE9vxOjABnSVS+jb7EA==", - "dependencies": { - "@types/js-yaml": "^4.0.1", - "@types/node": "^20.1.1", - "@types/request": "^2.47.1", - "@types/ws": "^8.5.3", - "byline": "^5.0.0", - "isomorphic-ws": "^5.0.0", - "js-yaml": "^4.1.0", - "jsonpath-plus": "^7.2.0", - "request": "^2.88.0", - "rfc4648": "^1.3.0", - "stream-buffers": "^3.0.2", - "tar": "^6.1.11", - "tslib": "^2.4.1", - "ws": "^8.11.0" - }, - "optionalDependencies": { - "openid-client": "^5.3.0" - } - }, - "node_modules/@kubernetes/client-node/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/@kubernetes/client-node/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@listr2/prompt-adapter-enquirer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-enquirer/-/prompt-adapter-enquirer-1.0.2.tgz", - "integrity": "sha512-+hFHGKuACQ/0FRMmnwRe8QpdXlYJG8LhkKC0/ftf6LptWAZDBuziWnqilWHCcInnQTtUsYXD2Sra1Oxjb5q0Dg==", - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - } - }, - "node_modules/@ljharb/through": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.11.tgz", - "integrity": "sha512-ccfcIDlogiXNq5KcbAwbaO7lMh3Tm1i3khMPYpxlK8hH/W53zN81KM9coerRLOnTGu3nfXIniAmQbRI9OxbC0w==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@npmcli/config": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/config/-/config-8.0.1.tgz", - "integrity": "sha512-NKGmMYv/YTLwJr+qK9CvADSe82NTM9AFwFFpsZpVcPCT3XTdxvJBdXi8xvXWjHSCMb0Cb+7FtU/a5qqguCOhxA==", - "dev": true, - "dependencies": { - "@npmcli/map-workspaces": "^3.0.2", - "ci-info": "^3.8.0", - "ini": "^4.1.0", - "nopt": "^7.0.0", - "proc-log": "^3.0.0", - "read-package-json-fast": "^3.0.2", - "semver": "^7.3.5", - "walk-up-path": "^3.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/config/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/@npmcli/config/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/@npmcli/config/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/@npmcli/map-workspaces": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-3.0.4.tgz", - "integrity": "sha512-Z0TbvXkRbacjFFLpVpV0e2mheCh+WzQpcqL+4xp49uNJOxOnIAPZyXtUxZ5Qn3QBTGKA11Exjd9a5411rBrhDg==", - "dev": true, - "dependencies": { - "@npmcli/name-from-folder": "^2.0.0", - "glob": "^10.2.2", - "minimatch": "^9.0.0", - "read-package-json-fast": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/map-workspaces/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@npmcli/map-workspaces/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@npmcli/map-workspaces/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@npmcli/name-from-folder": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-2.0.0.tgz", - "integrity": "sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@peculiar/asn1-cms": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.3.8.tgz", - "integrity": "sha512-Wtk9R7yQxGaIaawHorWKP2OOOm/RZzamOmSWwaqGphIuU6TcKYih0slL6asZlSSZtVoYTrBfrddSOD/jTu9vuQ==", - "dependencies": { - "@peculiar/asn1-schema": "^2.3.8", - "@peculiar/asn1-x509": "^2.3.8", - "@peculiar/asn1-x509-attr": "^2.3.8", - "asn1js": "^3.0.5", - "tslib": "^2.6.2" - } - }, - "node_modules/@peculiar/asn1-csr": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.3.8.tgz", - "integrity": "sha512-ZmAaP2hfzgIGdMLcot8gHTykzoI+X/S53x1xoGbTmratETIaAbSWMiPGvZmXRA0SNEIydpMkzYtq4fQBxN1u1w==", - "dependencies": { - "@peculiar/asn1-schema": "^2.3.8", - "@peculiar/asn1-x509": "^2.3.8", - "asn1js": "^3.0.5", - "tslib": "^2.6.2" - } - }, - "node_modules/@peculiar/asn1-ecc": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.3.8.tgz", - "integrity": "sha512-Ah/Q15y3A/CtxbPibiLM/LKcMbnLTdUdLHUgdpB5f60sSvGkXzxJCu5ezGTFHogZXWNX3KSmYqilCrfdmBc6pQ==", - "dependencies": { - "@peculiar/asn1-schema": "^2.3.8", - "@peculiar/asn1-x509": "^2.3.8", - "asn1js": "^3.0.5", - "tslib": "^2.6.2" - } - }, - "node_modules/@peculiar/asn1-pfx": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.3.8.tgz", - "integrity": "sha512-XhdnCVznMmSmgy68B9pVxiZ1XkKoE1BjO4Hv+eUGiY1pM14msLsFZ3N7K46SoITIVZLq92kKkXpGiTfRjlNLyg==", - "dependencies": { - "@peculiar/asn1-cms": "^2.3.8", - "@peculiar/asn1-pkcs8": "^2.3.8", - "@peculiar/asn1-rsa": "^2.3.8", - "@peculiar/asn1-schema": "^2.3.8", - "asn1js": "^3.0.5", - "tslib": "^2.6.2" - } - }, - "node_modules/@peculiar/asn1-pkcs8": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.3.8.tgz", - "integrity": "sha512-rL8k2x59v8lZiwLRqdMMmOJ30GHt6yuHISFIuuWivWjAJjnxzZBVzMTQ72sknX5MeTSSvGwPmEFk2/N8+UztFQ==", - "dependencies": { - "@peculiar/asn1-schema": "^2.3.8", - "@peculiar/asn1-x509": "^2.3.8", - "asn1js": "^3.0.5", - "tslib": "^2.6.2" - } - }, - "node_modules/@peculiar/asn1-pkcs9": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.3.8.tgz", - "integrity": "sha512-+nONq5tcK7vm3qdY7ZKoSQGQjhJYMJbwJGbXLFOhmqsFIxEWyQPHyV99+wshOjpOjg0wUSSkEEzX2hx5P6EKeQ==", - "dependencies": { - "@peculiar/asn1-cms": "^2.3.8", - "@peculiar/asn1-pfx": "^2.3.8", - "@peculiar/asn1-pkcs8": "^2.3.8", - "@peculiar/asn1-schema": "^2.3.8", - "@peculiar/asn1-x509": "^2.3.8", - "@peculiar/asn1-x509-attr": "^2.3.8", - "asn1js": "^3.0.5", - "tslib": "^2.6.2" - } - }, - "node_modules/@peculiar/asn1-rsa": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.3.8.tgz", - "integrity": "sha512-ES/RVEHu8VMYXgrg3gjb1m/XG0KJWnV4qyZZ7mAg7rrF3VTmRbLxO8mk+uy0Hme7geSMebp+Wvi2U6RLLEs12Q==", - "dependencies": { - "@peculiar/asn1-schema": "^2.3.8", - "@peculiar/asn1-x509": "^2.3.8", - "asn1js": "^3.0.5", - "tslib": "^2.6.2" - } - }, - "node_modules/@peculiar/asn1-schema": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.8.tgz", - "integrity": "sha512-ULB1XqHKx1WBU/tTFIA+uARuRoBVZ4pNdOA878RDrRbBfBGcSzi5HBkdScC6ZbHn8z7L8gmKCgPC1LHRrP46tA==", - "dependencies": { - "asn1js": "^3.0.5", - "pvtsutils": "^1.3.5", - "tslib": "^2.6.2" - } - }, - "node_modules/@peculiar/asn1-x509": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.3.8.tgz", - "integrity": "sha512-voKxGfDU1c6r9mKiN5ZUsZWh3Dy1BABvTM3cimf0tztNwyMJPhiXY94eRTgsMQe6ViLfT6EoXxkWVzcm3mFAFw==", - "dependencies": { - "@peculiar/asn1-schema": "^2.3.8", - "asn1js": "^3.0.5", - "ipaddr.js": "^2.1.0", - "pvtsutils": "^1.3.5", - "tslib": "^2.6.2" - } - }, - "node_modules/@peculiar/asn1-x509-attr": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.3.8.tgz", - "integrity": "sha512-4Z8mSN95MOuX04Aku9BUyMdsMKtVQUqWnr627IheiWnwFoheUhX3R4Y2zh23M7m80r4/WG8MOAckRKc77IRv6g==", - "dependencies": { - "@peculiar/asn1-schema": "^2.3.8", - "@peculiar/asn1-x509": "^2.3.8", - "asn1js": "^3.0.5", - "tslib": "^2.6.2" - } - }, - "node_modules/@peculiar/x509": { - "version": "1.9.6", - "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.9.6.tgz", - "integrity": "sha512-BQhsxZa8SMJ8rwKJMb6VrdZk3XXE/5ab+JRr9psxHI9dw9gZrR3BsWrL3EgLoxrqOd2nP/mWVSSJGlA76aAbRw==", - "dependencies": { - "@peculiar/asn1-cms": "^2.3.8", - "@peculiar/asn1-csr": "^2.3.8", - "@peculiar/asn1-ecc": "^2.3.8", - "@peculiar/asn1-pkcs9": "^2.3.8", - "@peculiar/asn1-rsa": "^2.3.8", - "@peculiar/asn1-schema": "^2.3.8", - "@peculiar/asn1-x509": "^2.3.8", - "pvtsutils": "^1.3.5", - "reflect-metadata": "^0.2.1", - "tslib": "^2.6.2", - "tsyringe": "^4.8.0" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" - }, - "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/@sindresorhus/is": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", - "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "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/@szmarczak/http-timer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", - "dependencies": { - "defer-to-connect": "^2.0.1" - }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/@types/babel__core": { - "version": "7.20.3", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.3.tgz", - "integrity": "sha512-54fjTSeSHwfan8AyHWrKbfBWiEUrNTZsUwPTDSNaaP1QDQIZbeNUg3a59E9D+375MzUw/x1vx2/0F5LBz+AeYA==", - "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.6", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.6.tgz", - "integrity": "sha512-66BXMKb/sUWbMdBNdMvajU7i/44RkrA3z/Yt1c7R5xejt8qh84iU54yUWCtm0QwGJlDcf/gg4zd/x4mpLAlb/w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.3.tgz", - "integrity": "sha512-ciwyCLeuRfxboZ4isgdNZi/tkt06m8Tw6uGbBSBgWrnnZGNXiEyM27xc/PjXGQLqlZ6ylbgHMnm7ccF9tCkOeQ==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.3", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.3.tgz", - "integrity": "sha512-Lsh766rGEFbaxMIDH7Qa+Yha8cMVI3qAK6CHt3OR0YfxOIn5Z54iHiyDRycHrBqeIiqGa20Kpsv1cavfBKkRSw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/caseless": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz", - "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==" - }, - "node_modules/@types/concat-stream": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-2.0.2.tgz", - "integrity": "sha512-hgEx+hdJnfCHa62l6SNHNoe/cRge2HoUZe9KEDwOs2TvyocLTlTuw0rUMiii99kG2avc+BubhNpZ+cu05Gl8oQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "dev": true, - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true - }, - "node_modules/@types/estree-jsx": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.3.tgz", - "integrity": "sha512-pvQ+TKeRHeiUGRhvYwRrQ/ISnohKkSJR14fT2yqyZ4e9K5vqc7hrtY2Y1Dw0ZwAzQ6DQsxsaCUuSIIi8v0Cq6w==", - "dev": true, - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.8.tgz", - "integrity": "sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/hast": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.8.tgz", - "integrity": "sha512-aMIqAlFd2wTIDZuvLbhUT+TGvMxrNC8ECUIVtH6xxy0sQLs3iu6NO8Kp/VT5je7i5ufnebXzdV1dNDMnvaH6IQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/@types/hast/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz", - "integrity": "sha512-V46MYLFp08Wf2mmaBhvgjStM3tPa+2GAdy/iqoX+noX1//zje2x4XmrIU0cAwyClATsTmahbtoQ2EwP7I5WSiA==" - }, - "node_modules/@types/is-empty": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/is-empty/-/is-empty-1.2.3.tgz", - "integrity": "sha512-4J1l5d79hoIvsrKh5VUKVRA1aIdsOb10Hu5j3J2VfP/msDnfTdGPmNp2E1Wg+vs97Bktzo+MZePFFXSGoykYJw==", - "dev": true - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-zONci81DZYCZjiLe0r6equvZut0b+dBRPBN5kBDjsONnutYNtJMoWQ9uR2RkL1gLG9NMTzvf+29e5RFfPbeKhQ==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.2.tgz", - "integrity": "sha512-8toY6FgdltSdONav1XtUHl4LN1yTmLza+EuDazb/fEmRNCwjyqNVIQWs2IfC74IqjHkREs/nQ2FWq5kZU9IC0w==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.3.tgz", - "integrity": "sha512-1nESsePMBlf0RPRffLZi5ujYh7IH1BWL4y9pr+Bn3cJBdxz+RTP8bUFljLz9HvzhhOSWKdyBZ4DIivdL6rvgZg==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/js-yaml": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", - "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==" - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/mdast": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.3.tgz", - "integrity": "sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==", - "dev": true, - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/ms": { - "version": "0.7.34", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", - "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", - "dev": true - }, - "node_modules/@types/node": { - "version": "20.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", - "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", - "dependencies": { - "undici-types": "~5.25.1" - } - }, - "node_modules/@types/request": { - "version": "2.48.12", - "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.12.tgz", - "integrity": "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==", - "dependencies": { - "@types/caseless": "*", - "@types/node": "*", - "@types/tough-cookie": "*", - "form-data": "^2.5.0" - } - }, - "node_modules/@types/request/node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/@types/stack-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.2.tgz", - "integrity": "sha512-g7CK9nHdwjK2n0ymT2CW698FuWJRIx+RP6embAzZ2Qi8/ilIrA1Imt2LVSeHUzKvpoi7BhmmQcXz95eS0f2JXw==", - "dev": true - }, - "node_modules/@types/supports-color": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@types/supports-color/-/supports-color-8.1.3.tgz", - "integrity": "sha512-Hy6UMpxhE3j1tLpl27exp1XqHD7n8chAiNPzWfz16LPZoMMoSc4dzLl6w9qijkEb/r5O1ozdu1CWGA2L83ZeZg==", - "dev": true - }, - "node_modules/@types/text-table": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@types/text-table/-/text-table-0.2.5.tgz", - "integrity": "sha512-hcZhlNvMkQG/k1vcZ6yHOl6WAYftQ2MLfTHcYRZ2xYZFD8tGVnE3qFV0lj1smQeDSR7/yY0PyuUalauf33bJeA==", - "dev": true - }, - "node_modules/@types/tough-cookie": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==" - }, - "node_modules/@types/triple-beam": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.4.tgz", - "integrity": "sha512-HlJjF3wxV4R2VQkFpKe0YqJLilYNgtRtsqqZtby7RkVsSs+i+vbyzjtUwpFEdUCKcrGzCiEJE7F/0mKjh0sunA==" - }, - "node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, - "node_modules/@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/yargs": { - "version": "17.0.29", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.29.tgz", - "integrity": "sha512-nacjqA3ee9zRF/++a3FUY1suHTFKZeHba2n8WeDw9cCVdmzmHpIxyzOJBcpHvvEmS8E9KqWlSnWHUkOrkhWcvA==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.2", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.2.tgz", - "integrity": "sha512-5qcvofLPbfjmBfKaLfj/+f+Sbd6pN4zl7w7VSVI5uz7m9QZTuB2aZAa2uo1wHFBNN2x6g/SoTkXmd8mQnQF2Cw==", - "dev": true - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "node_modules/abbrev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", - "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/adm-zip": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", - "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", - "engines": { - "node": ">=6.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "engines": { - "node": ">=6" - } - }, - "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==", - "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==", - "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==", - "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/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/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", - "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/asn1js": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", - "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", - "dependencies": { - "pvtsutils": "^1.3.2", - "pvutils": "^1.1.3", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/atomic-sleep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" - }, - "node_modules/axios": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.4.tgz", - "integrity": "sha512-heJnIs6N4aa1eSthhN9M5ioILu8Wi8vmQW9iHQ9NUvfkJb0lEEDUiIdQNAuBtfUt3FxReaKdpQA5DbmMOqzF/A==", - "dependencies": { - "follow-redirects": "^1.15.4", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "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-jest/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/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/bail": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", - "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "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==" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" - }, - "node_modules/bignumber.js": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", - "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" - }, - "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/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" - }, - "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/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": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dev": true, - "dependencies": { - "semver": "^7.0.0" - } - }, - "node_modules/builtins/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/builtins/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/builtins/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/byline": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", - "integrity": "sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cacheable-lookup": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", - "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", - "engines": { - "node": ">=14.16" - } - }, - "node_modules/cacheable-request": { - "version": "10.2.14", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", - "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", - "dependencies": { - "@types/http-cache-semantics": "^4.0.2", - "get-stream": "^6.0.1", - "http-cache-semantics": "^4.1.1", - "keyv": "^4.5.3", - "mimic-response": "^4.0.0", - "normalize-url": "^8.0.0", - "responselike": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", - "dependencies": { - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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.30001551", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001551.tgz", - "integrity": "sha512-vtBAez47BoGMMzlbYhfXrMV1kvRF2WP/lqiMuDu1Sb4EE4LKEgjopFDSRtZfdVnslNRpOqV/woE+Xgrwj6VQlg==", - "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/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, - "node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "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/character-entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "engines": { - "node": ">=10" - } - }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "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/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", - "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/cli-truncate/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "node_modules/cli-truncate/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", - "engines": { - "node": ">= 12" - } - }, - "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==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/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==", - "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/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "engines": { - "node": ">=0.8" - } - }, - "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": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", - "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", - "dependencies": { - "color-convert": "^1.9.3", - "color-string": "^1.6.0" - } - }, - "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==", - "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==" - }, - "node_modules/color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "node_modules/color/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==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color/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==" - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" - }, - "node_modules/colorspace": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", - "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", - "dependencies": { - "color": "^3.1.3", - "text-hex": "1.0.x" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "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/concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "dev": true, - "engines": [ - "node >= 6.0" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - } - }, - "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/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" - }, - "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-jest/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/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/crypto-js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", - "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/dateformat": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", - "engines": { - "node": "*" - } - }, - "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/debug/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/decode-named-character-reference": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", - "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", - "dev": true, - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": 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/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "engines": { - "node": ">=10" - } - }, - "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", - "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "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/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "dev": true, - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", - "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/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dotenv": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", - "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.561", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.561.tgz", - "integrity": "sha512-eS5t4ulWOBfVHdq9SW2dxEaFarj1lPjvJ8PaYMOjY0DecBaj/t4ARziL2IPpDr4atyWwjLFGQ2vo/VCgQFezVQ==", - "dev": true - }, - "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "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==" - }, - "node_modules/enabled": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", - "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enquirer": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", - "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", - "dependencies": { - "ansi-colors": "^4.1.1", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "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/error-ex/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/es-abstract": { - "version": "1.22.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", - "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.5", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.2", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", - "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.2", - "has-tostringtag": "^1.0.0", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz", - "integrity": "sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.3", - "@eslint/js": "8.53.0", - "@humanwhocodes/config-array": "^0.11.13", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-standard": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", - "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "eslint": "^8.0.1", - "eslint-plugin-import": "^2.25.2", - "eslint-plugin-n": "^15.0.0 || ^16.0.0 ", - "eslint-plugin-promise": "^6.0.0" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", - "dev": true, - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-es-x": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.3.0.tgz", - "integrity": "sha512-W9zIs+k00I/I13+Bdkl/zG1MEO07G97XjUSQuH117w620SJ6bHtLUmoMvkGA2oYnI/gNdr+G7BONLyYnFaLLEQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.1.2", - "@eslint-community/regexpp": "^4.6.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ota-meshi" - }, - "peerDependencies": { - "eslint": ">=8" - } - }, - "node_modules/eslint-plugin-headers": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-headers/-/eslint-plugin-headers-1.1.0.tgz", - "integrity": "sha512-8VEmq/hKzAPL1uvBk87TX5T3wBTanf0EqlboeLTPKhTBWO/oDQe6BYWkrvJufyQ11HNVFaBZVbm+55WlJjwMdg==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.0.0 || >= 18.0.0" - }, - "peerDependencies": { - "eslint": ">=7" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz", - "integrity": "sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.14.2" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-n": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.3.1.tgz", - "integrity": "sha512-w46eDIkxQ2FaTHcey7G40eD+FhTXOdKudDXPUO2n9WNcslze/i/HT2qJ3GXjHngYSGDISIgPNhwGtgoix4zeOw==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "builtins": "^5.0.1", - "eslint-plugin-es-x": "^7.1.0", - "get-tsconfig": "^4.7.0", - "ignore": "^5.2.4", - "is-builtin-module": "^3.2.1", - "is-core-module": "^2.12.1", - "minimatch": "^3.1.2", - "resolve": "^1.22.2", - "semver": "^7.5.3" - }, - "engines": { - "node": ">=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-n/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/eslint-plugin-n/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/eslint-plugin-n/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/eslint-plugin-promise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", - "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/eslint/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/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/esm": { - "version": "3.2.25", - "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", - "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "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/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "engines": { - "node": ">=0.8.x" - } - }, - "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/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/external-editor/node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-copy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", - "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "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==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fast-redact": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz", - "integrity": "sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "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/fecha": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", - "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" - }, - "node_modules/figlet": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.7.0.tgz", - "integrity": "sha512-gO8l3wvqo0V7wEFLXPbkX83b7MVjRrk1oRLfYlZXol8nEpb/ON9pcKLI4qpBv5YtOTfrINtqb7b40iYY2FTWFg==", - "bin": { - "figlet": "bin/index.js" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/figures": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", - "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", - "dependencies": { - "escape-string-regexp": "^5.0.0", - "is-unicode-supported": "^1.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "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/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", - "dev": true - }, - "node_modules/fn.name": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", - "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" - }, - "node_modules/follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/form-data-encoder": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", - "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", - "engines": { - "node": ">= 14.17" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs-minipass/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "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==" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", - "dependencies": { - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", - "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", - "dev": true, - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "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/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "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/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/got": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/got/-/got-13.0.0.tgz", - "integrity": "sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==", - "dependencies": { - "@sindresorhus/is": "^5.2.0", - "@szmarczak/http-timer": "^5.0.1", - "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.8", - "decompress-response": "^6.0.0", - "form-data-encoder": "^2.1.2", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^3.0.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "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/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", - "dependencies": { - "get-intrinsic": "^1.2.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/help-me": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", - "integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==", - "dependencies": { - "glob": "^8.0.0", - "readable-stream": "^3.6.0" - } - }, - "node_modules/help-me/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/help-me/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/help-me/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "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/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/http2-wrapper": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.0.tgz", - "integrity": "sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==", - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.2.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "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/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "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/import-meta-resolve": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-3.1.1.tgz", - "integrity": "sha512-qeywsE/KC3w9Fd2ORrRDUw6nS/nLwZpXgfrOc2IILvZYnCaEMd+D56Vfg9k4G29gIeVi3XKql1RQatME8iYsiw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "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==", - "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==" - }, - "node_modules/ini": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", - "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/inquirer": { - "version": "9.2.12", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.12.tgz", - "integrity": "sha512-mg3Fh9g2zfuVWJn6lhST0O7x4n03k7G8Tx5nvikJkbq8/CK47WDVm+UznF0G6s5Zi0KcyUisr6DU8T67N5U+1Q==", - "dependencies": { - "@ljharb/through": "^2.3.11", - "ansi-escapes": "^4.3.2", - "chalk": "^5.3.0", - "cli-cursor": "^3.1.0", - "cli-width": "^4.1.0", - "external-editor": "^3.1.0", - "figures": "^5.0.0", - "lodash": "^4.17.21", - "mute-stream": "1.0.0", - "ora": "^5.4.1", - "run-async": "^3.0.0", - "rxjs": "^7.8.1", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/internal-slot": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", - "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.2", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ipaddr.js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", - "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=4" - } - }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "dev": true, - "dependencies": { - "builtin-modules": "^3.3.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-empty": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-empty/-/is-empty-1.2.0.tgz", - "integrity": "sha512-F2FnH/otLNJv0J6wc73A5Xo7oHLNnqplYqZhUu01tD54DIPvxIRSTSLkrUB/M0nHO4vo1O9PDfN4KoTxCzLh/w==", - "dev": true - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "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-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", - "dev": true, - "dependencies": { - "which-typed-array": "^1.1.11" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, - "node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "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/isomorphic-ws": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", - "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", - "peerDependencies": { - "ws": "*" - } - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" - }, - "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.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", - "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", - "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/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dev": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "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-circus/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/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-cli/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/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-config/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/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-diff/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/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-each/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/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-matcher-utils/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/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-message-util/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/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-resolve/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/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/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/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-runtime/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/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/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/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-util/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/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-validate/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/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-watcher/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/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/jose": { - "version": "4.15.4", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.4.tgz", - "integrity": "sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==", - "optional": true, - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/joycon": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", - "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", - "engines": { - "node": ">=10" - } - }, - "node_modules/js-base64": { - "version": "3.7.5", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.5.tgz", - "integrity": "sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==" - }, - "node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" - }, - "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/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" - }, - "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-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" - }, - "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/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" - }, - "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/jsonpath-plus": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-7.2.0.tgz", - "integrity": "sha512-zBfiUPM5nD0YZSBT/o/fbCUlCcepMIdP0CJZxM1+KgA4f2T206f6VAg9e7mX35+KlMaIc5qXW34f3BnwJ3w+RA==", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "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/kuler": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", - "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" - }, - "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/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "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/listr2": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-7.0.2.tgz", - "integrity": "sha512-rJysbR9GKIalhTbVL2tYbF2hVyDnrf7pFUZBwjPaMIdadYHmeT+EVi/Bu3qd7ETQPahTotg2WRCatXwRBW554g==", - "dependencies": { - "cli-truncate": "^3.1.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", - "log-update": "^5.0.1", - "rfdc": "^1.3.0", - "wrap-ansi": "^8.1.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/listr2/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/listr2/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/listr2/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "node_modules/listr2/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/listr2/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/listr2/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/load-plugin": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/load-plugin/-/load-plugin-6.0.1.tgz", - "integrity": "sha512-YZyxJaWfN4F1xfPCyKFNIOL26vlFukmJY7wegxsriav4y2/0ZiICota6uFvyy52GjUj+tsPSjGLX+2m7kiU0+g==", - "dev": true, - "dependencies": { - "@npmcli/config": "^8.0.0", - "import-meta-resolve": "^4.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/load-plugin/node_modules/import-meta-resolve": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz", - "integrity": "sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "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": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "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/log-symbols/node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-5.0.1.tgz", - "integrity": "sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==", - "dependencies": { - "ansi-escapes": "^5.0.0", - "cli-cursor": "^4.0.0", - "slice-ansi": "^5.0.0", - "strip-ansi": "^7.0.1", - "wrap-ansi": "^8.0.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-escapes": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", - "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", - "dependencies": { - "type-fest": "^1.0.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-update/node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", - "dependencies": { - "restore-cursor": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "node_modules/log-update/node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/logform": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", - "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==", - "dependencies": { - "@colors/colors": "1.6.0", - "@types/triple-beam": "^1.3.2", - "fecha": "^4.2.0", - "ms": "^2.1.1", - "safe-stable-stringify": "^2.3.1", - "triple-beam": "^1.3.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, - "node_modules/longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/lowercase-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", - "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/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/markdown-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", - "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mdast-comment-marker": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/mdast-comment-marker/-/mdast-comment-marker-2.1.2.tgz", - "integrity": "sha512-HED3ezseRVkBzZ0uK4q6RJMdufr/2p3VfVZstE3H1N9K8bwtspztWo6Xd7rEatuGNoCXaBna8oEqMwUn0Ve1bw==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-mdx-expression": "^1.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-comment-marker/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/mdast-comment-marker/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/mdast-util-from-markdown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz", - "integrity": "sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==", - "dev": true, - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-heading-style": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-heading-style/-/mdast-util-heading-style-2.0.1.tgz", - "integrity": "sha512-0L5rthU4xKDVbw+UQ7D8Y8xOEsX4JXZvemWoEAsL+WAaeSH+TvVVwFnTb3G/OrjyP4VYQULoNWU+PdZfkmNu4A==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-heading-style/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/mdast-util-heading-style/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/mdast-util-mdx-expression": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-1.3.2.tgz", - "integrity": "sha512-xIPmR5ReJDu/DHH1OoIT1HkuybIfRGYRywC+gJtI7qHjCJp/M9jrmBEJW22O8lskDWm562BX2W8TiAwRTb0rKA==", - "dev": true, - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^2.0.0", - "@types/mdast": "^3.0.0", - "mdast-util-from-markdown": "^1.0.0", - "mdast-util-to-markdown": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/mdast-util-mdx-expression/node_modules/mdast-util-from-markdown": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz", - "integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "mdast-util-to-string": "^3.1.0", - "micromark": "^3.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-decode-string": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "unist-util-stringify-position": "^3.0.0", - "uvu": "^0.5.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/mdast-util-to-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", - "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz", - "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "micromark-core-commonmark": "^1.0.1", - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-chunked": "^1.0.0", - "micromark-util-combine-extensions": "^1.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-encode": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", - "micromark-util-subtokenize": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.1", - "uvu": "^0.5.0" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-core-commonmark": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz", - "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-factory-destination": "^1.0.0", - "micromark-factory-label": "^1.0.0", - "micromark-factory-space": "^1.0.0", - "micromark-factory-title": "^1.0.0", - "micromark-factory-whitespace": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-chunked": "^1.0.0", - "micromark-util-classify-character": "^1.0.0", - "micromark-util-html-tag-name": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-subtokenize": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.1", - "uvu": "^0.5.0" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-factory-destination": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz", - "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-factory-label": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz", - "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-factory-space": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", - "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-factory-title": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz", - "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-factory-whitespace": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz", - "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-util-character": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", - "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-util-chunked": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz", - "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-util-classify-character": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz", - "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-util-combine-extensions": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz", - "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-util-decode-numeric-character-reference": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz", - "integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-util-decode-string": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz", - "integrity": "sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-util-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz", - "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-util-html-tag-name": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz", - "integrity": "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-util-normalize-identifier": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz", - "integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-util-resolve-all": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz", - "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-util-sanitize-uri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz", - "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-encode": "^1.0.0", - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-util-subtokenize": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz", - "integrity": "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - } - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-util-symbol": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", - "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/mdast-util-mdx-expression/node_modules/micromark-util-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", - "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/mdast-util-mdx-expression/node_modules/unist-util-stringify-position": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", - "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-phrasing": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-3.0.1.tgz", - "integrity": "sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "unist-util-is": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-phrasing/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/mdast-util-phrasing/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/mdast-util-to-markdown": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-1.5.0.tgz", - "integrity": "sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^3.0.0", - "mdast-util-to-string": "^3.0.0", - "micromark-util-decode-string": "^1.0.0", - "unist-util-visit": "^4.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-markdown/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/mdast-util-to-markdown/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/mdast-util-to-markdown/node_modules/mdast-util-to-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", - "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-markdown/node_modules/micromark-util-character": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", - "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/mdast-util-to-markdown/node_modules/micromark-util-decode-numeric-character-reference": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz", - "integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/mdast-util-to-markdown/node_modules/micromark-util-decode-string": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz", - "integrity": "sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/mdast-util-to-markdown/node_modules/micromark-util-symbol": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", - "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/mdast-util-to-markdown/node_modules/micromark-util-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", - "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/mdast-util-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", - "dev": true, - "dependencies": { - "@types/mdast": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "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/micromark": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", - "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.0.tgz", - "integrity": "sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-destination": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", - "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-label": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", - "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-space": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", - "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-title": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", - "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-whitespace": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", - "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-chunked": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", - "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-classify-character": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", - "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-combine-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", - "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-chunked": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", - "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", - "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", - "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-html-tag-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", - "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-normalize-identifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", - "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-resolve-all": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", - "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", - "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-subtokenize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.0.tgz", - "integrity": "sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", - "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "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/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.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==", - "engines": { - "node": ">=6" - } - }, - "node_modules/mimic-response": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", - "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" - }, - "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/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "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-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "engines": { - "node": ">= 6.13.0" - } - }, - "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/nopt": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", - "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", - "dev": true, - "dependencies": { - "abbrev": "^2.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "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/normalize-url": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz", - "integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-normalize-package-bin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.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/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "engines": { - "node": "*" - } - }, - "node_modules/object-hash": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", - "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", - "optional": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" - } - }, - "node_modules/object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/oidc-token-hash": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz", - "integrity": "sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==", - "optional": true, - "engines": { - "node": "^10.13.0 || >=12.0.0" - } - }, - "node_modules/on-exit-leak-free": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", - "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", - "engines": { - "node": ">=14.0.0" - } - }, - "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==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/one-time": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", - "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", - "dependencies": { - "fn.name": "1.x.x" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/openid-client": { - "version": "5.6.4", - "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.6.4.tgz", - "integrity": "sha512-T1h3B10BRPKfcObdBklX639tVz+xh34O7GjofqrqiAQdm7eHsQ00ih18x6wuJ/E6FxdtS2u3FmUGPDeEcMwzNA==", - "optional": true, - "dependencies": { - "jose": "^4.15.4", - "lru-cache": "^6.0.0", - "object-hash": "^2.2.0", - "oidc-token-hash": "^5.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/openid-client/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==", - "optional": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/openid-client/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true - }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "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/ora/node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-cancelable": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", - "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", - "engines": { - "node": ">=12.20" - } - }, - "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/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "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/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", - "dev": true, - "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.2.tgz", - "integrity": "sha512-Yj9mA8fPiVgOUpByoTZO5pNrcl5Yk37FcSHsUINpAsaBIEZIuqcCclDZJCVxqQShDsmYX8QG63svJiTbOATZwg==", - "dev": true, - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "14 || >=16.14" - } - }, - "node_modules/path-scurry/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/path-scurry/node_modules/semver/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/path-scurry/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/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" - }, - "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/pino": { - "version": "8.16.2", - "resolved": "https://registry.npmjs.org/pino/-/pino-8.16.2.tgz", - "integrity": "sha512-2advCDGVEvkKu9TTVSa/kWW7Z3htI/sBKEZpqiHk6ive0i/7f5b1rsU8jn0aimxqfnSz5bj/nOYkwhBUn5xxvg==", - "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.7.0", - "thread-stream": "^2.0.0" - }, - "bin": { - "pino": "bin.js" - } - }, - "node_modules/pino-abstract-transport": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz", - "integrity": "sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==", - "dependencies": { - "readable-stream": "^4.0.0", - "split2": "^4.0.0" - } - }, - "node_modules/pino-abstract-transport/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/pino-abstract-transport/node_modules/readable-stream": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", - "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/pino-pretty": { - "version": "10.2.3", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.2.3.tgz", - "integrity": "sha512-4jfIUc8TC1GPUfDyMSlW1STeORqkoxec71yhxIpLDQapUu8WOuoz2TTCoidrIssyz78LZC69whBMPIKCMbi3cw==", - "dependencies": { - "colorette": "^2.0.7", - "dateformat": "^4.6.3", - "fast-copy": "^3.0.0", - "fast-safe-stringify": "^2.1.1", - "help-me": "^4.0.1", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.0.0", - "pump": "^3.0.0", - "readable-stream": "^4.0.0", - "secure-json-parse": "^2.4.0", - "sonic-boom": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "bin": { - "pino-pretty": "bin.js" - } - }, - "node_modules/pino-pretty/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/pino-pretty/node_modules/readable-stream": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", - "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/pino-std-serializers": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", - "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" - }, - "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/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "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/proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-warning": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.3.2.tgz", - "integrity": "sha512-n9wh8tvBe5sFmsqlg+XQhaQLumwpqoAUruLwjCopgTmUBjJ/fjtBsJzKleCaIGBOMXYEhp1YfKl4d7rJ5ZKJGA==" - }, - "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/protobufjs": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", - "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", - "hasInstallScript": true, - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/protobufjs/node_modules/long": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "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/pvtsutils": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.5.tgz", - "integrity": "sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==", - "dependencies": { - "tslib": "^2.6.1" - } - }, - "node_modules/pvutils": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", - "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/quick-format-unescaped": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", - "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/read-package-json-fast": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", - "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", - "dev": true, - "dependencies": { - "json-parse-even-better-errors": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/read-package-json-fast/node_modules/json-parse-even-better-errors": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", - "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/real-require": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", - "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/reflect-metadata": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz", - "integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==" - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", - "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/remark": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/remark/-/remark-15.0.1.tgz", - "integrity": "sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==", - "dev": true, - "dependencies": { - "@types/mdast": "^4.0.0", - "remark-parse": "^11.0.0", - "remark-stringify": "^11.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-cli": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/remark-cli/-/remark-cli-12.0.0.tgz", - "integrity": "sha512-IGxCo2VsXC/GS2YdlF7+S8DsUiyULyiauik01NFoiMIrOlbDhXjrKLD8hYazwQdD67nw2k7cwOBIxcK/cbNd9Q==", - "dev": true, - "dependencies": { - "import-meta-resolve": "^3.0.0", - "markdown-extensions": "^2.0.0", - "remark": "^15.0.0", - "unified-args": "^11.0.0" - }, - "bin": { - "remark": "cli.js" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/remark-lint/-/remark-lint-9.1.2.tgz", - "integrity": "sha512-m9e/aPlh7tsvfJfj8tPxrQzD6oEdb9Foko+Ya/6OwUP9EoGMfehv1Qtv26W1DoH58Wn8rT8CD+KuprTWscMmIA==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "remark-message-control": "^7.0.0", - "unified": "^10.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-blockquote-indentation": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-blockquote-indentation/-/remark-lint-blockquote-indentation-3.1.2.tgz", - "integrity": "sha512-5DOrFsZd5dXqA4p/VZvWSrqIWNFbBXjX7IV/FkVkxlNhNF/0FMf/4v8x1I2W3mzaZ7yDsWS/egpZnmligq1ckQ==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "pluralize": "^8.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-generated": "^2.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-blockquote-indentation/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-blockquote-indentation/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-blockquote-indentation/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-checkbox-character-style": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-checkbox-character-style/-/remark-lint-checkbox-character-style-4.1.2.tgz", - "integrity": "sha512-5ITz+1cCuJ3Jv/Q7rKgDEucCOnIgjWDnSHPJA1tb4TI/D316h+ALbDhZIpP8gyfAm6sBAh3Pwz9XZJN2uJB5UQ==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-checkbox-character-style/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-checkbox-character-style/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-checkbox-character-style/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-code-block-style": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-code-block-style/-/remark-lint-code-block-style-3.1.2.tgz", - "integrity": "sha512-3wsWmzzdyEsB9sOzBOf46TSkwwVKXN2JpTEQb6feN0Tl6Vg75F7T9MHqMz7aqk/56bOXSxUzdpXDscGBhziLRA==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-generated": "^2.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-code-block-style/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-code-block-style/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-code-block-style/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-emphasis-marker": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-emphasis-marker/-/remark-lint-emphasis-marker-3.1.2.tgz", - "integrity": "sha512-hPZ8vxZrIfxmLA5B66bA8y3PdHjcCQuaLsySIqi5PM2DkpN6a7zAP3v1znyRSaYJ1ANVWcu00/0bNzuUjflGCA==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-emphasis-marker/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-emphasis-marker/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-emphasis-marker/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-fenced-code-marker": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-fenced-code-marker/-/remark-lint-fenced-code-marker-3.1.2.tgz", - "integrity": "sha512-6XNqjOuhT+0c7Q/22aCsMz61ne9g8HRpYF79EXQPdbzYa+PcfPXMiQKStONY3PfC8OE2/3WXI2zcs8w9x+8+VQ==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-fenced-code-marker/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-fenced-code-marker/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-fenced-code-marker/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-final-newline": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-final-newline/-/remark-lint-final-newline-2.1.2.tgz", - "integrity": "sha512-K0FdPGPyEB94PwNgopwVJFE8oRWi7IhY2ycXFVAMReI51el7EHB8F1gX14tB6p6zyGy6mUh69bCVU9mMTNeOUg==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-final-newline/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-final-newline/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-final-newline/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-hard-break-spaces": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-hard-break-spaces/-/remark-lint-hard-break-spaces-3.1.2.tgz", - "integrity": "sha512-HaW0xsl3TI7VFAqGWWcZtPqyz0NWu19KKjSO7OGFTUJU4S9YiRnhIxmSFM0ZLSsVAynE+dhzVKa8U7dOpWDcOg==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-generated": "^2.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-hard-break-spaces/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-hard-break-spaces/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-hard-break-spaces/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-heading-style": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-heading-style/-/remark-lint-heading-style-3.1.2.tgz", - "integrity": "sha512-0RkcRPV/H2bPFgeInzBkK1cWUwtFTm83I+Db/Z5tDY02GzKOosHLvxtJyj/1391/opAH1LYbHtHWffir99IUgw==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-heading-style": "^2.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-generated": "^2.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-heading-style/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-heading-style/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-heading-style/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-link-title-style": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-link-title-style/-/remark-lint-link-title-style-3.1.2.tgz", - "integrity": "sha512-if4MahYJVvQUWlrXDF8GSv4b9VtLSgMSDHeikQp1/hGYlihLl9uGw3nlL5Lf9DqTN0qaT6RPbXOjuuzHlk38sg==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0", - "vfile-location": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-link-title-style/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-link-title-style/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-link-title-style/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-list-item-bullet-indent": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-list-item-bullet-indent/-/remark-lint-list-item-bullet-indent-4.1.2.tgz", - "integrity": "sha512-WgU5nooqIEm6f35opcbHKBzWrdFJA3XcyTfB3nv/v0KX43/h6qFGmmMJ5kEiaFExuQp3dZSdatWuY0YZ9YRbUg==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "pluralize": "^8.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-list-item-bullet-indent/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-list-item-bullet-indent/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-list-item-bullet-indent/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-list-item-content-indent": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-list-item-content-indent/-/remark-lint-list-item-content-indent-3.1.2.tgz", - "integrity": "sha512-TB0pmrWiRaQW80Y/PILFQTnHDghRxXNzMwyawlP+DBF9gNom3pEBmb4ZlGQlN0aa3r8VWeIKdv1ylHrfXE0vqA==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "pluralize": "^8.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-list-item-content-indent/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-list-item-content-indent/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-list-item-content-indent/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-list-item-indent": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-list-item-indent/-/remark-lint-list-item-indent-3.1.2.tgz", - "integrity": "sha512-tkrra1pxZVE4OVJGfN435u/v0ljruXU+dHzWiKDYeifquD4aWhJxvSApu7+FbE098D/4usVXgMxwFkNhrpZcSQ==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "pluralize": "^8.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-generated": "^2.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-list-item-indent/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-list-item-indent/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-list-item-indent/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-blockquote-without-marker": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-no-blockquote-without-marker/-/remark-lint-no-blockquote-without-marker-5.1.2.tgz", - "integrity": "sha512-QPbqsrt7EfpSWqTkZJ9tepabPIhBDlNqZkuxxMQYD0OQ2N+tHDUq3zE1JxI5ts1V9o/mWApgySocqGd3jlcKmQ==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-generated": "^2.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0", - "vfile-location": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-blockquote-without-marker/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-no-blockquote-without-marker/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-no-blockquote-without-marker/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-duplicate-definitions": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-no-duplicate-definitions/-/remark-lint-no-duplicate-definitions-3.1.2.tgz", - "integrity": "sha512-vi0nXA7p+pjQOorZOkr9E+QDhG74JAdbzqglWPrWWNI3z2rUYWYHTNSyWJbwEXaIIcev1ZAw8SCAOis5MNm+pA==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-generated": "^2.0.0", - "unist-util-position": "^4.0.0", - "unist-util-stringify-position": "^3.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-duplicate-definitions/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-no-duplicate-definitions/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-no-duplicate-definitions/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-duplicate-definitions/node_modules/unist-util-stringify-position": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", - "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-heading-content-indent": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-no-heading-content-indent/-/remark-lint-no-heading-content-indent-4.1.2.tgz", - "integrity": "sha512-TTxFsm1f4ZHFxZQCuz7j0QK4RvP6oArTiwazKLr16yaZe1608ypogMek4A30j2xX8WuO9+2uBzLXCY5OBo5x5Q==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-heading-style": "^2.0.0", - "pluralize": "^8.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-generated": "^2.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-heading-content-indent/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-no-heading-content-indent/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-no-heading-content-indent/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-inline-padding": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-no-inline-padding/-/remark-lint-no-inline-padding-4.1.2.tgz", - "integrity": "sha512-dGyhWsiqCZS3Slob0EVBUfsFBbdpMIBCvb56LlCgaHbnLsnNYx8PpF/wA5CgsN8BXIbXfRpyPB5cIJwIq5taYg==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-to-string": "^3.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-generated": "^2.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-inline-padding/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-no-inline-padding/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-no-inline-padding/node_modules/mdast-util-to-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", - "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-inline-padding/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-literal-urls": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-no-literal-urls/-/remark-lint-no-literal-urls-3.1.2.tgz", - "integrity": "sha512-4tV9JGLKxAMFSuWDMOqLozkFJ3HyRvhzgrPrxASoziaml23m7UXAozk5dkIrFny1cN2oG988Z8tORxX2FL1Ilw==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-to-string": "^3.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-generated": "^2.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-literal-urls/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-no-literal-urls/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-no-literal-urls/node_modules/mdast-util-to-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", - "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-literal-urls/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-shortcut-reference-image": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-no-shortcut-reference-image/-/remark-lint-no-shortcut-reference-image-3.1.2.tgz", - "integrity": "sha512-NX4XJFPyDeJJ77pmETxRj4oM/zayf7Lmn/O87HgExBkQIPz2NYbDeKD8QEyliLaV/oKA2rQufpzuFw55xa1Tww==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-generated": "^2.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-shortcut-reference-image/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-no-shortcut-reference-image/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-no-shortcut-reference-image/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-shortcut-reference-link": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-no-shortcut-reference-link/-/remark-lint-no-shortcut-reference-link-3.1.2.tgz", - "integrity": "sha512-/9iPN7FLKaaIzw4tLWKu7Rx0wAP7E2EuzIeentQlkY0rO/mMHipmT3IlgiebsAInKagzTY6TNFoG1rq2VnaCcA==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-generated": "^2.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-shortcut-reference-link/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-no-shortcut-reference-link/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-no-shortcut-reference-link/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-undefined-references": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/remark-lint-no-undefined-references/-/remark-lint-no-undefined-references-4.2.1.tgz", - "integrity": "sha512-HdNg5b2KiuNplcuVvRtsrUiROw557kAG1CiZYB7jQrrVWFgd86lKTa3bDiywe+87dGrGmHd3qQ28eZYTuHz2Nw==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-generated": "^2.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0", - "vfile-location": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-undefined-references/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-no-undefined-references/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-no-undefined-references/node_modules/micromark-util-normalize-identifier": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz", - "integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/remark-lint-no-undefined-references/node_modules/micromark-util-symbol": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", - "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/remark-lint-no-undefined-references/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-unused-definitions": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-no-unused-definitions/-/remark-lint-no-unused-definitions-3.1.2.tgz", - "integrity": "sha512-bOcaJAnjKxT3kASFquUA3fO9xem9wZhVqt8TbqjA84+G4n40qjaLXDs/4vq73aMsSde73K0f3j1u0pMe7et8yQ==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-generated": "^2.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-no-unused-definitions/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-no-unused-definitions/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-no-unused-definitions/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-ordered-list-marker-style": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-ordered-list-marker-style/-/remark-lint-ordered-list-marker-style-3.1.2.tgz", - "integrity": "sha512-62iVE/YQsA0Azaqt8yAJWPplWLS47kDLjXeC2PlRIAzCqbNt9qH3HId8vZ15QTSrp8rHmJwrCMdcqV6AZUi7gQ==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-generated": "^2.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-ordered-list-marker-style/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-ordered-list-marker-style/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-ordered-list-marker-style/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-rule-style": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-rule-style/-/remark-lint-rule-style-3.1.2.tgz", - "integrity": "sha512-0CsX2XcX9pIhAP5N7Y8mhYXp3/Ld+NvxXY1p0LHAq0NZu17UsZLuegvx/s25uFbQs08DcmSqyKnepU9qGGqmTQ==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-rule-style/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-rule-style/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-rule-style/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-strong-marker": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/remark-lint-strong-marker/-/remark-lint-strong-marker-3.1.2.tgz", - "integrity": "sha512-U/g4wngmiI0Q6WBRQG6pZxnDS33Wt/0QYA3+KNFBDykoi1vXsDEorIqy3dEag9z6XHwcMvFDsff6VRUhaOJWQg==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-strong-marker/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-strong-marker/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-strong-marker/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-table-cell-padding": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/remark-lint-table-cell-padding/-/remark-lint-table-cell-padding-4.1.3.tgz", - "integrity": "sha512-N9xtnS6MG/H3srAMjqqaF26A7socr87pIgt64dr5rxoSbDRWRPChGQ8y7wKyV8VeyRNF37e3E5KB3bQVqjSYaQ==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "unified": "^10.0.0", - "unified-lint-rule": "^2.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint-table-cell-padding/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint-table-cell-padding/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint-table-cell-padding/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-lint/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-lint/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-lint/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-message-control": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/remark-message-control/-/remark-message-control-7.1.1.tgz", - "integrity": "sha512-xKRWl1NTBOKed0oEtCd8BUfH5m4s8WXxFFSoo7uUwx6GW/qdCy4zov5LfPyw7emantDmhfWn5PdIZgcbVcWMDQ==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-comment-marker": "^2.0.0", - "unified": "^10.0.0", - "unified-message-control": "^4.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-message-control/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-message-control/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-message-control/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-parse": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", - "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", - "dev": true, - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-preset-lint-consistent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/remark-preset-lint-consistent/-/remark-preset-lint-consistent-5.1.2.tgz", - "integrity": "sha512-RQrWBFmyIkKfXtp9P1Fui7UbGSfXth9nuvRJUVnO0vfevBJe02iyMZWPokXSwkDOI/cM539wj0i3vrQupz+v5A==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "remark-lint": "^9.0.0", - "remark-lint-blockquote-indentation": "^3.0.0", - "remark-lint-checkbox-character-style": "^4.0.0", - "remark-lint-code-block-style": "^3.0.0", - "remark-lint-emphasis-marker": "^3.0.0", - "remark-lint-fenced-code-marker": "^3.0.0", - "remark-lint-heading-style": "^3.0.0", - "remark-lint-link-title-style": "^3.0.0", - "remark-lint-list-item-content-indent": "^3.0.0", - "remark-lint-ordered-list-marker-style": "^3.0.0", - "remark-lint-rule-style": "^3.0.0", - "remark-lint-strong-marker": "^3.0.0", - "remark-lint-table-cell-padding": "^4.0.0", - "unified": "^10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-preset-lint-consistent/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-preset-lint-consistent/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-preset-lint-consistent/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-preset-lint-recommended": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/remark-preset-lint-recommended/-/remark-preset-lint-recommended-6.1.3.tgz", - "integrity": "sha512-DGjbeP2TsFmQeJflUiIvJWAOs1PxJt7SG3WQyMxOppkRr/up+mxWVkuv+6AUuaR0EsuaaFGz7WmZM5TrSSFWJw==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "remark-lint": "^9.0.0", - "remark-lint-final-newline": "^2.0.0", - "remark-lint-hard-break-spaces": "^3.0.0", - "remark-lint-list-item-bullet-indent": "^4.0.0", - "remark-lint-list-item-indent": "^3.0.0", - "remark-lint-no-blockquote-without-marker": "^5.0.0", - "remark-lint-no-duplicate-definitions": "^3.0.0", - "remark-lint-no-heading-content-indent": "^4.0.0", - "remark-lint-no-inline-padding": "^4.0.0", - "remark-lint-no-literal-urls": "^3.0.0", - "remark-lint-no-shortcut-reference-image": "^3.0.0", - "remark-lint-no-shortcut-reference-link": "^3.0.0", - "remark-lint-no-undefined-references": "^4.0.0", - "remark-lint-no-unused-definitions": "^3.0.0", - "remark-lint-ordered-list-marker-style": "^3.0.0", - "unified": "^10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-preset-lint-recommended/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/remark-preset-lint-recommended/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/remark-preset-lint-recommended/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-stringify": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", - "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", - "dev": true, - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-to-markdown": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-stringify/node_modules/mdast-util-phrasing": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.0.0.tgz", - "integrity": "sha512-xadSsJayQIucJ9n053dfQwVu1kuXg7jCTdYsMK8rqzKZh52nLfSH/k0sAxE0u+pj/zKZX+o5wB+ML5mRayOxFA==", - "dev": true, - "dependencies": { - "@types/mdast": "^4.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-stringify/node_modules/mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", - "dev": true, - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-stringify/node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-stringify/node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-stringify/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/request/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, - "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==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "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-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" - }, - "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-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "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/responselike": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", - "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", - "dependencies": { - "lowercase-keys": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rfc4648": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/rfc4648/-/rfc4648-1.5.3.tgz", - "integrity": "sha512-MjOWxM065+WswwnmNONOT+bD1nXzY9Km6u3kzvnx8F8/HXGZdz3T6e6vZJ8Q/RIMUSp/nxqjH3GwvJDy8ijeQQ==" - }, - "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-async": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", - "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/sade": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", - "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", - "dev": true, - "dependencies": { - "mri": "^1.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/safe-array-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", - "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-stable-stringify": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", - "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", - "engines": { - "node": ">=10" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/secure-json-parse": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", - "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" - }, - "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/set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", - "dependencies": { - "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==" - }, - "node_modules/simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, - "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/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/sonic-boom": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.7.0.tgz", - "integrity": "sha512-IudtNvSqA/ObjN97tfgNmOKyDOs4dNcg4cUUsHDebqsgb8wGBBwb31LIgShNO8fye0dFI52X1+tFoKKI6Rq1Gg==", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/spark-md5": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/spark-md5/-/spark-md5-3.0.2.tgz", - "integrity": "sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw==" - }, - "node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "engines": { - "node": ">= 10.x" - } - }, - "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/sshpk": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", - "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sshpk/node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" - }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", - "engines": { - "node": "*" - } - }, - "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/stack-utils/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/stream-buffers": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.2.tgz", - "integrity": "sha512-DQi1h8VEBA/lURbSwFtEHnSTb9s2/pwLEaFuNhXwy1Dx3Sa0lOuYT2yNUr4/j2fs8oCAMANtrZ5OrPZtyVs3MQ==", - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "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==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs": { - "name": "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/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "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==", - "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==", - "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/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "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/text-hex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/thread-stream": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.1.tgz", - "integrity": "sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==", - "dependencies": { - "real-require": "^0.2.0" - } - }, - "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/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/triple-beam": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", - "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/trough": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz", - "integrity": "sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "node_modules/tsyringe": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.8.0.tgz", - "integrity": "sha512-YB1FG+axdxADa3ncEtRnQCFq/M0lALGLxSZeVNbTU8NqhOVc51nnv2CISTcvc1kyv6EGPtXVr0v6lWeDxiijOA==", - "dependencies": { - "tslib": "^1.9.3" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/tsyringe/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "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==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==" - }, - "node_modules/unified": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", - "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unified-args": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/unified-args/-/unified-args-11.0.0.tgz", - "integrity": "sha512-4q3OQ2EbNIaxVX1pMoB/QdFxw9BSOWBGUwn5LK3UJict+6i0ud18A1DZ177+2r5hC2nYFOw1jbCp27ydl44Zhg==", - "dev": true, - "dependencies": { - "@types/text-table": "^0.2.0", - "chalk": "^5.0.0", - "chokidar": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "json5": "^2.0.0", - "minimist": "^1.0.0", - "strip-ansi": "^7.0.0", - "text-table": "^0.2.0", - "unified-engine": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unified-args/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/unified-args/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/unified-engine": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/unified-engine/-/unified-engine-11.1.1.tgz", - "integrity": "sha512-uVx/R+Q8V5wv5EPdPzBPPscSKpbqWeqqIc0lMfDcn3aS+QDENTpDY+wdPQ5oswuQSpPn/miuP0FspIwo19++IA==", - "dev": true, - "dependencies": { - "@types/concat-stream": "^2.0.0", - "@types/debug": "^4.0.0", - "@types/is-empty": "^1.0.0", - "@types/node": "^20.0.0", - "@types/unist": "^3.0.0", - "@ungap/structured-clone": "^1.0.0", - "concat-stream": "^2.0.0", - "debug": "^4.0.0", - "glob": "^10.0.0", - "ignore": "^5.0.0", - "is-empty": "^1.0.0", - "is-plain-obj": "^4.0.0", - "load-plugin": "^6.0.0", - "parse-json": "^7.0.0", - "trough": "^2.0.0", - "unist-util-inspect": "^8.0.0", - "vfile": "^6.0.0", - "vfile-message": "^4.0.0", - "vfile-reporter": "^8.0.0", - "vfile-statistics": "^3.0.0", - "yaml": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unified-engine/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/unified-engine/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/unified-engine/node_modules/json-parse-even-better-errors": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", - "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/unified-engine/node_modules/lines-and-columns": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", - "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/unified-engine/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/unified-engine/node_modules/parse-json": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-7.1.1.tgz", - "integrity": "sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.21.4", - "error-ex": "^1.3.2", - "json-parse-even-better-errors": "^3.0.0", - "lines-and-columns": "^2.0.3", - "type-fest": "^3.8.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/unified-engine/node_modules/type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/unified-engine/node_modules/vfile": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", - "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unified-lint-rule": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/unified-lint-rule/-/unified-lint-rule-2.1.2.tgz", - "integrity": "sha512-JWudPtRN7TLFHVLEVZ+Rm8FUb6kCAtHxEXFgBGDxRSdNMnGyTU5zyYvduHSF/liExlFB3vdFvsAHnNVE/UjAwA==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "trough": "^2.0.0", - "unified": "^10.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unified-lint-rule/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/unified-lint-rule/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unified-message-control": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unified-message-control/-/unified-message-control-4.0.0.tgz", - "integrity": "sha512-1b92N+VkPHftOsvXNOtkJm4wHlr+UDmTBF2dUzepn40oy9NxanJ9xS1RwUBTjXJwqr2K0kMbEyv1Krdsho7+Iw==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^5.0.0", - "unist-util-visit": "^3.0.0", - "vfile": "^5.0.0", - "vfile-location": "^4.0.0", - "vfile-message": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unified-message-control/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/unified-message-control/node_modules/unist-util-stringify-position": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", - "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unified-message-control/node_modules/unist-util-visit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-3.1.0.tgz", - "integrity": "sha512-Szoh+R/Ll68QWAyQyZZpQzZQm2UPbxibDvaY8Xc9SUtYgPsDzx5AWSk++UUt2hJuow8mvwR+rG+LQLw+KsuAKA==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^5.0.0", - "unist-util-visit-parents": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unified-message-control/node_modules/unist-util-visit-parents": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-4.1.1.tgz", - "integrity": "sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unified-message-control/node_modules/vfile-message": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz", - "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-stringify-position": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unified/node_modules/vfile": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", - "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-generated": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.1.tgz", - "integrity": "sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-inspect": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/unist-util-inspect/-/unist-util-inspect-8.0.0.tgz", - "integrity": "sha512-/3Wn/wU6/H6UEo4FoYUeo8KUePN8ERiZpQYFWYoihOsr1DoDuv80PeB0hobVZyYSvALa2e556bG1A1/AbwU4yg==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-is": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz", - "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-is/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/unist-util-position": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.4.tgz", - "integrity": "sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-position/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.2.tgz", - "integrity": "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^5.0.0", - "unist-util-visit-parents": "^5.1.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz", - "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/unist-util-visit/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "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/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", - "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==" - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/uvu": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", - "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", - "dev": true, - "dependencies": { - "dequal": "^2.0.0", - "diff": "^5.0.0", - "kleur": "^4.0.3", - "sade": "^1.7.3" - }, - "bin": { - "uvu": "bin.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/uvu/node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/v8-to-istanbul": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz", - "integrity": "sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/vfile": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz", - "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "is-buffer": "^2.0.0", - "unist-util-stringify-position": "^3.0.0", - "vfile-message": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-location": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-4.1.0.tgz", - "integrity": "sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-location/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/vfile-message": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", - "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-reporter": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-8.1.0.tgz", - "integrity": "sha512-NfHyHdkCcy0BsXiLA3nId29TY7W7hgpc8nd8Soe3imATx5N4/+mkLYdMR+Y6Zvu6BXMMi0FZsD4FLCm1dN85Pg==", - "dev": true, - "dependencies": { - "@types/supports-color": "^8.0.0", - "string-width": "^6.0.0", - "supports-color": "^9.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile": "^6.0.0", - "vfile-message": "^4.0.0", - "vfile-sort": "^4.0.0", - "vfile-statistics": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-reporter/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/vfile-reporter/node_modules/emoji-regex": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", - "dev": true - }, - "node_modules/vfile-reporter/node_modules/string-width": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-6.1.0.tgz", - "integrity": "sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^10.2.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vfile-reporter/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/vfile-reporter/node_modules/supports-color": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", - "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/vfile-reporter/node_modules/vfile": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", - "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-sort": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-4.0.0.tgz", - "integrity": "sha512-lffPI1JrbHDTToJwcq0rl6rBmkjQmMuXkAxsZPRS9DXbaJQvc642eCg6EGxcX2i1L+esbuhq+2l9tBll5v8AeQ==", - "dev": true, - "dependencies": { - "vfile": "^6.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-sort/node_modules/vfile": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", - "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-statistics": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-3.0.0.tgz", - "integrity": "sha512-/qlwqwWBWFOmpXujL/20P+Iuydil0rZZNglR+VNm6J0gpLHwuVM5s7g2TfVoswbXjZ4HuIhLMySEyIw5i7/D8w==", - "dev": true, - "dependencies": { - "vfile": "^6.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-statistics/node_modules/vfile": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", - "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", - "dev": true - }, - "node_modules/vfile/node_modules/unist-util-stringify-position": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", - "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile/node_modules/vfile-message": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz", - "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-stringify-position": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/walk-up-path": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-3.0.1.tgz", - "integrity": "sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==", - "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/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "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/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", - "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.4", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/winston": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.11.0.tgz", - "integrity": "sha512-L3yR6/MzZAOl0DsysUXHVjOwv8mKZ71TrA/41EIduGpOOV5LQVodqN+QdQ6BS6PJ/RdIshZhq84P/fStEZkk7g==", - "dependencies": { - "@colors/colors": "^1.6.0", - "@dabh/diagnostics": "^2.0.2", - "async": "^3.2.3", - "is-stream": "^2.0.0", - "logform": "^2.4.0", - "one-time": "^1.0.0", - "readable-stream": "^3.4.0", - "safe-stable-stringify": "^2.3.1", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.5.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/winston-transport": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.6.0.tgz", - "integrity": "sha512-wbBA9PbPAHxKiygo7ub7BYRiKxms0tpfU2ljtWzb3SjRjv5yl6Ozuy/TkXf00HTAt+Uylo3gSkNwzc4ME0wiIg==", - "dependencies": { - "logform": "^2.3.2", - "readable-stream": "^3.6.0", - "triple-beam": "^1.3.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "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==" - }, - "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/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "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/yaml": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", - "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", - "engines": { - "node": ">= 14" - } - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "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==", - "engines": { - "node": ">=12" - } - }, - "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" - } - }, - "node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - } - } -} diff --git a/solo/package.json b/solo/package.json deleted file mode 100644 index 20968d273..000000000 --- a/solo/package.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "name": "@hashgraph/solo", - "version": "0.21.0", - "description": "An opinionated CLI tool to deploy and manage private Hedera Networks.", - "main": "src/index.mjs", - "type": "module", - "bin": { - "solo": "solo.mjs" - }, - "publishConfig": { - "access": "public" - }, - "scripts": { - "test": "NODE_OPTIONS=--experimental-vm-modules jest --runInBand --detectOpenHandles --forceExit --testPathIgnorePatterns=\".*/e2e/.*\"", - "test-e2e": "NODE_OPTIONS=--experimental-vm-modules jest --runInBand --detectOpenHandles --forceExit --testPathIgnorePatterns=\\\".*/unit/.*\\\"", - "solo": "NODE_OPTIONS=--experimental-vm-modules node solo.mjs", - "check": "remark . --quiet --frail && eslint .", - "format": "remark . --quiet --frail --output && eslint --fix ." - }, - "keywords": [ - "solo", - "full-stack-testing", - "fullstack-network-manager" - ], - "author": "Swirlds Labs", - "license": "Apache2.0", - "dependencies": { - "@hashgraph/sdk": "^2.40.0", - "@kubernetes/client-node": "^0.20.0", - "@listr2/prompt-adapter-enquirer": "^1.0.2", - "@peculiar/x509": "^1.9.5", - "adm-zip": "^0.5.10", - "chalk": "^5.3.0", - "dotenv": "^16.3.1", - "enquirer": "^2.4.1", - "esm": "^3.2.25", - "figlet": "^1.7.0", - "got": "^13.0.0", - "inquirer": "^9.2.12", - "listr2": "^7.0.2", - "tar": "^6.2.0", - "uuid": "^9.0.1", - "winston": "^3.11.0", - "yaml": "^2.3.4", - "yargs": "^17.7.2" - }, - "devDependencies": { - "@jest/globals": "^29.7.0", - "@jest/test-sequencer": "^29.7.0", - "eslint": "^8.53.0", - "eslint-config-standard": "^17.1.0", - "eslint-plugin-headers": "^1.1.0", - "eslint-plugin-import": "^2.29.0", - "eslint-plugin-n": "^16.3.1", - "eslint-plugin-promise": "^6.1.1", - "jest": "^29.7.0", - "remark-cli": "^12.0.0", - "remark-lint-list-item-indent": "^3.1.2", - "remark-preset-lint-consistent": "^5.1.2", - "remark-preset-lint-recommended": "^6.1.3" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/hashgraph/solo.git" - }, - "os": [ - "darwin", - "linux" - ], - "engines": { - "node": ">=18.18.2", - "npm": ">=9.8.1" - } -} diff --git a/solo/resources/extract-jar.sh b/solo/resources/extract-jar.sh deleted file mode 100644 index 1b473a064..000000000 --- a/solo/resources/extract-jar.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -# Extract a jar file to a destination directory -# Usage: ./extract.sh - -if [ -z "${1}" ]; then - echo "jarFile arg is required"; - exit 1 -fi - -if [ -z "${2}" ]; then - echo "destDir arg is required"; - exit 1 -fi - -cd "${2}" && jar xvf "${1}" diff --git a/solo/resources/templates/api-permission.properties b/solo/resources/templates/api-permission.properties deleted file mode 100644 index 8a33c31d4..000000000 --- a/solo/resources/templates/api-permission.properties +++ /dev/null @@ -1,70 +0,0 @@ -# Crypto -createAccount=0-* -cryptoTransfer=0-* -updateAccount=0-* -cryptoGetBalance=0-* -getAccountInfo=0-* -cryptoDelete=0-* -getAccountRecords=0-* -getTxRecordByTxID=0-* -getTransactionReceipts=0-* -approveAllowances=0-* -deleteAllowances=0-* -# File -createFile=0-* -updateFile=0-* -deleteFile=0-* -appendContent=0-* -getFileContent=0-* -getFileInfo=0-* -# Contract -createContract=0-* -updateContract=0-* -contractCallMethod=0-* -getContractInfo=0-* -contractCallLocalMethod=0-* -contractGetBytecode=0-* -getTxRecordByContractID=0-* -deleteContract=0-* -# Consensus -createTopic=0-* -updateTopic=0-* -deleteTopic=0-* -submitMessage=0-* -getTopicInfo=0-* -# Ethereum -ethereumTransaction=0-* -# Scheduling -scheduleCreate=0-* -scheduleSign=0-* -scheduleDelete=0-* -scheduleGetInfo=0-* -# Token -tokenCreate=0-* -tokenFreezeAccount=0-* -tokenUnfreezeAccount=0-* -tokenGrantKycToAccount=0-* -tokenRevokeKycFromAccount=0-* -tokenDelete=0-* -tokenMint=0-* -tokenBurn=0-* -tokenAccountWipe=0-* -tokenUpdate=0-* -tokenGetInfo=0-* -tokenGetNftInfo=0-* -tokenGetNftInfos=0-* -tokenGetAccountNftInfos=0-* -tokenAssociateToAccount=0-* -tokenDissociateFromAccount=0-* -tokenFeeScheduleUpdate=0-* -tokenPause=0-* -tokenUnpause=0-* -# Network -getVersionInfo=0-* -networkGetExecutionTime=2-50 -systemDelete=2-59 -systemUndelete=2-60 -freeze=2-58 -getAccountDetails=2-50 -# Util -utilPrng=0-* diff --git a/solo/resources/templates/application.properties b/solo/resources/templates/application.properties deleted file mode 100644 index 4994eb276..000000000 --- a/solo/resources/templates/application.properties +++ /dev/null @@ -1 +0,0 @@ -autoRenew.targetTypes= diff --git a/solo/resources/templates/bootstrap.properties b/solo/resources/templates/bootstrap.properties deleted file mode 100644 index 74d317b61..000000000 --- a/solo/resources/templates/bootstrap.properties +++ /dev/null @@ -1,9 +0,0 @@ -ledger.id=0x01 -netty.mode=DEV -contracts.chainId=298 -hedera.recordStream.logPeriod=1 -balances.exportPeriodSecs=400 -files.maxSizeKb=2048 -hedera.recordStream.compressFilesOnCreation=true -balances.compressOnCreation=true -contracts.maxNumWithHapiSigsAccess=0 diff --git a/solo/resources/templates/config.template b/solo/resources/templates/config.template deleted file mode 100644 index 142933e96..000000000 --- a/solo/resources/templates/config.template +++ /dev/null @@ -1,62 +0,0 @@ -# ====================================================================================================================== -# Address book Format Description -# ====================================================================================================================== -# Address book format varies across versions since it evolved over time. As of July 27, 2023 the below formats were -# relevant for recent versions. Latest version is available in the file: hedera-services/hedera-node/config.txt -# -# - v.0.39.* (or before) format: -# Fields: address, , , , , , , , -# Example: address, 0, node0, 1, 10.128.0.27, 50111, 35.223.93.31, 30124, 0.0.3 -# -# - v.0.4* format: -# Fields: address, , , , , , , , , -# Example: address, 0, n0, node0, 1, 10.128.0.27, 50111, 35.223.93.31, 30124, 0.0.3 -# -# - v.0.41* (onward) we need to append the below formatted line with next node ID after the list of "address" lines -#

-# nextNodeId, -# -# Field descriptions: -# =========================== -# NODE_ID: This increments for each node and starts from 0. -# NEXT_NODE_ID: The id for the next node (i.e. last node ID + 1) -# NODE_NICK_NAME: This is a string (alphanumeric). e.g. node0 -# NODE_NAME: This is a string (alphanumeric). e.g. node0 or n0 -# NODE_STAKE_AMOUNT: A long value. e.g. 1 or a larger number -# INTERNAL_IP: This is the pod IP -# INTERNAL_GOSSIP_PORT: Default gossip port is 50111. So use the exposed port that is mapped to 50111 in container. -# EXTERNAL_IP: This is the service IP -# EXTERNAL_GOSSIP_PORT: Default gossip port is 50111. This is usually same as INTERNAL_GOSSIP_PORT unless mapped differently. -# ACCOUNT_ID: Must start from 0.0.3 -# - -# Account restrictions: -# =========================== -# All ACCOUNT_ID should start from 0.0.3 because of restricted accounts as below: -# - 0.0.0 restricted and not usable -# - 0.0.1 minting account and not usable -# - 0.0.2 treasury account -# -# Default Ports -# =========================== -# We only need to specify the gossip port (INTERNAL_GOSSIP_PORT, EXTERNAL_GOSSIP_PORT). Below are some details on other -# ports that a node may expose: -# - 50111: gossip port -# - 50211: grpc non-tls (for platform services) -# - 50212: grpc tls (for platform services) -# -# IP Address -# =========================== -# When deploying in a kubernetes cluster, we need to use the following IP mapping: -# - INTERNAL_IP: This should be the Pod IP exposing gossip port (i.e. 50111) -# - EXTERNAL_IP: This should be the cluster IP of the service exposing gossip port (i.e. 50111) -# -# -# Example config.txt (for v0.4* onward) -# =========================== -# swirld, 123 -# app, HederaNode.jar -# address, 0, node0, node0, 1, 10.244.0.197, 56789, 10.96.61.84, 50111, 0.0.0 -# address, 1, node1, node1, 1, 10.244.0.198, 56789, 10.96.163.93, 50111, 0.0.1 -# nextNodeId, 2 -# ====================================================================================================================== diff --git a/solo/resources/templates/log4j2.xml b/solo/resources/templates/log4j2.xml deleted file mode 100644 index 590949c2a..000000000 --- a/solo/resources/templates/log4j2.xml +++ /dev/null @@ -1,318 +0,0 @@ - - - - - - - - - - - %d{yyyy-MM-dd HH:mm:ss.SSS} %-5p %-4L %c{1} - %m{nolookups}%n - - - - - - - - - - - %d{yyyy-MM-dd HH:mm:ss.SSS} %-5p %-4L %c{1} - %m{nolookups}%n - - - - - - - - - - %d{yyyy-MM-dd HH:mm:ss.SSS} %-8sn %-5p %-16marker <%t> %c{1}: %msg{nolookups}%n - - - - - - - - - - %d{yyyy-MM-dd HH:mm:ss.SSS} %-8sn %-5p %-16marker <%t> %c{1}: %msg{nolookups}%n - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/solo/resources/templates/settings.txt b/solo/resources/templates/settings.txt deleted file mode 100644 index 307954212..000000000 --- a/solo/resources/templates/settings.txt +++ /dev/null @@ -1,25 +0,0 @@ -checkSignedStateFromDisk, 1 -csvFileName, MainNetStats -csvOutputFolder, data/stats -doUpnp, false -enableEventStreaming, true -eventsLogDir, /opt/hgcapp/eventsStreams -eventsLogPeriod, 5 -maxEventQueueForCons, 1000 -maxOutgoingSyncs, 8 -numConnections, 1000 -reconnect.active, 1 -reconnect.asyncStreamTimeoutMilliseconds, 60000 -reconnect.reconnectWindowSeconds, -1 -showInternalStats, 1 -state.saveStatePeriod, 900 -state.signedStateDisk, 5 -throttle7extra, 0.5 -useLoopbackIp, false -waitAtStartup, false -jasperDb.iteratorInputBufferBytes, 16777216 -prometheusEndpointEnabled, true -transactionMaxBytes, 6144 -loadKeysFromPfxFiles, true -crypto.enableNewKeyStoreModel, true - diff --git a/solo/solo.mjs b/solo/solo.mjs deleted file mode 100755 index a16d7818c..000000000 --- a/solo/solo.mjs +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env node -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import * as fnm from './src/index.mjs' - -fnm.main(process.argv) diff --git a/solo/src/commands/account.mjs b/solo/src/commands/account.mjs deleted file mode 100644 index b594dde50..000000000 --- a/solo/src/commands/account.mjs +++ /dev/null @@ -1,388 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { BaseCommand } from './base.mjs' -import { FullstackTestingError, IllegalArgumentError } from '../core/errors.mjs' -import { flags } from './index.mjs' -import { Listr } from 'listr2' -import * as prompts from './prompts.mjs' -import { constants } from '../core/index.mjs' -import { sleep } from '../core/helpers.mjs' -import { HbarUnit, PrivateKey } from '@hashgraph/sdk' - -export class AccountCommand extends BaseCommand { - constructor (opts) { - super(opts) - - if (!opts || !opts.accountManager) throw new IllegalArgumentError('An instance of core/AccountManager is required', opts.accountManager) - - this.accountManager = opts.accountManager - this.nodeClient = null - this.accountInfo = null - } - - async closeConnections () { - if (this.nodeClient) { - this.nodeClient.close() - await sleep(5) // sleep a couple of ticks for connections to close - } - await this.accountManager.stopPortForwards() - await sleep(5) // sleep a couple of ticks for connections to close - } - - async buildAccountInfo (accountInfo, namespace, shouldRetrievePrivateKey) { - const newAccountInfo = { - accountId: accountInfo.accountId.toString(), - publicKey: accountInfo.key.toString(), - balance: accountInfo.balance.to(HbarUnit.Hbar).toNumber() - } - - if (shouldRetrievePrivateKey) { - const accountKeys = await this.accountManager.getAccountKeysFromSecret(newAccountInfo.accountId, namespace) - newAccountInfo.privateKey = accountKeys.privateKey - } - - return newAccountInfo - } - - async createNewAccount (ctx) { - if (ctx.config.privateKey) { - ctx.privateKey = PrivateKey.fromStringED25519(ctx.config.privateKey) - } else { - ctx.privateKey = PrivateKey.generateED25519() - } - - return await this.accountManager.createNewAccount(ctx.config.namespace, - ctx.nodeClient, ctx.privateKey, ctx.config.amount) - } - - async loadNodeClient (ctx) { - const serviceMap = await this.accountManager.getNodeServiceMap(ctx.config.namespace) - - ctx.nodeClient = await this.accountManager.getNodeClient(ctx.config.namespace, - serviceMap, ctx.treasuryAccountId, ctx.treasuryPrivateKey) - this.nodeClient = ctx.nodeClient // store in class so that we can make sure connections are closed - } - - async loadTreasuryAccount (ctx) { - ctx.treasuryAccountId = constants.TREASURY_ACCOUNT_ID - // check to see if the treasure account is in the secrets - const accountInfo = await this.accountManager.getAccountKeysFromSecret(ctx.treasuryAccountId, ctx.config.namespace) - - // if it isn't in the secrets we can load genesis key - if (accountInfo) { - ctx.treasuryPrivateKey = accountInfo.privateKey - } else { - ctx.treasuryPrivateKey = constants.GENESIS_KEY - } - } - - async getAccountInfo (ctx) { - return this.accountManager.accountInfoQuery(ctx.config.accountId, ctx.nodeClient) - } - - async updateAccountInfo (ctx) { - let amount = ctx.config.amount - if (ctx.config.privateKey) { - if (!(await this.accountManager.sendAccountKeyUpdate(ctx.accountInfo.accountId, ctx.config.privateKey, ctx.nodeClient, ctx.accountInfo.privateKey))) { - this.logger.error(`failed to update account keys for accountId ${ctx.accountInfo.accountId}`) - return false - } - this.logger.debug(`sent account key update for account ${ctx.accountInfo.accountId}`) - } else { - amount = amount || flags.amount.definition.defaultValue - } - - const hbarAmount = Number.parseFloat(amount) - if (amount && isNaN(hbarAmount)) { - throw new FullstackTestingError(`The HBAR amount was invalid: ${amount}`) - } - - if (hbarAmount > 0) { - if (!(await this.transferAmountFromOperator(ctx.nodeClient, ctx.accountInfo.accountId, hbarAmount))) { - this.logger.error(`failed to transfer amount for accountId ${ctx.accountInfo.accountId}`) - return false - } - this.logger.debug(`sent transfer amount for account ${ctx.accountInfo.accountId}`) - } - return true - } - - async transferAmountFromOperator (nodeClient, toAccountId, amount) { - return await this.accountManager.transferAmount(nodeClient, constants.TREASURY_ACCOUNT_ID, toAccountId, amount) - } - - async create (argv) { - const self = this - - const tasks = new Listr([ - { - title: 'Initialize', - task: async (ctx, task) => { - self.configManager.update(argv) - await prompts.execute(task, self.configManager, [ - flags.namespace - ]) - - const config = { - namespace: self.configManager.getFlag(flags.namespace), - privateKey: self.configManager.getFlag(flags.privateKey), - amount: self.configManager.getFlag(flags.amount) - } - - if (!config.amount) { - config.amount = flags.amount.definition.defaultValue - } - - if (!await this.k8.hasNamespace(config.namespace)) { - throw new FullstackTestingError(`namespace ${config.namespace} does not exist`) - } - - // set config in the context for later tasks to use - ctx.config = config - - self.logger.debug('Initialized config', { config }) - - await self.loadTreasuryAccount(ctx) - await self.loadNodeClient(ctx) - } - }, - { - title: 'create the new account', - task: async (ctx, task) => { - self.accountInfo = await self.createNewAccount(ctx) - const accountInfoCopy = { ...self.accountInfo } - delete accountInfoCopy.privateKey - - this.logger.showJSON('new account created', accountInfoCopy) - } - } - ], { - concurrent: false, - rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION - }) - - try { - await tasks.run() - } catch (e) { - throw new FullstackTestingError(`Error in creating account: ${e.message}`, e) - } finally { - await this.closeConnections() - } - - return true - } - - async update (argv) { - const self = this - - const tasks = new Listr([ - { - title: 'Initialize', - task: async (ctx, task) => { - self.configManager.update(argv) - await prompts.execute(task, self.configManager, [ - flags.namespace, - flags.accountId - ]) - - const config = { - namespace: self.configManager.getFlag(flags.namespace), - accountId: self.configManager.getFlag(flags.accountId), - privateKey: self.configManager.getFlag(flags.privateKey), - amount: self.configManager.getFlag(flags.amount) - } - - if (!await this.k8.hasNamespace(config.namespace)) { - throw new FullstackTestingError(`namespace ${config.namespace} does not exist`) - } - - // set config in the context for later tasks to use - ctx.config = config - - self.logger.debug('Initialized config', { config }) - } - }, - { - title: 'get the account info', - task: async (ctx, task) => { - await self.loadTreasuryAccount(ctx) - await self.loadNodeClient(ctx) - ctx.accountInfo = await self.buildAccountInfo(await self.getAccountInfo(ctx), ctx.config.namespace, ctx.config.privateKey) - } - }, - { - title: 'update the account', - task: async (ctx, task) => { - if (!(await self.updateAccountInfo(ctx))) { - throw new FullstackTestingError(`An error occurred updating account ${ctx.accountInfo.accountId}`) - } - } - }, - { - title: 'get the updated account info', - task: async (ctx, task) => { - self.accountInfo = await self.buildAccountInfo(await self.getAccountInfo(ctx), ctx.config.namespace, false) - this.logger.showJSON('account info', self.accountInfo) - } - } - ], { - concurrent: false, - rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION - }) - - try { - await tasks.run() - } catch (e) { - throw new FullstackTestingError(`Error in updating account: ${e.message}`, e) - } finally { - await this.closeConnections() - } - - return true - } - - async get (argv) { - const self = this - - const tasks = new Listr([ - { - title: 'Initialize', - task: async (ctx, task) => { - self.configManager.update(argv) - await prompts.execute(task, self.configManager, [ - flags.namespace, - flags.accountId - ]) - - const config = { - namespace: self.configManager.getFlag(flags.namespace), - accountId: self.configManager.getFlag(flags.accountId) - } - - if (!await this.k8.hasNamespace(config.namespace)) { - throw new FullstackTestingError(`namespace ${config.namespace} does not exist`) - } - - // set config in the context for later tasks to use - ctx.config = config - - self.logger.debug('Initialized config', { config }) - } - }, - { - title: 'get the account info', - task: async (ctx, task) => { - await self.loadTreasuryAccount(ctx) - await self.loadNodeClient(ctx) - self.accountInfo = await self.buildAccountInfo(await self.getAccountInfo(ctx), ctx.config.namespace, false) - this.logger.showJSON('account info', self.accountInfo) - } - } - ], { - concurrent: false, - rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION - }) - - try { - await tasks.run() - } catch (e) { - throw new FullstackTestingError(`Error in getting account info: ${e.message}`, e) - } finally { - await this.closeConnections() - } - - return true - } - - /** - * Return Yargs command definition for 'node' command - * @param accountCmd an instance of NodeCommand - */ - static getCommandDefinition (accountCmd) { - return { - command: 'account', - desc: 'Manage Hedera accounts in fullstack testing network', - builder: yargs => { - return yargs - .command({ - command: 'create', - desc: 'Creates a new account with a new key and stores the key in the Kubernetes secrets', - builder: y => flags.setCommandFlags(y, - flags.namespace, - flags.privateKey, - flags.amount - ), - handler: argv => { - accountCmd.logger.debug("==== Running 'account create' ===") - accountCmd.logger.debug(argv) - - accountCmd.create(argv).then(r => { - accountCmd.logger.debug("==== Finished running 'account create' ===") - if (!r) process.exit(1) - }).catch(err => { - accountCmd.logger.showUserError(err) - process.exit(1) - }) - } - }) - .command({ - command: 'update', - desc: 'Updates an existing account with the provided info\n', - builder: y => flags.setCommandFlags(y, - flags.namespace, - flags.accountId, - flags.privateKey, - flags.amount - ), - handler: argv => { - accountCmd.logger.debug("==== Running 'account update' ===") - accountCmd.logger.debug(argv) - - accountCmd.update(argv).then(r => { - accountCmd.logger.debug("==== Finished running 'account update' ===") - if (!r) process.exit(1) - }).catch(err => { - accountCmd.logger.showUserError(err) - process.exit(1) - }) - } - }) - .command({ - command: 'get', - desc: 'Gets the account info including the current amount of HBAR', - builder: y => flags.setCommandFlags(y, - flags.namespace, - flags.accountId - ), - handler: argv => { - accountCmd.logger.debug("==== Running 'account get' ===") - accountCmd.logger.debug(argv) - - accountCmd.get(argv).then(r => { - accountCmd.logger.debug("==== Finished running 'account get' ===") - if (!r) process.exit(1) - }).catch(err => { - accountCmd.logger.showUserError(err) - process.exit(1) - }) - } - }) - .demandCommand(1, 'Select an account command') - } - } - } -} diff --git a/solo/src/commands/base.mjs b/solo/src/commands/base.mjs deleted file mode 100644 index 78a113fa9..000000000 --- a/solo/src/commands/base.mjs +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -'use strict' -import { MissingArgumentError } from '../core/errors.mjs' -import { ShellRunner } from '../core/shell_runner.mjs' - -export class BaseCommand extends ShellRunner { - async prepareChartPath (chartDir, chartRepo, chartName) { - if (!chartRepo) throw new MissingArgumentError('chart repo name is required') - if (!chartName) throw new MissingArgumentError('chart name is required') - - if (chartDir) { - const chartPath = `${chartDir}/${chartName}` - await this.helm.dependency('update', chartPath) - return chartPath - } - - return `${chartRepo}/${chartName}` - } - - constructor (opts) { - if (!opts || !opts.logger) throw new Error('An instance of core/Logger is required') - if (!opts || !opts.helm) throw new Error('An instance of core/Helm is required') - if (!opts || !opts.k8) throw new Error('An instance of core/K8 is required') - if (!opts || !opts.chartManager) throw new Error('An instance of core/ChartManager is required') - if (!opts || !opts.configManager) throw new Error('An instance of core/ConfigManager is required') - if (!opts || !opts.depManager) throw new Error('An instance of core/DependencyManager is required') - - super(opts.logger) - - this.helm = opts.helm - this.k8 = opts.k8 - this.chartManager = opts.chartManager - this.configManager = opts.configManager - this.depManager = opts.depManager - } -} diff --git a/solo/src/commands/cluster.mjs b/solo/src/commands/cluster.mjs deleted file mode 100644 index 659c704c3..000000000 --- a/solo/src/commands/cluster.mjs +++ /dev/null @@ -1,354 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { ListrEnquirerPromptAdapter } from '@listr2/prompt-adapter-enquirer' -import { Listr } from 'listr2' -import { FullstackTestingError } from '../core/errors.mjs' -import * as flags from './flags.mjs' -import { BaseCommand } from './base.mjs' -import chalk from 'chalk' -import { constants } from '../core/index.mjs' -import * as prompts from './prompts.mjs' - -/** - * Define the core functionalities of 'cluster' command - */ -export class ClusterCommand extends BaseCommand { - async showClusterList () { - this.logger.showList('Clusters', await this.k8.getClusters()) - return true - } - - /** - * Get cluster-info for the given cluster name - * @returns {Promise} - */ - async getClusterInfo () { - try { - const cluster = this.k8.getKubeConfig().getCurrentCluster() - this.logger.showJSON(`Cluster Information (${cluster.name})`, cluster) - this.logger.showUser('\n') - return true - } catch (e) { - this.logger.showUserError(e) - } - - return false - } - - /** - * Show list of installed chart - * @param clusterSetupNamespace - */ - async showInstalledChartList (clusterSetupNamespace) { - this.logger.showList('Installed Charts', await this.chartManager.getInstalledCharts(clusterSetupNamespace)) - } - - /** - * Setup cluster with shared components - * @param argv - * @returns {Promise} - */ - async setup (argv) { - const self = this - - const tasks = new Listr([ - { - title: 'Initialize', - task: async (ctx, task) => { - self.configManager.update(argv) - await prompts.execute(task, self.configManager, [ - flags.clusterSetupNamespace, - flags.chartDirectory, - flags.fstChartVersion, - flags.deployPrometheusStack, - flags.deployMinio, - flags.deployCertManager, - flags.deployCertManagerCrds - ]) - - // prepare config - ctx.config = { - clusterSetupNamespace: self.configManager.getFlag(flags.clusterSetupNamespace), - chartDir: self.configManager.getFlag(flags.chartDirectory), - deployPrometheusStack: self.configManager.getFlag(flags.deployPrometheusStack), - deployMinio: self.configManager.getFlag(flags.deployMinio), - deployCertManager: self.configManager.getFlag(flags.deployCertManager), - deployCertManagerCrds: self.configManager.getFlag(flags.deployCertManagerCrds), - fstChartVersion: self.configManager.getFlag(flags.fstChartVersion) - } - - self.logger.debug('Prepare ctx.config', { config: ctx.config, argv }) - - ctx.isChartInstalled = await this.chartManager.isChartInstalled(ctx.config.clusterSetupNamespace, constants.FULLSTACK_CLUSTER_SETUP_CHART) - } - }, - { - title: 'Prepare chart values', - task: async (ctx, _) => { - ctx.chartPath = await this.prepareChartPath(ctx.config.chartDir) - ctx.valuesArg = this.prepareValuesArg( - ctx.config.chartDir, - ctx.config.deployPrometheusStack, - ctx.config.deployMinio, - ctx.config.deployCertManager, - ctx.config.deployCertManagerCrds - ) - }, - skip: (ctx, _) => ctx.isChartInstalled - }, - { - title: `Install '${constants.FULLSTACK_CLUSTER_SETUP_CHART}' chart`, - task: async (ctx, _) => { - const clusterSetupNamespace = ctx.config.clusterSetupNamespace - const version = ctx.config.fstChartVersion - - const chartPath = ctx.chartPath - const valuesArg = ctx.valuesArg - - try { - await self.chartManager.install(clusterSetupNamespace, constants.FULLSTACK_CLUSTER_SETUP_CHART, chartPath, version, valuesArg) - } catch (e) { - // if error, uninstall the chart and rethrow the error - self.logger.debug(`Error on installing ${constants.FULLSTACK_CLUSTER_SETUP_CHART}. attempting to rollback by uninstalling the chart`, e) - try { - await self.chartManager.uninstall(clusterSetupNamespace, constants.FULLSTACK_CLUSTER_SETUP_CHART) - } catch (ex) { - // ignore error during uninstall since we are doing the best-effort uninstall here - } - - throw e - } - - if (argv.dev) { - await self.showInstalledChartList(clusterSetupNamespace) - } - }, - skip: (ctx, _) => ctx.isChartInstalled - } - ], { - concurrent: false, - rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION - }) - - try { - await tasks.run() - } catch (e) { - throw new FullstackTestingError('Error on cluster setup', e) - } - - return true - } - - /** - * Uninstall shared components from the cluster and perform any other necessary cleanups - * @param argv - * @returns {Promise} - */ - async reset (argv) { - const self = this - - const tasks = new Listr([ - { - title: 'Initialize', - task: async (ctx, task) => { - const confirm = await task.prompt(ListrEnquirerPromptAdapter).run({ - type: 'toggle', - default: false, - message: 'Are you sure you would like to uninstall fullstack-cluster-setup chart?' - }) - - if (!confirm) { - process.exit(0) - } - - self.configManager.update(argv) - const clusterName = self.configManager.getFlag(flags.clusterName) - const clusterSetupNamespace = self.configManager.getFlag(flags.clusterSetupNamespace) - ctx.config = { - clusterName, - clusterSetupNamespace - } - - ctx.isChartInstalled = await this.chartManager.isChartInstalled(ctx.config.clusterSetupNamespace, constants.FULLSTACK_CLUSTER_SETUP_CHART) - } - }, - { - title: `Uninstall '${constants.FULLSTACK_CLUSTER_SETUP_CHART}' chart`, - task: async (ctx, _) => { - const clusterSetupNamespace = ctx.config.clusterSetupNamespace - await self.chartManager.uninstall(clusterSetupNamespace, constants.FULLSTACK_CLUSTER_SETUP_CHART) - if (argv.dev) { - await self.showInstalledChartList(clusterSetupNamespace) - } - }, - skip: (ctx, _) => !ctx.isChartInstalled - } - ], { - concurrent: false, - rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION - }) - - try { - await tasks.run() - } catch (e) { - throw new FullstackTestingError('Error on cluster reset', e) - } - - return true - } - - /** - * Return Yargs command definition for 'cluster' command - * @param clusterCmd an instance of ClusterCommand - */ - static getCommandDefinition (clusterCmd) { - return { - command: 'cluster', - desc: 'Manage fullstack testing cluster', - builder: yargs => { - return yargs - .command({ - command: 'list', - desc: 'List all available clusters', - handler: argv => { - clusterCmd.logger.debug("==== Running 'cluster list' ===", { argv }) - - clusterCmd.showClusterList().then(r => { - clusterCmd.logger.debug('==== Finished running `cluster list`====') - - if (!r) process.exit(1) - }).catch(err => { - clusterCmd.logger.showUserError(err) - process.exit(1) - }) - } - }) - .command({ - command: 'info', - desc: 'Get cluster info', - handler: argv => { - clusterCmd.logger.debug("==== Running 'cluster info' ===", { argv }) - clusterCmd.getClusterInfo(argv).then(r => { - clusterCmd.logger.debug('==== Finished running `cluster info`====') - - if (!r) process.exit(1) - }).catch(err => { - clusterCmd.logger.showUserError(err) - process.exit(1) - }) - } - }) - .command({ - command: 'setup', - desc: 'Setup cluster with shared components', - builder: y => flags.setCommandFlags(y, - flags.clusterName, - flags.clusterSetupNamespace, - flags.chartDirectory, - flags.deployPrometheusStack, - flags.deployMinio, - flags.deployCertManager, - flags.deployCertManagerCrds, - flags.fstChartVersion - ), - handler: argv => { - clusterCmd.logger.debug("==== Running 'cluster setup' ===", { argv }) - - clusterCmd.setup(argv).then(r => { - clusterCmd.logger.debug('==== Finished running `cluster setup`====') - - if (!r) process.exit(1) - }).catch(err => { - clusterCmd.logger.showUserError(err) - process.exit(1) - }) - } - }) - .command({ - command: 'reset', - desc: 'Uninstall shared components from cluster', - builder: y => flags.setCommandFlags(y, - flags.clusterName, - flags.clusterSetupNamespace - ), - handler: argv => { - clusterCmd.logger.debug("==== Running 'cluster reset' ===", { argv }) - - clusterCmd.reset(argv).then(r => { - clusterCmd.logger.debug('==== Finished running `cluster reset`====') - - if (!r) process.exit(1) - }).catch(err => { - clusterCmd.logger.showUserError(err) - process.exit(1) - }) - } - }) - .demandCommand(1, 'Select a cluster command') - } - } - } - - /** - * Prepare values arg for cluster setup command - * - * @param chartDir local charts directory (default is empty) - * @param prometheusStackEnabled a bool to denote whether to install prometheus stack - * @param minioEnabled a bool to denote whether to install minio - * @param certManagerEnabled a bool to denote whether to install cert manager - * @param certManagerCrdsEnabled a bool to denote whether to install cert manager CRDs - * @returns {string} - */ - prepareValuesArg (chartDir = flags.chartDirectory.definition.default, - prometheusStackEnabled = flags.deployPrometheusStack.definition.default, - minioEnabled = flags.deployMinio.definition.default, - certManagerEnabled = flags.deployCertManager.definition.default, - certManagerCrdsEnabled = flags.deployCertManagerCrds.definition.default - ) { - let valuesArg = '' - if (chartDir) { - valuesArg = `-f ${chartDir}/fullstack-cluster-setup/values.yaml` - } - - valuesArg += ` --set cloud.prometheusStack.enabled=${prometheusStackEnabled}` - valuesArg += ` --set cloud.minio.enabled=${minioEnabled}` - valuesArg += ` --set cloud.certManager.enabled=${certManagerEnabled}` - valuesArg += ` --set cert-manager.installCRDs=${certManagerCrdsEnabled}` - - if (certManagerEnabled && !certManagerCrdsEnabled) { - this.logger.showUser(chalk.yellowBright('> WARNING:'), chalk.yellow( - 'cert-manager CRDs are required for cert-manager, please enable it if you have not installed it independently.')) - } - - return valuesArg - } - - /** - * Prepare chart path - * @param chartDir local charts directory (default is empty) - * @returns {Promise} - */ - async prepareChartPath (chartDir = flags.chartDirectory.definition.default) { - let chartPath = 'full-stack-testing/fullstack-cluster-setup' - if (chartDir) { - chartPath = `${chartDir}/fullstack-cluster-setup` - await this.helm.dependency('update', chartPath) - } - - return chartPath - } -} diff --git a/solo/src/commands/flags.mjs b/solo/src/commands/flags.mjs deleted file mode 100644 index 9c2dae8ba..000000000 --- a/solo/src/commands/flags.mjs +++ /dev/null @@ -1,470 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { constants } from '../core/index.mjs' -import * as core from '../core/index.mjs' -import * as helpers from '../core/helpers.mjs' - -/** - * Set flag from the flag option - * @param y an instance of yargs - * @param commandFlags a set of command flags - * - */ -export function setCommandFlags (y, ...commandFlags) { - commandFlags.forEach(flag => { - y.option(flag.name, flag.definition) - }) -} - -export const devMode = { - name: 'dev', - definition: { - describe: 'Enable developer mode', - defaultValue: false, - type: 'boolean' - } -} - -// list of common flags across commands. command specific flags are defined in the command's module. -export const clusterName = { - name: 'cluster-name', - definition: { - describe: 'Cluster name', - defaultValue: '', - alias: 'c', - type: 'string' - } -} - -export const clusterSetupNamespace = { - name: 'cluster-setup-namespace', - definition: { - describe: 'Cluster Setup Namespace', - alias: 's', - type: 'string' - } -} - -export const namespace = { - name: 'namespace', - definition: { - describe: 'Namespace', - alias: 'n', - type: 'string' - } -} - -export const deployMirrorNode = { - name: 'mirror-node', - definition: { - describe: 'Deploy mirror node', - defaultValue: true, - alias: 'm', - type: 'boolean' - } -} - -export const deployHederaExplorer = { - name: 'hedera-explorer', - definition: { - describe: 'Deploy hedera explorer', - defaultValue: true, - alias: 'x', - type: 'boolean' - } -} - -export const valuesFile = { - name: 'values-file', - definition: { - describe: 'Comma separated chart values files', - defaultValue: '', - alias: 'f', - type: 'string' - } -} - -export const deployPrometheusStack = { - name: 'prometheus-stack', - definition: { - describe: 'Deploy prometheus stack', - defaultValue: false, - type: 'boolean' - } -} - -export const enablePrometheusSvcMonitor = { - name: 'enable-prometheus-svc-monitor', - definition: { - describe: 'Enable prometheus service monitor for the network nodes', - defaultValue: false, - type: 'boolean' - } -} - -export const deployMinio = { - name: 'minio', - definition: { - describe: 'Deploy minio operator', - defaultValue: true, - type: 'boolean' - } -} - -export const deployCertManager = { - name: 'cert-manager', - definition: { - describe: 'Deploy cert manager, also deploys acme-cluster-issuer', - defaultValue: false, - type: 'boolean' - } -} - -/* - Deploy cert manager CRDs separately from cert manager itself. Cert manager - CRDs are required for cert manager to deploy successfully. - */ -export const deployCertManagerCrds = { - name: 'cert-manager-crds', - definition: { - describe: 'Deploy cert manager CRDs', - defaultValue: false, - type: 'boolean' - } -} - -export const deployJsonRpcRelay = { - name: 'json-rpc-relay', - definition: { - describe: 'Deploy JSON RPC Relay', - defaultValue: false, - alias: 'j', - type: 'boolean' - } -} - -export const releaseTag = { - name: 'release-tag', - definition: { - describe: 'Release tag to be used (e.g. v0.42.5)', - alias: 't', - type: 'string' - } -} - -export const relayReleaseTag = { - name: 'relay-release', - definition: { - describe: 'Relay release tag to be used (e.g. v0.39.1)', - defaultValue: '', - type: 'string' - } -} - -export const cacheDir = { - name: 'cache-dir', - definition: { - describe: 'Local cache directory', - defaultValue: core.constants.SOLO_CACHE_DIR, - type: 'string' - } -} - -export const nodeIDs = { - name: 'node-ids', - definition: { - describe: 'Comma separated node IDs (empty means all nodes)', - alias: 'i', - type: 'string' - } -} - -export const force = { - name: 'force', - definition: { - describe: 'Force actions even if those can be skipped', - defaultValue: false, - alias: 'f', - type: 'boolean' - } -} - -export const chartDirectory = { - name: 'chart-dir', - definition: { - describe: 'Local chart directory path (e.g. ~/full-stack-testing/charts', - defaultValue: '', - alias: 'd', - type: 'string' - } -} - -export const replicaCount = { - name: 'replica-count', - definition: { - describe: 'Replica count', - defaultValue: 1, - alias: '', - type: 'number' - } -} - -export const chainId = { - name: 'ledger-id', - definition: { - describe: 'Ledger ID (a.k.a. Chain ID)', - defaultValue: '298', // Ref: https://github.com/hashgraph/hedera-json-rpc-relay#configuration - alias: 'l', - type: 'string' - } -} - -// Ref: https://github.com/hashgraph/hedera-json-rpc-relay/blob/main/docs/configuration.md -export const operatorId = { - name: 'operator-id', - definition: { - describe: 'Operator ID', - defaultValue: constants.OPERATOR_ID, - type: 'string' - } -} - -// Ref: https://github.com/hashgraph/hedera-json-rpc-relay/blob/main/docs/configuration.md -export const operatorKey = { - name: 'operator-key', - definition: { - describe: 'Operator Key', - defaultValue: constants.OPERATOR_KEY, - type: 'string' - } -} - -export const generateGossipKeys = { - name: 'gossip-keys', - definition: { - describe: 'Generate gossip keys for nodes', - defaultValue: false, - type: 'boolean' - } -} - -export const generateTlsKeys = { - name: 'tls-keys', - definition: { - describe: 'Generate gRPC TLS keys for nodes', - defaultValue: false, - type: 'boolean' - } -} - -export const keyFormat = { - name: 'key-format', - definition: { - describe: 'Public and Private key file format (pem or pfx)', - defaultValue: 'pfx', - type: 'string' - } -} - -export const tlsClusterIssuerType = { - name: 'tls-cluster-issuer-type', - definition: { - describe: 'The TLS cluster issuer type to use for hedera explorer, defaults to "self-signed", the available options are: "acme-staging", "acme-prod", or "self-signed"', - defaultValue: 'self-signed', - type: 'string' - } -} - -export const enableHederaExplorerTls = { // KEEP - name: 'enable-hedera-explorer-tls', - definition: { - describe: 'Enable the Hedera Explorer TLS, defaults to false', - defaultValue: false, - type: 'boolean' - } -} - -export const hederaExplorerTlsLoadBalancerIp = { - name: 'hedera-explorer-tls-load-balancer-ip', - definition: { - describe: 'The static IP address to use for the Hedera Explorer TLS load balancer, defaults to ""', - defaultValue: '', - type: 'string' - } -} - -export const hederaExplorerTlsHostName = { - name: 'hedera-explorer-tls-host-name', - definition: { - describe: 'The host name to use for the Hedera Explorer TLS, defaults to "explorer.fst.local"', - defaultValue: 'explorer.fst.local', - type: 'string' - } -} - -export const deletePvcs = { - name: 'delete-pvcs', - definition: { - describe: 'Delete the persistent volume claims', - defaultValue: false, - type: 'boolean' - } -} - -export const fstChartVersion = { - name: 'fst-chart-version', - definition: { - describe: 'Fullstack testing chart version', - defaultValue: helpers.packageVersion(), - type: 'string' - } -} - -export const applicationProperties = { - name: 'application-properties', - definition: { - describe: 'application.properties file for node', - defaultValue: `${constants.SOLO_CACHE_DIR}/templates/application.properties`, - type: 'string' - } -} - -export const apiPermissionProperties = { - name: 'api-permission-properties', - definition: { - describe: 'api-permission.properties file for node', - defaultValue: `${constants.SOLO_CACHE_DIR}/templates/api-permission.properties`, - type: 'string' - } -} - -export const bootstrapProperties = { - name: 'bootstrap-properties', - definition: { - describe: 'bootstrap.properties file for node', - defaultValue: `${constants.SOLO_CACHE_DIR}/templates/bootstrap.properties`, - type: 'string' - } -} - -export const settingTxt = { - name: 'settings-txt', - definition: { - describe: 'settings.txt file for node', - defaultValue: `${constants.SOLO_CACHE_DIR}/templates/settings.txt`, - type: 'string' - } -} - -export const log4j2Xml = { - name: 'log4j2-xml', - definition: { - describe: 'log4j2.xml file for node', - defaultValue: `${constants.SOLO_CACHE_DIR}/templates/log4j2.xml`, - type: 'string' - } -} - -export const updateAccountKeys = { - name: 'update-account-keys', - definition: { - describe: 'Updates the special account keys to new keys and stores their keys in a corresponding Kubernetes secret', - defaultValue: true, - type: 'boolean' - } -} - -export const privateKey = { - name: 'private-key', - definition: { - describe: 'private key for the Hedera account', - defaultValue: '', - type: 'string' - } -} - -export const accountId = { - name: 'account-id', - definition: { - describe: 'The Hedera account id, e.g.: 0.0.1001', - defaultValue: '', - type: 'string' - } -} - -export const amount = { - name: 'hbar-amount', - definition: { - describe: 'Amount of HBAR to add', - defaultValue: 100, - type: 'number' - } -} - -export const allFlags = [ - devMode, - clusterName, - clusterSetupNamespace, - namespace, - deployMirrorNode, - deployHederaExplorer, - deployJsonRpcRelay, - valuesFile, - deployPrometheusStack, - enablePrometheusSvcMonitor, - deployMinio, - deployCertManager, - deployCertManagerCrds, - releaseTag, - relayReleaseTag, - cacheDir, - nodeIDs, - chartDirectory, - replicaCount, - chainId, - operatorId, - operatorKey, - generateGossipKeys, - generateTlsKeys, - keyFormat, - tlsClusterIssuerType, - enableHederaExplorerTls, - hederaExplorerTlsLoadBalancerIp, - hederaExplorerTlsHostName, - deletePvcs, - fstChartVersion, - applicationProperties, - apiPermissionProperties, - bootstrapProperties, - settingTxt, - log4j2Xml, - updateAccountKeys, - privateKey, - accountId, - amount -] - -export const allFlagsMap = new Map(allFlags.map(f => [f.name, f])) -export const nodeConfigFileFlags = new Map([ - applicationProperties, - apiPermissionProperties, - bootstrapProperties, - settingTxt, - log4j2Xml -].map(f => [f.name, f])) - -export const integerFlags = new Map([replicaCount].map(f => [f.name, f])) diff --git a/solo/src/commands/index.mjs b/solo/src/commands/index.mjs deleted file mode 100644 index c6028e486..000000000 --- a/solo/src/commands/index.mjs +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { ClusterCommand } from './cluster.mjs' -import { InitCommand } from './init.mjs' -import { NetworkCommand } from './network.mjs' -import { NodeCommand } from './node.mjs' -import { RelayCommand } from './relay.mjs' -import { AccountCommand } from './account.mjs' -import * as flags from './flags.mjs' - -/* - * Return a list of Yargs command builder to be exposed through CLI - * @param opts it is an Options object containing logger - */ -function Initialize (opts) { - const initCmd = new InitCommand(opts) - const clusterCmd = new ClusterCommand(opts) - const networkCommand = new NetworkCommand(opts) - const nodeCmd = new NodeCommand(opts) - const relayCmd = new RelayCommand(opts) - const accountCmd = new AccountCommand(opts) - - return [ - InitCommand.getCommandDefinition(initCmd), - ClusterCommand.getCommandDefinition(clusterCmd), - NetworkCommand.getCommandDefinition(networkCommand), - NodeCommand.getCommandDefinition(nodeCmd), - RelayCommand.getCommandDefinition(relayCmd), - AccountCommand.getCommandDefinition(accountCmd) - ] -} - -// Expose components from the command module -export { Initialize, flags } diff --git a/solo/src/commands/init.mjs b/solo/src/commands/init.mjs deleted file mode 100644 index f7316c5b3..000000000 --- a/solo/src/commands/init.mjs +++ /dev/null @@ -1,175 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { Listr } from 'listr2' -import path from 'path' -import { BaseCommand } from './base.mjs' -import * as core from '../core/index.mjs' -import { constants } from '../core/index.mjs' -import * as fs from 'fs' -import { FullstackTestingError } from '../core/errors.mjs' -import * as flags from './flags.mjs' -import chalk from 'chalk' - -/** - * Defines the core functionalities of 'init' command - */ -export class InitCommand extends BaseCommand { - /** - * Setup home directories - * @param dirs a list of directories that need to be created in sequence - */ - setupHomeDirectory (dirs = [ - constants.SOLO_HOME_DIR, - constants.SOLO_LOGS_DIR, - constants.SOLO_CACHE_DIR - ]) { - const self = this - - try { - dirs.forEach(dirPath => { - if (!fs.existsSync(dirPath)) { - fs.mkdirSync(dirPath) - } - self.logger.debug(`OK: setup directory: ${dirPath}`) - }) - } catch (e) { - this.logger.error(e) - throw new FullstackTestingError(e.message, e) - } - - return dirs - } - - /** - * Executes the init CLI command - * @returns {Promise} - */ - async init (argv) { - const self = this - - const tasks = new Listr([ - { - title: 'Setup home directory and cache', - task: async (ctx, _) => { - ctx.dirs = this.setupHomeDirectory() - } - }, - { - title: 'Check dependencies', - task: async (_, task) => { - const deps = [ - core.constants.HELM - ] - - const subTasks = self.depManager.taskCheckDependencies(deps) - - // set up the sub-tasks - return task.newListr(subTasks, { - concurrent: true, - rendererOptions: { - collapseSubtasks: false - } - }) - } - }, - { - title: 'Setup chart manager', - task: async (ctx, _) => { - ctx.repoURLs = await this.chartManager.setup() - } - }, - { - title: 'Copy configuration file templates', - task: (ctx, _) => { - let cacheDir = this.configManager.getFlag(flags.cacheDir) - if (!cacheDir) { - cacheDir = constants.SOLO_CACHE_DIR - } - - const templatesDir = `${cacheDir}/templates` - if (!fs.existsSync(templatesDir)) { - fs.mkdirSync(templatesDir) - } - - const configFiles = [ - `${constants.RESOURCES_DIR}/templates/application.properties`, - `${constants.RESOURCES_DIR}/templates/api-permission.properties`, - `${constants.RESOURCES_DIR}/templates/bootstrap.properties`, - `${constants.RESOURCES_DIR}/templates/settings.txt`, - `${constants.RESOURCES_DIR}/templates/log4j2.xml` - ] - - for (const filePath of configFiles) { - const fileName = path.basename(filePath) - fs.cpSync(`${filePath}`, `${templatesDir}/${fileName}`, { recursive: true }) - } - - if (argv.dev) { - self.logger.showList('Home Directories', ctx.dirs) - self.logger.showList('Chart Repository', ctx.repoURLs) - } - - self.logger.showUser(chalk.grey('\n***************************************************************************************')) - self.logger.showUser(chalk.grey(`Note: solo stores various artifacts (config, logs, keys etc.) in its home directory: ${constants.SOLO_HOME_DIR}\n` + - 'If a full reset is needed, delete the directory or relevant sub-directories before running \'solo init\'.')) - self.logger.showUser(chalk.grey('***************************************************************************************')) - } - } - ], { - concurrent: false, - rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION - }) - - try { - await tasks.run() - } catch (e) { - throw new FullstackTestingError('Error running init', e) - } - - return true - } - - /** - * Return Yargs command definition for 'init' command - * @param initCmd an instance of InitCommand - */ - static getCommandDefinition (initCmd) { - return { - command: 'init', - desc: 'Initialize local environment and default flags', - builder: y => { - flags.setCommandFlags(y, - flags.releaseTag, - flags.nodeIDs, - flags.namespace, - flags.clusterSetupNamespace, - flags.cacheDir, - flags.chartDirectory, - flags.keyFormat - ) - }, - handler: (argv) => { - initCmd.init(argv).then(r => { - if (!r) process.exit(1) - }).catch(err => { - initCmd.logger.showUserError(err) - process.exit(1) - }) - } - } - } -} diff --git a/solo/src/commands/network.mjs b/solo/src/commands/network.mjs deleted file mode 100644 index 0f6cfbce1..000000000 --- a/solo/src/commands/network.mjs +++ /dev/null @@ -1,438 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { ListrEnquirerPromptAdapter } from '@listr2/prompt-adapter-enquirer' -import chalk from 'chalk' -import { Listr } from 'listr2' -import { FullstackTestingError } from '../core/errors.mjs' -import { BaseCommand } from './base.mjs' -import * as flags from './flags.mjs' -import * as paths from 'path' -import { constants, Templates } from '../core/index.mjs' -import * as prompts from './prompts.mjs' -import * as helpers from '../core/helpers.mjs' - -export class NetworkCommand extends BaseCommand { - getTlsValueArguments (tlsClusterIssuerType, enableHederaExplorerTls, namespace, - hederaExplorerTlsLoadBalancerIp, hederaExplorerTlsHostName) { - let valuesArg = '' - - if (enableHederaExplorerTls) { - if (!['acme-staging', 'acme-prod', 'self-signed'].includes(tlsClusterIssuerType)) { - throw new Error(`Invalid TLS cluster issuer type: ${tlsClusterIssuerType}, must be one of: "acme-staging", "acme-prod", or "self-signed"`) - } - - valuesArg += ' --set hedera-explorer.ingress.enabled=true' - valuesArg += ' --set cloud.haproxyIngressController.enabled=true' - valuesArg += ` --set global.ingressClassName=${namespace}-hedera-explorer-ingress-class` - valuesArg += ` --set-json 'hedera-explorer.ingress.hosts[0]={"host":"${hederaExplorerTlsHostName}","paths":[{"path":"/","pathType":"Prefix"}]}'` - - if (hederaExplorerTlsLoadBalancerIp !== '') { - valuesArg += ` --set haproxy-ingress.controller.service.loadBalancerIP=${hederaExplorerTlsLoadBalancerIp}` - } - - if (tlsClusterIssuerType === 'self-signed') { - valuesArg += ' --set cloud.selfSignedClusterIssuer.enabled=true' - } else { - valuesArg += ' --set cloud.acmeClusterIssuer.enabled=true' - valuesArg += ` --set hedera-explorer.certClusterIssuerType=${tlsClusterIssuerType}` - } - } - - return valuesArg - } - - prepareValuesFiles (valuesFile) { - let valuesArg = '' - if (valuesFile) { - const valuesFiles = valuesFile.split(',') - valuesFiles.forEach(vf => { - const vfp = paths.resolve(vf) - valuesArg += ` --values ${vfp}` - }) - } - - return valuesArg - } - - prepareValuesArg (config = {}) { - let valuesArg = '' - if (config.chartDir) { - valuesArg = `-f ${config.chartDir}/fullstack-deployment/values.yaml` - } - - valuesArg += this.prepareValuesFiles(config.valuesFile) - - valuesArg += ` --set hedera-mirror-node.enabled=${config.deployMirrorNode} --set hedera-explorer.enabled=${config.deployHederaExplorer}` - valuesArg += ` --set telemetry.prometheus.svcMonitor.enabled=${config.enablePrometheusSvcMonitor}` - - if (config.enableHederaExplorerTls) { - valuesArg += this.getTlsValueArguments(config.tlsClusterIssuerType, config.enableHederaExplorerTls, config.namespace, - config.hederaExplorerTlsLoadBalancerIp, config.hederaExplorerTlsHostName) - } - - if (config.releaseTag) { - const rootImage = helpers.getRootImageRepository(config.releaseTag) - valuesArg += ` --set defaults.root.image.repository=${rootImage}` - } - - // prepare name and account IDs for nodes - const realm = constants.HEDERA_NODE_ACCOUNT_ID_START.realm - const shard = constants.HEDERA_NODE_ACCOUNT_ID_START.shard - let accountId = constants.HEDERA_NODE_ACCOUNT_ID_START.num - let i = 0 - config.nodeIds.forEach(nodeId => { - valuesArg += ` --set hedera.nodes[${i}].name=${nodeId},hedera.nodes[${i++}].accountId=${realm}.${shard}.${accountId++}` - }) - - this.logger.debug('Prepared helm chart values', { valuesArg }) - return valuesArg - } - - async prepareConfig (task, argv) { - const flagList = [ - flags.releaseTag, // we need it to determine which version of root image(Java17 or Java21) we should use - flags.namespace, - flags.nodeIDs, - flags.chartDirectory, - flags.fstChartVersion, - flags.valuesFile, - flags.deployMirrorNode, - flags.deployHederaExplorer, - flags.tlsClusterIssuerType, - flags.enableHederaExplorerTls, - flags.hederaExplorerTlsHostName, - flags.enablePrometheusSvcMonitor - ] - - this.configManager.update(argv) - this.logger.debug('Loaded cached config', { config: this.configManager.config }) - await prompts.execute(task, this.configManager, flagList) - - // create a config object for subsequent steps - const config = { - releaseTag: this.configManager.getFlag(flags.releaseTag), - namespace: this.configManager.getFlag(flags.namespace), - nodeIds: helpers.parseNodeIDs(this.configManager.getFlag(flags.nodeIDs)), - chartDir: this.configManager.getFlag(flags.chartDirectory), - fstChartVersion: this.configManager.getFlag(flags.fstChartVersion), - valuesFile: this.configManager.getFlag(flags.valuesFile), - deployMirrorNode: this.configManager.getFlag(flags.deployMirrorNode), - deployHederaExplorer: this.configManager.getFlag(flags.deployHederaExplorer), - tlsClusterIssuerType: this.configManager.getFlag(flags.tlsClusterIssuerType), - enableHederaExplorerTls: this.configManager.getFlag(flags.enableHederaExplorerTls), - hederaExplorerTlsHostName: this.configManager.getFlag(flags.hederaExplorerTlsHostName), - enablePrometheusSvcMonitor: this.configManager.getFlag(flags.enablePrometheusSvcMonitor) - } - - // compute values - config.hederaExplorerTlsLoadBalancerIp = argv.hederaExplorerTlsLoadBalancerIp - config.chartPath = await this.prepareChartPath(config.chartDir, - constants.FULLSTACK_TESTING_CHART, constants.FULLSTACK_DEPLOYMENT_CHART) - - config.valuesArg = this.prepareValuesArg(config) - - this.logger.debug('Prepared config', { config, cachedConfig: this.configManager.config }) - return config - } - - /** - * Run helm install and deploy network components - * @param argv - * @return {Promise} - */ - async deploy (argv) { - const self = this - - const tasks = new Listr([ - { - title: 'Initialize', - task: async (ctx, task) => { - ctx.config = await self.prepareConfig(task, argv) - } - }, - { - title: `Install chart '${constants.FULLSTACK_DEPLOYMENT_CHART}'`, - task: async (ctx, _) => { - if (await self.chartManager.isChartInstalled(ctx.config.namespace, constants.FULLSTACK_DEPLOYMENT_CHART)) { - await self.chartManager.uninstall(ctx.config.namespace, constants.FULLSTACK_DEPLOYMENT_CHART) - } - - await this.chartManager.install( - ctx.config.namespace, - constants.FULLSTACK_DEPLOYMENT_CHART, - ctx.config.chartPath, - ctx.config.fstChartVersion, - ctx.config.valuesArg) - } - }, - { - title: 'Waiting for network pods to be ready', - task: - async (ctx, task) => { - const subTasks = [] - for (const nodeId of ctx.config.nodeIds) { - const podName = Templates.renderNetworkPodName(nodeId) - subTasks.push({ - title: `Node: ${chalk.yellow(nodeId)} (Pod: ${podName})`, - task: () => - self.k8.waitForPod(constants.POD_STATUS_RUNNING, [ - 'fullstack.hedera.com/type=network-node', - `fullstack.hedera.com/node-name=${nodeId}` - ], 1, 60 * 15, 1000) // timeout 15 minutes - }) - } - - // set up the sub-tasks - return task.newListr(subTasks, { - concurrent: false, // no need to run concurrently since if one node is up, the rest should be up by then - rendererOptions: { - collapseSubtasks: false - } - }) - } - } - ], { - concurrent: false, - rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION - }) - - try { - await tasks.run() - } catch (e) { - throw new FullstackTestingError(`Error installing chart ${constants.FULLSTACK_DEPLOYMENT_CHART}`, e) - } - - return true - } - - /** - * Run helm uninstall and destroy network components - * @param argv - * @return {Promise} - */ - async destroy (argv) { - const self = this - - const tasks = new Listr([ - { - title: 'Initialize', - task: async (ctx, task) => { - if (!argv.force) { - const confirm = await task.prompt(ListrEnquirerPromptAdapter).run({ - type: 'toggle', - default: false, - message: 'Are you sure you would like to destroy the network components?' - }) - - if (!confirm) { - process.exit(0) - } - } - - self.configManager.update(argv) - await prompts.execute(task, self.configManager, [ - flags.namespace, - flags.deletePvcs - ]) - - ctx.config = { - namespace: self.configManager.getFlag(flags.namespace), - deletePvcs: self.configManager.getFlag(flags.deletePvcs) - } - } - }, - { - title: `Uninstall chart ${constants.FULLSTACK_DEPLOYMENT_CHART}`, - task: async (ctx, _) => { - await self.chartManager.uninstall(ctx.config.namespace, constants.FULLSTACK_DEPLOYMENT_CHART) - } - }, - { - title: 'Get PVCs for namespace', - task: async (ctx, _) => { - if (ctx.config.deletePvcs === true) { - ctx.config.pvcs = await self.k8.listPvcsByNamespace(ctx.config.namespace) - } - } - }, - { - title: 'Delete PVCs for namespace', - task: async (ctx, _) => { - if (ctx.config.pvcs) { - for (const pvc of ctx.config.pvcs) { - await self.k8.deletePvc(pvc, ctx.config.namespace) - } - } - }, - skip: (ctx, _) => !ctx.config.pvcs - } - ], { - concurrent: false, - rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION - }) - - try { - await tasks.run() - } catch (e) { - throw new FullstackTestingError('Error starting node', e) - } - - return true - } - - /** - * Run helm upgrade to refresh network components with new settings - * @param argv - * @return {Promise} - */ - async refresh (argv) { - const self = this - - const tasks = new Listr([ - { - title: 'Initialize', - task: async (ctx, task) => { - ctx.config = await self.prepareConfig(task, argv) - } - }, - { - title: `Upgrade chart '${constants.FULLSTACK_DEPLOYMENT_CHART}'`, - task: async (ctx, _) => { - await this.chartManager.upgrade( - ctx.config.namespace, - constants.FULLSTACK_DEPLOYMENT_CHART, - ctx.config.chartPath, - ctx.config.valuesArg - ) - } - }, - { - title: 'Waiting for network pods to be ready', - task: async (ctx, _) => { - await this.k8.waitForPod(constants.POD_STATUS_RUNNING, [ - 'fullstack.hedera.com/type=network-node' - ], 1) - } - } - ], { - concurrent: false, - rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION - }) - - try { - await tasks.run() - } catch (e) { - throw new FullstackTestingError(`Error upgrading chart ${constants.FULLSTACK_DEPLOYMENT_CHART}`, e) - } - - return true - } - - static getCommandDefinition (networkCmd) { - return { - command: 'network', - desc: 'Manage fullstack testing network deployment', - builder: yargs => { - return yargs - .command({ - command: 'deploy', - desc: 'Deploy fullstack testing network', - builder: y => flags.setCommandFlags(y, - flags.releaseTag, - flags.namespace, - flags.nodeIDs, - flags.chartDirectory, - flags.valuesFile, - flags.deployMirrorNode, - flags.deployHederaExplorer, - flags.tlsClusterIssuerType, - flags.enableHederaExplorerTls, - flags.hederaExplorerTlsLoadBalancerIp, - flags.hederaExplorerTlsHostName, - flags.enablePrometheusSvcMonitor, - flags.fstChartVersion - ), - handler: argv => { - networkCmd.logger.debug("==== Running 'network deploy' ===") - networkCmd.logger.debug(argv) - - networkCmd.deploy(argv).then(r => { - networkCmd.logger.debug('==== Finished running `network deploy`====') - - if (!r) process.exit(1) - }).catch(err => { - networkCmd.logger.showUserError(err) - process.exit(1) - }) - } - }) - .command({ - command: 'destroy', - desc: 'Destroy fullstack testing network', - builder: y => flags.setCommandFlags(y, - flags.namespace, - flags.force, - flags.deletePvcs - ), - handler: argv => { - networkCmd.logger.debug("==== Running 'network destroy' ===") - networkCmd.logger.debug(argv) - - networkCmd.destroy(argv).then(r => { - networkCmd.logger.debug('==== Finished running `network destroy`====') - - if (!r) process.exit(1) - }).catch(err => { - networkCmd.logger.showUserError(err) - process.exit(1) - }) - } - }) - .command({ - command: 'refresh', - desc: 'Refresh fullstack testing network deployment', - builder: y => flags.setCommandFlags(y, - flags.namespace, - flags.chartDirectory, - flags.valuesFile, - flags.deployMirrorNode, - flags.deployHederaExplorer, - flags.tlsClusterIssuerType, - flags.enableHederaExplorerTls, - flags.hederaExplorerTlsLoadBalancerIp, - flags.hederaExplorerTlsHostName, - flags.enablePrometheusSvcMonitor - ), - handler: argv => { - networkCmd.logger.debug("==== Running 'chart upgrade' ===") - networkCmd.logger.debug(argv) - - networkCmd.refresh(argv).then(r => { - networkCmd.logger.debug('==== Finished running `chart upgrade`====') - - if (!r) process.exit(1) - }).catch(err => { - networkCmd.logger.showUserError(err) - process.exit(1) - }) - } - }) - .demandCommand(1, 'Select a chart command') - } - } - } -} diff --git a/solo/src/commands/node.mjs b/solo/src/commands/node.mjs deleted file mode 100644 index 19b553bff..000000000 --- a/solo/src/commands/node.mjs +++ /dev/null @@ -1,805 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import chalk from 'chalk' -import * as fs from 'fs' -import { Listr } from 'listr2' -import path from 'path' -import { FullstackTestingError, IllegalArgumentError } from '../core/errors.mjs' -import * as helpers from '../core/helpers.mjs' -import { sleep } from '../core/helpers.mjs' -import { constants, Templates } from '../core/index.mjs' -import { BaseCommand } from './base.mjs' -import * as flags from './flags.mjs' -import * as prompts from './prompts.mjs' - -/** - * Defines the core functionalities of 'node' command - */ -export class NodeCommand extends BaseCommand { - constructor (opts) { - super(opts) - - if (!opts || !opts.downloader) throw new IllegalArgumentError('An instance of core/PackageDowner is required', opts.downloader) - if (!opts || !opts.platformInstaller) throw new IllegalArgumentError('An instance of core/PlatformInstaller is required', opts.platformInstaller) - if (!opts || !opts.keyManager) throw new IllegalArgumentError('An instance of core/KeyManager is required', opts.keyManager) - if (!opts || !opts.accountManager) throw new IllegalArgumentError('An instance of core/AccountManager is required', opts.accountManager) - - this.downloader = opts.downloader - this.plaformInstaller = opts.platformInstaller - this.keyManager = opts.keyManager - this.accountManager = opts.accountManager - } - - async checkNetworkNodePod (namespace, nodeId) { - nodeId = nodeId.trim() - const podName = Templates.renderNetworkPodName(nodeId) - - try { - await this.k8.waitForPod(constants.POD_STATUS_RUNNING, [ - 'fullstack.hedera.com/type=network-node', - `fullstack.hedera.com/node-name=${nodeId}` - ], 1) - - return podName - } catch (e) { - throw new FullstackTestingError(`no pod found for nodeId: ${nodeId}`, e) - } - } - - async checkNetworkNodeStarted (nodeId, maxAttempt = 50, status = 'ACTIVE') { - nodeId = nodeId.trim() - const podName = Templates.renderNetworkPodName(nodeId) - const logfilePath = `${constants.HEDERA_HAPI_PATH}/logs/hgcaa.log` - let attempt = 0 - let isActive = false - - await sleep(10000) // sleep in case this the user ran the start command again at a later time - - // check log file is accessible - let logFileAccessible = false - while (attempt++ < maxAttempt) { - try { - if (await this.k8.hasFile(podName, constants.ROOT_CONTAINER, logfilePath)) { - logFileAccessible = true - break - } - } catch (e) {} // ignore errors - - await sleep(1000) - } - - if (!logFileAccessible) { - throw new FullstackTestingError(`Logs are not accessible: ${logfilePath}`) - } - - attempt = 0 - while (attempt < maxAttempt) { - try { - const output = await this.k8.execContainer(podName, constants.ROOT_CONTAINER, ['tail', '-10', logfilePath]) - if (output.indexOf(`Terminating Netty = ${status}`) < 0 && // make sure we are not at the beginning of a restart - output.indexOf(`Now current platform status = ${status}`) > 0) { - this.logger.debug(`Node ${nodeId} is ${status} [ attempt: ${attempt}/${maxAttempt}]`) - isActive = true - break - } - this.logger.debug(`Node ${nodeId} is not ${status} yet. Trying again... [ attempt: ${attempt}/${maxAttempt} ]`) - } catch (e) { - this.logger.warn(`error in checking if node ${nodeId} is ${status}: ${e.message}. Trying again... [ attempt: ${attempt}/${maxAttempt} ]`) - - // ls the HAPI path for debugging - await this.k8.execContainer(podName, constants.ROOT_CONTAINER, `ls -la ${constants.HEDERA_HAPI_PATH}`) - - // ls the logs directory for debugging - await this.k8.execContainer(podName, constants.ROOT_CONTAINER, `ls -la ${constants.HEDERA_HAPI_PATH}/logs`) - } - attempt += 1 - await sleep(1000) - } - - this.logger.info(`!> -- Node ${nodeId} is ${status} -- { - ctx.config.podNames[nodeId] = await this.checkNetworkNodePod(ctx.config.namespace, nodeId) - } - }) - } - - // setup the sub-tasks - return task.newListr(subTasks, { - concurrent: true, - rendererOptions: { - collapseSubtasks: false - } - }) - } - - async _copyNodeKeys (nodeKey, destDir) { - for (const keyFile of [nodeKey.privateKeyFile, nodeKey.certificateFile]) { - if (!fs.existsSync(keyFile)) { - throw new FullstackTestingError(`file (${keyFile}) is missing`) - } - - const fileName = path.basename(keyFile) - fs.cpSync(keyFile, `${destDir}/${fileName}`) - } - } - - async setup (argv) { - const self = this - - const tasks = new Listr([ - { - title: 'Initialize', - task: async (ctx, task) => { - self.configManager.update(argv) - await prompts.execute(task, self.configManager, [ - flags.namespace, - flags.nodeIDs, - flags.releaseTag, - flags.cacheDir, - flags.chainId, - flags.generateGossipKeys, - flags.generateTlsKeys, - flags.keyFormat - ]) - - const config = { - namespace: self.configManager.getFlag(flags.namespace), - nodeIds: helpers.parseNodeIDs(self.configManager.getFlag(flags.nodeIDs)), - releaseTag: self.configManager.getFlag(flags.releaseTag), - cacheDir: self.configManager.getFlag(flags.cacheDir), - force: self.configManager.getFlag(flags.force), - chainId: self.configManager.getFlag(flags.chainId), - generateGossipKeys: self.configManager.getFlag(flags.generateGossipKeys), - generateTlsKeys: self.configManager.getFlag(flags.generateTlsKeys), - keyFormat: self.configManager.getFlag(flags.keyFormat) - } - - // compute other config parameters - config.releasePrefix = Templates.prepareReleasePrefix(config.releaseTag) - config.buildZipFile = `${config.cacheDir}/${config.releasePrefix}/build-${config.releaseTag}.zip` - config.keysDir = path.join(config.cacheDir, 'keys') - config.stagingDir = `${config.cacheDir}/${config.releasePrefix}/staging/${config.releaseTag}` - config.stagingKeysDir = path.join(config.stagingDir, 'keys') - - if (config.keyFormat === constants.KEY_FORMAT_PFX && config.generateGossipKeys) { - throw new FullstackTestingError('Unable to generate PFX gossip keys.\n' + - `Please ensure you have pre-generated (*.pfx) key files in keys directory: ${config.keysDir}\n` - ) - } - - if (!await this.k8.hasNamespace(config.namespace)) { - throw new FullstackTestingError(`namespace ${config.namespace} does not exist`) - } - - // prepare staging keys directory - if (!fs.existsSync(config.stagingKeysDir)) { - fs.mkdirSync(config.stagingKeysDir, { recursive: true }) - } - - // create cached keys dir if it does not exist yet - if (!fs.existsSync(config.keysDir)) { - fs.mkdirSync(config.keysDir) - } - - // set config in the context for later tasks to use - ctx.config = config - - self.logger.debug('Initialized config', { config }) - } - }, - { - title: 'Identify network pods', - task: (ctx, task) => self.taskCheckNetworkNodePods(ctx, task) - }, - { - title: 'Fetch platform software', - task: async (ctx, _) => { - const config = ctx.config - if (config.force || !fs.existsSync(config.buildZipFile)) { - ctx.config.buildZipFile = await self.downloader.fetchPlatform(ctx.config.releaseTag, config.cacheDir) - } - } - }, - { - title: 'Generate Gossip keys', - task: async (ctx, _) => { - const config = ctx.config - - // generate gossip keys if required - if (config.generateGossipKeys) { - for (const nodeId of ctx.config.nodeIds) { - const signingKey = await self.keyManager.generateSigningKey(nodeId) - const signingKeyFiles = await self.keyManager.storeSigningKey(nodeId, signingKey, config.keysDir) - self.logger.debug(`generated Gossip signing keys for node ${nodeId}`, { keyFiles: signingKeyFiles }) - - const agreementKey = await self.keyManager.generateAgreementKey(nodeId, signingKey) - const agreementKeyFiles = await self.keyManager.storeAgreementKey(nodeId, agreementKey, config.keysDir) - self.logger.debug(`generated Gossip agreement keys for node ${nodeId}`, { keyFiles: agreementKeyFiles }) - } - } - }, - skip: (ctx, _) => !ctx.config.generateGossipKeys - }, - { - title: 'Generate gRPC TLS keys', - task: async (ctx, _) => { - const config = ctx.config - // generate TLS keys if required - if (config.generateTlsKeys) { - for (const nodeId of ctx.config.nodeIds) { - const tlsKeys = await self.keyManager.generateGrpcTLSKey(nodeId) - const tlsKeyFiles = await self.keyManager.storeTLSKey(nodeId, tlsKeys, config.keysDir) - self.logger.debug(`generated TLS keys for node: ${nodeId}`, { keyFiles: tlsKeyFiles }) - } - } - }, - skip: (ctx, _) => !ctx.config.generateTlsKeys - }, - { - title: 'Prepare staging directory', - task: async (ctx, parentTask) => { - const config = ctx.config - const subTasks = [ - { - title: 'Copy configuration files', - task: () => { - for (const flag of flags.nodeConfigFileFlags.values()) { - const filePath = self.configManager.getFlag(flag) - if (!filePath) { - throw new FullstackTestingError(`Configuration file path is missing for: ${flag.name}`) - } - - const fileName = path.basename(filePath) - fs.cpSync(`${filePath}`, `${config.stagingDir}/templates/${fileName}`, { recursive: true }) - } - } - }, - { - title: 'Copy Gossip keys to staging', - task: async (ctx, _) => { - const config = ctx.config - - // copy gossip keys to the staging - for (const nodeId of ctx.config.nodeIds) { - switch (config.keyFormat) { - case constants.KEY_FORMAT_PEM: { - const signingKeyFiles = self.keyManager.prepareNodeKeyFilePaths(nodeId, config.keysDir, constants.SIGNING_KEY_PREFIX) - await self._copyNodeKeys(signingKeyFiles, config.stagingKeysDir) - - // generate missing agreement keys - const agreementKeyFiles = self.keyManager.prepareNodeKeyFilePaths(nodeId, config.keysDir, constants.AGREEMENT_KEY_PREFIX) - await self._copyNodeKeys(agreementKeyFiles, config.stagingKeysDir) - break - } - - case constants.KEY_FORMAT_PFX: { - const privateKeyFile = Templates.renderGossipPfxPrivateKeyFile(nodeId) - fs.cpSync(`${config.keysDir}/${privateKeyFile}`, `${config.stagingKeysDir}/${privateKeyFile}`) - fs.cpSync(`${config.keysDir}/public.pfx`, `${config.stagingKeysDir}/public.pfx`) - break - } - - default: - throw new FullstackTestingError(`Unsupported key-format ${config.keyFormat}`) - } - } - } - }, - { - title: 'Copy gRPC TLS keys to staging', - task: async (ctx, _) => { - const config = ctx.config - for (const nodeId of ctx.config.nodeIds) { - const tlsKeyFiles = self.keyManager.prepareTLSKeyFilePaths(nodeId, config.keysDir) - await self._copyNodeKeys(tlsKeyFiles, config.stagingKeysDir) - } - } - }, - { - title: 'Prepare config.txt for the network', - task: async (ctx, _) => { - const config = ctx.config - const configTxtPath = `${config.stagingDir}/config.txt` - const template = `${constants.RESOURCES_DIR}/templates/config.template` - await self.plaformInstaller.prepareConfigTxt(config.nodeIds, configTxtPath, config.releaseTag, config.chainId, template) - } - } - ] - - return parentTask.newListr(subTasks, { - concurrent: false, - rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION - }) - } - }, - { - title: 'Upload platform software into network nodes', - task: - async (ctx, task) => { - const config = ctx.config - - const subTasks = [] - for (const nodeId of ctx.config.nodeIds) { - const podName = ctx.config.podNames[nodeId] - subTasks.push({ - title: `Node: ${chalk.yellow(nodeId)}`, - task: () => - self.plaformInstaller.copyPlatform(podName, config.buildZipFile) - }) - } - - // set up the sub-tasks - return task.newListr(subTasks, { - concurrent: false, // parallel uploading of the zip file seems to be unreliable, so we just upload in sequence - rendererOptions: { - collapseSubtasks: false - } - }) - } - }, - { - title: 'Setup network nodes', - task: async (ctx, parentTask) => { - const config = ctx.config - - const subTasks = [] - for (const nodeId of config.nodeIds) { - const podName = config.podNames[nodeId] - subTasks.push({ - title: `Node: ${chalk.yellow(nodeId)}`, - task: () => - self.plaformInstaller.taskInstall(podName, config.buildZipFile, config.stagingDir, config.nodeIds, config.keyFormat, config.force) - }) - } - - // set up the sub-tasks - return parentTask.newListr(subTasks, { - concurrent: true, - rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION - }) - } - } - ], { - concurrent: false, - rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION - }) - - try { - await tasks.run() - } catch (e) { - throw new FullstackTestingError(`Error in setting up nodes: ${e.message}`, e) - } - - return true - } - - async start (argv) { - const self = this - - const tasks = new Listr([ - { - title: 'Initialize', - task: async (ctx, task) => { - self.configManager.update(argv) - await prompts.execute(task, self.configManager, [ - flags.namespace, - flags.nodeIDs, - flags.updateAccountKeys - ]) - - ctx.config = { - namespace: self.configManager.getFlag(flags.namespace), - nodeIds: helpers.parseNodeIDs(self.configManager.getFlag(flags.nodeIDs)), - updateAccountKeys: self.configManager.getFlag(flags.updateAccountKeys) - } - - if (!await this.k8.hasNamespace(ctx.config.namespace)) { - throw new FullstackTestingError(`namespace ${ctx.config.namespace} does not exist`) - } - } - }, - { - title: 'Identify network pods', - task: (ctx, task) => self.taskCheckNetworkNodePods(ctx, task) - }, - { - title: 'Starting nodes', - task: (ctx, task) => { - const subTasks = [] - for (const nodeId of ctx.config.nodeIds) { - const podName = ctx.config.podNames[nodeId] - subTasks.push({ - title: `Start node: ${chalk.yellow(nodeId)}`, - task: async () => { - await self.k8.execContainer(podName, constants.ROOT_CONTAINER, ['rm', '-rf', `${constants.HEDERA_HAPI_PATH}/data/logs`]) - await self.k8.execContainer(podName, constants.ROOT_CONTAINER, ['systemctl', 'restart', 'network-node']) - } - }) - } - - // set up the sub-tasks - return task.newListr(subTasks, { - concurrent: true, - rendererOptions: { - collapseSubtasks: false, - timer: constants.LISTR_DEFAULT_RENDERER_TIMER_OPTION - } - }) - } - }, - { - title: 'Check nodes are ACTIVE', - task: (ctx, task) => { - const subTasks = [] - for (const nodeId of ctx.config.nodeIds) { - subTasks.push({ - title: `Check node: ${chalk.yellow(nodeId)}`, - task: () => self.checkNetworkNodeStarted(nodeId) - }) - } - - // set up the sub-tasks - return task.newListr(subTasks, { - concurrent: false, - rendererOptions: { - collapseSubtasks: false - } - }) - } - }, - { - title: 'Update special account keys', - task: async (ctx, task) => { - if (ctx.config.updateAccountKeys) { - await self.accountManager.prepareAccounts(ctx.config.namespace) - } else { - this.logger.showUser(chalk.yellowBright('> WARNING:'), chalk.yellow( - 'skipping special account keys update, special accounts will retain genesis private keys')) - } - } - } - ], { - concurrent: false, - rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION - }) - - try { - await tasks.run() - } catch (e) { - throw new FullstackTestingError(`Error starting node: ${e.message}`, e) - } - - return true - } - - async stop (argv) { - const self = this - - const tasks = new Listr([ - { - title: 'Initialize', - task: async (ctx, task) => { - self.configManager.update(argv) - await prompts.execute(task, self.configManager, [ - flags.namespace, - flags.nodeIDs - ]) - - ctx.config = { - namespace: self.configManager.getFlag(flags.namespace), - nodeIds: helpers.parseNodeIDs(self.configManager.getFlag(flags.nodeIDs)) - } - - if (!await this.k8.hasNamespace(ctx.config.namespace)) { - throw new FullstackTestingError(`namespace ${ctx.config.namespace} does not exist`) - } - } - }, - { - title: 'Identify network pods', - task: (ctx, task) => self.taskCheckNetworkNodePods(ctx, task) - }, - { - title: 'Stopping nodes', - task: (ctx, task) => { - const subTasks = [] - for (const nodeId of ctx.config.nodeIds) { - const podName = ctx.config.podNames[nodeId] - subTasks.push({ - title: `Stop node: ${chalk.yellow(nodeId)}`, - task: () => self.k8.execContainer(podName, constants.ROOT_CONTAINER, 'systemctl stop network-node') - }) - } - - // setup the sub-tasks - return task.newListr(subTasks, { - concurrent: true, - rendererOptions: { - collapseSubtasks: false, - timer: constants.LISTR_DEFAULT_RENDERER_TIMER_OPTION - } - }) - } - } - ], { - concurrent: false, - rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION - }) - - try { - await tasks.run() - } catch (e) { - throw new FullstackTestingError('Error starting node', e) - } - - return true - } - - async keys (argv) { - const self = this - const tasks = new Listr([ - { - title: 'Initialize', - task: async (ctx, task) => { - self.configManager.update(argv) - await prompts.execute(task, self.configManager, [ - flags.nodeIDs, - flags.cacheDir, - flags.generateGossipKeys, - flags.generateTlsKeys, - flags.keyFormat - ]) - - const config = { - nodeIds: helpers.parseNodeIDs(self.configManager.getFlag(flags.nodeIDs)), - cacheDir: self.configManager.getFlag(flags.cacheDir), - generateGossipKeys: self.configManager.getFlag(flags.generateGossipKeys), - generateTlsKeys: self.configManager.getFlag(flags.generateTlsKeys), - keyFormat: self.configManager.getFlag(flags.keyFormat), - keysDir: path.join(self.configManager.getFlag(flags.cacheDir), 'keys') - } - - if (!fs.existsSync(config.keysDir)) { - fs.mkdirSync(config.keysDir) - } - - if (config.keyFormat === constants.KEY_FORMAT_PFX && config.generateGossipKeys) { - throw new FullstackTestingError('Unable to generate PFX gossip keys.\n' + - `Please ensure you have pre-generated (*.pfx) key files in keys directory: ${config.keysDir}\n` - ) - } - - ctx.config = config - } - }, - { - title: 'Generate gossip keys', - task: async (ctx, task) => { - const keysDir = ctx.config.keysDir - const nodeKeyFiles = new Map() - if (ctx.config.generateGossipKeys) { - for (const nodeId of ctx.config.nodeIds) { - const signingKey = await self.keyManager.generateSigningKey(nodeId) - const signingKeyFiles = await self.keyManager.storeSigningKey(nodeId, signingKey, keysDir) - const agreementKey = await self.keyManager.generateAgreementKey(nodeId, signingKey) - const agreementKeyFiles = await self.keyManager.storeAgreementKey(nodeId, agreementKey, keysDir) - nodeKeyFiles.set(nodeId, { - signingKey, - agreementKey, - signingKeyFiles, - agreementKeyFiles - }) - } - - if (argv.dev) { - self.logger.showUser(chalk.green('*** Generated Node Gossip Keys ***')) - for (const entry of nodeKeyFiles.entries()) { - const nodeId = entry[0] - const fileList = entry[1] - self.logger.showUser(chalk.cyan('---------------------------------------------------------------------------------------------')) - self.logger.showUser(chalk.cyan(`Node ID: ${nodeId}`)) - self.logger.showUser(chalk.cyan('===========================')) - self.logger.showUser(chalk.green('Signing key\t\t:'), chalk.yellow(fileList.signingKeyFiles.privateKeyFile)) - self.logger.showUser(chalk.green('Signing certificate\t:'), chalk.yellow(fileList.signingKeyFiles.certificateFile)) - self.logger.showUser(chalk.green('Agreement key\t\t:'), chalk.yellow(fileList.agreementKeyFiles.privateKeyFile)) - self.logger.showUser(chalk.green('Agreement certificate\t:'), chalk.yellow(fileList.agreementKeyFiles.certificateFile)) - self.logger.showUser(chalk.blue('Inspect certificate\t: '), chalk.yellow(`openssl storeutl -noout -text -certs ${fileList.agreementKeyFiles.certificateFile}`)) - self.logger.showUser(chalk.blue('Verify certificate\t: '), chalk.yellow(`openssl verify -CAfile ${fileList.signingKeyFiles.certificateFile} ${fileList.agreementKeyFiles.certificateFile}`)) - } - self.logger.showUser(chalk.cyan('---------------------------------------------------------------------------------------------')) - } - } - }, - skip: (ctx, _) => !ctx.config.generateGossipKeys - }, - { - title: 'Generate gRPC TLS keys', - task: async (ctx, task) => { - const keysDir = ctx.config.keysDir - const nodeKeyFiles = new Map() - if (ctx.config.generateTlsKeys) { - for (const nodeId of ctx.config.nodeIds) { - const tlsKey = await self.keyManager.generateGrpcTLSKey(nodeId) - const tlsKeyFiles = await self.keyManager.storeTLSKey(nodeId, tlsKey, keysDir) - nodeKeyFiles.set(nodeId, { - tlsKeyFiles - }) - } - - if (argv.dev) { - self.logger.showUser(chalk.green('*** Generated Node TLS Keys ***')) - for (const entry of nodeKeyFiles.entries()) { - const nodeId = entry[0] - const fileList = entry[1] - self.logger.showUser(chalk.cyan('---------------------------------------------------------------------------------------------')) - self.logger.showUser(chalk.cyan(`Node ID: ${nodeId}`)) - self.logger.showUser(chalk.cyan('===========================')) - self.logger.showUser(chalk.green('TLS key\t\t:'), chalk.yellow(fileList.tlsKeyFiles.privateKeyFile)) - self.logger.showUser(chalk.green('TLS certificate\t:'), chalk.yellow(fileList.tlsKeyFiles.certificateFile)) - self.logger.showUser(chalk.blue('Inspect certificate\t: '), chalk.yellow(`openssl storeutl -noout -text -certs ${fileList.tlsKeyFiles.certificateFile}`)) - self.logger.showUser(chalk.blue('Verify certificate\t: '), chalk.yellow(`openssl verify -CAfile ${fileList.tlsKeyFiles.certificateFile} ${fileList.tlsKeyFiles.certificateFile}`)) - } - self.logger.showUser(chalk.cyan('---------------------------------------------------------------------------------------------')) - } - } - }, - skip: (ctx, _) => !ctx.config.generateTlsKeys - } - ]) - - try { - await tasks.run() - } catch (e) { - throw new FullstackTestingError(`Error generating keys: ${e.message}`, e) - } - - return true - } - - /** - * Return Yargs command definition for 'node' command - * @param nodeCmd an instance of NodeCommand - */ - static getCommandDefinition (nodeCmd) { - return { - command: 'node', - desc: 'Manage Hedera platform node in fullstack testing network', - builder: yargs => { - return yargs - .command({ - command: 'setup', - desc: 'Setup node with a specific version of Hedera platform', - builder: y => flags.setCommandFlags(y, - flags.namespace, - flags.nodeIDs, - flags.releaseTag, - flags.generateGossipKeys, - flags.generateTlsKeys, - flags.cacheDir, - flags.chainId, - flags.force, - flags.keyFormat, - flags.applicationProperties, - flags.apiPermissionProperties, - flags.bootstrapProperties, - flags.settingTxt, - flags.log4j2Xml - ), - handler: argv => { - nodeCmd.logger.debug("==== Running 'node setup' ===") - nodeCmd.logger.debug(argv) - - nodeCmd.setup(argv).then(r => { - nodeCmd.logger.debug('==== Finished running `node setup`====') - if (!r) process.exit(1) - }).catch(err => { - nodeCmd.logger.showUserError(err) - process.exit(1) - }) - } - }) - .command({ - command: 'start', - desc: 'Start a node', - builder: y => flags.setCommandFlags(y, - flags.namespace, - flags.nodeIDs, - flags.updateAccountKeys - ), - handler: argv => { - nodeCmd.logger.debug("==== Running 'node start' ===") - nodeCmd.logger.debug(argv) - - nodeCmd.start(argv).then(r => { - nodeCmd.logger.debug('==== Finished running `node start`====') - if (!r) process.exit(1) - }).catch(err => { - nodeCmd.logger.showUserError(err) - process.exit(1) - }) - } - }) - .command({ - command: 'stop', - desc: 'Stop a node', - builder: y => flags.setCommandFlags(y, - flags.namespace, - flags.nodeIDs - ), - handler: argv => { - nodeCmd.logger.debug("==== Running 'node stop' ===") - nodeCmd.logger.debug(argv) - - nodeCmd.stop(argv).then(r => { - nodeCmd.logger.debug('==== Finished running `node stop`====') - if (!r) process.exit(1) - }).catch(err => { - nodeCmd.logger.showUserError(err) - process.exit(1) - }) - } - }) - .command({ - command: 'keys', - desc: 'Generate node keys', - builder: y => flags.setCommandFlags(y, - flags.nodeIDs, - flags.cacheDir, - flags.generateGossipKeys, - flags.generateTlsKeys, - flags.keyFormat - ), - handler: argv => { - nodeCmd.logger.debug("==== Running 'node keys' ===") - nodeCmd.logger.debug(argv) - - nodeCmd.keys(argv).then(r => { - nodeCmd.logger.debug('==== Finished running `node keys`====') - if (!r) process.exit(1) - }).catch(err => { - nodeCmd.logger.showUserError(err) - process.exit(1) - }) - } - }) - .demandCommand(1, 'Select a node command') - } - } - } -} diff --git a/solo/src/commands/prompts.mjs b/solo/src/commands/prompts.mjs deleted file mode 100644 index 7a3dc1321..000000000 --- a/solo/src/commands/prompts.mjs +++ /dev/null @@ -1,419 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { ListrEnquirerPromptAdapter } from '@listr2/prompt-adapter-enquirer' -import fs from 'fs' -import { FullstackTestingError, IllegalArgumentError } from '../core/errors.mjs' -import { constants } from '../core/index.mjs' -import * as flags from './flags.mjs' -import * as helpers from '../core/helpers.mjs' - -async function prompt (type, task, input, defaultValue, promptMessage, emptyCheckMessage, flagName) { - try { - let needsPrompt = type === 'toggle' ? (input === undefined || typeof input !== 'boolean') : !input - needsPrompt = type === 'number' ? typeof input !== 'number' : needsPrompt - - if (needsPrompt) { - input = await task.prompt(ListrEnquirerPromptAdapter).run({ - type, - default: defaultValue, - message: promptMessage - }) - } - - if (emptyCheckMessage && !input) { - throw new FullstackTestingError(emptyCheckMessage) - } - - return input - } catch (e) { - throw new FullstackTestingError(`input failed: ${flagName}: ${e.message}`, e) - } -} -async function promptText (task, input, defaultValue, promptMessage, emptyCheckMessage, flagName) { - return await prompt('text', task, input, defaultValue, promptMessage, emptyCheckMessage, flagName) -} - -async function promptToggle (task, input, defaultValue, promptMessage, emptyCheckMessage, flagName) { - return await prompt('toggle', task, input, defaultValue, promptMessage, emptyCheckMessage, flagName) -} - -export async function promptNamespace (task, input) { - return await promptText(task, input, - 'solo', - 'Enter namespace name: ', - 'namespace cannot be empty', - flags.namespace.name) -} - -export async function promptClusterSetupNamespace (task, input) { - return await promptText(task, input, - 'solo-cluster', - 'Enter cluster setup namespace name: ', - 'cluster setup namespace cannot be empty', - flags.clusterSetupNamespace.name) -} - -export async function promptNodeIds (task, input) { - return await prompt('input', task, input, - 'node0,node1,node2', - 'Enter list of node IDs (comma separated list): ', - null, - flags.nodeIDs.name) -} - -export async function promptReleaseTag (task, input) { - return await promptText(task, input, - 'v0.42.5', - 'Enter release version: ', - 'release tag cannot be empty', - flags.releaseTag.name) -} - -export async function promptRelayReleaseTag (task, input) { - return await promptText(task, input, - flags.relayReleaseTag.definition.defaultValue, - 'Enter relay release version: ', - 'relay-release-tag cannot be empty', - flags.relayReleaseTag.name) -} - -export async function promptCacheDir (task, input) { - return await promptText(task, input, - constants.SOLO_CACHE_DIR, - 'Enter local cache directory path: ', - null, - flags.cacheDir.name) -} - -export async function promptForce (task, input) { - return await promptToggle(task, input, - flags.force.definition.defaultValue, - 'Would you like to force changes? ', - null, - flags.force.name) -} - -export async function promptChainId (task, input) { - return await promptText(task, input, - flags.chainId.definition.defaultValue, - 'Enter chain ID: ', - null, - flags.chainId.name) -} - -export async function promptChartDir (task, input) { - try { - if (input && !fs.existsSync(input)) { - input = await task.prompt(ListrEnquirerPromptAdapter).run({ - type: 'text', - default: flags.chartDirectory.definition.defaultValue, - message: 'Enter local charts directory path: ' - }) - - if (!fs.existsSync(input)) { - throw new IllegalArgumentError('Invalid chart directory', input) - } - } - - return input - } catch (e) { - throw new FullstackTestingError(`input failed: ${flags.chartDirectory.name}`, e) - } -} - -export async function promptValuesFile (task, input) { - try { - if (input && !fs.existsSync(input)) { - input = await task.prompt(ListrEnquirerPromptAdapter).run({ - type: 'text', - default: flags.valuesFile.definition.defaultValue, - message: 'Enter path to values.yaml: ' - }) - - if (!fs.existsSync(input)) { - throw new IllegalArgumentError('Invalid values.yaml file', input) - } - } - - return input - } catch (e) { - throw new FullstackTestingError(`input failed: ${flags.valuesFile.name}`, e) - } -} - -export async function promptDeployPrometheusStack (task, input) { - return await promptToggle(task, input, - flags.deployPrometheusStack.definition.defaultValue, - 'Would you like to deploy prometheus stack? ', - null, - flags.deployPrometheusStack.name) -} - -export async function promptEnablePrometheusSvcMonitor (task, input) { - return await promptToggle(task, input, - flags.enablePrometheusSvcMonitor.definition.defaultValue, - 'Would you like to enable the Prometheus service monitor for the network nodes? ', - null, - flags.enablePrometheusSvcMonitor.name) -} - -export async function promptDeployMinio (task, input) { - return await promptToggle(task, input, - flags.deployMinio.definition.defaultValue, - 'Would you like to deploy MinIO? ', - null, - flags.deployMinio.name) -} - -export async function promptDeployCertManager (task, input) { - return await promptToggle(task, input, - flags.deployCertManager.definition.defaultValue, - 'Would you like to deploy Cert Manager? ', - null, - flags.deployCertManager.name) -} - -export async function promptDeployCertManagerCrds (task, input) { - return await promptToggle(task, input, - flags.deployCertManagerCrds.definition.defaultValue, - 'Would you like to deploy Cert Manager CRDs? ', - null, - flags.deployCertManagerCrds.name) -} - -export async function promptDeployMirrorNode (task, input) { - return await promptToggle(task, input, - flags.deployMirrorNode.definition.defaultValue, - 'Would you like to deploy Hedera Mirror Node? ', - null, - flags.deployMirrorNode.name) -} - -export async function promptDeployHederaExplorer (task, input) { - return await promptToggle(task, input, - flags.deployHederaExplorer.definition.defaultValue, - 'Would you like to deploy Hedera Explorer? ', - null, - flags.deployHederaExplorer.name) -} - -export async function promptTlsClusterIssuerType (task, input) { - try { - if (!input) { - input = await task.prompt(ListrEnquirerPromptAdapter).run({ - type: 'text', - default: flags.tlsClusterIssuerType.definition.defaultValue, - message: 'Enter TLS cluster issuer type, available options are: "acme-staging", "acme-prod", or "self-signed":' - }) - } - - if (!input || !['acme-staging', 'acme-prod', 'self-signed'].includes(input)) { - throw new FullstackTestingError('must be one of: "acme-staging", "acme-prod", or "self-signed"') - } - - return input - } catch (e) { - throw new FullstackTestingError(`input failed: ${flags.tlsClusterIssuerType.name}`, e) - } -} - -export async function promptEnableHederaExplorerTls (task, input) { - return await promptToggle(task, input, - flags.enableHederaExplorerTls.definition.defaultValue, - 'Would you like to enable the Hedera Explorer TLS? ', - null, - flags.enableHederaExplorerTls.name) -} - -export async function promptHederaExplorerTlsHostName (task, input) { - return await promptText(task, input, - flags.hederaExplorerTlsHostName.definition.defaultValue, - 'Enter the host name to use for the Hedera Explorer TLS: ', - null, - flags.hederaExplorerTlsHostName.name) -} - -export async function promptOperatorId (task, input) { - return await promptText(task, input, - flags.operatorId.definition.defaultValue, - 'Enter operator ID: ', - null, - flags.operatorId.name) -} - -export async function promptOperatorKey (task, input) { - return await promptText(task, input, - flags.operatorKey.definition.defaultValue, - 'Enter operator private key: ', - null, - flags.operatorKey.name) -} - -export async function promptReplicaCount (task, input) { - return await prompt('number', task, input, - flags.replicaCount.definition.defaultValue, - 'How many replica do you want? ', - null, - flags.replicaCount.name) -} - -export async function promptGenerateGossipKeys (task, input) { - return await promptToggle(task, input, - flags.generateGossipKeys.definition.defaultValue, - `Would you like to generate Gossip keys? ${typeof input} ${input} `, - null, - flags.generateGossipKeys.name) -} - -export async function promptGenerateTLSKeys (task, input) { - return await promptToggle(task, input, - flags.generateTlsKeys.definition.defaultValue, - 'Would you like to generate TLS keys? ', - null, - flags.generateTlsKeys.name) -} - -export async function promptDeletePvcs (task, input) { - return await promptToggle(task, input, - flags.deletePvcs.definition.defaultValue, - 'Would you like to delete persistent volume claims upon uninstall? ', - null, - flags.deletePvcs.name) -} - -export async function promptKeyFormat (task, input, choices = [constants.KEY_FORMAT_PFX, constants.KEY_FORMAT_PEM]) { - try { - const initial = choices.indexOf(input) - if (initial < 0) { - const input = await task.prompt(ListrEnquirerPromptAdapter).run({ - type: 'select', - initial: choices.indexOf(flags.keyFormat.definition.defaultValue), - message: 'Select key format', - choices: helpers.cloneArray(choices) - }) - - if (!input) { - throw new FullstackTestingError('key-format cannot be empty') - } - - return input - } - - return input - } catch (e) { - throw new FullstackTestingError(`input failed: ${flags.keyFormat.name}: ${e.message}`, e) - } -} - -export async function promptFstChartVersion (task, input) { - return await promptText(task, input, - flags.fstChartVersion.definition.defaultValue, - 'Enter fullstack testing chart version: ', - null, - flags.fstChartVersion.name) -} - -export async function promptUpdateAccountKeys (task, input) { - return await promptToggle(task, input, - flags.updateAccountKeys.definition.defaultValue, - 'Would you like to updates the special account keys to new keys and stores their keys in a corresponding Kubernetes secret? ', - null, - flags.updateAccountKeys.name) -} - -export async function promptPrivateKey (task, input) { - return await promptText(task, input, - flags.privateKey.definition.defaultValue, - 'Enter the private key: ', - null, - flags.privateKey.name) -} - -export async function promptAccountId (task, input) { - return await promptText(task, input, - flags.accountId.definition.defaultValue, - 'Enter the account id: ', - null, - flags.accountId.name) -} - -export async function promptAmount (task, input) { - return await prompt('number', task, input, - flags.amount.definition.defaultValue, - 'How much HBAR do you want to add? ', - null, - flags.amount.name) -} - -export function getPromptMap () { - return new Map() - .set(flags.nodeIDs.name, promptNodeIds) - .set(flags.releaseTag.name, promptReleaseTag) - .set(flags.relayReleaseTag.name, promptRelayReleaseTag) - .set(flags.clusterSetupNamespace.name, promptClusterSetupNamespace) - .set(flags.namespace.name, promptNamespace) - .set(flags.cacheDir.name, promptCacheDir) - .set(flags.force.name, promptForce) - .set(flags.chainId.name, promptChainId) - .set(flags.chartDirectory.name, promptChartDir) - .set(flags.valuesFile.name, promptValuesFile) - .set(flags.deployPrometheusStack.name, promptDeployPrometheusStack) - .set(flags.enablePrometheusSvcMonitor.name, promptEnablePrometheusSvcMonitor) - .set(flags.deployMinio.name, promptDeployMinio) - .set(flags.deployCertManager.name, promptDeployCertManager) - .set(flags.deployCertManagerCrds.name, promptDeployCertManagerCrds) - .set(flags.deployMirrorNode.name, promptDeployMirrorNode) - .set(flags.deployHederaExplorer.name, promptDeployHederaExplorer) - .set(flags.tlsClusterIssuerType.name, promptTlsClusterIssuerType) - .set(flags.enableHederaExplorerTls.name, promptEnableHederaExplorerTls) - .set(flags.hederaExplorerTlsHostName.name, promptHederaExplorerTlsHostName) - .set(flags.operatorId.name, promptOperatorId) - .set(flags.operatorKey.name, promptOperatorKey) - .set(flags.replicaCount.name, promptReplicaCount) - .set(flags.generateGossipKeys.name, promptGenerateGossipKeys) - .set(flags.generateTlsKeys.name, promptGenerateTLSKeys) - .set(flags.deletePvcs.name, promptDeletePvcs) - .set(flags.keyFormat.name, promptKeyFormat) - .set(flags.fstChartVersion.name, promptFstChartVersion) - .set(flags.updateAccountKeys.name, promptUpdateAccountKeys) - .set(flags.privateKey.name, promptPrivateKey) - .set(flags.accountId.name, promptAccountId) - .set(flags.amount.name, promptAmount) -} - -// build the prompt registry -/** - * Run prompts for the given set of flags - * @param task task object from listr2 - * @param configManager config manager to store flag values - * @param flagList list of flag objects - * @return {Promise} - */ -export async function execute (task, configManager, flagList = []) { - const prompts = getPromptMap() - for (const flag of flagList) { - if (!prompts.has(flag.name)) { - throw new FullstackTestingError(`No prompt available for flag: ${flag.name}`) - } - - const prompt = prompts.get(flag.name) - const input = await prompt(task, configManager.getFlag(flag)) - configManager.setFlag(flag, input) - } - - configManager.persist() -} diff --git a/solo/src/commands/relay.mjs b/solo/src/commands/relay.mjs deleted file mode 100644 index e74097921..000000000 --- a/solo/src/commands/relay.mjs +++ /dev/null @@ -1,278 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { Listr } from 'listr2' -import { FullstackTestingError, MissingArgumentError } from '../core/errors.mjs' -import { BaseCommand } from './base.mjs' -import * as flags from './flags.mjs' -import * as paths from 'path' -import { constants } from '../core/index.mjs' -import * as prompts from './prompts.mjs' - -export class RelayCommand extends BaseCommand { - prepareValuesArg (valuesFile, nodeIDs, chainID, relayRelease, replicaCount, operatorID, operatorKey) { - let valuesArg = '' - if (valuesFile) { - const valuesFiles = valuesFile.split(',') - valuesFiles.forEach(vf => { - const vfp = paths.resolve(vf) - valuesArg += ` --values ${vfp}` - }) - } - - valuesArg += ` --set config.MIRROR_NODE_URL=${constants.FULLSTACK_DEPLOYMENT_CHART}-rest` - - if (chainID) { - valuesArg += ` --set config.CHAIN_ID=${chainID}` - } - - if (relayRelease) { - valuesArg += ` --set image.tag=${relayRelease.replace(/^v/, '')}` - } - - if (replicaCount) { - valuesArg += ` --set replicaCount=${replicaCount}` - } - - if (operatorID) { - valuesArg += ` --set config.OPERATOR_ID_MAIN=${operatorID}` - } - - if (operatorKey) { - valuesArg += ` --set config.OPERATOR_KEY_MAIN=${operatorKey}` - } - - if (!nodeIDs) { - throw new MissingArgumentError('Node IDs must be specified') - } - - nodeIDs.forEach(nodeID => { - const networkKey = `network-${nodeID.trim()}-0-svc:50211` - valuesArg += ` --set config.HEDERA_NETWORK.${networkKey}=0.0.3` - }) - - return valuesArg - } - - prepareReleaseName (nodeIDs = []) { - if (!nodeIDs) { - throw new MissingArgumentError('Node IDs must be specified') - } - - let releaseName = 'relay' - nodeIDs.forEach(nodeID => { - releaseName += `-${nodeID}` - }) - - return releaseName - } - - async install (argv) { - const self = this - const tasks = new Listr([ - { - title: 'Initialize', - task: async (ctx, task) => { - self.configManager.update(argv) - - // extract config values - const valuesFile = self.configManager.getFlag(flags.valuesFile) - const nodeIds = self.configManager.getFlag(flags.nodeIDs) - const chainId = self.configManager.getFlag(flags.chainId) - const relayRelease = self.configManager.getFlag(flags.relayReleaseTag) - const replicaCount = self.configManager.getFlag(flags.replicaCount) - const operatorId = self.configManager.getFlag(flags.operatorId) - const operatorKey = self.configManager.getFlag(flags.operatorKey) - - const namespace = self.configManager.getFlag(flags.namespace) - const chartDir = self.configManager.getFlag(flags.chartDirectory) - - // prompt if inputs are empty and set it in the context - const namespaces = await self.k8.getNamespaces() - ctx.config = { - chartDir: await prompts.promptChartDir(task, chartDir), - namespace: await prompts.promptSelectNamespaceArg(task, namespace, namespaces), - valuesFile: await prompts.promptValuesFile(task, valuesFile), - nodeIds: await prompts.promptNodeIds(task, nodeIds), - chainId: await prompts.promptChainId(task, chainId), - relayRelease: await prompts.promptRelayReleaseTag(task, relayRelease), - replicaCount: await prompts.promptReplicaCount(task, replicaCount), - operatorId: await prompts.promptOperatorId(task, operatorId), - operatorKey: await prompts.promptOperatorId(task, operatorKey) - } - - self.logger.debug('Finished prompts', { ctx }) - - ctx.releaseName = this.prepareReleaseName(ctx.config.nodeIds) - ctx.isChartInstalled = await this.chartManager.isChartInstalled(ctx.config.namespace, ctx.releaseName) - - self.logger.debug('Finished ctx initialization', { ctx }) - } - }, - { - title: 'Prepare chart values', - task: async (ctx, _) => { - ctx.chartPath = await this.prepareChartPath(ctx.config.chartDir, constants.JSON_RPC_RELAY_CHART, constants.CHART_JSON_RPC_RELAY_NAME) - ctx.valuesArg = this.prepareValuesArg( - ctx.config.valuesFile, - ctx.config.nodeIds, - ctx.config.chainId, - ctx.config.relayRelease, - ctx.config.replicaCount, - ctx.config.operatorId, - ctx.config.operatorKey - ) - } - }, - { - title: 'Install JSON RPC Relay', - task: async (ctx, _) => { - const namespace = ctx.config.namespace - const releaseName = ctx.releaseName - const chartPath = ctx.chartPath - const valuesArg = ctx.valuesArg - - await this.chartManager.install(namespace, releaseName, chartPath, '', valuesArg) - - await this.k8.waitForPod(constants.POD_STATUS_RUNNING, [ - 'app=hedera-json-rpc-relay', - `app.kubernetes.io/instance=${releaseName}` - ], 1, 120, 1000) - - this.logger.showList('Deployed Relays', await self.chartManager.getInstalledCharts(namespace)) - } - } - ], { - concurrent: false, - rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION - }) - - try { - await tasks.run() - } catch (e) { - throw new FullstackTestingError('Error installing relays', e) - } - - return true - } - - async uninstall (argv) { - const self = this - - const tasks = new Listr([ - { - title: 'Initialize', - task: async (ctx, task) => { - self.configManager.update(argv) - - // extract config values - const nodeIds = self.configManager.getFlag(flags.nodeIDs) - const namespace = self.configManager.getFlag(flags.namespace) - - // prompt if inputs are empty and set it in the context - const namespaces = await self.k8.getNamespaces() - ctx.config = { - namespace: await prompts.promptSelectNamespaceArg(task, namespace, namespaces), - nodeIds: await prompts.promptNodeIds(task, nodeIds) - } - - ctx.config.releaseName = this.prepareReleaseName(ctx.config.nodeIds) - self.logger.debug('Finished ctx initialization', { ctx }) - } - }, - { - title: 'Install JSON RPC Relay', - task: async (ctx, _) => { - const namespace = ctx.config.namespace - const releaseName = ctx.config.releaseName - - await this.chartManager.uninstall(namespace, releaseName) - - this.logger.showList('Deployed Relays', await self.chartManager.getInstalledCharts(namespace)) - } - } - ], { - concurrent: false, - rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION - }) - - try { - await tasks.run() - } catch (e) { - throw new FullstackTestingError('Error uninstalling relays', e) - } - - return true - } - - static getCommandDefinition (relayCmd) { - return { - command: 'relay', - desc: 'Manage JSON RPC relays in fullstack testing network', - builder: yargs => { - return yargs - .command({ - command: 'install', - desc: 'Install a JSON RPC relay', - builder: y => { - flags.setCommandFlags(y, - flags.namespace, - flags.valuesFile, - flags.chartDirectory, - flags.replicaCount, - flags.chainId, - flags.nodeIDs, - flags.relayReleaseTag, - flags.operatorId, - flags.operatorKey - ) - }, - handler: argv => { - relayCmd.logger.debug("==== Running 'relay install' ===", { argv }) - - relayCmd.install(argv).then(r => { - relayCmd.logger.debug('==== Finished running `relay install`====') - - if (!r) process.exit(1) - }).catch(err => { - relayCmd.logger.showUserError(err) - process.exit(1) - }) - } - }) - .command({ - command: 'uninstall', - desc: 'Uninstall JSON RPC relay', - builder: y => flags.setCommandFlags(y, - flags.namespace, - flags.nodeIDs - ), - handler: argv => { - relayCmd.logger.debug("==== Running 'relay uninstall' ===", { argv }) - relayCmd.logger.debug(argv) - - relayCmd.uninstall(argv).then(r => { - relayCmd.logger.debug('==== Finished running `relay uninstall`====') - - if (!r) process.exit(1) - }) - } - }) - .demandCommand(1, 'Select a relay command') - } - } - } -} diff --git a/solo/src/core/account_manager.mjs b/solo/src/core/account_manager.mjs deleted file mode 100644 index 7419cdcc9..000000000 --- a/solo/src/core/account_manager.mjs +++ /dev/null @@ -1,518 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import * as constants from './constants.mjs' -import { - AccountCreateTransaction, - AccountId, - AccountInfoQuery, - AccountUpdateTransaction, - Client, - Hbar, - HbarUnit, - KeyList, - PrivateKey, - Status, - TransferTransaction -} from '@hashgraph/sdk' -import { FullstackTestingError } from './errors.mjs' -import { sleep } from './helpers.mjs' -import net from 'net' -import chalk from 'chalk' -import { Templates } from './templates.mjs' - -const REASON_FAILED_TO_GET_KEYS = 'failed to get keys for accountId' -const REASON_SKIPPED = 'skipped since it does not have a genesis key' -const REASON_FAILED_TO_UPDATE_ACCOUNT = 'failed to update account keys' -const REASON_FAILED_TO_CREATE_K8S_S_KEY = 'failed to create k8s scrt key' - -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -export class AccountManager { - /** - * creates a new AccountManager instance - * @param logger the logger to use - * @param k8 the K8 instance - */ - constructor (logger, k8) { - if (!logger) throw new Error('An instance of core/Logger is required') - if (!k8) throw new Error('An instance of core/K8 is required') - - this.logger = logger - this.k8 = k8 - this.portForwards = [] - } - - /** - * Gets the account keys from the Kubernetes secret from which it is stored - * @param accountId the account ID for which we want its keys - * @param namespace the namespace that is storing the secret - * @returns {Promise<{accountId: string, privateKey: string, publicKey: string}|null>} a - * custom object with the account id, private key, and public key - */ - async getAccountKeysFromSecret (accountId, namespace) { - const secret = await this.k8.getSecret(namespace, Templates.renderAccountKeySecretLabelSelector(accountId)) - if (secret) { - return { - accountId: secret.labels['fullstack.hedera.com/account-id'], - privateKey: secret.data.privateKey, - publicKey: secret.data.publicKey - } - } else { - return null - } - } - - /** - * Prepares the accounts with updated keys so that they do not contain the default genesis keys - * @param namespace the namespace to run the update of account keys for - * @returns {Promise} - */ - async prepareAccounts (namespace) { - const serviceMap = await this.getNodeServiceMap(namespace) - - const nodeClient = await this.getNodeClient( - namespace, serviceMap, constants.OPERATOR_ID, constants.OPERATOR_KEY) - - await this.updateSpecialAccountsKeys(namespace, nodeClient, constants.SYSTEM_ACCOUNTS) - // update the treasury account last - await this.updateSpecialAccountsKeys(namespace, nodeClient, constants.TREASURY_ACCOUNTS) - - nodeClient.close() - await this.stopPortForwards() - } - - /** - * stops and closes all of the port forwards that are running - * @returns {Promise} - */ - async stopPortForwards () { - if (this.portForwards) { - this.portForwards.forEach(server => { - server.close() - }) - this.portForwards = [] - await sleep(1) // give a tick for connections to close - } - } - - /** - * Returns a node client that can be used to make calls against - * @param namespace the namespace for which the node client resides - * @param serviceMap a map of the service objects that proxy the nodes - * @param operatorId the account id of the operator of the transactions - * @param operatorKey the private key of the operator of the transactions - * @returns {Promise} a node client that can be used to call transactions - */ - async getNodeClient (namespace, serviceMap, operatorId, operatorKey) { - const nodes = {} - try { - let localPort = constants.LOCAL_NODE_START_PORT - - for (const serviceObject of serviceMap.values()) { - if (!this.isLocalhost() && !serviceObject.loadBalancerIp) { - throw new Error( - `Expected service ${serviceObject.name} to have a loadBalancerIP set for basepath ${this.k8.kubeClient.basePath}`) - } - const host = this.isLocalhost() ? '127.0.0.1' : serviceObject.loadBalancerIp - const port = serviceObject.grpcPort - const targetPort = this.isLocalhost() ? localPort : port - - if (this.isLocalhost()) { - this.portForwards.push(await this.k8.portForward(serviceObject.podName, localPort, port)) - } - - nodes[`${host}:${targetPort}`] = AccountId.fromString(serviceObject.accountId) - await this.testConnection(serviceObject.podName, host, targetPort) - - localPort++ - } - - this.logger.debug(`creating client from network configuration: ${JSON.stringify(nodes)}`) - const nodeClient = Client.fromConfig({ network: nodes }) - nodeClient.setOperator(operatorId, operatorKey) - - return nodeClient - } catch (e) { - throw new FullstackTestingError(`failed to setup node client: ${e.message}`, e) - } - } - - /** - * returns true if we detect that we are running against a local Kubernetes cluster - * @returns boolean true if we are running against a local Kubernetes cluster, else false - */ - isLocalhost () { - return this.k8.kubeClient.basePath.includes('127.0.0.1') - } - - /** - * Gets a Map of the Hedera node services and the attributes needed - * @param namespace the namespace of the fullstack network deployment - * @returns {Map} the Map of - */ - async getNodeServiceMap (namespace) { - const labelSelector = 'fullstack.hedera.com/node-name,fullstack.hedera.com/type=haproxy-svc' - const serviceMap = new Map() - - const serviceList = await this.k8.kubeClient.listNamespacedService( - namespace, undefined, undefined, undefined, undefined, labelSelector) - - // retrieve the list of services and build custom objects for the attributes we need - for (const service of serviceList.body.items) { - const serviceObject = {} - serviceObject.name = service.metadata.name - serviceObject.loadBalancerIp = service.status.loadBalancer.ingress ? service.status.loadBalancer.ingress[0].ip : undefined - serviceObject.grpcPort = service.spec.ports.filter(port => port.name === 'non-tls-grpc-client-port')[0].port - serviceObject.grpcsPort = service.spec.ports.filter(port => port.name === 'tls-grpc-client-port')[0].port - serviceObject.node = service.metadata.labels['fullstack.hedera.com/node-name'] - serviceObject.accountId = service.metadata.labels['fullstack.hedera.com/account-id'] - serviceObject.selector = service.spec.selector.app - serviceMap.set(serviceObject.node, serviceObject) - } - - // get the pod name for the service to use with portForward if needed - for (const serviceObject of serviceMap.values()) { - const labelSelector = `app=${serviceObject.selector}` - const podList = await this.k8.kubeClient.listNamespacedPod( - namespace, null, null, null, null, labelSelector) - serviceObject.podName = podList.body.items[0].metadata.name - } - - return serviceMap - } - - /** - * updates a set of special accounts keys with a newly generated key and stores them in a - * Kubernetes secret - * @param namespace the namespace of the nodes network - * @param nodeClient the active node client configured to point at the network - * @param accounts the accounts to update - * @returns {Promise} - */ - async updateSpecialAccountsKeys (namespace, nodeClient, accounts) { - const genesisKey = PrivateKey.fromStringED25519(constants.OPERATOR_KEY) - const accountUpdatePromiseArray = [] - const realm = constants.HEDERA_NODE_ACCOUNT_ID_START.realm - const shard = constants.HEDERA_NODE_ACCOUNT_ID_START.shard - - for (const [start, end] of accounts) { - for (let i = start; i <= end; i++) { - accountUpdatePromiseArray.push(this.updateAccountKeys( - namespace, nodeClient, AccountId.fromString(`${realm}.${shard}.${i}`), genesisKey)) - - await sleep(constants.ACCOUNT_KEYS_UPDATE_PAUSE) // sleep a little to prevent overwhelming the servers - } - } - - await Promise.allSettled(accountUpdatePromiseArray).then((results) => { - let rejectedCount = 0 - let fulfilledCount = 0 - let skippedCount = 0 - - for (const result of results) { - switch (result.status) { - case 'rejected': - if (result.reason === REASON_SKIPPED) { - skippedCount++ - } else { - this.logger.error(`REJECT: ${result.reason}: ${result.value}`) - rejectedCount++ - } - break - case 'fulfilled': - fulfilledCount++ - break - } - } - this.logger.showUser(chalk.green(`Account keys updated SUCCESSFULLY: ${fulfilledCount}`)) - if (skippedCount > 0) this.logger.showUser(chalk.cyan(`Account keys updates SKIPPED: ${skippedCount}`)) - if (rejectedCount > 0) this.logger.showUser(chalk.yellowBright(`Account keys updates with ERROR: ${rejectedCount}`)) - }) - } - - /** - * update the account keys for a given account and store its new key in a Kubernetes - * secret - * @param namespace the namespace of the nodes network - * @param nodeClient the active node client configured to point at the network - * @param accountId the account that will get its keys updated - * @param genesisKey the genesis key to compare against - * @returns {Promise<{value: string, status: string}|{reason: string, value: string, status: string}>} the result of the call - */ - async updateAccountKeys (namespace, nodeClient, accountId, genesisKey) { - let keys - try { - keys = await this.getAccountKeys(accountId, nodeClient) - this.logger.debug(`retrieved keys for account ${accountId.toString()}`) - } catch (e) { - this.logger.error(`failed to get keys for accountId ${accountId.toString()}, e: ${e.toString()}\n ${e.stack}`) - return { - status: 'rejected', - reason: REASON_FAILED_TO_GET_KEYS, - value: accountId.toString() - } - } - - if (constants.OPERATOR_PUBLIC_KEY !== keys[0].toString()) { - this.logger.debug(`account ${accountId.toString()} can be skipped since it does not have a genesis key`) - return { - status: 'rejected', - reason: REASON_SKIPPED, - value: accountId.toString() - } - } - - const newPrivateKey = PrivateKey.generateED25519() - const data = { - privateKey: newPrivateKey.toString(), - publicKey: newPrivateKey.publicKey.toString() - } - - try { - if (!(await this.k8.createSecret( - Templates.renderAccountKeySecretName(accountId), - namespace, 'Opaque', data, - Templates.renderAccountKeySecretLabelObject(accountId), true)) - ) { - this.logger.error(`failed to create secret for accountId ${accountId.toString()}`) - return { - status: 'rejected', - reason: REASON_FAILED_TO_CREATE_K8S_S_KEY, - value: accountId.toString() - } - } - this.logger.debug(`created k8s secret for account ${accountId.toString()}`) - } catch (e) { - this.logger.error(`failed to create secret for accountId ${accountId.toString()}, e: ${e.toString()}`) - return { - status: 'rejected', - reason: REASON_FAILED_TO_CREATE_K8S_S_KEY, - value: accountId.toString() - } - } - - try { - if (!(await this.sendAccountKeyUpdate(accountId, newPrivateKey, nodeClient, genesisKey))) { - this.logger.error(`failed to update account keys for accountId ${accountId.toString()}`) - return { - status: 'rejected', - reason: REASON_FAILED_TO_UPDATE_ACCOUNT, - value: accountId.toString() - } - } - this.logger.debug(`sent account key update for account ${accountId.toString()}`) - } catch (e) { - this.logger.error(`failed to update account keys for accountId ${accountId.toString()}, e: ${e.toString()}`) - return { - status: 'rejected', - reason: REASON_FAILED_TO_UPDATE_ACCOUNT, - value: accountId.toString() - } - } - - return { - status: 'fulfilled', - value: accountId.toString() - } - } - - /** - * gets the account info from Hedera network - * @param accountId the account - * @param nodeClient the active and configured node client - * @returns {AccountInfo} the private key of the account - */ - async accountInfoQuery (accountId, nodeClient) { - return await new AccountInfoQuery() - .setAccountId(accountId) - .execute(nodeClient) - } - - /** - * gets the account private and public key from the Kubernetes secret from which it is stored - * @param accountId the account - * @param nodeClient the active and configured node client - * @returns {Promise} the private key of the account - */ - async getAccountKeys (accountId, nodeClient) { - const accountInfo = await this.accountInfoQuery(accountId, nodeClient) - - let keys - if (accountInfo.key instanceof KeyList) { - keys = accountInfo.key.toArray() - } else { - keys = [] - keys.push(accountInfo.key) - } - - return keys - } - - /** - * send an account key update transaction to the network of nodes - * @param accountId the account that will get it's keys updated - * @param newPrivateKey the new private key - * @param nodeClient the active and configured node client - * @param oldPrivateKey the genesis key that is the current key - * @returns {Promise} whether the update was successful - */ - async sendAccountKeyUpdate (accountId, newPrivateKey, nodeClient, oldPrivateKey) { - this.logger.debug( - `Updating account ${accountId.toString()} with new public and private keys`) - - if (typeof newPrivateKey === 'string') { - newPrivateKey = PrivateKey.fromStringED25519(newPrivateKey) - } - - if (typeof oldPrivateKey === 'string') { - oldPrivateKey = PrivateKey.fromStringED25519(oldPrivateKey) - } - - // Create the transaction to update the key on the account - const transaction = await new AccountUpdateTransaction() - .setAccountId(accountId) - .setKey(newPrivateKey.publicKey) - .freezeWith(nodeClient) - - // Sign the transaction with the old key and new key - const signTx = await (await transaction.sign(oldPrivateKey)).sign( - newPrivateKey) - - // SIgn the transaction with the client operator private key and submit to a Hedera network - const txResponse = await signTx.execute(nodeClient) - - // Request the receipt of the transaction - const receipt = await txResponse.getReceipt(nodeClient) - - this.logger.debug( - `The transaction consensus status for update of accountId ${accountId.toString()} is ${receipt.status}`) - - return receipt.status === Status.Success - } - - /** - * to test the connection to the node within the network - * @param podName the podName is only used for logging messages and errors - * @param host the host of the target connection - * @param port the port of the target connection - * @returns {Promise} - */ - async testConnection (podName, host, port) { - // check if the port is actually accessible - let attempt = 1 - let socket = null - while (attempt < 10) { - try { - await sleep(250) - this.logger.debug(`Checking exposed port '${port}' of pod ${podName} at IP address ${host}`) - socket = net.createConnection({ host, port }) - this.logger.debug(`Connected to port '${port}' of pod ${podName} at IP address ${host}`) - break - } catch (e) { - attempt += 1 - } - } - if (!socket) { - throw new FullstackTestingError(`failed to connect to port '${port}' of pod ${podName} at IP address ${host}`) - } - socket.destroy() - await sleep(1) // gives a few ticks for connections to close - } - - /** - * creates a new Hedera account - * @param namespace the namespace to store the Kubernetes key secret into - * @param nodeClient the active and network configured node client - * @param privateKey the private key of type PrivateKey - * @param amount the amount of HBAR to add to the account - * @returns {{accountId: AccountId, privateKey: string, publicKey: string, balance: number}} a - * custom object with the account information in it - */ - async createNewAccount (namespace, nodeClient, privateKey, amount) { - const newAccount = await new AccountCreateTransaction() - .setKey(privateKey) - .setInitialBalance(Hbar.from(amount, HbarUnit.Hbar)) - .execute(nodeClient) - - // Get the new account ID - const getReceipt = await newAccount.getReceipt(nodeClient) - const accountInfo = { - accountId: getReceipt.accountId.toString(), - privateKey: privateKey.toString(), - publicKey: privateKey.publicKey.toString(), - balance: amount - } - - if (!(await this.k8.createSecret( - Templates.renderAccountKeySecretName(accountInfo.accountId), - namespace, 'Opaque', { - privateKey: accountInfo.privateKey, - publicKey: accountInfo.publicKey - }, - Templates.renderAccountKeySecretLabelObject(accountInfo.accountId), true)) - ) { - this.logger.error(`new account created [accountId=${accountInfo.accountId}, amount=${amount} HBAR, publicKey=${accountInfo.publicKey}, privateKey=${accountInfo.privateKey}] but failed to create secret in Kubernetes`) - - throw new FullstackTestingError(`failed to create secret for accountId ${accountInfo.accountId.toString()}, keys were sent to log file`) - } - this.logger.debug(`created k8s secret for account ${accountInfo.accountId}`) - - return accountInfo - } - - /** - * transfer the specified amount of HBAR from one account to another - * @param nodeClient the configured and active network node client - * @param fromAccountId the account to pull the HBAR from - * @param toAccountId the account to put the HBAR - * @param hbarAmount the amount of HBAR - * @returns {Promise} if the transaction was successfully posted - */ - async transferAmount (nodeClient, fromAccountId, toAccountId, hbarAmount) { - try { - const transaction = new TransferTransaction() - .addHbarTransfer(fromAccountId, new Hbar(-1 * hbarAmount)) - .addHbarTransfer(toAccountId, new Hbar(hbarAmount)) - - const txResponse = await transaction.execute(nodeClient) - - const receipt = await txResponse.getReceipt(nodeClient) - - this.logger.debug(`The transfer from account ${fromAccountId} to account ${toAccountId} for amount ${hbarAmount} was ${receipt.status.toString()} `) - - return receipt.status === Status.Success - } catch (e) { - const errorMessage = `transfer amount failed with an error: ${e.toString()}` - this.logger.error(errorMessage) - throw new FullstackTestingError(errorMessage, e) - } - } -} diff --git a/solo/src/core/chart_manager.mjs b/solo/src/core/chart_manager.mjs deleted file mode 100644 index 570b7f916..000000000 --- a/solo/src/core/chart_manager.mjs +++ /dev/null @@ -1,140 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { constants } from './index.mjs' -import chalk from 'chalk' -import { FullstackTestingError } from './errors.mjs' - -export class ChartManager { - constructor (helm, logger) { - if (!logger) throw new Error('An instance of core/Logger is required') - if (!helm) throw new Error('An instance of core/Helm is required') - - this.logger = logger - this.helm = helm - } - - /** - * Setup chart repositories - * - * This must be invoked before calling other methods - * - * @param repoURLs a map of name and chart repository URLs - * @param force whether or not to update the repo - * @returns {Promise} - */ - async setup (repoURLs = constants.DEFAULT_CHART_REPO, force = true) { - try { - let forceUpdateArg = '' - if (force) { - forceUpdateArg = '--force-update' - } - - const urls = [] - for (const [name, url] of repoURLs.entries()) { - this.logger.debug(`Adding repo ${name} -> ${url}`, { repoName: name, repoURL: url }) - await this.helm.repo('add', name, url, forceUpdateArg) - urls.push(url) - } - - return urls - } catch (e) { - throw new FullstackTestingError(`failed to setup chart repositories: ${e.message}`, e) - } - } - - /** - * List available clusters - * @returns {Promise} - */ - async getInstalledCharts (namespaceName) { - try { - return await this.helm.list(`-n ${namespaceName}`, '--no-headers | awk \'{print $1 " [" $9"]"}\'') - } catch (e) { - this.logger.showUserError(e) - } - - return [] - } - - async install (namespaceName, chartName, chartPath, version, valuesArg = '') { - try { - const isInstalled = await this.isChartInstalled(namespaceName, chartName) - if (!isInstalled) { - let versionArg = '' - if (version) { - versionArg = `--version ${version}` - } - - let namespaceArg = '' - if (namespaceName) { - namespaceArg = `-n ${namespaceName} --create-namespace` - } - - this.logger.debug(`> installing chart:${chartPath}`) - await this.helm.install(`${chartName} ${chartPath} ${versionArg} ${namespaceArg} ${valuesArg}`) - this.logger.debug(`OK: chart is installed: ${chartName} (${chartPath})`) - } else { - this.logger.debug(`OK: chart is already installed:${chartName} (${chartPath})`) - } - } catch (e) { - throw new FullstackTestingError(`failed to install chart ${chartName}: ${e.message}`, e) - } - - return true - } - - async isChartInstalled (namespaceName, chartName) { - this.logger.debug(`> checking if chart is installed [ chart: ${chartName}, namespace: ${namespaceName} ]`) - const charts = await this.getInstalledCharts(namespaceName) - for (const item of charts) { - if (item.startsWith(chartName)) { - return true - } - } - - return false - } - - async uninstall (namespaceName, chartName) { - try { - const isInstalled = await this.isChartInstalled(namespaceName, chartName) - if (isInstalled) { - this.logger.debug(`uninstalling chart release: ${chartName}`) - await this.helm.uninstall(`-n ${namespaceName} ${chartName}`) - this.logger.debug(`OK: chart release is uninstalled: ${chartName}`) - } else { - this.logger.debug(`OK: chart release is already uninstalled: ${chartName}`) - } - } catch (e) { - throw new FullstackTestingError(`failed to uninstall chart ${chartName}: ${e.message}`, e) - } - - return true - } - - async upgrade (namespaceName, chartName, chartPath, valuesArg = '') { - try { - this.logger.showUser(chalk.cyan('> upgrading chart:'), chalk.yellow(`${chartName}`)) - await this.helm.upgrade(`-n ${namespaceName} ${chartName} ${chartPath} ${valuesArg}`) - this.logger.showUser(chalk.green('OK'), `chart '${chartName}' is upgraded`) - } catch (e) { - throw new FullstackTestingError(`failed to upgrade chart ${chartName}: ${e.message}`, e) - } - - return true - } -} diff --git a/solo/src/core/config_manager.mjs b/solo/src/core/config_manager.mjs deleted file mode 100644 index ae1f26436..000000000 --- a/solo/src/core/config_manager.mjs +++ /dev/null @@ -1,228 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import fs from 'fs' -import { FullstackTestingError, MissingArgumentError } from './errors.mjs' -import { constants } from './index.mjs' -import { Logger } from './logging.mjs' -import * as flags from '../commands/flags.mjs' -import * as paths from 'path' -import * as helpers from './helpers.mjs' - -/** - * ConfigManager cache command flag values so that user doesn't need to enter the same values repeatedly. - * - * For example, 'namespace' is usually remains the same across commands once it is entered, and therefore user - * doesn't need to enter it repeatedly. However, user should still be able to specify the flag explicitly for any command. - */ -export class ConfigManager { - constructor (logger, cachedConfigFile = constants.SOLO_CONFIG_FILE) { - if (!logger || !(logger instanceof Logger)) throw new MissingArgumentError('An instance of core/Logger is required') - if (!cachedConfigFile) throw new MissingArgumentError('cached config file path is required') - - this.logger = logger - this.cachedConfigFile = cachedConfigFile - this.reset() - } - - /** - * Load the cached config - */ - load () { - try { - if (fs.existsSync(this.cachedConfigFile)) { - const configJSON = fs.readFileSync(this.cachedConfigFile) - this.config = JSON.parse(configJSON.toString()) - } - } catch (e) { - throw new FullstackTestingError(`failed to initialize config manager: ${e.message}`, e) - } - } - - /** - * Reset config - */ - reset () { - this.config = { - flags: {}, - version: helpers.packageVersion(), - updatedAt: new Date().toISOString() - } - } - - /** - * Apply the command flags precedence - * - * It uses the below precedence for command flag values: - * 1. User input of the command flag - * 2. Cached config value of the command flag. - * 3. Default value of the command flag if the command is not 'init'. - * - * @param argv yargs.argv - * @param aliases yargv.parsed.aliases - * @return {*} updated argv - */ - applyPrecedence (argv, aliases) { - for (const key of Object.keys(aliases)) { - const flag = flags.allFlagsMap.get(key) - if (flag) { - if (argv[key] !== undefined) { - // argv takes precedence, nothing to do - } else if (this.hasFlag(flag)) { - argv[key] = this.getFlag(flag) - } else { - argv[key] = flag.definition.defaultValue - } - } - } - - return argv - } - - /** - * Update the config using the argv - * - * @param argv list of yargs argv - * @param persist - */ - update (argv = {}, persist = false) { - if (argv && Object.keys(argv).length > 0) { - for (const flag of flags.allFlags) { - if (flag.name === flags.force.name) { - continue // we don't want to cache force flag - } - - if (argv[flag.name] === '' && - [flags.namespace.name, flags.clusterName.name, flags.chartDirectory.name].includes(flag.name)) { - continue // don't cache empty namespace, clusterName, or chartDirectory - } - - if (argv[flag.name] !== undefined) { - let val = argv[flag.name] - switch (flag.definition.type) { - case 'string': - if (flag.name === flags.chartDirectory.name || flag.name === flags.cacheDir.name) { - this.logger.debug(`Resolving directory path for '${flag.name}': ${val}`) - val = paths.resolve(val) - } - this.logger.debug(`Setting flag '${flag.name}' of type '${flag.definition.type}': ${val}`) - this.config.flags[flag.name] = `${val}` // force convert to string - break - - case 'number': - this.logger.debug(`Setting flag '${flag.name}' of type '${flag.definition.type}': ${val}`) - try { - if (flags.integerFlags.has(flag.name)) { - this.config.flags[flag.name] = Number.parseInt(val) - } else { - this.config.flags[flag.name] = Number.parseFloat(val) - } - } catch (e) { - throw new FullstackTestingError(`invalid number value '${val}': ${e.message}`, e) - } - break - - case 'boolean': - this.logger.debug(`Setting flag '${flag.name}' of type '${flag.definition.type}': ${val}`) - this.config.flags[flag.name] = (val === true) || (val === 'true') // use comparison to enforce boolean value - break - - default: - throw new FullstackTestingError(`Unsupported field type for flag '${flag.name}': ${flag.definition.type}`) - } - } - } - - // store last command that was run - if (argv._) { - this.config.lastCommand = argv._ - } - - this.config.updatedAt = new Date().toISOString() - - if (persist) { - this.persist() - } - } - } - - /** - * Persist the config in the cached config file - */ - persist () { - try { - this.config.updatedAt = new Date().toISOString() - let configJSON = JSON.stringify(this.config) - fs.writeFileSync(`${this.cachedConfigFile}`, configJSON) - - // refresh config with the file contents - configJSON = fs.readFileSync(this.cachedConfigFile) - this.config = JSON.parse(configJSON.toString()) - } catch (e) { - throw new FullstackTestingError(`failed to persis config: ${e.message}`, e) - } - } - - /** - * Check if a flag value is set - * @param flag flag object - * @return {boolean} - */ - hasFlag (flag) { - return this.config.flags[flag.name] !== undefined - } - - /** - * Return the value of the given flag - * - * @param flag flag object - * @return {*|string} value of the flag or undefined if flag value is not available - */ - getFlag (flag) { - if (this.config.flags[flag.name] !== undefined) { - return this.config.flags[flag.name] - } - - return undefined - } - - /** - * Set value for the flag - * @param flag flag object - * @param value value of the flag - */ - - setFlag (flag, value) { - if (!flag || !flag.name) throw new MissingArgumentError('flag must have a name') - this.config.flags[flag.name] = value - } - - /** - * Get package version - * @return {*} - */ - getVersion () { - return this.config.version - } - - /** - * Get last updated at timestamp - * @return {string} - */ - getUpdatedAt () { - return this.config.updatedAt - } -} diff --git a/solo/src/core/constants.mjs b/solo/src/core/constants.mjs deleted file mode 100644 index 2213836f3..000000000 --- a/solo/src/core/constants.mjs +++ /dev/null @@ -1,115 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { AccountId } from '@hashgraph/sdk' -import { color, PRESET_TIMER } from 'listr2' -import { dirname, normalize } from 'path' -import { fileURLToPath } from 'url' -import chalk from 'chalk' - -// -------------------- solo related constants --------------------------------------------------------------------- -export const CUR_FILE_DIR = dirname(fileURLToPath(import.meta.url)) -export const USER = `${process.env.USER}` -export const USER_SANITIZED = USER.replace(/[\W_]+/g, '-') -export const SOLO_HOME_DIR = `${process.env.HOME}/.solo` -export const SOLO_LOGS_DIR = `${SOLO_HOME_DIR}/logs` -export const SOLO_CACHE_DIR = `${SOLO_HOME_DIR}/cache` -export const DEFAULT_NAMESPACE = 'default' -export const HELM = 'helm' -export const CWD = process.cwd() -export const SOLO_CONFIG_FILE = `${SOLO_HOME_DIR}/solo.config` -export const RESOURCES_DIR = normalize(CUR_FILE_DIR + '/../../resources') - -export const ROOT_CONTAINER = 'root-container' - -// --------------- Hedera network and node related constants -------------------------------------------------------------------- -export const HEDERA_CHAIN_ID = process.env.SOLO_CHAIN_ID || '298' -export const HEDERA_HGCAPP_DIR = '/opt/hgcapp' -export const HEDERA_SERVICES_PATH = `${HEDERA_HGCAPP_DIR}/services-hedera` -export const HEDERA_HAPI_PATH = `${HEDERA_SERVICES_PATH}/HapiApp2.0` -export const HEDERA_DATA_APPS_DIR = 'data/apps' -export const HEDERA_DATA_LIB_DIR = 'data/lib' -export const HEDERA_USER_HOME_DIR = '/home/hedera' -export const HEDERA_APP_NAME = 'HederaNode.jar' -export const HEDERA_BUILDS_URL = 'https://builds.hedera.com' -export const HEDERA_NODE_ACCOUNT_ID_START = AccountId.fromString(process.env.SOLO_NODE_ACCOUNT_ID_START || '0.0.3') -export const HEDERA_NODE_INTERNAL_GOSSIP_PORT = process.env.SOLO_NODE_INTERNAL_GOSSIP_PORT || '50111' -export const HEDERA_NODE_EXTERNAL_GOSSIP_PORT = process.env.SOLO_NODE_EXTERNAL_GOSSIP_PORT || '50111' - -export const HEDERA_NODE_GRPC_PORT = process.env.SOLO_NODE_GRPC_PORT || '50211' -export const HEDERA_NODE_GRPCS_PORT = process.env.SOLO_NODE_GRPC_PORT || '50212' -export const HEDERA_NODE_DEFAULT_STAKE_AMOUNT = process.env.SOLO_NODE_DEFAULT_STAKE_AMOUNT || 1 - -// --------------- Logging related constants --------------------------------------------------------------------------- -export const LOG_STATUS_PROGRESS = chalk.cyan('>>') -export const LOG_STATUS_DONE = chalk.green('OK') -export const LOG_GROUP_DIVIDER = chalk.yellow('----------------------------------------------------------------------------') - -// --------------- Charts related constants ---------------------------------------------------------------------------- -export const FULLSTACK_TESTING_CHART_URL = 'https://hashgraph.github.io/full-stack-testing/charts' -export const FULLSTACK_TESTING_CHART = 'full-stack-testing' -export const FULLSTACK_CLUSTER_SETUP_CHART = 'fullstack-cluster-setup' -export const FULLSTACK_DEPLOYMENT_CHART = 'fullstack-deployment' -export const JSON_RPC_RELAY_CHART_URL = 'https://hashgraph.github.io/hedera-json-rpc-relay/charts' -export const JSON_RPC_RELAY_CHART = 'hedera-json-rpc-relay' -export const MIRROR_NODE_CHART_URL = 'https://hashgraph.github.io/hedera-mirror-node/charts' -export const MIRROR_NODE_CHART = 'hedera-mirror' -export const DEFAULT_CHART_REPO = new Map() - .set(FULLSTACK_TESTING_CHART, FULLSTACK_TESTING_CHART_URL) - .set(JSON_RPC_RELAY_CHART, JSON_RPC_RELAY_CHART_URL) - .set(MIRROR_NODE_CHART, MIRROR_NODE_CHART_URL) - -// ------------------- Hedera Account related --------------------------------------------------------------------------------- -export const OPERATOR_ID = process.env.SOLO_OPERATOR_ID || '0.0.2' -export const OPERATOR_KEY = process.env.SOLO_OPERATOR_KEY || '302e020100300506032b65700422042091132178e72057a1d7528025956fe39b0b847f200ab59b2fdd367017f3087137' -export const OPERATOR_PUBLIC_KEY = process.env.SOLO_OPERATOR_PUBLIC_KEY || '302a300506032b65700321000aa8e21064c61eab86e2a9c164565b4e7a9a4146106e0a6cd03a8c395a110e92' -export const TREASURY_ACCOUNT_ID = `${HEDERA_NODE_ACCOUNT_ID_START.realm}.${HEDERA_NODE_ACCOUNT_ID_START.shard}.2` -export const GENESIS_KEY = process.env.GENESIS_KEY || '302e020100300506032b65700422042091132178e72057a1d7528025956fe39b0b847f200ab59b2fdd367017f3087137' -export const SYSTEM_ACCOUNTS = [[3, 100], [200, 349], [400, 750], [900, 1000]] // do account 0.0.2 last and outside the loop -export const TREASURY_ACCOUNTS = [[2, 2]] -export const LOCAL_NODE_START_PORT = process.env.LOCAL_NODE_START_PORT || 30212 -export const ACCOUNT_KEYS_UPDATE_PAUSE = process.env.ACCOUNT_KEYS_UPDATE_PAUSE || 5 - -export const POD_STATUS_RUNNING = 'Running' -export const POD_STATUS_READY = 'Ready' - -// Listr related -export const LISTR_DEFAULT_RENDERER_TIMER_OPTION = { - ...PRESET_TIMER, - condition: (duration) => duration > 100, - format: (duration) => { - if (duration > 10000) { - return color.red - } - - return color.green - } -} - -export const LISTR_DEFAULT_RENDERER_OPTION = { - collapseSubtasks: false, - timer: LISTR_DEFAULT_RENDERER_TIMER_OPTION -} - -export const KEY_FORMAT_PEM = 'pem' - -export const KEY_FORMAT_PFX = 'pfx' - -export const KEY_TYPE_GOSSIP = 'gossip' - -export const KEY_TYPE_TLS = 'tls' -export const SIGNING_KEY_PREFIX = 's' -export const AGREEMENT_KEY_PREFIX = 'a' diff --git a/solo/src/core/dependency_manager.mjs b/solo/src/core/dependency_manager.mjs deleted file mode 100644 index 325ac43e5..000000000 --- a/solo/src/core/dependency_manager.mjs +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { FullstackTestingError } from './errors.mjs' -import { constants } from './index.mjs' -import * as core from './index.mjs' -import * as helpers from './helpers.mjs' -import { ShellRunner } from './shell_runner.mjs' - -export class DependencyManager extends ShellRunner { - static depVersions = new Map() - .set(constants.HELM, 'v3.12.3') - - constructor (logger) { - super(logger) - - // map of dependency checks - this.checks = new Map() - .set(core.constants.HELM, () => this.checkHelm()) - } - - /** - * Check if 'helm' CLI program is installed or not - * @returns {Promise} - */ - async checkHelm () { - try { - const output = await this.run(`${core.constants.HELM} version --short`) - const parts = output[0].split('+') - this.logger.debug(`Found dependency ${constants.HELM}:${parts[0]}`) - return helpers.compareVersion(DependencyManager.depVersions.get(constants.HELM), parts[0]) >= 0 - } catch (e) { - this.logger.error(`failed to check helm dependency:${e.message}`, e) - } - - return false - } - - /** - * Check if the required dependency is installed or not - * @param dep is the name of the program - * @returns {Promise} - */ - async checkDependency (dep) { - this.logger.debug(`Checking for dependency: ${dep}`) - - let status = false - const check = this.checks.get(dep) - if (check) { - status = await check() - } - - if (!status) { - throw new FullstackTestingError(`${dep}:^${DependencyManager.depVersions.get(dep)} is not found`) - } - - this.logger.debug(`Dependency ${dep} is found`) - return true - } - - taskCheckDependencies (deps = []) { - const subTasks = [] - deps.forEach(dep => { - subTasks.push({ - title: `Check dependency: ${dep}`, - task: () => this.checkDependency(dep) - }) - }) - - return subTasks - } -} diff --git a/solo/src/core/errors.mjs b/solo/src/core/errors.mjs deleted file mode 100644 index d20bd7b1e..000000000 --- a/solo/src/core/errors.mjs +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -export class FullstackTestingError extends Error { - /** - * Create a custom error object - * - * error metadata will include the `cause` - * - * @param message error message - * @param cause source error (if any) - * @param meta additional metadata (if any) - */ - constructor (message, cause = {}, meta = {}) { - super(message) - this.name = this.constructor.name - - this.meta = meta - if (cause) { - this.cause = cause - } - - Error.captureStackTrace(this, this.constructor) - } -} - -export class ResourceNotFoundError extends FullstackTestingError { - /** - * Create a custom error for resource not found scenario - * - * error metadata will include `resource` - * - * @param message error message - * @param resource name of the resource - * @param cause source error (if any) - */ - constructor (message, resource, cause = {}) { - super(message, cause, { resource }) - } -} - -export class MissingArgumentError extends FullstackTestingError { - /** - * Create a custom error for missing argument scenario - * - * @param message error message - * @param cause source error (if any) - */ - constructor (message, cause = {}) { - super(message, cause) - } -} - -export class IllegalArgumentError extends FullstackTestingError { - /** - * Create a custom error for illegal argument scenario - * - * error metadata will include `value` - * - * @param message error message - * @param value value of the invalid argument - * @param cause source error (if any) - */ - constructor (message, value = '', cause = {}) { - super(message, cause, { value }) - } -} - -export class DataValidationError extends FullstackTestingError { - /** - * Create a custom error for data validation error scenario - * - * error metadata will include `expected` and `found` values. - * - * @param message error message - * @param expected expected value - * @param found value found - * @param cause source error (if any) - */ - constructor (message, expected, found, cause = {}) { - super(message, cause, { expected, found }) - } -} diff --git a/solo/src/core/helm.mjs b/solo/src/core/helm.mjs deleted file mode 100644 index 840275ecc..000000000 --- a/solo/src/core/helm.mjs +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { ShellRunner } from './shell_runner.mjs' - -export class Helm extends ShellRunner { - /** - * Prepare a `helm` shell command string - * @param action represents a helm command (e.g. create | install | get ) - * @param args args of the command - * @returns {string} - */ - prepareCommand (action, ...args) { - let cmd = `helm ${action}` - args.forEach(arg => { cmd += ` ${arg}` }) - return cmd - } - - /** - * Invoke `helm install` command - * @param args args of the command - * @returns {Promise} console output as an array of strings - */ - async install (...args) { - return this.run(this.prepareCommand('install', ...args), true) - } - - /** - * Invoke `helm uninstall` command - * @param args args of the command - * @returns {Promise} console output as an array of strings - */ - async uninstall (...args) { - return this.run(this.prepareCommand('uninstall', ...args)) - } - - /** - * Invoke `helm upgrade` command - * @param args args of the command - * @returns {Promise} console output as an array of strings - */ - async upgrade (...args) { - return this.run(this.prepareCommand('upgrade', ...args)) - } - - /** - * Invoke `helm list` command - * @param args args of the command - * @returns {Promise} console output as an array of strings - */ - async list (...args) { - return this.run(this.prepareCommand('list', ...args)) - } - - /** - * Invoke `helm dependency` command - * @param subCommand sub-command - * @param args args of the command - * @returns {Promise} console output as an array of strings - */ - async dependency (subCommand, ...args) { - return this.run(this.prepareCommand('dependency', subCommand, ...args)) - } - - /** - * Invoke `helm repo` command - * @param subCommand sub-command - * @param args args of the command - * @returns {Promise} console output as an array of strings - */ - async repo (subCommand, ...args) { - return this.run(this.prepareCommand('repo', subCommand, ...args)) - } -} diff --git a/solo/src/core/helpers.mjs b/solo/src/core/helpers.mjs deleted file mode 100644 index 3921aaac3..000000000 --- a/solo/src/core/helpers.mjs +++ /dev/null @@ -1,134 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import fs from 'fs' -import { FullstackTestingError } from './errors.mjs' -import * as paths from 'path' -import { fileURLToPath } from 'url' - -// cache current directory -const CUR_FILE_DIR = paths.dirname(fileURLToPath(import.meta.url)) - -export function sleep (ms) { - return new Promise((resolve) => { - setTimeout(resolve, ms) - }) -} - -export function parseNodeIDs (input) { - if (typeof input === 'string') { - const nodeIds = [] - input.split(',').forEach(item => { - const nodeId = item.trim() - if (nodeId) { - nodeIds.push(nodeId) - } - }) - - return nodeIds - } - - throw new FullstackTestingError('node IDs is not a comma separated string') -} - -export function cloneArray (arr) { - return JSON.parse(JSON.stringify(arr)) -} - -/** - * load package.json - * @returns {any} - */ -export function loadPackageJSON () { - try { - const raw = fs.readFileSync(`${CUR_FILE_DIR}/../../package.json`) - return JSON.parse(raw.toString()) - } catch (e) { - throw new FullstackTestingError('failed to load package.json', e) - } -} - -export function packageVersion () { - const packageJson = loadPackageJSON() - return packageJson.version -} - -/** - * Split semantic version into its major, minor and patch number - * @param semver release version - * @return {{patch: number, major: number, minor: number}} - */ -export function parseSemver (semver) { - if (!semver || semver[0] !== 'v') { - throw new FullstackTestingError(`invalid version. Expected 'v..', found '${semver}'`) - } - - const version = semver.replace('v', '') // remove first 'v' - const parts = version.split('-')[0].split('.') // just take the major.minor.patch part of the version - if (parts.length < 3) { - throw new FullstackTestingError(`version '${semver}' must have the format MAJOR.MINOR.PATCH`) - } - - return { - major: Number.parseInt(parts[0]), - minor: Number.parseInt(parts[1]), - patch: Number.parseInt(parts[2]) - } -} - -/** - * Compare two version - * - * It returns 1, 0, -1 depending on the following three cases: - * - candidate > target: 1 - * - candidate == target: 0 - * - candidate < target: -1 - * - * @param target target version - * @param candidate candidate version - * @return {number} - */ -export function compareVersion (target, candidate) { - const v1 = parseSemver(target) - const v2 = parseSemver(candidate) - - if (v2.major === v1.major && v2.minor === v1.minor && v2.patch === v1.patch) { - return 0 - } - - if ((v2.major > v1.major) || - (v2.major >= v1.major && v2.minor > v1.minor) || - (v2.major >= v1.major && v2.minor >= v1.minor && v2.patch >= v1.patch) - ) { - return 1 - } - - return -1 -} - -/** - * Return the required root image for a platform version - * @param releaseTag platform version - * @return {string} - */ -export function getRootImageRepository (releaseTag) { - const releaseVersion = parseSemver(releaseTag) - if (releaseVersion.minor < 46) { - return 'hashgraph/full-stack-testing/ubi8-init-java17' - } - - return 'hashgraph/full-stack-testing/ubi8-init-java21' -} diff --git a/solo/src/core/index.mjs b/solo/src/core/index.mjs deleted file mode 100644 index e0a7a5af3..000000000 --- a/solo/src/core/index.mjs +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import * as logging from './logging.mjs' -import * as constants from './constants.mjs' -import { Helm } from './helm.mjs' -import { K8 } from './k8.mjs' -import { PackageDownloader } from './package_downloader.mjs' -import { PlatformInstaller } from './platform_installer.mjs' -import { Zippy } from './zippy.mjs' -import { Templates } from './templates.mjs' -import { ChartManager } from './chart_manager.mjs' -import { ConfigManager } from './config_manager.mjs' -import { DependencyManager } from './dependency_manager.mjs' -import { KeyManager } from './key_manager.mjs' - -// Expose components from the core module -export { - logging, - constants, - Helm, - K8, - PackageDownloader, - PlatformInstaller, - Zippy, - Templates, - ChartManager, - ConfigManager, - DependencyManager, - KeyManager -} diff --git a/solo/src/core/k8.mjs b/solo/src/core/k8.mjs deleted file mode 100644 index de2bdae15..000000000 --- a/solo/src/core/k8.mjs +++ /dev/null @@ -1,761 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import * as k8s from '@kubernetes/client-node' -import fs from 'fs' -import net from 'net' -import os from 'os' -import path from 'path' -import { flags } from '../commands/index.mjs' -import { FullstackTestingError, MissingArgumentError } from './errors.mjs' -import * as sb from 'stream-buffers' -import * as tar from 'tar' -import { v4 as uuid4 } from 'uuid' -import { V1ObjectMeta, V1Secret } from '@kubernetes/client-node' - -/** - * A kubernetes API wrapper class providing custom functionalities required by solo - * - * Note: Take care if the same instance is used for parallel execution, as the behaviour may be unpredictable. - * For parallel execution, create separate instances by invoking clone() - */ -export class K8 { - constructor (configManager, logger) { - if (!configManager) throw new MissingArgumentError('An instance of core/ConfigManager is required') - if (!logger) throw new MissingArgumentError('An instance of core/Logger is required') - - this.configManager = configManager - this.logger = logger - - this.init() - } - - /** - * Clone a new instance with the same config manager and logger - * Internally it instantiates a new kube API client - * - * @return {K8} - */ - clone () { - const c = new K8(this.configManager, this.logger) - return c.init() - } - - getKubeConfig () { - return this.kubeConfig - } - - init () { - this.kubeConfig = new k8s.KubeConfig() - this.kubeConfig.loadFromDefault() - - if (!this.kubeConfig.getCurrentCluster()) { - throw new FullstackTestingError('No active kubernetes cluster found. ' + - 'Please create a cluster and set current context.') - } - - if (!this.kubeConfig.getCurrentContext()) { - throw new FullstackTestingError('No active kubernetes context found. ' + - 'Please set current kubernetes context.') - } - - this.kubeClient = this.kubeConfig.makeApiClient(k8s.CoreV1Api) - - return this // to enable chaining - } - - /** - * Apply filters to metadata - * @param items list of items - * @param filters an object with metadata fields and value - * @return {*[]} - */ - applyMetadataFilter (items, filters = {}) { - if (!filters) throw new MissingArgumentError('filters are required') - - const matched = [] - const filterMap = new Map(Object.entries(filters)) - for (const item of items) { - // match all filters - let foundMatch = true - for (const entry of filterMap.entries()) { - const field = entry[0] - const value = entry[1] - - if (item.metadata[field] !== value) { - foundMatch = false - break - } - } - - if (foundMatch) { - matched.push(item) - } - } - - return matched - } - - /** - * Filter a single item using metadata filter - * @param items list of items - * @param filters an object with metadata fields and value - * @return {*} - */ - filterItem (items, filters = {}) { - const filtered = this.applyMetadataFilter(items, filters) - if (filtered.length > 1) throw new FullstackTestingError('multiple items found with filters', { filters }) - if (filtered.length !== 1) throw new FullstackTestingError('item not found with filters', { filters }) - return filtered[0] - } - - /** - * Create a new namespace - * @param name name of the namespace - * @return {Promise} - */ - async createNamespace (name) { - const payload = { - metadata: { - name - } - } - - const resp = await this.kubeClient.createNamespace(payload) - return resp.response.statusCode === 201 - } - - /** - * Delete a namespace - * @param name name of the namespace - * @return {Promise} - */ - async deleteNamespace (name) { - const resp = await this.kubeClient.deleteNamespace(name) - return resp.response.statusCode === 200.0 - } - - /** - * Get a list of namespaces - * @return {Promise<[string]>} list of namespaces - */ - async getNamespaces () { - const resp = await this.kubeClient.listNamespace() - if (resp.body && resp.body.items) { - const namespaces = [] - resp.body.items.forEach(item => { - namespaces.push(item.metadata.name) - }) - - return namespaces - } - - throw new FullstackTestingError('incorrect response received from kubernetes API. Unable to list namespaces') - } - - /** - * Returns true if a namespace exists with the given name - * @param namespace namespace name - * @return {Promise} - */ - async hasNamespace (namespace) { - const namespaces = await this.getNamespaces() - return namespaces.includes(namespace) - } - - /** - * Get a podName by name - * @param name podName name - * @return {Promise<{}>} k8s.V1Pod object - */ - async getPodByName (name) { - const ns = this._getNamespace() - const fieldSelector = `metadata.name=${name}` - const resp = await this.kubeClient.listNamespacedPod( - ns, - undefined, - undefined, - undefined, - fieldSelector - ) - - return this.filterItem(resp.body.items, { name }) - } - - /** - * Get host IP of a podName - * @param podNameName name of the podName - * @returns {Promise} podName IP - */ - async getPodIP (podNameName) { - const pod = await this.getPodByName(podNameName) - if (pod && pod.status && pod.status.podIP) { - this.logger.debug(`Found pod IP for ${podNameName}: ${pod.status.podIP}`) - return pod.status.podIP - } - - this.logger.debug(`Unable to find pod IP for ${podNameName}`) - throw new FullstackTestingError(`unable to find host IP of podName: ${podNameName}`) - } - - /** - * Get a svc by name - * @param name svc name - * @return {Promise<{}>} k8s.V1Service object - */ - async getSvcByName (name) { - const ns = this._getNamespace() - const fieldSelector = `metadata.name=${name}` - const resp = await this.kubeClient.listNamespacedService( - ns, - undefined, - undefined, - undefined, - fieldSelector - ) - - return this.filterItem(resp.body.items, { name }) - } - - /** - * Get cluster IP of a service - * @param svcName name of the service - * @returns {Promise} cluster IP - */ - async getClusterIP (svcName) { - const svc = await this.getSvcByName(svcName) - if (svc && svc.spec && svc.spec.clusterIP) { - return svc.spec.clusterIP - } - - throw new FullstackTestingError(`unable to find cluster IP for svc: ${svcName}`) - } - - /** - * Get a list of clusters - * @return {Promise<[string]>} list of clusters - */ - async getClusters () { - const clusters = [] - for (const cluster of this.kubeConfig.getClusters()) { - clusters.push(cluster.name) - } - - return clusters - } - - /** - * Get a list of contexts - * @return {Promise<[string]>} list of contexts - */ - async getContexts () { - const contexts = [] - for (const context of this.kubeConfig.getContexts()) { - contexts.push(context.name) - } - - return contexts - } - - /** - * List files and directories in a container - * - * It runs ls -la on the specified path and returns a list of object containing the entries. - * For example: - * [{ - * directory: false, - * owner: hedera, - * group: hedera, - * size: 121, - * modifiedAt: Jan 15 13:50 - * name: config.txt - * }] - * - * @param podName pod name - * @param containerName container name - * @param destPath path inside the container - * @param timeout timeout in ms - * @return {Promise<{}>} - */ - async listDir (podName, containerName, destPath, timeout = 5000) { - try { - const output = await this.execContainer(podName, containerName, ['ls', '-la', destPath]) - if (!output) return [] - - // parse the output and return the entries - const items = [] - const lines = output.split('\n') - for (let line of lines) { - line = line.replace(/\s+/g, '|') - const parts = line.split('|') - if (parts.length === 9) { - const name = parts[parts.length - 1] - if (name !== '.' && name !== '..') { - const permission = parts[0] - const item = { - directory: permission[0] === 'd', - owner: parts[2], - group: parts[3], - size: parts[4], - modifiedAt: `${parts[5]} ${parts[6]} ${parts[7]}`, - name - } - - items.push(item) - } - } - } - - return items - } catch (e) { - throw new FullstackTestingError(`unable to check path in '${podName}':${containerName}' - ${destPath}: ${e.message}`, e) - } - } - - /** - * Check if a filepath exists in the container - * @param podName pod name - * @param containerName container name - * @param destPath path inside the container - * @param filters an object with metadata fields and value - * @return {Promise} - */ - async hasFile (podName, containerName, destPath, filters = {}) { - const parentDir = path.dirname(destPath) - const fileName = path.basename(destPath) - const filterMap = new Map(Object.entries(filters)) - const entries = await this.listDir(podName, containerName, parentDir) - - for (const item of entries) { - if (item.name === fileName && !item.directory) { - let found = true - - for (const entry of filterMap.entries()) { - const field = entry[0] - const value = entry[1] - this.logger.debug(`Checking file ${podName}:${containerName} ${destPath}; ${field} expected ${value}, found ${item[field]}`, { filters }) - if (`${value}` !== `${item[field]}`) { - found = false - break - } - } - - if (found) { - this.logger.debug(`File check succeeded ${podName}:${containerName} ${destPath}`, { filters }) - return true - } - } - } - - return false - } - - /** - * Check if a directory path exists in the container - * @param podName pod name - * @param containerName container name - * @param destPath path inside the container - * @return {Promise} - */ - async hasDir (podName, containerName, destPath) { - return await this.execContainer( - podName, - containerName, - ['bash', '-c', '[[ -d "' + destPath + '" ]] && echo -n "true" || echo -n "false"'] - ) === 'true' - } - - /** - * Copy a file into a container - * - * It overwrites any existing file inside the container at the destination directory - * - * @param podName podName name - * @param containerName container name - * @param srcPath source file path in the local - * @param destDir destination directory in the container - * @returns {Promise<>} - */ - async copyTo (podName, containerName, srcPath, destDir) { - const namespace = this._getNamespace() - - if (!await this.hasDir(podName, containerName, destDir)) { - throw new FullstackTestingError(`invalid destination path: ${destDir}`) - } - - if (!fs.existsSync(srcPath)) { - throw new FullstackTestingError(`invalid source path: ${srcPath}`) - } - - try { - const srcFile = path.basename(srcPath) - const srcDir = path.dirname(srcPath) - const destPath = `${destDir}/${srcFile}` - - // zip the source file - const tmpFile = this._tempFileFor(srcFile) - await tar.c({ file: tmpFile, cwd: srcDir }, [srcFile]) - - const self = this - return new Promise((resolve, reject) => { - const execInstance = new k8s.Exec(this.kubeConfig) - const command = ['tar', 'xf', '-', '-C', destDir] - const readStream = fs.createReadStream(tmpFile) - const errStream = new sb.WritableStreamBuffer() - - execInstance.exec(namespace, podName, containerName, command, null, errStream, readStream, false, - async ({ status }) => { - if (status === 'Failure' || errStream.size()) { - self._deleteTempFile(tmpFile) - } - }).then(conn => { - conn.on('close', async (code, reason) => { - if (code !== 1000) { // code 1000 is the success code - return reject(new FullstackTestingError(`failed to copy because of error (${code}): ${reason}`)) - } - - return resolve(true) - }) - - conn.on('error', (e) => { - self._deleteTempFile(tmpFile) - return reject(new FullstackTestingError(`failed to copy file ${destPath} because of connection error: ${e.message}`, e)) - }) - }) - }) - } catch (e) { - throw new FullstackTestingError(`failed to copy file to ${podName}:${containerName} [${srcPath} -> ${destDir}]: ${e.message}`, e) - } - } - - /** - * Copy a file from a container - * - * It overwrites any existing file at the destination directory - * - * @param podName podName name - * @param containerName container name - * @param srcPath source file path in the container - * @param destDir destination directory in the local - * @returns {Promise} - */ - async copyFrom (podName, containerName, srcPath, destDir) { - const namespace = this._getNamespace() - - // get stat for source file in the container - const entries = await this.listDir(podName, containerName, srcPath) - if (entries.length !== 1) { - throw new FullstackTestingError(`invalid source path: ${srcPath}`) - } - const srcFileDesc = entries[0] // cache for later comparison after copy - - if (!fs.existsSync(destDir)) { - throw new FullstackTestingError(`invalid destination path: ${destDir}`) - } - - try { - const srcFileSize = Number.parseInt(srcFileDesc.size) - - const srcFile = path.basename(srcPath) - const srcDir = path.dirname(srcPath) - const destPath = `${destDir}/${srcFile}` - - // download the tar file to a temp location - const tmpFile = this._tempFileFor(srcFile) - - const self = this - return new Promise((resolve, reject) => { - const execInstance = new k8s.Exec(this.kubeConfig) - const command = ['tar', 'zcf', '-', '-C', srcDir, srcFile] - const writerStream = fs.createWriteStream(tmpFile) - const errStream = new sb.WritableStreamBuffer() - - execInstance.exec( - namespace, - podName, - containerName, - command, - writerStream, - errStream, - null, - false, - async ({ status }) => { - writerStream.close() - if (status === 'Failure' || errStream.size()) { - self._deleteTempFile(tmpFile) - } - }) - .then(conn => { - conn.on('close', async (code, reason) => { - if (code !== 1000) { // code 1000 is the success code - return reject(new FullstackTestingError(`failed to copy because of error (${code}): ${reason}`)) - } - - // extract the downloaded file - await tar.x({ - file: tmpFile, - cwd: destDir - }) - - self._deleteTempFile(tmpFile) - - const stat = fs.statSync(destPath) - if (stat && stat.size === srcFileSize) { - return resolve(true) - } - - return reject(new FullstackTestingError(`failed to download file completely: ${destPath}`)) - }) - - conn.on('error', (e) => { - self._deleteTempFile(tmpFile) - return reject(new FullstackTestingError( - `failed to copy file ${destPath} because of connection error: ${e.message}`, e)) - }) - }) - }) - } catch (e) { - throw new FullstackTestingError( - `failed to download file from ${podName}:${containerName} [${srcPath} -> ${destDir}]: ${e.message}`, e) - } - } - - /** - * Invoke bash command within a container and return the console output as string - * - * @param podName pod name - * @param containerName container name - * @param command bash commands as an array to be run within the containerName (e.g 'ls -la /opt/hgcapp') - * @param timeoutMs timout in milliseconds - * @returns {Promise} console output as string - */ - async execContainer (podName, containerName, command, timeoutMs = 1000) { - const ns = this._getNamespace() - if (timeoutMs < 0 || timeoutMs === 0) throw new MissingArgumentError('timeout cannot be negative or zero') - if (!command) throw new MissingArgumentError('command cannot be empty') - if (!Array.isArray(command)) { - command = command.split(' ') - } - - const self = this - return new Promise((resolve, reject) => { - const execInstance = new k8s.Exec(this.kubeConfig) - const outStream = new sb.WritableStreamBuffer() - const errStream = new sb.WritableStreamBuffer() - - self.logger.debug(`Running exec ${podName} -c ${containerName} -- ${command.join(' ')}`) - execInstance.exec( - ns, - podName, - containerName, - command, - outStream, - errStream, - null, - false, - ({ status }) => { - if (status === 'Failure' || errStream.size()) { - reject(new FullstackTestingError(`Exec error: - [exec ${podName} -c ${containerName} -- ${command.join(' ')}'] - error details: - ${errStream.getContentsAsString()}`)) - return - } - - const output = outStream.getContentsAsString() - self.logger.debug(`Finished exec ${podName} -c ${containerName} -- ${command.join(' ')}`, { output }) - - resolve(output) - } - ) - }) - } - - /** - * Port forward a port from a pod to localhost - * - * This simple server just forwards traffic from itself to a service running in kubernetes - * -> localhost:localPort -> port-forward-tunnel -> kubernetes-pod:targetPort - * - * @param podName pod name - * @param localPort local port - * @param podPort port of the pod - */ - async portForward (podName, localPort, podPort) { - const ns = this._getNamespace() - const forwarder = new k8s.PortForward(this.kubeConfig, true) - const server = net.createServer((socket) => { - forwarder.portForward(ns, podName, [podPort], socket, null, socket) - }) - - return server.listen(localPort, '127.0.0.1') - } - - /** - * Wait for pod - * @param status phase of the pod - * @param labels pod labels - * @param podCount number of pod expected - * @param maxAttempts maximum attempts to check - * @param delay delay between checks in milliseconds - * @return {Promise} - */ - async waitForPod (status = 'Running', labels = [], podCount = 1, maxAttempts = 10, delay = 500) { - const ns = this._getNamespace() - const fieldSelector = `status.phase=${status}` - const labelSelector = labels.join(',') - - this.logger.debug(`WaitForPod [${fieldSelector}, ${labelSelector}], maxAttempts: ${maxAttempts}`) - - return new Promise((resolve, reject) => { - let attempts = 0 - - const check = async () => { - this.logger.debug(`Checking for pod ${fieldSelector}, ${labelSelector} [attempt: ${attempts}/${maxAttempts}]`) - - // wait for the pod to be available with the given status and labels - const resp = await this.kubeClient.listNamespacedPod( - ns, - false, - false, - undefined, - fieldSelector, - labelSelector, - podCount - ) - - if (resp.body && resp.body.items && resp.body.items.length === podCount) { - this.logger.debug(`Found ${resp.body.items.length}/${podCount} pod with ${fieldSelector}, ${labelSelector} [attempt: ${attempts}/${maxAttempts}]`) - return resolve(true) - } - - if (attempts++ < maxAttempts) { - setTimeout(check, delay) - } else { - reject(new FullstackTestingError(`Expected number of pod (${podCount}) not found ${fieldSelector} ${labelSelector} [maxAttempts = ${maxAttempts}]`)) - } - } - - check() - }) - } - - /** - * Get a list of persistent volume claim names for the given namespace - * @param namespace the namespace of the persistent volume claims to return - * @returns {Promise<*[]>} list of persistent volume claims - */ - async listPvcsByNamespace (namespace) { - const pvcs = [] - const resp = await this.kubeClient.listNamespacedPersistentVolumeClaim( - namespace - ) - - for (const item of resp.body.items) { - pvcs.push(item.metadata.name) - } - - return pvcs - } - - /** - * Delete a persistent volume claim - * @param name the name of the persistent volume claim to delete - * @param namespace the namespace of the persistent volume claim to delete - * @returns {Promise} true if the persistent volume claim was deleted - */ - async deletePvc (name, namespace) { - const resp = await this.kubeClient.deleteNamespacedPersistentVolumeClaim( - name, - namespace - ) - - return resp.response.statusCode === 200.0 - } - - /** - * retrieve the secret of the given namespace and label selector, if there is more than one, it returns the first - * @param namespace the namespace of the secret to search for - * @param labelSelector the label selector used to fetch the Kubernetes secret - * @returns {Promise} a - * custom secret object with the relevant attributes - */ - async getSecret (namespace, labelSelector) { - const result = await this.kubeClient.listNamespacedSecret( - namespace, null, null, null, null, labelSelector) - if (result.response.statusCode === 200 && result.body.items && result.body.items.length > 0) { - const secretObject = result.body.items[0] - return { - name: secretObject.metadata.name, - labels: secretObject.metadata.labels, - namespace: secretObject.metadata.namespace, - type: secretObject.type, - data: secretObject.data - } - } else { - return null - } - } - - /** - * creates a new Kubernetes secret with the provided attributes - * @param name the name of the new secret - * @param namespace the namespace to store the secret - * @param secretType the secret type - * @param data the secret - * @param labels the label to use for future label selector queries - * @param recreate if we should first run delete in the case that there the secret exists from a previous install - * @returns {Promise} whether the secret was created successfully - */ - async createSecret (name, namespace, secretType, data, labels, recreate) { - if (recreate) { - try { - await this.kubeClient.deleteNamespacedSecret(name, namespace) - } catch (e) { - // do nothing - } - } - - const v1Secret = new V1Secret() - v1Secret.apiVersion = 'v1' - v1Secret.kind = 'Secret' - v1Secret.type = secretType - v1Secret.data = data - v1Secret.metadata = new V1ObjectMeta() - v1Secret.metadata.name = name - v1Secret.metadata.labels = labels - - const resp = await this.kubeClient.createNamespacedSecret(namespace, v1Secret) - - return resp.response.statusCode === 201 - } - - _getNamespace () { - const ns = this.configManager.getFlag(flags.namespace) - if (!ns) throw new MissingArgumentError('namespace is not set') - return ns - } - - _tempFileFor (fileName) { - const tmpFile = `${fileName}-${uuid4()}` - return path.join(os.tmpdir(), tmpFile) - } - - _deleteTempFile (tmpFile) { - if (fs.existsSync(tmpFile)) { - fs.rmSync(tmpFile) - } - } -} diff --git a/solo/src/core/key_manager.mjs b/solo/src/core/key_manager.mjs deleted file mode 100644 index 88c66d409..000000000 --- a/solo/src/core/key_manager.mjs +++ /dev/null @@ -1,496 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import * as x509 from '@peculiar/x509' -import crypto from 'crypto' -import fs from 'fs' -import path from 'path' -import { FullstackTestingError, MissingArgumentError } from './errors.mjs' -import { constants } from './index.mjs' -import { Logger } from './logging.mjs' -import { Templates } from './templates.mjs' - -x509.cryptoProvider.set(crypto) - -export class KeyManager { - static CertificateExpiryYears = 10 - - static SigningKeyAlgo = { - name: 'RSASSA-PKCS1-v1_5', - hash: 'SHA-384', - publicExponent: new Uint8Array([1, 0, 1]), - modulusLength: 3072 - } - - static SigningKeyUsage = ['sign', 'verify'] - - static TLSKeyAlgo = { - name: 'RSASSA-PKCS1-v1_5', - hash: 'SHA-384', - publicExponent: new Uint8Array([1, 0, 1]), - modulusLength: 4096 - } - - static TLSKeyUsage = ['sign', 'verify'] - static TLSCertKeyUsages = - x509.KeyUsageFlags.digitalSignature | - x509.KeyUsageFlags.keyEncipherment | - x509.KeyUsageFlags.dataEncipherment - - static TLSCertKeyExtendedUsages = [ - x509.ExtendedKeyUsage.serverAuth, - x509.ExtendedKeyUsage.clientAuth - ] - - static ECKeyAlgo = { - name: 'ECDSA', - namedCurve: 'P-384', - hash: 'SHA-384' - } - - constructor (logger) { - if (!logger || !(logger instanceof Logger)) throw new MissingArgumentError('An instance of core/Logger is required') - this.logger = logger - } - - /** - * Convert CryptoKey into PEM string - * @param privateKey - * @returns {Promise} - */ - async convertPrivateKeyToPem (privateKey) { - const ab = await crypto.subtle.exportKey('pkcs8', privateKey) - return x509.PemConverter.encode(ab, 'PRIVATE KEY') - } - - /** - * Convert PEM private key into CryptoKey - * @param pemStr PEM string - * @param algo key algorithm - * @param keyUsages key usages - * @returns {Promise} - */ - async convertPemToPrivateKey (pemStr, algo, keyUsages = ['sign']) { - if (!algo) throw new MissingArgumentError('algo is required') - - const items = x509.PemConverter.decode(pemStr) - - // Since pem file may include multiple PEM data, the decoder returns an array - // However for private key there should be a single item. - // So, we just being careful here to pick the last item (similar to how last PEM data represents the actual cert in - // a certificate bundle) - const lastItem = items[items.length - 1] - - return await crypto.subtle.importKey('pkcs8', lastItem, algo, false, keyUsages) - } - - /** - * Return file names for node key - * @param nodeId node ID - * @param keyPrefix key prefix such as constants.PFX_AGREEMENT_KEY_PREFIX - * @param keysDir directory where keys and certs are stored - * @returns {{privateKeyFile: string, certificateFile: string}} - */ - prepareNodeKeyFilePaths (nodeId, keysDir, keyPrefix = constants.SIGNING_KEY_PREFIX) { - if (!nodeId) throw new MissingArgumentError('nodeId is required') - if (!keysDir) throw new MissingArgumentError('keysDir is required') - if (!keyPrefix) throw new MissingArgumentError('keyPrefix is required') - - const keyFile = path.join(keysDir, Templates.renderGossipPemPrivateKeyFile(keyPrefix, nodeId)) - const certFile = path.join(keysDir, Templates.renderGossipPemPublicKeyFile(keyPrefix, nodeId)) - - return { - privateKeyFile: keyFile, - certificateFile: certFile - } - } - - /** - * Return file names for TLS key - * @param nodeId node ID - * @param keysDir directory where keys and certs are stored - * @returns {{privateKeyFile: string, certificateFile: string}} - */ - prepareTLSKeyFilePaths (nodeId, keysDir) { - if (!nodeId) throw new MissingArgumentError('nodeId is required') - if (!keysDir) throw new MissingArgumentError('keysDir is required') - - const keyFile = path.join(keysDir, `hedera-${nodeId}.key`) - const certFile = path.join(keysDir, `hedera-${nodeId}.crt`) - - return { - privateKeyFile: keyFile, - certificateFile: certFile - } - } - - /** - * Store node keys and certs as PEM files - * @param nodeId node ID - * @param nodeKey an object containing privateKeyPem, certificatePem data - * @param keysDir directory where keys and certs are stored - * @param nodeKeyFiles an object {privateKeyFile: string, certificateFile: string} - * @param keyName optional key type name for logging - * @return {privateKeyFile: string, certificateFile: string} - */ - async storeNodeKey (nodeId, nodeKey, keysDir, nodeKeyFiles, keyName = '') { - if (!nodeId) { - throw new MissingArgumentError('nodeId is required') - } - - if (!nodeKey || !nodeKey.privateKey) { - throw new MissingArgumentError('nodeKey.privateKey is required') - } - - if (!nodeKey || !nodeKey.certificateChain) { - throw new MissingArgumentError('nodeKey.certificateChain is required') - } - - if (!keysDir) { - throw new MissingArgumentError('keysDir is required') - } - - if (!nodeKeyFiles || !nodeKeyFiles.privateKeyFile) { - throw new MissingArgumentError('nodeKeyFiles.privateKeyFile is required') - } - - if (!nodeKeyFiles || !nodeKeyFiles.certificateFile) { - throw new MissingArgumentError('nodeKeyFiles.certificateFile is required') - } - - const keyPem = await this.convertPrivateKeyToPem(nodeKey.privateKey) - const certPems = [] - nodeKey.certificateChain.forEach(cert => { - certPems.push(cert.toString('pem')) - }) - - const self = this - return new Promise((resolve, reject) => { - try { - this.logger.debug(`Storing ${keyName} key for node: ${nodeId}`, { nodeKeyFiles }) - - fs.writeFileSync(nodeKeyFiles.privateKeyFile, keyPem) - - // remove if the certificate file exists already as otherwise we'll keep appending to the last - if (fs.existsSync(nodeKeyFiles.certificateFile)) { - fs.rmSync(nodeKeyFiles.certificateFile) - } - - certPems.forEach(certPem => { - fs.writeFileSync(nodeKeyFiles.certificateFile, certPem + '\n', { flag: 'a' }) - }) - - self.logger.debug(`Stored ${keyName} key for node: ${nodeId}`, { nodeKeyFiles, cert: certPems[0] }) - - resolve(nodeKeyFiles) - } catch (e) { - reject(e) - } - }) - } - - /** - * Load node keys and certs from PEM files - * @param nodeId node ID - * @param keysDir directory where keys and certs are stored - * @param algo algorithm used for key - * @param nodeKeyFiles an object {privateKeyFile: string, certificateFile: string} - * @param keyName optional key type name for logging - * @return {privateKey: CryptoKey, certificate: x509.X509Certificate, certificateChain: x509.X509Certificates} - */ - async loadNodeKey (nodeId, keysDir, algo, nodeKeyFiles, keyName = '') { - if (!nodeId) { - throw new MissingArgumentError('nodeId is required') - } - - if (!keysDir) { - throw new MissingArgumentError('keysDir is required') - } - - if (!algo) { - throw new MissingArgumentError('algo is required') - } - - if (!nodeKeyFiles || !nodeKeyFiles.privateKeyFile) { - throw new MissingArgumentError('nodeKeyFiles.privateKeyFile is required') - } - - if (!nodeKeyFiles || !nodeKeyFiles.certificateFile) { - throw new MissingArgumentError('nodeKeyFiles.certificateFile is required') - } - - this.logger.debug(`Loading ${keyName}-keys for node: ${nodeId}`, { nodeKeyFiles }) - - const keyBytes = await fs.readFileSync(nodeKeyFiles.privateKeyFile) - const keyPem = keyBytes.toString() - const key = await this.convertPemToPrivateKey(keyPem, algo) - - const certBytes = await fs.readFileSync(nodeKeyFiles.certificateFile) - const certPems = x509.PemConverter.decode(certBytes.toString()) - - const certs = [] - certPems.forEach(certPem => { - const cert = new x509.X509Certificate(certPem) - certs.push(cert) - }) - - const certChain = await new x509.X509ChainBuilder({ certificates: certs.slice(1) }).build(certs[0]) - - this.logger.debug(`Loaded ${keyName}-key for node: ${nodeId}`, { nodeKeyFiles, cert: certs[0].toString('pem') }) - return { - privateKey: key, - certificate: certs[0], - certificateChain: certChain - } - } - - /** - * Generate signing key and certificate - * @param nodeId node ID - * @return {privateKey: CryptoKey, certificate: x509.X509Certificate, certificateChain: x509.X509Certificates} - */ - async generateSigningKey (nodeId) { - try { - const keyPrefix = constants.SIGNING_KEY_PREFIX - const curDate = new Date() - const friendlyName = Templates.renderNodeFriendlyName(keyPrefix, nodeId) - - this.logger.debug(`generating ${keyPrefix}-key for node: ${nodeId}`, { friendlyName }) - - const keypair = await crypto.subtle.generateKey( - KeyManager.SigningKeyAlgo, - true, - KeyManager.SigningKeyUsage) - - const cert = await x509.X509CertificateGenerator.createSelfSigned({ - serialNumber: '01', - name: `CN=${friendlyName}`, - notBefore: curDate, - notAfter: new Date().setFullYear(curDate.getFullYear() + KeyManager.CertificateExpiryYears), - keys: keypair, - extensions: [ - new x509.BasicConstraintsExtension(true, 1, true), - new x509.ExtendedKeyUsageExtension([x509.ExtendedKeyUsage.serverAuth, x509.ExtendedKeyUsage.clientAuth], true), - new x509.KeyUsagesExtension(x509.KeyUsageFlags.keyCertSign | x509.KeyUsageFlags.cRLSign, true), - await x509.SubjectKeyIdentifierExtension.create(keypair.publicKey) - ] - }) - - const certChain = await new x509.X509ChainBuilder().build(cert) - - this.logger.debug(`generated ${keyPrefix}-key for node: ${nodeId}`, { cert: cert.toString('pem') }) - - return { - privateKey: keypair.privateKey, - certificate: cert, - certificateChain: certChain - } - } catch (e) { - throw new FullstackTestingError(`failed to generate signing key: ${e.message}`, e) - } - } - - /** - * Store signing key and certificate - * @param nodeId node ID - * @param nodeKey an object containing privateKeyPem, certificatePem data - * @param keysDir directory where keys and certs are stored - * @return {privateKeyFile: string, certificateFile: string} - */ - async storeSigningKey (nodeId, nodeKey, keysDir) { - const nodeKeyFiles = this.prepareNodeKeyFilePaths(nodeId, keysDir, constants.SIGNING_KEY_PREFIX) - return this.storeNodeKey(nodeId, nodeKey, keysDir, nodeKeyFiles, 'signing') - } - - /** - * Load signing key and certificate - * @param nodeId node ID - * @param keysDir directory path where pem files are stored - * @return {privateKey: CryptoKey, certificate: x509.X509Certificate, certificateChain: x509.X509Certificates} - */ - async loadSigningKey (nodeId, keysDir) { - const nodeKeyFiles = this.prepareNodeKeyFilePaths(nodeId, keysDir, constants.SIGNING_KEY_PREFIX) - return this.loadNodeKey(nodeId, keysDir, KeyManager.SigningKeyAlgo, nodeKeyFiles, 'signing') - } - - /** - * Generate EC key and cert - * - * @param nodeId node ID - * @param keyPrefix key prefix such as constants.PFX_AGREEMENT_KEY_PREFIX - * @param signingKey signing key - * @return {privateKey: CryptoKey, certificate: x509.X509Certificate, certificateChain: x509.X509Certificates} - */ - async ecKey (nodeId, keyPrefix, signingKey) { - if (!nodeId) throw new MissingArgumentError('nodeId is required') - if (!keyPrefix) throw new MissingArgumentError('keyPrefix is required') - if (!signingKey) throw new MissingArgumentError('no signing key found') - - try { - const curDate = new Date() - const notAfter = new Date().setFullYear(curDate.getFullYear() + KeyManager.CertificateExpiryYears) - const friendlyName = Templates.renderNodeFriendlyName(keyPrefix, nodeId) - - this.logger.debug(`generating ${keyPrefix}-key for node: ${nodeId}`, { friendlyName }) - - const keypair = await crypto.subtle.generateKey(KeyManager.ECKeyAlgo, true, ['sign', 'verify']) - - const cert = await x509.X509CertificateGenerator.create({ - publicKey: keypair.publicKey, - signingKey: signingKey.privateKey, - subject: `CN=${friendlyName}`, - issuer: signingKey.certificate.subject, - serialNumber: '01', - notBefore: curDate, - notAfter, - extensions: [ - new x509.KeyUsagesExtension( - x509.KeyUsageFlags.digitalSignature | x509.KeyUsageFlags.keyEncipherment) - ] - }) - - if (!await cert.verify({ - date: new Date(notAfter), - publicKey: signingKey.certificate.publicKey, - signatureOnly: true - })) { - throw new FullstackTestingError(`failed to verify generated certificate for '${friendlyName}'`) - } - - const certChain = await new x509.X509ChainBuilder({ certificates: [signingKey.certificate] }).build(cert) - - this.logger.debug(`generated ${keyPrefix}-key for node: ${nodeId}`, { cert: cert.toString('pem') }) - return { - privateKey: keypair.privateKey, - certificate: cert, - certificateChain: certChain - } - } catch (e) { - throw new FullstackTestingError(`failed to generate ${keyPrefix}-key: ${e.message}`, e) - } - } - - /** - * Generate agreement key - * @param nodeId node ID - * @param signingKey signing key - * @return {privateKey: CryptoKey, certificate: x509.X509Certificate, certificateChain: x509.X509Certificates} - */ - async generateAgreementKey (nodeId, signingKey) { - return this.ecKey(nodeId, constants.AGREEMENT_KEY_PREFIX, signingKey) - } - - /** - * Store agreement key and certificate - * @param nodeId node ID - * @param nodeKey an object containing privateKeyPem, certificatePem data - * @param keysDir directory where keys and certs are stored - * @return {privateKeyFile: string, certificateFile: string} - */ - async storeAgreementKey (nodeId, nodeKey, keysDir) { - const nodeKeyFiles = this.prepareNodeKeyFilePaths(nodeId, keysDir, constants.AGREEMENT_KEY_PREFIX) - return this.storeNodeKey(nodeId, nodeKey, keysDir, nodeKeyFiles, 'agreement') - } - - /** - * Load agreement key and certificate - * @param nodeId node ID - * @param keysDir directory path where pem files are stored - * @return {privateKey: CryptoKey, certificate: x509.X509Certificate, certificateChain: x509.X509Certificates} - */ - async loadAgreementKey (nodeId, keysDir) { - const nodeKeyFiles = this.prepareNodeKeyFilePaths(nodeId, keysDir, constants.AGREEMENT_KEY_PREFIX) - return this.loadNodeKey(nodeId, keysDir, KeyManager.ECKeyAlgo, nodeKeyFiles, 'agreement') - } - - /** - * Generate gRPC TLS key - * - * It generates TLS keys in PEM format such as below: - * hedera-.key - * hedera-.crt - * - * @param nodeId - * @param distinguishedName distinguished name as: new x509.Name(`CN=${nodeId},ST=${state},L=${locality},O=${org},OU=${orgUnit},C=${country}`) - * @return {Promise} - */ - async generateGrpcTLSKey (nodeId, distinguishedName = new x509.Name(`CN=${nodeId}`)) { - if (!nodeId) throw new MissingArgumentError('nodeId is required') - if (!distinguishedName) throw new MissingArgumentError('distinguishedName is required') - - try { - const curDate = new Date() - - this.logger.debug(`generating gRPC TLS for node: ${nodeId}`, { distinguishedName }) - - const keypair = await crypto.subtle.generateKey( - KeyManager.TLSKeyAlgo, - true, - KeyManager.TLSKeyUsage) - - const cert = await x509.X509CertificateGenerator.createSelfSigned({ - serialNumber: '01', - name: distinguishedName, - notBefore: curDate, - notAfter: new Date().setFullYear(curDate.getFullYear() + KeyManager.CertificateExpiryYears), - keys: keypair, - extensions: - [ - new x509.BasicConstraintsExtension(false, 0, true), - new x509.KeyUsagesExtension(KeyManager.TLSCertKeyUsages, true), - new x509.ExtendedKeyUsageExtension(KeyManager.TLSCertKeyExtendedUsages, true), - await x509.SubjectKeyIdentifierExtension.create(keypair.publicKey, false), - await x509.AuthorityKeyIdentifierExtension.create(keypair.publicKey, false) - ] - }) - - const certChain = await new x509.X509ChainBuilder().build(cert) - - this.logger.debug(`generated gRPC TLS for node: ${nodeId}`, { cert: cert.toString('pem') }) - - return { - privateKey: keypair.privateKey, - certificate: cert, - certificateChain: certChain - } - } catch (e) { - throw new FullstackTestingError(`failed to generate gRPC TLS key: ${e.message}`, e) - } - } - - /** - * Store TLS key and certificate - * @param nodeId node ID - * @param nodeKey an object containing privateKeyPem, certificatePem data - * @param keysDir directory where keys and certs are stored - * @return {privateKeyFile: string, certificateFile: string} - */ - async storeTLSKey (nodeId, nodeKey, keysDir) { - const nodeKeyFiles = this.prepareTLSKeyFilePaths(nodeId, keysDir) - return this.storeNodeKey(nodeId, nodeKey, keysDir, nodeKeyFiles, 'gRPC TLS') - } - - /** - * Load TLS key and certificate - * @param nodeId node ID - * @param keysDir directory path where pem files are stored - * @return {privateKey: CryptoKey, certificate: x509.X509Certificate, certificateChain: x509.X509Certificates} - */ - async loadTLSKey (nodeId, keysDir) { - const nodeKeyFiles = this.prepareTLSKeyFilePaths(nodeId, keysDir) - return this.loadNodeKey(nodeId, keysDir, KeyManager.TLSKeyAlgo, nodeKeyFiles, 'gRPC TLS') - } -} diff --git a/solo/src/core/logging.mjs b/solo/src/core/logging.mjs deleted file mode 100644 index f0bbeb2cf..000000000 --- a/solo/src/core/logging.mjs +++ /dev/null @@ -1,186 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import * as winston from 'winston' -import { constants } from './index.mjs' -import { v4 as uuidv4 } from 'uuid' -import * as util from 'util' -import chalk from 'chalk' - -const customFormat = winston.format.combine( - winston.format.label({ label: 'SOLO', message: false }), - - winston.format.splat(), - - // include timestamp in logs - winston.format.timestamp(), - - winston.format.ms(), - - // add label metadata - winston.format.label({ label: '' }), - - // convert levels to upper case - winston.format(data => { - data.level = data.level.toUpperCase() - return data - })(), - - // use custom format TIMESTAMP [LABEL] LEVEL: MESSAGE - winston.format.printf(data => { - return `${data.timestamp}|${data.level}| ${data.message}` - }), - - // Ignore log messages if they have { private: true } - winston.format((data, opts) => { - if (data.private) { - return false - } - return data - })() -) - -export const Logger = class { - /** - * Create a new logger - * @param level logging level as supported by winston library: - * @constructor - */ - constructor (level = 'debug', devMode = false) { - this.nextTraceId() - this.devMode = devMode - - this.winstonLogger = winston.createLogger({ - level, - format: winston.format.combine( - customFormat, - winston.format.json() - ), - // format: winston.format.json(), - // defaultMeta: { service: 'user-service' }, - transports: [ - // - // - Write all logs with importance level of `error` or less to `error.log` - // - Write all logs with importance level of `info` or less to `solo.log` - // - new winston.transports.File({ filename: `${constants.SOLO_LOGS_DIR}/solo.log` }) - // new winston.transports.File({filename: constants.TMP_DIR + "/logs/error.log", level: 'error'}), - // new winston.transports.Console({format: customFormat}) - ] - }) - } - - setDevMode (devMode) { - this.debug(`dev mode logging: ${devMode}`) - this.devMode = devMode - } - - setLevel (level) { - this.winstonLogger.setLevel(level) - } - - nextTraceId () { - this.traceId = uuidv4() - } - - prepMeta (meta) { - if (meta === undefined) { - meta = {} - } - - meta.traceId = this.traceId - return meta - } - - showUser (msg, ...args) { - console.log(util.format(msg, ...args)) - } - - showUserError (err) { - const stack = [{ message: err.message, stacktrace: err.stack }] - if (err.cause) { - let depth = 0 - let cause = err.cause - while (cause !== undefined && depth < 10) { - if (cause.stack) { - stack.push({ message: cause.message, stacktrace: cause.stack }) - } - - cause = cause.cause - depth += 1 - } - } - - console.log(chalk.red('*********************************** ERROR *****************************************')) - if (this.devMode) { - let prefix = '' - let indent = '' - stack.forEach(s => { - console.log(indent + prefix + chalk.yellow(s.message)) - console.log(indent + chalk.gray(s.stacktrace) + '\n') - indent += ' ' - prefix += 'Caused by: ' - }) - } else { - const lines = err.message.split('\n') - lines.forEach(line => { - console.log(chalk.yellow(line)) - }) - } - console.log(chalk.red('***********************************************************************************')) - - this.error(err.message, { error: err.message, stacktrace: stack }) - } - - error (msg, ...args) { - this.winstonLogger.error(msg, ...args, this.prepMeta()) - } - - warn (msg, ...args) { - this.winstonLogger.warn(msg, ...args, this.prepMeta()) - } - - info (msg, ...args) { - this.winstonLogger.info(msg, ...args, this.prepMeta()) - } - - debug (msg, ...args) { - this.winstonLogger.debug(msg, ...args, this.prepMeta()) - } - - showList (title, items = []) { - this.showUser(chalk.green(`\n *** ${title} ***`)) - this.showUser(chalk.green('-------------------------------------------------------------------------------')) - if (items.length > 0) { - items.forEach(name => this.showUser(chalk.cyan(` - ${name}`))) - } else { - this.showUser(chalk.blue('[ None ]')) - } - - this.showUser('\n') - return true - } - - showJSON (title, obj) { - this.showUser(chalk.green(`\n *** ${title} ***`)) - this.showUser(chalk.green('-------------------------------------------------------------------------------')) - console.log(JSON.stringify(obj, null, ' ')) - } -} - -export function NewLogger (level = 'debug', devMode = false) { - return new Logger(level, devMode) -} diff --git a/solo/src/core/package_downloader.mjs b/solo/src/core/package_downloader.mjs deleted file mode 100644 index 6e8a13985..000000000 --- a/solo/src/core/package_downloader.mjs +++ /dev/null @@ -1,216 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import * as crypto from 'crypto' -import * as fs from 'fs' -import { pipeline as streamPipeline } from 'node:stream/promises' -import got from 'got' -import { DataValidationError, FullstackTestingError, IllegalArgumentError, ResourceNotFoundError } from './errors.mjs' -import * as https from 'https' -import { Templates } from './templates.mjs' -import { constants } from './index.mjs' - -export class PackageDownloader { - /** - * Create an instance of Downloader - * @param logger an instance of core/Logger - */ - constructor (logger) { - if (!logger) throw new IllegalArgumentError('an instance of core/Logger is required', logger) - this.logger = logger - } - - isValidURL (url) { - try { - // attempt to parse to check URL format - const out = new URL(url) - return out.href !== undefined - } catch (e) { - } - - return false - } - - async urlExists (url) { - const self = this - - return new Promise((resolve, reject) => { - try { - self.logger.debug(`Checking URL: ${url}`) - // attempt to send a HEAD request to check URL exists - const req = https.request(url, { method: 'HEAD', timeout: 100, headers: { Connection: 'close' } }) - - req.on('response', r => { - const statusCode = r.statusCode - self.logger.debug({ - response: { - connectOptions: r['connect-options'], - statusCode: r.statusCode, - headers: r.headers - } - - }) - - if (statusCode === 200) { - resolve(true) - return - } - - resolve(false) - }) - - req.on('error', err => { - self.logger.error(err) - resolve(false) - }) - - req.end() // make the request - } catch (e) { - self.logger.error(e) - resolve(false) - } - }) - } - - /** - * Fetch data from a URL and save the output to a file - * - * @param url source file URL - * @param destPath destination path for the downloaded file - */ - async fetchFile (url, destPath) { - if (!url) { - throw new IllegalArgumentError('package URL is required', url) - } - - if (!destPath) { - throw new IllegalArgumentError('destination path is required', destPath) - } - - if (!this.isValidURL(url)) { - throw new IllegalArgumentError(`package URL '${url}' is invalid`, url) - } - - if (!await this.urlExists(url)) { - throw new ResourceNotFoundError(`package URL '${url}' does not exist`, url) - } - - try { - await streamPipeline( - got.stream(url), - fs.createWriteStream(destPath) - ) - - return destPath - } catch (e) { - throw new ResourceNotFoundError(e.message, url, e) - } - } - - /** - * Compute hash of the file contents - * @param filePath path of the file - * @param algo hash algorithm - * @returns {Promise} returns hex digest of the computed hash - * @throws Error if the file cannot be read - */ - async computeFileHash (filePath, algo = 'sha384') { - const self = this - - return new Promise((resolve, reject) => { - try { - self.logger.debug(`Computing checksum for '${filePath}' using algo '${algo}'`) - const checksum = crypto.createHash(algo) - const s = fs.createReadStream(filePath) - s.on('data', function (d) { - checksum.update(d) - }) - s.on('end', function () { - const d = checksum.digest('hex') - self.logger.debug(`Computed checksum '${d}' for '${filePath}' using algo '${algo}'`) - resolve(d) - }) - } catch (e) { - reject(new FullstackTestingError('failed to compute checksum', e, { filePath, algo })) - } - }) - } - - /** - * Verifies that the checksum of the sourceFile matches with the contents of the checksumFile - * - * It throws error if the checksum doesn't match. - * - * @param sourceFile path to the file for which checksum to be computed - * @param checksum expected checksum - * @param algo hash algorithm to be used to compute checksum - * @throws DataValidationError if the checksum doesn't match - */ - async verifyChecksum (sourceFile, checksum, algo = 'sha384') { - const computed = await this.computeFileHash(sourceFile, algo) - if (checksum !== computed) throw new DataValidationError('checksum', checksum, computed) - } - - /** - * Fetch platform release artifact - * - * It fetches the build.zip file containing the release from a URL like: https://builds.hedera.com/node/software/v0.40/build-v0.40.4.zip - * - * @param tag full semantic version e.g. v0.40.4 - * @param destDir directory where the artifact needs to be saved - * @param force whether to download even if the file exists - * @returns {Promise} full path to the downloaded file - */ - async fetchPlatform (tag, destDir, force = false) { - const self = this - const releaseDir = Templates.prepareReleasePrefix(tag) - - if (!destDir) throw new Error('destination directory path is required') - - if (!fs.existsSync(destDir)) { - throw new IllegalArgumentError(`destDir (${destDir}) does not exist`, destDir) - } else if (!fs.statSync(destDir).isDirectory()) { - throw new IllegalArgumentError(`destDir (${destDir}) is not a directory`, destDir) - } - - const downloadDir = `${destDir}/${releaseDir}` - const packageURL = `${constants.HEDERA_BUILDS_URL}/node/software/${releaseDir}/build-${tag}.zip` - const packageFile = `${downloadDir}/build-${tag}.zip` - const checksumURL = `${constants.HEDERA_BUILDS_URL}/node/software/${releaseDir}/build-${tag}.sha384` - const checksumPath = `${downloadDir}/build-${tag}.sha384` - this.logger.debug(`Package URL: ${packageURL}`) - - try { - if (fs.existsSync(packageFile) && !force) { - return packageFile - } - - if (!fs.existsSync(downloadDir)) { - fs.mkdirSync(downloadDir, { recursive: true }) - } - - await this.fetchFile(packageURL, packageFile) - await this.fetchFile(checksumURL, checksumPath) - - const checksum = fs.readFileSync(checksumPath).toString().split(' ')[0] - await this.verifyChecksum(packageFile, checksum) - return packageFile - } catch (e) { - self.logger.error(e) - throw new FullstackTestingError(e.message, e, { tag, destDir }) - } - } -} diff --git a/solo/src/core/platform_installer.mjs b/solo/src/core/platform_installer.mjs deleted file mode 100644 index 712bd6671..000000000 --- a/solo/src/core/platform_installer.mjs +++ /dev/null @@ -1,424 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import * as fs from 'fs' -import * as os from 'os' -import { Listr } from 'listr2' -import * as path from 'path' -import { FullstackTestingError, IllegalArgumentError, MissingArgumentError } from './errors.mjs' -import { constants } from './index.mjs' -import { Templates } from './templates.mjs' -import * as helpers from './helpers.mjs' - -/** - * PlatformInstaller install platform code in the root-container of a network pod - */ -export class PlatformInstaller { - constructor (logger, k8) { - if (!logger) throw new MissingArgumentError('an instance of core/Logger is required') - if (!k8) throw new MissingArgumentError('an instance of core/K8 is required') - - this.logger = logger - this.k8 = k8 - } - - /** - * Setup directories - * @param podName - * @param containerName - * @return {Promise} - */ - async resetHapiDirectories (podName, containerName = constants.ROOT_CONTAINER) { - if (!podName) throw new MissingArgumentError('podName is required') - - try { - // reset data directory - // Note: we cannot delete the data/stats and data/saved as those are volume mounted - const reset_paths = [ - `${constants.HEDERA_HAPI_PATH}/data/apps`, - `${constants.HEDERA_HAPI_PATH}/data/config`, - `${constants.HEDERA_HAPI_PATH}/data/keys`, - `${constants.HEDERA_HAPI_PATH}/data/lib`, - `${constants.HEDERA_HAPI_PATH}/data/upgrade` - ] - - for (const p of reset_paths) { - await this.k8.execContainer(podName, containerName, `rm -rf ${p}`) - await this.k8.execContainer(podName, containerName, `mkdir ${p}`) - } - - await this.setPathPermission(podName, constants.HEDERA_SERVICES_PATH) - - return true - } catch (e) { - throw new FullstackTestingError(`failed to setup directories in pod '${podName}': ${e.message}`, e) - } - } - - async validatePlatformReleaseDir (releaseDir) { - if (!releaseDir) throw new MissingArgumentError('releaseDir is required') - if (!fs.existsSync(releaseDir)) { - throw new IllegalArgumentError('releaseDir does not exists', releaseDir) - } - - const dataDir = `${releaseDir}/data` - const appsDir = `${releaseDir}/${constants.HEDERA_DATA_APPS_DIR}` - const libDir = `${releaseDir}/${constants.HEDERA_DATA_LIB_DIR}` - - if (!fs.existsSync(dataDir)) { - throw new IllegalArgumentError('releaseDir does not have data directory', releaseDir) - } - - if (!fs.existsSync(appsDir)) { - throw new IllegalArgumentError(`'${constants.HEDERA_DATA_APPS_DIR}' missing in '${releaseDir}'`, releaseDir) - } - - if (!fs.existsSync(libDir)) { - throw new IllegalArgumentError(`'${constants.HEDERA_DATA_LIB_DIR}' missing in '${releaseDir}'`, releaseDir) - } - - if (!fs.statSync(appsDir).isEmpty()) { - throw new IllegalArgumentError(`'${constants.HEDERA_DATA_APPS_DIR}' is empty in releaseDir: ${releaseDir}`, releaseDir) - } - - if (!fs.statSync(libDir).isEmpty()) { - throw new IllegalArgumentError(`'${constants.HEDERA_DATA_LIB_DIR}' is empty in releaseDir: ${releaseDir}`, releaseDir) - } - } - - async copyPlatform (podName, buildZipSrc) { - if (!podName) throw new MissingArgumentError('podName is required') - if (!buildZipSrc) throw new MissingArgumentError('buildZipSrc is required') - if (!fs.statSync(buildZipSrc).isFile()) throw new IllegalArgumentError('buildZipFile does not exists', buildZipSrc) - - try { - await this.copyFiles(podName, [buildZipSrc], constants.HEDERA_USER_HOME_DIR) - return this.extractPlatform(podName, buildZipSrc) - } catch (e) { - throw new FullstackTestingError(`failed to copy platform code in to pod '${podName}': ${e.message}`, e) - } - } - - async extractPlatform (podName, buildZipSrc) { - if (!podName) throw new MissingArgumentError('podName is required') - if (!buildZipSrc) throw new MissingArgumentError('buildZipSrc is required') - - const buildZipFileName = path.basename(buildZipSrc) - const buildZip = path.join(constants.HEDERA_USER_HOME_DIR, buildZipFileName) // inside the container - const extractScriptName = 'extract-jar.sh' - const extractScriptSrc = path.join(constants.RESOURCES_DIR, extractScriptName) - const extractScript = path.join(constants.HEDERA_USER_HOME_DIR, extractScriptName) // inside the container - - this.logger.debug(`Extracting platform code in pod ${podName}`, { - extractScript, - buildZip, - dest: constants.HEDERA_HAPI_PATH - }) - - try { - await this.copyFiles(podName, [extractScriptSrc], constants.HEDERA_USER_HOME_DIR) - await this.k8.execContainer(podName, constants.ROOT_CONTAINER, `chmod +x ${extractScript}`) - await this.k8.execContainer(podName, constants.ROOT_CONTAINER, [extractScript, buildZip, constants.HEDERA_HAPI_PATH]) - - return true - } catch (e) { - throw new FullstackTestingError(`failed to extract platform code in this pod '${podName}': ${e.message}`, e) - } - } - - /** - * Copy a list of files to a directory in the container - * - * @param podName pod name - * @param srcFiles list of source files - * @param destDir destination directory - * @param container name of the container - * - * @return {Promise} list of pathso of the copied files insider the container - */ - async copyFiles (podName, srcFiles, destDir, container = constants.ROOT_CONTAINER) { - try { - const copiedFiles = [] - - // prepare the file mapping - for (const srcPath of srcFiles) { - if (!fs.existsSync(srcPath)) { - throw new FullstackTestingError(`file does not exist: ${srcPath}`) - } - - this.logger.debug(`Copying file into ${podName}: ${srcPath} -> ${destDir}`) - await this.k8.copyTo(podName, container, srcPath, destDir) - - const fileName = path.basename(srcPath) - copiedFiles.push(path.join(destDir, fileName)) - } - - return copiedFiles - } catch (e) { - throw new FullstackTestingError(`failed to copy files to pod '${podName}': ${e.message}`, e) - } - } - - async copyGossipKeys (podName, stagingDir, nodeIds, keyFormat = constants.KEY_FORMAT_PEM) { - const self = this - - if (!podName) throw new MissingArgumentError('podName is required') - if (!stagingDir) throw new MissingArgumentError('stagingDir is required') - if (!nodeIds || nodeIds.length <= 0) throw new MissingArgumentError('nodeIds cannot be empty') - - try { - const keysDir = `${constants.HEDERA_HAPI_PATH}/data/keys` - const nodeId = Templates.extractNodeIdFromPodName(podName) - const srcFiles = [] - - switch (keyFormat) { - case constants.KEY_FORMAT_PEM: - // copy private keys for the node - srcFiles.push(`${stagingDir}/keys/${Templates.renderGossipPemPrivateKeyFile(constants.SIGNING_KEY_PREFIX, nodeId)}`) - srcFiles.push(`${stagingDir}/keys/${Templates.renderGossipPemPrivateKeyFile(constants.AGREEMENT_KEY_PREFIX, nodeId)}`) - - // copy all public keys for all nodes - nodeIds.forEach(id => { - srcFiles.push(`${stagingDir}/keys/${Templates.renderGossipPemPublicKeyFile(constants.SIGNING_KEY_PREFIX, id)}`) - srcFiles.push(`${stagingDir}/keys/${Templates.renderGossipPemPublicKeyFile(constants.AGREEMENT_KEY_PREFIX, id)}`) - }) - break - case constants.KEY_FORMAT_PFX: - srcFiles.push(`${stagingDir}/keys/${Templates.renderGossipPfxPrivateKeyFile(nodeId)}`) - srcFiles.push(`${stagingDir}/keys/public.pfx`) - break - default: - throw new FullstackTestingError(`Unsupported key file format ${keyFormat}`) - } - - return await self.copyFiles(podName, srcFiles, keysDir) - } catch (e) { - throw new FullstackTestingError(`failed to copy gossip keys to pod '${podName}': ${e.message}`, e) - } - } - - async copyPlatformConfigFiles (podName, stagingDir) { - const self = this - - if (!podName) throw new MissingArgumentError('podName is required') - if (!stagingDir) throw new MissingArgumentError('stagingDir is required') - - try { - const srcFilesSet1 = [ - `${stagingDir}/config.txt`, - `${stagingDir}/templates/log4j2.xml`, - `${stagingDir}/templates/settings.txt` - ] - - const fileList1 = await self.copyFiles(podName, srcFilesSet1, constants.HEDERA_HAPI_PATH) - - const srcFilesSet2 = [ - `${stagingDir}/templates/api-permission.properties`, - `${stagingDir}/templates/application.properties`, - `${stagingDir}/templates/bootstrap.properties` - ] - - const fileList2 = await self.copyFiles(podName, srcFilesSet2, `${constants.HEDERA_HAPI_PATH}/data/config`) - - return fileList1.concat(fileList2) - } catch (e) { - throw new FullstackTestingError(`failed to copy config files to pod '${podName}': ${e.message}`, e) - } - } - - async copyTLSKeys (podName, stagingDir) { - if (!podName) throw new MissingArgumentError('podName is required') - if (!stagingDir) throw new MissingArgumentError('stagingDir is required') - - try { - const nodeId = Templates.extractNodeIdFromPodName(podName) - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), `${nodeId}-tls-keys-`)) - - // rename files appropriately in the tmp directory - fs.cpSync(`${stagingDir}/keys/${Templates.renderTLSPemPrivateKeyFile(nodeId)}`, - `${tmpDir}/hedera.key`) - fs.cpSync(`${stagingDir}/keys/${Templates.renderTLSPemPublicKeyFile(nodeId)}`, - `${tmpDir}/hedera.crt`) - - const srcFiles = [] - srcFiles.push(`${tmpDir}/hedera.key`) - srcFiles.push(`${tmpDir}/hedera.crt`) - - return this.copyFiles(podName, srcFiles, constants.HEDERA_HAPI_PATH) - } catch (e) { - throw new FullstackTestingError(`failed to copy TLS keys to pod '${podName}': ${e.message}`, e) - } - } - - async setPathPermission (podName, destPath, mode = '0755', recursive = true, container = constants.ROOT_CONTAINER) { - if (!podName) throw new MissingArgumentError('podName is required') - if (!destPath) throw new MissingArgumentError('destPath is required') - - try { - const recursiveFlag = recursive ? '-R' : '' - await this.k8.execContainer(podName, container, `chown ${recursiveFlag} hedera:hedera ${destPath}`) - await this.k8.execContainer(podName, container, `chmod ${recursiveFlag} ${mode} ${destPath}`) - return true - } catch (e) { - throw new FullstackTestingError(`failed to set permission in '${podName}': ${destPath}`, e) - } - } - - async setPlatformDirPermissions (podName) { - const self = this - if (!podName) throw new MissingArgumentError('podName is required') - - try { - const destPaths = [ - constants.HEDERA_HAPI_PATH - ] - - for (const destPath of destPaths) { - await self.setPathPermission(podName, destPath) - } - - return true - } catch (e) { - throw new FullstackTestingError(`failed to set permission in '${podName}'`, e) - } - } - - /** - * Prepares config.txt file for the node - * @param nodeIDs node IDs - * @param destPath path where config.txt should be written - * @param releaseTag release tag e.g. v0.42.0 - * @param template path to the confit.template file - * @param chainId chain ID (298 for local network) - * @returns {Promise} - */ - async prepareConfigTxt (nodeIDs, destPath, releaseTag, chainId = constants.HEDERA_CHAIN_ID, template = `${constants.RESOURCES_DIR}/templates/config.template`) { - const self = this - - if (!nodeIDs || nodeIDs.length === 0) throw new MissingArgumentError('list of node IDs is required') - if (!destPath) throw new MissingArgumentError('destPath is required') - if (!template) throw new MissingArgumentError('config templatePath is required') - if (!releaseTag) throw new MissingArgumentError('release tag is required') - - if (!fs.existsSync(path.dirname(destPath))) throw new IllegalArgumentError(`destPath does not exist: ${destPath}`, destPath) - if (!fs.existsSync(template)) throw new IllegalArgumentError(`config templatePath does not exist: ${template}`, destPath) - - // init variables - const startAccountId = constants.HEDERA_NODE_ACCOUNT_ID_START - const accountIdPrefix = `${startAccountId.realm}.${startAccountId.shard}` - const internalPort = constants.HEDERA_NODE_INTERNAL_GOSSIP_PORT - const externalPort = constants.HEDERA_NODE_EXTERNAL_GOSSIP_PORT - const appName = constants.HEDERA_APP_NAME - const nodeStakeAmount = constants.HEDERA_NODE_DEFAULT_STAKE_AMOUNT - - const releaseVersion = helpers.parseSemver(releaseTag) - - try { - const configLines = [] - configLines.push(`swirld, ${chainId}`) - configLines.push(`app, ${appName}`) - - let nodeSeq = 0 - let accountIdSeq = parseInt(startAccountId.num.toString(), 10) - for (const nodeId of nodeIDs) { - const podName = Templates.renderNetworkPodName(nodeId) - const svcName = Templates.renderNetworkSvcName(nodeId) - - const nodeName = nodeId - const nodeNickName = nodeId - - const internalIP = await self.k8.getPodIP(podName) - const externalIP = await self.k8.getClusterIP(svcName) - - const account = `${accountIdPrefix}.${accountIdSeq}` - if (releaseVersion.minor >= 40) { - configLines.push(`address, ${nodeSeq}, ${nodeNickName}, ${nodeName}, ${nodeStakeAmount}, ${internalIP}, ${internalPort}, ${externalIP}, ${externalPort}, ${account}`) - } else { - configLines.push(`address, ${nodeSeq}, ${nodeName}, ${nodeStakeAmount}, ${internalIP}, ${internalPort}, ${externalIP}, ${externalPort}, ${account}`) - } - - nodeSeq += 1 - accountIdSeq += 1 - } - - if (releaseVersion.minor >= 41) { - configLines.push(`nextNodeId, ${nodeSeq}`) - } - - fs.writeFileSync(destPath, configLines.join('\n')) - - return configLines - } catch (e) { - throw new FullstackTestingError('failed to generate config.txt', e) - } - } - - /** - * Return a list of task to perform node installation - * - * It assumes the staging directory has the following files and resources: - * ${staging}/keys/s-.key: signing key for a node - * ${staging}/keys/s-.crt: signing cert for a node - * ${staging}/keys/a-.key: agreement key for a node - * ${staging}/keys/a-.crt: agreement cert for a node - * ${staging}/keys/hedera-.key: gRPC TLS key for a node - * ${staging}/keys/hedera-.crt: gRPC TSL cert for a node - * ${staging}/properties: contains all properties files - * ${staging}/log4j2.xml: LOG4J file - * ${staging}/settings.txt: settings.txt file for the network - * ${staging}/config.txt: config.txt file for the network - * - * @param podName name of the pod - * @param buildZipFile path to the platform build.zip file - * @param stagingDir staging directory path - * @param nodeIds list of node ids - * @param keyFormat key format (pfx or pem) - * @param force force flag - * @returns {Listr} - */ - taskInstall (podName, buildZipFile, stagingDir, nodeIds, keyFormat = constants.KEY_FORMAT_PEM, force = false) { - const self = this - return new Listr([ - { - title: 'Copy Gossip keys', - task: (_, task) => - self.copyGossipKeys(podName, stagingDir, nodeIds, keyFormat) - }, - { - title: 'Copy TLS keys', - task: (_, task) => - self.copyTLSKeys(podName, stagingDir, keyFormat) - }, - { - title: 'Copy configuration files', - task: (_, task) => - self.copyPlatformConfigFiles(podName, stagingDir) - }, - { - title: 'Set file permissions', - task: (_, task) => - self.setPlatformDirPermissions(podName) - } - ], - { - concurrent: false, - rendererOptions: { - collapseSubtasks: false - } - } - ) - } -} diff --git a/solo/src/core/shell_runner.mjs b/solo/src/core/shell_runner.mjs deleted file mode 100644 index 8241c7421..000000000 --- a/solo/src/core/shell_runner.mjs +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { spawn } from 'child_process' -import chalk from 'chalk' - -export class ShellRunner { - constructor (logger) { - if (!logger) throw new Error('An instance of core/Logger is required') - this.logger = logger - } - - /** - * Returns a promise that invokes the shell command - * @param cmd shell command string - * @returns {Promise} console output as an array of strings - */ - async run (cmd, verbose = false) { - const self = this - const callStack = new Error().stack // capture the callstack to be included in error - self.logger.debug(`Executing command: '${cmd}'`) - - return new Promise((resolve, reject) => { - const child = spawn(cmd, { - shell: true - }) - - const output = [] - child.stdout.on('data', d => { - const items = d.toString().split(/\r?\n/) - items.forEach(item => { - if (item) { - output.push(item) - } - }) - }) - - const errOutput = [] - child.stderr.on('data', d => { - const items = d.toString().split(/\r?\n/) - items.forEach(item => { - if (item) { - errOutput.push(item.trim()) - } - }) - }) - - child.on('exit', (code, signal) => { - if (code) { - const err = new Error(`Command exit with error code ${code}: ${cmd}`) - - // include the callStack to the parent run() instead of from inside this handler. - // this is needed to ensure we capture the proper callstack for easier debugging. - err.stack = callStack - - if (verbose) { - errOutput.forEach(m => self.logger.showUser(chalk.red(m))) - } - - self.logger.error(`Error executing: '${cmd}'`, { - commandExitCode: code, - commandExitSignal: signal, - commandOutput: output, - errOutput, - error: { message: err.message, stack: err.stack } - }) - - reject(err) - } - - self.logger.debug(`Finished executing: '${cmd}'`, { - commandExitCode: code, - commandExitSignal: signal, - commandOutput: output, - errOutput - }) - resolve(output) - }) - }) - } -} diff --git a/solo/src/core/templates.mjs b/solo/src/core/templates.mjs deleted file mode 100644 index 2040067ab..000000000 --- a/solo/src/core/templates.mjs +++ /dev/null @@ -1,119 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import * as x509 from '@peculiar/x509' -import { DataValidationError, MissingArgumentError } from './errors.mjs' - -export class Templates { - static renderNetworkPodName (nodeId) { - return `network-${nodeId}-0` - } - - static renderNodeSvcName (nodeId) { - return `network-${nodeId}-svc` - } - - static renderNetworkSvcName (nodeId) { - return `network-${nodeId}-svc` - } - - /** - * Generate pfx node private key file name - * @param nodeId node ID - * @returns {string} - */ - static renderGossipPfxPrivateKeyFile (nodeId) { - return `private-${nodeId}.pfx` - } - - static renderGossipPemPrivateKeyFile (prefix, nodeId) { - // s-node0-key.pem - return `${prefix}-private-${nodeId}.pem` - } - - static renderGossipPemPublicKeyFile (prefix, nodeId) { - // s-node0-cert.pem - return `${prefix}-public-${nodeId}.pem` - } - - static renderTLSPemPrivateKeyFile (nodeId) { - return `hedera-${nodeId}.key` - } - - static renderTLSPemPublicKeyFile (nodeId) { - // s-node0-cert.pem - return `hedera-${nodeId}.crt` - } - - static renderNodeFriendlyName (prefix, nodeId, suffix = '') { - const parts = [prefix, nodeId] - if (suffix) parts.push(suffix) - return parts.join('-') - } - - static extractNodeIdFromPodName (podName) { - const parts = podName.split('-') - if (parts.length !== 3) throw new DataValidationError(`pod name is malformed : ${podName}`, 3, parts.length) - return parts[1].trim() - } - - static prepareReleasePrefix (tag) { - if (!tag) throw new MissingArgumentError('tag cannot be empty') - - const parsed = tag.split('.') - if (parsed.length < 3) throw new Error(`tag (${tag}) must include major, minor and patch fields (e.g. v0.40.4)`) - return `${parsed[0]}.${parsed[1]}` - } - - /** - * renders the name to be used to store the new account key as a Kubernetes secret - * @param accountId the account ID, string or AccountId type - * @returns {string} the name of the Kubernetes secret to store the account key - */ - static renderAccountKeySecretName (accountId) { - return `account-key-${accountId.toString()}` - } - - /** - * renders the label selector to be used to fetch the new account key from the Kubernetes secret - * @param accountId the account ID, string or AccountId type - * @returns {string} the label selector of the Kubernetes secret to retrieve the account key */ - static renderAccountKeySecretLabelSelector (accountId) { - return `fullstack.hedera.com/account-id=${accountId.toString()}` - } - - /** - * renders the label object to be used to store the new account key in the Kubernetes secret - * @param accountId the account ID, string or AccountId type - * @returns {{"fullstack.hedera.com/account-id": string}} the label object to be used to - * store the new account key in the Kubernetes secret - */ - static renderAccountKeySecretLabelObject (accountId) { - return { - 'fullstack.hedera.com/account-id': accountId.toString() - } - } - - static renderDistinguishedName (nodeId, - state = 'TX', - locality = 'Richardson', - org = 'Hedera', - orgUnit = 'Hedera', - country = 'US' - ) { - return new x509.Name(`CN=${nodeId},ST=${state},L=${locality},O=${org},OU=${orgUnit},C=${country}`) - } -} diff --git a/solo/src/core/zippy.mjs b/solo/src/core/zippy.mjs deleted file mode 100644 index b17e6792e..000000000 --- a/solo/src/core/zippy.mjs +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { FullstackTestingError, IllegalArgumentError, MissingArgumentError } from './errors.mjs' -import fs from 'fs' -import AdmZip from 'adm-zip' -import chalk from 'chalk' -import path from 'path' - -export class Zippy { - constructor (logger) { - if (!logger) throw new Error('An instance of core/Logger is required') - this.logger = logger - } - - /** - * Zip a file or directory - * @param srcPath path to a file or directory - * @param destPath path to the output zip file - * @returns {Promise} - */ - async zip (srcPath, destPath, verbose = false) { - if (!srcPath) throw new MissingArgumentError('srcPath is required') - if (!destPath) throw new MissingArgumentError('destPath is required') - if (!destPath.endsWith('.zip')) throw new MissingArgumentError('destPath must be a path to a zip file') - - try { - const zip = AdmZip('', {}) - - const stat = fs.statSync(srcPath) - if (stat.isDirectory()) { - zip.addLocalFolder(srcPath, '') - } else { - zip.addFile(path.basename(srcPath), fs.readFileSync(srcPath), '', stat) - } - - await zip.writeZipPromise(destPath, { overwrite: true }) - - return destPath - } catch (e) { - throw new FullstackTestingError(`failed to unzip ${srcPath}: ${e.message}`, e) - } - } - - async unzip (srcPath, destPath, verbose = false) { - const self = this - - if (!srcPath) throw new MissingArgumentError('srcPath is required') - if (!destPath) throw new MissingArgumentError('destPath is required') - - if (!fs.existsSync(srcPath)) throw new IllegalArgumentError('srcPath does not exists', srcPath) - - try { - const zip = AdmZip(srcPath, { readEntries: true }) - - zip.getEntries().forEach(function (zipEntry) { - if (verbose) { - self.logger.debug(`Extracting file: ${zipEntry.entryName} -> ${destPath}/${zipEntry.entryName} ...`, { - src: zipEntry.entryName, - dst: `${destPath}/${zipEntry.entryName}` - }) - } - - zip.extractEntryTo(zipEntry, destPath, true, true, true, zipEntry.entryName) - if (verbose) { - self.logger.showUser(chalk.green('OK'), `Extracted: ${zipEntry.entryName} -> ${destPath}/${zipEntry.entryName}`) - } - }) - - return destPath - } catch (e) { - throw new FullstackTestingError(`failed to unzip ${srcPath}: ${e.message}`, e) - } - } -} diff --git a/solo/src/index.mjs b/solo/src/index.mjs deleted file mode 100644 index 34f4a7b9a..000000000 --- a/solo/src/index.mjs +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import chalk from 'chalk' -import yargs from 'yargs' -import { hideBin } from 'yargs/helpers' -import { flags } from './commands/index.mjs' -import * as commands from './commands/index.mjs' -import { - ChartManager, - ConfigManager, - DependencyManager, - PackageDownloader, - PlatformInstaller, - Helm, - logging, - KeyManager -} from './core/index.mjs' -import 'dotenv/config' -import { K8 } from './core/k8.mjs' -import { AccountManager } from './core/account_manager.mjs' - -export function main (argv) { - const logger = logging.NewLogger('debug') - - try { - const helm = new Helm(logger) - const downloader = new PackageDownloader(logger) - const chartManager = new ChartManager(helm, logger) - const configManager = new ConfigManager(logger) - const depManager = new DependencyManager(logger) - const k8 = new K8(configManager, logger) - const platformInstaller = new PlatformInstaller(logger, k8) - const keyManager = new KeyManager(logger) - const accountManager = new AccountManager(logger, k8) - - // set cluster and namespace in the global configManager from kubernetes context - // so that we don't need to prompt the user - const kubeConfig = k8.getKubeConfig() - const context = kubeConfig.getContextObject(kubeConfig.getCurrentContext()) - const cluster = kubeConfig.getCurrentCluster() - - const opts = { - logger, - helm, - k8, - downloader, - platformInstaller, - chartManager, - configManager, - depManager, - keyManager, - accountManager - } - - const processArguments = (argv, yargs) => { - if (argv._[0] === 'init') { - configManager.reset() - } else { - configManager.load() - } - - // Set default cluster name and namespace from kubernetes context - // these will be overwritten if user has entered the flag values explicitly - configManager.setFlag(flags.clusterName, cluster.name) - if (context.namespace) { - configManager.setFlag(flags.namespace, context.namespace) - } - - // apply precedence for flags - argv = configManager.applyPrecedence(argv, yargs.parsed.aliases) - - // update and persist config - configManager.update(argv, true) - - logger.showUser(chalk.cyan('\n******************************* Solo *********************************************')) - logger.showUser(chalk.cyan('Version\t\t\t:'), chalk.yellow(configManager.getVersion())) - logger.showUser(chalk.cyan('Kubernetes Context\t:'), chalk.yellow(context.name)) - logger.showUser(chalk.cyan('Kubernetes Cluster\t:'), chalk.yellow(configManager.getFlag(flags.clusterName))) - logger.showUser(chalk.cyan('Kubernetes Namespace\t:'), chalk.yellow(configManager.getFlag(flags.namespace))) - logger.showUser(chalk.cyan('**********************************************************************************')) - - return argv - } - - return yargs(hideBin(argv)) - .usage('Usage:\n $0 [options]') - .alias('h', 'help') - .alias('v', 'version') - .command(commands.Initialize(opts)) - .strict() - .option(flags.devMode.name, flags.devMode.definition) - .wrap(120) - .demand(1, 'Select a command') - .middleware(processArguments, false) // applyBeforeValidate = false as otherwise middleware is called twice - .parse() - } catch (e) { - logger.showUserError(e) - } -} diff --git a/solo/test/data/.empty b/solo/test/data/.empty deleted file mode 100644 index e69de29bb..000000000 diff --git a/solo/test/data/s-private-node0.pem b/solo/test/data/s-private-node0.pem deleted file mode 100644 index 2521f85c7..000000000 --- a/solo/test/data/s-private-node0.pem +++ /dev/null @@ -1,40 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIG/AIBADANBgkqhkiG9w0BAQEFAASCBuYwggbiAgEAAoIBgQCaFyWCsQAszvOy -UzSHXiSMTFeHw6ZkuN19elmwVNerCp1F0oKLjl/WnZ1ZBulibGeCXPQioxawpe+m -O6u4dx1T0Cx2IcI35ENvlwYAW9jAV5T0etbkeqbCV4Al8+x+ObD1JRkomwjhKVxo -EXauWBmlZhWpUDlnJ2bI1Ol13V4xRVGTjvAq+lkfNNi3lpRhq//Jo1n5jbtvQ20e -jVQdQ72+QGIN6wlPUIcg3gnIVqiznr070auteiJKxi13L20DobaarXJM0QR8H1mb -4CW2nuAWHQ7czNUCOHDx6vpzfzn13YTw4ooWfJpOr6vgYjzuv7CWCvwzXfkw/GxR -d15sui9tkCdxROE/02rFSvU3LieDz/6NLR5zWpd5nvPcWpFbLfCi9PZ8063+0XE/ -M9TT3ODkiteGAVN6OCS5ScJDbe94jRlIk70jVfFpLrnmLK2VC0ok+0wpoS4U+5px -xqNvAzBn2d8lt3F8uKhicDYw0F/kvDUoLSRKRwqhwDaAexN3+TkCAwEAAQKCAYAB -TvYCFJewSbeXCY7WIW4FBPbvT7F/hHRZButxDF9ic+4e9CkonzZgH6mA4oajz9DX -MgveqWzdZiNRUYtlPxmwJwHhpOq9x8Hs1ib2ZNFD3NqGcu6VNRdqagzMBbS546qF -gmGizyI1q0C+H3vXAieBmIrRi71ZC2Qbi3dKCW2t1G1bZ+jRLJwKIExAztYGuEut -PiZa8KGpUbTBACk5MGSRk4Fhpd/H3SKwnEIQAfBfyhbIRcED8ZgN833aV7xAviRH -73W/Abw22/B60hJHKGnR0+J6gtlRbLbQ92WP7BlXyxQwuxTk5PYvDWYspbZ9ZKnQ -hwQOLBQf9Udt4CiQUZOpQ0ZFl4xscsmn4j//unOfRUhSyK9KHXzX62ll7eL4MGQP -WLYds7OsNYISGsgQsW5Uzq9mN277sxMdN2+UjvuaM1rlx1AWakziCHRaRCsGFZ/4 -P9WOs4QAMJ1Gr6J8j95JDlc3CQffbQYLywR0BQc2+jY2yLPbrD06UqKRG4wexgkC -gcEAxrbNI596ZZd1LMJiuqyTfRIyeifv0w1kl/CYYGJbbaukMqEuSv3ZXKc/3Gde -CxH5jZo9pAp0dXrzsFSJtnj0oP+exQcXL0EGjB91S3j6iF5Pg3/TUrmk1qsv3tuh -94ie5kzC9nY4A4KwxpQYFhV5cpvwn5fKUYdJdo4sRTZsGpDcASKIEXuST5M2VkU3 -eqlU8LggngYeKRJYM1iYjhXmhaY7lSWjmjxGw7LFIK869D9FrVVae/kVeNbiRLpD -x8clAoHBAMaDGN7owT8r9nw0BvYbtg+iEOAUEXM8awg6FRrb4n3hYd2kNHlywdvp -9Nl67C5cbRzCXAePLyb2098yurtAFsLvDTgrYaRe0lGYHi1Ic0NAMEW0nrZ3kLID -8zcY25Lcow0JDWIbgYXrfUG4RSX5iOquLKNTl9F9pnRkRqR7+1jx2AN+Jj6GvbXb -vTFcZwlLKXla8y1Et0YFkMTLzoaZorOuka5bkH4FBQLDxMTs0w27o88QiQAr9kgG -l0jPqDWHhQKBwAObsiHhdXF+zIvhg7VsCMmOmQgKzZoBdkAkCEBHyO023qZksth9 -v4KlLs2rutNsoiFmGZRu9Cpl7yLWhiGgFKEPwyxEsrES9zF4KMMUEUiEneD/YzDv -WgTj2tyrFEfQXUJFRoz/HIlDyD3y1nUgMrJYDoh3Ux8j27uhXUBseo4I71W98MaQ -fdmgDK6IVzeM95PfZAg6iDWqtZtJEowR7bujhxVwN4ZHbemDx3yOcf2ZYISDNj9m -CHPHQxiIYU6xWQKBwHjbf9zWoDCxt1NO6Z4UqPdDmDqUfTtHYXKUyhycGnzBJzAl -tLzsHRKikauGpxxisRt9SUJg7jgutjeBTyaJklID8GxuHPhRsoJytoyjO2mKPtlx -ad91U+bNeNnmjGgRZEOfa0J7tJOwF4ZXheHk1nLqr8qQLjIg6aKbGlcyFIjGVNlr -iCUxK3b43Wqb8y85T3rO4JaC64H6CXWHD6nrB5+VfKRGouXWcIKKZdXuyV/nCYgb -bQ1ptnuLZ7ewlZxhcQKBwGdjXGgNuLIb7lZouqB9zNFcTT3fTPfyFybkeUzgFZ+u -ogbsj7jt0gAAUuY+w1P4eutso+gsWcx3H4r0y5ikKKcoGebXHXZjUvXzW39gcxo3 -qY4MRESXS8shJrvsHBpOwqPENOSL4RiR4vNodnJdnxuf5k95EQkk6PmtemYxUbvS -tK/+5zGLWKflPWAxQdodRZYbY9XU1rlz8k5148s0AzLMsCbT2MFBRJ3F4/2fC7rj -qF46awRdlR5URKcdbZQ7dQ== ------END PRIVATE KEY----- diff --git a/solo/test/data/s-public-node0.pem b/solo/test/data/s-public-node0.pem deleted file mode 100644 index 264dd84a5..000000000 --- a/solo/test/data/s-public-node0.pem +++ /dev/null @@ -1,23 +0,0 @@ ------BEGIN CERTIFICATE----- -MIID1TCCAj2gAwIBAgIUIg/elSbgRpf1rdASIgXZrcFfsCYwDQYJKoZIhvcNAQEM -BQAwEjEQMA4GA1UEAwwHcy1ub2RlMDAgFw0yNDAxMzExMTU5MDNaGA8yMTI0MDEz -MTExNTkwM1owEjEQMA4GA1UEAwwHcy1ub2RlMDCCAaIwDQYJKoZIhvcNAQEBBQAD -ggGPADCCAYoCggGBAJoXJYKxACzO87JTNIdeJIxMV4fDpmS43X16WbBU16sKnUXS -gouOX9adnVkG6WJsZ4Jc9CKjFrCl76Y7q7h3HVPQLHYhwjfkQ2+XBgBb2MBXlPR6 -1uR6psJXgCXz7H45sPUlGSibCOEpXGgRdq5YGaVmFalQOWcnZsjU6XXdXjFFUZOO -8Cr6WR802LeWlGGr/8mjWfmNu29DbR6NVB1Dvb5AYg3rCU9QhyDeCchWqLOevTvR -q616IkrGLXcvbQOhtpqtckzRBHwfWZvgJbae4BYdDtzM1QI4cPHq+nN/OfXdhPDi -ihZ8mk6vq+BiPO6/sJYK/DNd+TD8bFF3Xmy6L22QJ3FE4T/TasVK9TcuJ4PP/o0t -HnNal3me89xakVst8KL09nzTrf7RcT8z1NPc4OSK14YBU3o4JLlJwkNt73iNGUiT -vSNV8WkuueYsrZULSiT7TCmhLhT7mnHGo28DMGfZ3yW3cXy4qGJwNjDQX+S8NSgt -JEpHCqHANoB7E3f5OQIDAQABoyEwHzAdBgNVHQ4EFgQUHLOUJ0xEvq/APhxN2adO -xvGx0oYwDQYJKoZIhvcNAQEMBQADggGBAEqFpZ9bTIYyUAaKlbgJTaPWmMenmOwx -R777HmPndxjcPa9bJM03DWNly/m4V0KPzExD+1EvZizjLggEOEhhveh3yzUd1x34 -SQIIrg6hNpIT8Gy7HkbliUptTfOAUnVp5jfpbkSJIzRH12OUhqsRIiZVf5mURayD -yJLSMRCLRddy3y79dyyjM2O/McLASmGboW7mgWN+eNll4YAZs8jNzMwCzsstAhrk -2T6fiQ17Prtft/yjPYgYN6vsXsi218KZ25aYjjrfm576DX+tAhEoSLl5zHJ3VvuO -etMOUg7t71ln5kHES2+mQ+cLjXtJA5wxG6HrCOeswCslInVqLfO0/jlNcj1SVF0z -ZFaxSlfeHIhutHBMOV0/IWEz5hTQSMdmecqT71x/xV29Otd58hVViYb7V8C1u6r6 -HtHXiw7QsErjRYkRkkxZhmZUOtaSc9gFxExEfQ+EVn+fltCSycGrk0WZjMj4bLIL -MHwrhrn4Mkm+bHkjPNAvnugfTT9kNAle8w== ------END CERTIFICATE----- diff --git a/solo/test/data/solo-test-1.config b/solo/test/data/solo-test-1.config deleted file mode 100644 index 454d1a211..000000000 --- a/solo/test/data/solo-test-1.config +++ /dev/null @@ -1,18 +0,0 @@ -{ - "flags": { - "dev": false, - "namespace": "solo-user", - "chart-dir": "", - "cluster-name": "kind-kind", - "prometheus-stack": false, - "minio": false, - "cert-manager": false, - "cert-manager-crds": false - }, - "version": "0.18.0", - "lastCommand": [ - "cluster", - "setup" - ], - "updatedAt": "2024-01-29T17:20:54.779Z" -} diff --git a/solo/test/data/solo-test-2.config b/solo/test/data/solo-test-2.config deleted file mode 100644 index 454d1a211..000000000 --- a/solo/test/data/solo-test-2.config +++ /dev/null @@ -1,18 +0,0 @@ -{ - "flags": { - "dev": false, - "namespace": "solo-user", - "chart-dir": "", - "cluster-name": "kind-kind", - "prometheus-stack": false, - "minio": false, - "cert-manager": false, - "cert-manager-crds": false - }, - "version": "0.18.0", - "lastCommand": [ - "cluster", - "setup" - ], - "updatedAt": "2024-01-29T17:20:54.779Z" -} diff --git a/solo/test/e2e/commands/01_node.test.mjs b/solo/test/e2e/commands/01_node.test.mjs deleted file mode 100644 index 84e0f6e5b..000000000 --- a/solo/test/e2e/commands/01_node.test.mjs +++ /dev/null @@ -1,228 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { - AccountBalanceQuery, - AccountCreateTransaction, - Hbar, - PrivateKey -} from '@hashgraph/sdk' -import { - afterAll, - afterEach, beforeAll, - describe, - expect, - it -} from '@jest/globals' -import path from 'path' -import { flags } from '../../../src/commands/index.mjs' -import { NodeCommand } from '../../../src/commands/node.mjs' -import { - ChartManager, - ConfigManager, - Helm, - K8, - PackageDownloader, - PlatformInstaller, - constants, - DependencyManager, - KeyManager -} from '../../../src/core/index.mjs' -import { ShellRunner } from '../../../src/core/shell_runner.mjs' -import { getTestCacheDir, testLogger } from '../../test_util.js' -import { AccountManager } from '../../../src/core/account_manager.mjs' -import { sleep } from '../../../src/core/helpers.mjs' - -class TestHelper { - static async getNodeClient (accountManager, argv) { - const operator = await accountManager.getAccountKeysFromSecret(constants.OPERATOR_ID, argv[flags.namespace.name]) - if (!operator) { - throw new Error(`account key not found for operator ${constants.OPERATOR_ID} during getNodeClient()\n` + - 'this implies that node start did not finish the accountManager.prepareAccounts successfully') - } - const serviceMap = await accountManager.getNodeServiceMap(argv[flags.namespace.name]) - return await accountManager.getNodeClient(argv[flags.namespace.name], serviceMap, operator.accountId, operator.privateKey) - } -} - -describe.each([ - ['v0.42.5', constants.KEY_FORMAT_PFX] - // ['v0.47.0-alpha.0', constants.KEY_FORMAT_PFX], - // ['v0.47.0-alpha.0', constants.KEY_FORMAT_PEM] -])('NodeCommand', (testRelease, testKeyFormat) => { - const helm = new Helm(testLogger) - const chartManager = new ChartManager(helm, testLogger) - const configManager = new ConfigManager(testLogger, path.join(getTestCacheDir(), 'solo.config')) - const packageDownloader = new PackageDownloader(testLogger) - const depManager = new DependencyManager(testLogger) - const k8 = new K8(configManager, testLogger) - const platformInstaller = new PlatformInstaller(testLogger, k8) - const keyManager = new KeyManager(testLogger) - const accountManager = new AccountManager(testLogger, k8, constants) - - const nodeCmd = new NodeCommand({ - logger: testLogger, - helm, - k8, - chartManager, - configManager, - downloader: packageDownloader, - platformInstaller, - depManager, - keyManager, - accountManager - }) - - const cacheDir = getTestCacheDir() - - describe(`node start should succeed [release ${testRelease}, keyFormat: ${testKeyFormat}]`, () => { - const argv = {} - argv[flags.releaseTag.name] = testRelease - argv[flags.keyFormat.name] = testKeyFormat - argv[flags.nodeIDs.name] = 'node0,node1,node2' - argv[flags.cacheDir.name] = cacheDir - argv[flags.force.name] = false - argv[flags.chainId.name] = constants.HEDERA_CHAIN_ID - argv[flags.generateGossipKeys.name] = false - argv[flags.generateTlsKeys.name] = true - argv[flags.applicationProperties.name] = flags.applicationProperties.definition.defaultValue - argv[flags.apiPermissionProperties.name] = flags.apiPermissionProperties.definition.defaultValue - argv[flags.bootstrapProperties.name] = flags.bootstrapProperties.definition.defaultValue - argv[flags.settingTxt.name] = flags.settingTxt.definition.defaultValue - argv[flags.log4j2Xml.name] = flags.log4j2Xml.definition.defaultValue - argv[flags.namespace.name] = 'solo-e2e' - argv[flags.clusterName.name] = 'kind-solo-e2e' - argv[flags.clusterSetupNamespace.name] = 'solo-e2e-cluster' - argv[flags.updateAccountKeys.name] = true - configManager.update(argv) - const nodeIds = argv[flags.nodeIDs.name].split(',') - - afterEach(() => { - sleep(5).then().catch() // give a few ticks so that connections can close - }) - - it('should pre-generate keys', async () => { - if (argv[flags.keyFormat.name] === constants.KEY_FORMAT_PFX) { - const shellRunner = new ShellRunner(testLogger) - await shellRunner.run(`test/scripts/gen-legacy-keys.sh ${nodeIds.join(',')} ${path.join(cacheDir, 'keys')}`) - } - }, 60000) - - it('node setup should succeed', async () => { - expect.assertions(1) - try { - await expect(nodeCmd.setup(argv)).resolves.toBeTruthy() - } catch (e) { - nodeCmd.logger.showUserError(e) - expect(e).toBeNull() - } - }, 60000) - - it('node start should succeed', async () => { - expect.assertions(1) - try { - await expect(nodeCmd.start(argv)).resolves.toBeTruthy() - } catch (e) { - nodeCmd.logger.showUserError(e) - expect(e).toBeNull() - } - }, 600000) - - describe('only genesis account should have genesis key for all special accounts', () => { - let client = null - const genesisKey = PrivateKey.fromStringED25519(constants.OPERATOR_KEY) - const realm = constants.HEDERA_NODE_ACCOUNT_ID_START.realm - const shard = constants.HEDERA_NODE_ACCOUNT_ID_START.shard - - beforeAll(async () => { - client = await TestHelper.getNodeClient(accountManager, argv) - }) - - afterAll(() => { - if (client) { - client.close() - } - accountManager.stopPortForwards().then().catch() - sleep(100).then().catch() - }) - - for (const [start, end] of constants.SYSTEM_ACCOUNTS) { - for (let i = start; i <= end; i++) { - it(`special account ${i} should not have genesis key`, async () => { - const accountId = `${realm}.${shard}.${i}` - nodeCmd.logger.info(`getAccountKeys: accountId ${accountId}`) - const keys = await accountManager.getAccountKeys(accountId, client) - expect(keys[0].toString()).not.toEqual(genesisKey.toString()) - }, 60000) - } - } - }) - - it('balance query should succeed', async () => { - expect.assertions(1) - let client = null - - try { - client = await TestHelper.getNodeClient(accountManager, argv) - - const balance = await new AccountBalanceQuery() - .setAccountId(client.getOperator().accountId) - .execute(client) - - expect(balance.hbars).not.toBeNull() - } catch (e) { - nodeCmd.logger.showUserError(e) - expect(e).toBeNull() - } finally { - if (client) { - client.close() - } - await accountManager.stopPortForwards() - await sleep(100) - } - }, 20000) - - it('account creation should succeed', async () => { - expect.assertions(1) - let client = null - - try { - client = await TestHelper.getNodeClient(accountManager, argv) - const accountKey = PrivateKey.generate() - - let transaction = await new AccountCreateTransaction() - .setNodeAccountIds([constants.HEDERA_NODE_ACCOUNT_ID_START]) - .setInitialBalance(new Hbar(0)) - .setKey(accountKey.publicKey) - .freezeWith(client) - - transaction = await transaction.sign(accountKey) - const response = await transaction.execute(client) - const receipt = await response.getReceipt(client) - - expect(receipt.accountId).not.toBeNull() - } catch (e) { - nodeCmd.logger.showUserError(e) - expect(e).toBeNull() - } finally { - if (client) { - client.close() - } - await accountManager.stopPortForwards() - } - }, 20000) - }) -}) diff --git a/solo/test/e2e/commands/02_account.test.mjs b/solo/test/e2e/commands/02_account.test.mjs deleted file mode 100644 index 916d89a7c..000000000 --- a/solo/test/e2e/commands/02_account.test.mjs +++ /dev/null @@ -1,210 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { - afterEach, - beforeAll, - beforeEach, - describe, - expect, - it -} from '@jest/globals' -import { - ChartManager, - ConfigManager, - constants, - DependencyManager, - Helm, - K8 -} from '../../../src/core/index.mjs' -import { getTestCacheDir, testLogger } from '../../test_util.js' -import path from 'path' -import { AccountManager } from '../../../src/core/account_manager.mjs' -import { AccountCommand } from '../../../src/commands/account.mjs' -import { flags } from '../../../src/commands/index.mjs' -import { sleep } from '../../../src/core/helpers.mjs' - -describe('account commands should work correctly', () => { - const defaultTimeout = 20000 - let accountCmd - let accountManager - let configManager - let k8 - let helm - let chartManager - let depManager - let argv = {} - let accountId1 - let accountId2 - - beforeAll(() => { - configManager = new ConfigManager(testLogger, path.join(getTestCacheDir('accountCmd'), 'solo.config')) - k8 = new K8(configManager, testLogger) - accountManager = new AccountManager(testLogger, k8, constants) - helm = new Helm(testLogger) - chartManager = new ChartManager(helm, testLogger) - depManager = new DependencyManager(testLogger) - accountCmd = new AccountCommand({ - logger: testLogger, - helm, - k8, - chartManager, - configManager, - depManager, - accountManager - }) - }) - - beforeEach(() => { - configManager.reset() - argv = {} - argv[flags.cacheDir.name] = getTestCacheDir('accountCmd') - argv[flags.namespace.name] = 'solo-e2e' - argv[flags.clusterName.name] = 'kind-solo-e2e' - argv[flags.clusterSetupNamespace.name] = 'solo-e2e-cluster' - configManager.update(argv, true) - }) - - afterEach(() => { - sleep(5).then().catch() // give a few ticks so that connections can close - }) - - it('account create with no options', async () => { - try { - await expect(accountCmd.create(argv)).resolves.toBeTruthy() - - const accountInfo = accountCmd.accountInfo - expect(accountInfo).not.toBeNull() - expect(accountInfo.accountId).not.toBeNull() - accountId1 = accountInfo.accountId - expect(accountInfo.privateKey).not.toBeNull() - expect(accountInfo.publicKey).not.toBeNull() - expect(accountInfo.balance).toEqual(flags.amount.definition.defaultValue) - } catch (e) { - testLogger.showUserError(e) - expect(e).toBeNull() - } finally { - await accountCmd.closeConnections() - } - }, defaultTimeout) - - it('account create with private key and hbar amount options', async () => { - try { - argv[flags.privateKey.name] = constants.GENESIS_KEY - argv[flags.amount.name] = 777 - configManager.update(argv, true) - - await expect(accountCmd.create(argv)).resolves.toBeTruthy() - - const accountInfo = accountCmd.accountInfo - expect(accountInfo).not.toBeNull() - expect(accountInfo.accountId).not.toBeNull() - accountId2 = accountInfo.accountId - expect(accountInfo.privateKey.toString()).toEqual(constants.GENESIS_KEY) - expect(accountInfo.publicKey).not.toBeNull() - expect(accountInfo.balance).toEqual(777) - } catch (e) { - testLogger.showUserError(e) - expect(e).toBeNull() - } finally { - await accountCmd.closeConnections() - } - }, defaultTimeout) - - it('account update with account', async () => { - try { - argv[flags.accountId.name] = accountId1 - configManager.update(argv, true) - - await expect(accountCmd.update(argv)).resolves.toBeTruthy() - - const accountInfo = accountCmd.accountInfo - expect(accountInfo).not.toBeNull() - expect(accountInfo.accountId).toEqual(argv[flags.accountId.name]) - expect(accountInfo.privateKey).toBeUndefined() - expect(accountInfo.publicKey).not.toBeNull() - expect(accountInfo.balance).toEqual(200) - } catch (e) { - testLogger.showUserError(e) - expect(e).toBeNull() - } finally { - await accountCmd.closeConnections() - } - }, defaultTimeout) - - it('account update with account, amount, new private key, and standard out options', async () => { - try { - argv[flags.accountId.name] = accountId2 - argv[flags.privateKey.name] = constants.GENESIS_KEY - argv[flags.amount.name] = 333 - configManager.update(argv, true) - - await expect(accountCmd.update(argv)).resolves.toBeTruthy() - - const accountInfo = accountCmd.accountInfo - expect(accountInfo).not.toBeNull() - expect(accountInfo.accountId).toEqual(argv[flags.accountId.name]) - expect(accountInfo.privateKey).toBeUndefined() - expect(accountInfo.publicKey).not.toBeNull() - expect(accountInfo.balance).toEqual(1110) - } catch (e) { - testLogger.showUserError(e) - expect(e).toBeNull() - } finally { - await accountCmd.closeConnections() - } - }, defaultTimeout) - - it('account get with account option', async () => { - try { - argv[flags.accountId.name] = accountId1 - configManager.update(argv, true) - - await expect(accountCmd.get(argv)).resolves.toBeTruthy() - const accountInfo = accountCmd.accountInfo - expect(accountInfo).not.toBeNull() - expect(accountInfo.accountId).toEqual(argv[flags.accountId.name]) - expect(accountInfo.privateKey).toBeUndefined() - expect(accountInfo.publicKey).toBeTruthy() - expect(accountInfo.balance).toEqual(200) - } catch (e) { - testLogger.showUserError(e) - expect(e).toBeNull() - } finally { - await accountCmd.closeConnections() - } - }, defaultTimeout) - - it('account get with account id option', async () => { - try { - argv[flags.accountId.name] = accountId2 - configManager.update(argv, true) - - await expect(accountCmd.get(argv)).resolves.toBeTruthy() - const accountInfo = accountCmd.accountInfo - expect(accountInfo).not.toBeNull() - expect(accountInfo.accountId).toEqual(argv[flags.accountId.name]) - expect(accountInfo.privateKey).toBeUndefined() - expect(accountInfo.publicKey).toBeTruthy() - expect(accountInfo.balance).toEqual(1110) - } catch (e) { - testLogger.showUserError(e) - expect(e).toBeNull() - } finally { - await accountCmd.closeConnections() - } - }, defaultTimeout) -}) diff --git a/solo/test/e2e/core/k8_e2e.test.mjs b/solo/test/e2e/core/k8_e2e.test.mjs deleted file mode 100644 index 2158ced04..000000000 --- a/solo/test/e2e/core/k8_e2e.test.mjs +++ /dev/null @@ -1,159 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { beforeAll, describe, expect, it } from '@jest/globals' -import fs from 'fs' -import net from 'net' -import os from 'os' -import path from 'path' -import { v4 as uuid4 } from 'uuid' -import { FullstackTestingError } from '../../../src/core/errors.mjs' -import { ConfigManager, constants, logging, PackageDownloader, Templates } from '../../../src/core/index.mjs' -import { K8 } from '../../../src/core/k8.mjs' - -describe('K8', () => { - const testLogger = logging.NewLogger('debug') - const configManager = new ConfigManager(testLogger) - const k8 = new K8(configManager, testLogger) - const downloader = new PackageDownloader(testLogger) - - beforeAll(() => { - configManager.load() - }) - - it('should be able to list clusters', async () => { - const clusters = await k8.getClusters() - expect(clusters).not.toHaveLength(0) - }) - - it('should be able to list namespaces', async () => { - const namespaces = await k8.getNamespaces() - expect(namespaces).not.toHaveLength(0) - expect(namespaces).toContain(constants.DEFAULT_NAMESPACE) - }) - - it('should be able to list contexts', async () => { - const contexts = await k8.getContexts() - expect(contexts).not.toHaveLength(0) - }) - - it('should be able to create and delete a namespaces', async () => { - const name = uuid4() - await expect(k8.createNamespace(name)).resolves.toBeTruthy() - await expect(k8.deleteNamespace(name)).resolves.toBeTruthy() - }) - - it('should be able to detect pod IP of a pod', async () => { - const podName = Templates.renderNetworkPodName('node0') - await expect(k8.getPodIP(podName)).resolves.not.toBeNull() - await expect(k8.getPodIP('INVALID')).rejects.toThrow(FullstackTestingError) - }) - - it('should be able to detect cluster IP', async () => { - const svcName = Templates.renderNetworkSvcName('node0') - await expect(k8.getClusterIP(svcName)).resolves.not.toBeNull() - await expect(k8.getClusterIP('INVALID')).rejects.toThrow(FullstackTestingError) - }) - - it('should be able to check if a path is directory inside a container', async () => { - const podName = Templates.renderNetworkPodName('node0') - await expect(k8.hasDir(podName, constants.ROOT_CONTAINER, constants.HEDERA_USER_HOME_DIR)).resolves.toBeTruthy() - }) - - it('should be able to copy a file to and from a container', async () => { - const podName = Templates.renderNetworkPodName('node0') - const containerName = constants.ROOT_CONTAINER - - // attempt fetch platform jar as we need to check if a big zip file can be uploaded/downloaded - const testCacheDir = 'test/data/tmp' - const tag = 'v0.42.5' - const releasePrefix = Templates.prepareReleasePrefix(tag) - const pkgPath = `${testCacheDir}/${releasePrefix}/build-${tag}.zip` - await expect(downloader.fetchPlatform(tag, testCacheDir)).resolves.toBe(pkgPath) - expect(fs.existsSync(pkgPath)).toBeTruthy() - - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'k8-')) - const destDir = constants.HEDERA_USER_HOME_DIR - const destPath = `${destDir}/build-${tag}.zip` - - // upload the file - await expect(k8.copyTo(podName, containerName, pkgPath, destDir)).resolves.toBeTruthy() - - // download the same file - await expect(k8.copyFrom(podName, containerName, destPath, tmpDir)).resolves.toBeTruthy() - - // rm file inside the container - await expect(k8.execContainer(podName, containerName, ['rm', '-f', destPath])).resolves - - fs.rmdirSync(tmpDir, { recursive: true }) - }, 120000) - - it('should be able to port forward gossip port', (done) => { - const podName = Templates.renderNetworkPodName('node0') - const localPort = constants.HEDERA_NODE_INTERNAL_GOSSIP_PORT - k8.portForward(podName, localPort, constants.HEDERA_NODE_INTERNAL_GOSSIP_PORT).then((server) => { - expect(server).not.toBeNull() - - // client - const client = new net.Socket() - client.on('ready', () => { - client.destroy() - server.close() - done() - }) - - client.on('error', (e) => { - client.destroy() - server.close() - done(new FullstackTestingError(`could not connect to local port '${localPort}': ${e.message}`, e)) - }) - - client.connect(localPort) - }) - }) - - it('should be able to run watch for pod', async () => { - const nodeId = 'node0' - const labels = [ - 'fullstack.hedera.com/type=network-node', - `fullstack.hedera.com/node-name=${nodeId}` - ] - - await expect(k8.waitForPod(constants.POD_STATUS_RUNNING, labels)).resolves.toBeTruthy() - }) - - it('should be able to cat a log file inside the container', async () => { - const podName = Templates.renderNetworkPodName('node0') - const containerName = constants.ROOT_CONTAINER - const testFileName = 'test.txt' - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'k8-')) - const tmpFile = path.join(tmpDir, testFileName) - const destDir = constants.HEDERA_USER_HOME_DIR - const destPath = `${destDir}/${testFileName}` - fs.writeFileSync(tmpFile, 'TEST\nNow current platform status = ACTIVE') - - await expect(k8.copyTo(podName, containerName, tmpFile, destDir)).resolves.toBeTruthy() - const output = await k8.execContainer(podName, containerName, ['tail', '-10', destPath]) - expect(output.indexOf('Now current platform status = ACTIVE')).toBeGreaterThan(0) - - fs.rmdirSync(tmpDir, { recursive: true }) - }) - - it('should be able to get two persistent volume claims', async () => { - const pvcs = await k8.listPvcsByNamespace(k8._getNamespace()) - expect(pvcs).toHaveLength(2) - }) -}) diff --git a/solo/test/e2e/core/package_downloader_e2e.test.mjs b/solo/test/e2e/core/package_downloader_e2e.test.mjs deleted file mode 100644 index 5f3c5bc43..000000000 --- a/solo/test/e2e/core/package_downloader_e2e.test.mjs +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { describe, expect, it } from '@jest/globals' -import * as fs from 'fs' -import { logging, PackageDownloader, Templates } from '../../../src/core/index.mjs' - -describe('PackageDownloaderE2E', () => { - const testLogger = logging.NewLogger('debug') - const downloader = new PackageDownloader(testLogger) - - it('should succeed with a valid Hedera release tag', async () => { - const testCacheDir = 'test/data/tmp' - - const tag = 'v0.42.5' - const releasePrefix = Templates.prepareReleasePrefix(tag) - - const destPath = `${testCacheDir}/${releasePrefix}/build-${tag}.zip` - await expect(downloader.fetchPlatform(tag, testCacheDir)).resolves.toBe(destPath) - expect(fs.existsSync(destPath)).toBeTruthy() - testLogger.showUser(destPath) - }, 200000) -}) diff --git a/solo/test/e2e/core/platform_installer_e2e.test.mjs b/solo/test/e2e/core/platform_installer_e2e.test.mjs deleted file mode 100644 index 6794c5330..000000000 --- a/solo/test/e2e/core/platform_installer_e2e.test.mjs +++ /dev/null @@ -1,213 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { beforeAll, describe, expect, it } from '@jest/globals' -import { - PackageDownloader, - PlatformInstaller, - constants, - Templates, - ConfigManager, Templates as Template -} from '../../../src/core/index.mjs' -import * as fs from 'fs' -import * as path from 'path' -import { K8 } from '../../../src/core/k8.mjs' -import { ShellRunner } from '../../../src/core/shell_runner.mjs' - -import { getTestCacheDir, getTmpDir, testLogger } from '../../test_util.js' - -describe('PackageInstallerE2E', () => { - const configManager = new ConfigManager(testLogger) - const k8 = new K8(configManager, testLogger) - const installer = new PlatformInstaller(testLogger, k8) - const downloader = new PackageDownloader(testLogger) - const testCacheDir = getTestCacheDir() - const podName = 'network-node0-0' - const packageVersion = 'v0.42.5' - let packageFile = '' - - beforeAll(async () => { - if (!fs.existsSync(testCacheDir)) { - fs.mkdirSync(testCacheDir) - } - - configManager.load() - }) - - describe('resetHapiDirectories', () => { - it('should succeed with valid pod', async () => { - expect.assertions(1) - try { - await expect(installer.resetHapiDirectories(podName)).resolves.toBeTruthy() - } catch (e) { - console.error(e) - expect(e).toBeNull() - } - }) - }) - - describe('copyPlatform', () => { - it('should succeed fetching platform release', async () => { - const releasePrefix = Templates.prepareReleasePrefix(packageVersion) - const destPath = `${testCacheDir}/${releasePrefix}/build-${packageVersion}.zip` - await expect(downloader.fetchPlatform(packageVersion, testCacheDir)).resolves.toBe(destPath) - expect(fs.existsSync(destPath)).toBeTruthy() - testLogger.showUser(destPath) - - // do not delete the cache dir - }, 200000) - - it('should succeed with valid tag and pod', async () => { - expect.assertions(1) - try { - packageFile = await downloader.fetchPlatform(packageVersion, testCacheDir) - await expect(installer.copyPlatform(podName, packageFile, true)).resolves.toBeTruthy() - const outputs = await k8.execContainer(podName, constants.ROOT_CONTAINER, `ls -la ${constants.HEDERA_HAPI_PATH}`) - testLogger.showUser(outputs) - } catch (e) { - console.error(e) - expect(e).toBeNull() - } - }, 20000) - }) - - describe('prepareConfigTxt', () => { - it('should succeed in generating config.txt', async () => { - const tmpDir = getTmpDir() - const configPath = `${tmpDir}/config.txt` - const nodeIDs = ['node0', 'node1', 'node2'] - const chainId = '299' - - const configLines = await installer.prepareConfigTxt(nodeIDs, configPath, packageVersion, chainId) - - // verify format is correct - expect(configLines.length).toBe(6) - expect(configLines[0]).toBe(`swirld, ${chainId}`) - expect(configLines[1]).toBe(`app, ${constants.HEDERA_APP_NAME}`) - expect(configLines[2]).toContain('address, 0, node0, node0, 1') - expect(configLines[3]).toContain('address, 1, node1, node1, 1') - expect(configLines[4]).toContain('address, 2, node2, node2, 1') - expect(configLines[5]).toBe('nextNodeId, 3') - - // verify the file exists - expect(fs.existsSync(configPath)).toBeTruthy() - const fileContents = fs.readFileSync(configPath).toString() - - // verify file content matches - expect(fileContents).toBe(configLines.join('\n')) - - fs.rmSync(tmpDir, { recursive: true }) - }) - }) - - describe('copyGossipKeys', () => { - it('should succeed to copy legacy pfx gossip keys for node0', async () => { - const podName = 'network-node0-0' - const nodeId = 'node0' - - // generate pfx keys - const tmpDir = getTmpDir() - const keysDir = path.join(tmpDir, 'keys') - const shellRunner = new ShellRunner(testLogger) - await shellRunner.run(`test/scripts/gen-legacy-keys.sh node0,node1 ${keysDir}`) - - await installer.resetHapiDirectories(podName) - const fileList = await installer.copyGossipKeys(podName, tmpDir, ['node0', 'node1'], constants.KEY_FORMAT_PFX) - - const destDir = `${constants.HEDERA_HAPI_PATH}/data/keys` - expect(fileList.length).toBe(2) - expect(fileList).toContain(`${destDir}/${Templates.renderGossipPfxPrivateKeyFile(nodeId)}`) - expect(fileList).toContain(`${destDir}/public.pfx`) - - fs.rmSync(tmpDir, { recursive: true }) - }, 60000) - - it('should succeed to copy pem gossip keys for node1', async () => { - const podName = 'network-node1-0' - - // generate pem keys - const tmpDir = getTmpDir() - const keysDir = path.join(tmpDir, 'keys') - const shellRunner = new ShellRunner(testLogger) - await shellRunner.run(`test/scripts/gen-standard-keys.sh node0,node1 ${keysDir}`) - - await installer.resetHapiDirectories(podName) - const fileList = await installer.copyGossipKeys(podName, tmpDir, ['node0', 'node1'], constants.KEY_FORMAT_PEM) - - const destDir = `${constants.HEDERA_HAPI_PATH}/data/keys` - expect(fileList.length).toBe(6) - expect(fileList).toContain(`${destDir}/${Templates.renderGossipPemPrivateKeyFile(constants.SIGNING_KEY_PREFIX, 'node1')}`) - expect(fileList).toContain(`${destDir}/${Templates.renderGossipPemPrivateKeyFile(constants.AGREEMENT_KEY_PREFIX, 'node1')}`) - - // public keys - expect(fileList).toContain(`${destDir}/${Templates.renderGossipPemPublicKeyFile(constants.SIGNING_KEY_PREFIX, 'node0')}`) - expect(fileList).toContain(`${destDir}/${Templates.renderGossipPemPublicKeyFile(constants.AGREEMENT_KEY_PREFIX, 'node0')}`) - expect(fileList).toContain(`${destDir}/${Templates.renderGossipPemPublicKeyFile(constants.AGREEMENT_KEY_PREFIX, 'node1')}`) - expect(fileList).toContain(`${destDir}/${Templates.renderGossipPemPublicKeyFile(constants.SIGNING_KEY_PREFIX, 'node1')}`) - - fs.rmSync(tmpDir, { recursive: true }) - }, 60000) - }) - - describe('copyTLSKeys', () => { - it('should succeed to copy TLS keys for node0', async () => { - const nodeId = 'node1' - const podName = Template.renderNetworkPodName(nodeId) - const tmpDir = getTmpDir() - const keysDir = path.join(tmpDir, 'keys') - - // create mock files - fs.mkdirSync(keysDir) - fs.writeFileSync(path.join(keysDir, `hedera-${nodeId}.key`), '') - fs.writeFileSync(path.join(keysDir, `hedera-${nodeId}.crt`), '') - - await installer.resetHapiDirectories(podName) - - const fileList = await installer.copyTLSKeys(podName, tmpDir) - - expect(fileList.length).toBe(2) // [data , hedera.crt, hedera.key] - expect(fileList.length).toBeGreaterThanOrEqual(2) - expect(fileList).toContain(`${constants.HEDERA_HAPI_PATH}/hedera.crt`) - expect(fileList).toContain(`${constants.HEDERA_HAPI_PATH}/hedera.key`) - - fs.rmSync(tmpDir, { recursive: true }) - }) - }) - - describe('copyPlatformConfigFiles', () => { - it('should succeed to copy platform config files for node0', async () => { - const podName = 'network-node0-0' - await installer.resetHapiDirectories(podName) - - const tmpDir = getTmpDir() - const nodeIDs = ['node0'] - const releaseTag = 'v0.42.0' - - fs.cpSync(`${constants.RESOURCES_DIR}/templates`, `${tmpDir}/templates`, { recursive: true }) - await installer.prepareConfigTxt(nodeIDs, `${tmpDir}/config.txt`, releaseTag, constants.HEDERA_CHAIN_ID, `${tmpDir}/templates/config.template`) - - const fileList = await installer.copyPlatformConfigFiles(podName, tmpDir) - expect(fileList.length).toBeGreaterThanOrEqual(6) - expect(fileList).toContain(`${constants.HEDERA_HAPI_PATH}/config.txt`) - expect(fileList).toContain(`${constants.HEDERA_HAPI_PATH}/log4j2.xml`) - expect(fileList).toContain(`${constants.HEDERA_HAPI_PATH}/settings.txt`) - expect(fileList).toContain(`${constants.HEDERA_HAPI_PATH}/data/config/api-permission.properties`) - expect(fileList).toContain(`${constants.HEDERA_HAPI_PATH}/data/config/application.properties`) - expect(fileList).toContain(`${constants.HEDERA_HAPI_PATH}/data/config/bootstrap.properties`) - fs.rmSync(tmpDir, { recursive: true }) - }, 10000) - }) -}) diff --git a/solo/test/e2e/jestCustomSequencer.cjs b/solo/test/e2e/jestCustomSequencer.cjs deleted file mode 100644 index 282666cc6..000000000 --- a/solo/test/e2e/jestCustomSequencer.cjs +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -const Sequencer = require('@jest/test-sequencer').default - -const isEndToEnd = (test) => { - const contextConfig = test.context.config - return contextConfig.displayName.name === 'end-to-end' -} - -class CustomSequencer extends Sequencer { - sort (tests) { - const copyTests = Array.from(tests) - const normalTests = copyTests.filter((t) => !isEndToEnd(t)) - const endToEndTests = copyTests.filter((t) => isEndToEnd(t)) - return super.sort(normalTests).concat(endToEndTests.sort((a, b) => (a.path > b.path ? 1 : -1))) - } -} - -module.exports = CustomSequencer diff --git a/solo/test/e2e/setup-e2e.sh b/solo/test/e2e/setup-e2e.sh deleted file mode 100755 index 71a42fb1e..000000000 --- a/solo/test/e2e/setup-e2e.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -SOLO_CLUSTER_NAME=solo-e2e -SOLO_NAMESPACE=solo-e2e -SOLO_CLUSTER_SETUP_NAMESPACE=solo-e2e-cluster -kind delete cluster -n "${SOLO_CLUSTER_NAME}" || true -kind create cluster -n "${SOLO_CLUSTER_NAME}" || exit 1 -kubectl create ns "${SOLO_NAMESPACE}" || exit 1 -kubectl create ns "${SOLO_CLUSTER_SETUP_NAMESPACE}" || exit 1 -solo init -d ../charts --namespace "${SOLO_NAMESPACE}" -i node0,node1,node2 -t v0.42.5 -s "${SOLO_CLUSTER_SETUP_NAMESPACE}" || exit 1 # cache args for subsequent commands -solo cluster setup || exit 1 -solo network deploy || exit 1 diff --git a/solo/test/scripts/README.md b/solo/test/scripts/README.md deleted file mode 100644 index 9ff2b6064..000000000 --- a/solo/test/scripts/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# Generate node gossip key using openssl - -There are two scripts to generate node gossip keys in `pkcs12` format (`*.pfx` files) as below: - -* `legacy-key-generate.sh`: It generates keys using `keytool` in legacy format where each nodes keys are combined in a single `pfx` file. -* `standard-key-generate.sh`: It generates keys using `openssl` where each private and public keys are separate `pfx` as well as `pem` files - -In order to generate keys in PEM format for 3 nodes (`node0,node1,node3`), you may run the script as below: - -``` -./standard-key-generate.sh node0,node1,node3 -``` - -Or, - -``` -./legacy-key-generate.sh node0,node1,node3 -``` - -## Useful commands for reference - -* Generate pkcs12 file using keytool - -``` -keytool -genkeypair -alias "s-node0" -keystore "private-node0.pfx" -storetype "pkcs12" -storepass "password" -dname "cn=s-node0" -keyalg "rsa" -sigalg "SHA384withRSA" -keysize "3072" -validity "36524" -``` - -* Inspect pkcs12 file using openssl - -``` -openssl pkcs12 -info -in private-node0.pfx -passin pass:password -passout pass:password -``` - -* extract private key from .pfx - -``` -openssl pkcs12 -in a-private-node0.pfx -nocerts -out a-test-key.pem -nodes -``` - -* Extract only client certificate from .pfx - -``` -openssl pkcs12 -in a-private-node0.pfx -clcerts -nokeys -out a-test-cert.pem -``` - -* Extract certificate chain from .pfx - -``` -openssl pkcs12 -in a-private-node0.pfx -nokeys -out a-test-cert.pem -``` diff --git a/solo/test/scripts/gen-legacy-keys.sh b/solo/test/scripts/gen-legacy-keys.sh deleted file mode 100755 index 980e3d847..000000000 --- a/solo/test/scripts/gen-legacy-keys.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright 2016-2022 Hedera Hashgraph, LLC -# -# This software is the confidential and proprietary information of -# Hedera Hashgraph, LLC. ("Confidential Information"). You shall not -# disclose such Confidential Information and shall use it only in -# accordance with the terms of the license agreement you entered into -# with Hedera Hashgraph. -# -# HEDERA HASHGRAPH MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF -# THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -# TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -# PARTICULAR PURPOSE, OR NON-INFRINGEMENT. HEDERA HASHGRAPH SHALL NOT BE LIABLE FOR -# ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR -# DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. -# - -keysDir="${HOME}/.solo/cache/keys" -ids="node0,node1,node2" -validity=36524 # number of days - -if [ "$#" -gt 0 ]; then - ids="${1}" -fi - -if [ "$#" -eq 2 ]; then - keysDir="${2}" -fi - -if [ "$#" -eq 3 ]; then - validity="${3}" -fi - -mkdir -p "${keysDir}" -cd "${keysDir}" - -IFS=',' read -ra names <<< "${ids}" -echo "KeyDir: ${keysDir}" -echo "Node Names: ${names[*]}" - -mkdir unused 2>/dev/null -mv ./*.pfx unused 2>/dev/null -rmdir unused 2>/dev/null - -for nm in "${names[@]}"; do - n="$(echo "${nm}" | tr '[A-Z]' '[a-z]')" - keytool -genkeypair -alias "s-$n" -keystore "private-$n.pfx" -storetype "pkcs12" -storepass "password" -dname "cn=s-$n" -keyalg "rsa" -sigalg "SHA384withRSA" -keysize "3072" -validity "${validity}" - keytool -genkeypair -alias "a-$n" -keystore "private-$n.pfx" -storetype "pkcs12" -storepass "password" -dname "cn=a-$n" -keyalg "ec" -sigalg "SHA384withECDSA" -groupname "secp384r1" -validity "${validity}" - keytool -genkeypair -alias "e-$n" -keystore "private-$n.pfx" -storetype "pkcs12" -storepass "password" -dname "cn=e-$n" -keyalg "ec" -sigalg "SHA384withECDSA" -groupname "secp384r1" -validity "${validity}" - - keytool -certreq -alias "a-$n" -keystore "private-$n.pfx" -storetype "pkcs12" -storepass "password" | - keytool -gencert -alias "s-$n" -keystore "private-$n.pfx" -storetype "pkcs12" -storepass "password" -validity "${validity}" | - keytool -importcert -alias "a-$n" -keystore "private-$n.pfx" -storetype "pkcs12" -storepass "password" - - keytool -certreq -alias "e-$n" -keystore "private-$n.pfx" -storetype "pkcs12" -storepass "password" | - keytool -gencert -alias "s-$n" -keystore "private-$n.pfx" -storetype "pkcs12" -storepass "password" -validity "${validity}" | - keytool -importcert -alias "e-$n" -keystore "private-$n.pfx" -storetype "pkcs12" -storepass "password" - - keytool -exportcert -alias "s-$n" -keystore "private-$n.pfx" -storetype "pkcs12" -storepass "password" | - keytool -importcert -alias "s-$n" -keystore "public.pfx" -storetype "pkcs12" -storepass "password" -noprompt - - keytool -exportcert -alias "a-$n" -keystore "private-$n.pfx" -storetype "pkcs12" -storepass "password" | - keytool -importcert -alias "a-$n" -keystore "public.pfx" -storetype "pkcs12" -storepass "password" -noprompt - - keytool -exportcert -alias "e-$n" -keystore "private-$n.pfx" -storetype "pkcs12" -storepass "password" | - keytool -importcert -alias "e-$n" -keystore "public.pfx" -storetype "pkcs12" -storepass "password" -noprompt - - echo "---------------------------------------------------------------------------------------------------------------" - echo "Generated private key of node '${n}': ${keysDir}/private-$n.pfx" - echo "---------------------------------------------------------------------------------------------------------------" - keytool -list -keystore "private-$n.pfx" -storetype "pkcs12" -storepass "password" - - # Generate node mTLS keys - openssl req -new -newkey rsa:3072 -out "hedera-${n}.csr" -keyout "hedera-${n}.key" -sha384 -nodes -subj "/CN=${n}" || exit 1 - openssl x509 -req -in "hedera-${n}.csr" -out "hedera-${n}.crt" -signkey "hedera-${n}.key" -days "${validity}" -sha384 || exit 1 - rm -f "hedera-${n}.csr" -done - -echo "---------------------------------------------------------------------------------------------------------------" -echo "Generated public keys: ${keysDir}/public.pfx" -echo "---------------------------------------------------------------------------------------------------------------" -keytool -list -keystore "public.pfx" -storetype "pkcs12" -storepass "password" -ls - diff --git a/solo/test/scripts/gen-standard-keys.sh b/solo/test/scripts/gen-standard-keys.sh deleted file mode 100755 index ef8b1dd49..000000000 --- a/solo/test/scripts/gen-standard-keys.sh +++ /dev/null @@ -1,184 +0,0 @@ -#!/bin/bash - -keysDir="${HOME}/.solo/cache/keys" -ids="node0,node1,node2" -validity=36524 # number of days -generate_pfx=false - -if [ "$#" -gt 0 ]; then - ids="${1}" -fi - -if [ "$#" -eq 2 ]; then - keysDir="${2}" -fi - -if [ "$#" -eq 3 ]; then - validity="${3}" -fi - -mkdir -p "${keysDir}" -cd "${keysDir}" - -IFS=',' read -ra names <<< "${ids}" -echo "KeyDir: ${keysDir}" -echo "Node Names: ${names[*]}" - -backup_dir="backup/$(date +"%Y-%m-%dT%H_%M_%S")" -dummy_password="password" -s_key_prefix="s" # signing key -a_key_prefix="a" # agreement key - -function backup() { - local pattern="${1}" - mkdir -p "${backup_dir}" - mv "${pattern}" "${backup_dir}" 2>/dev/null -} - -# make a backup of old *.pem files -backup "*.pem" -backup "*.pfx" - -# Generate RSA:3072 key to for signing -function generate_signing_key() { - local n="${1}" - local prefix="${2}" - - local s_key="${prefix}-private-${n}.pem" - local s_csr="${prefix}-csr-${n}.pem" - local s_cert="${prefix}-public-${n}.pem" - local s_key_pfx="${prefix}-private-${n}.pfx" - local s_cert_pfx="${prefix}-public-${n}.pfx" - local s_friendly_name="${prefix}-${n}" - - echo "------------------------------------------------------------------------------------" - echo "Generating RSA key and cert for node: ${n}" [ "${prefix}"-key ] - echo "friendly_name: ${s_friendly_name}" - echo "key_file: ${s_key}" - echo "csr_file: ${s_csr}" - echo "cert_file: ${s_cert}" - echo "key_pfx: ${s_key_pfx}" - echo "cert_pfx: ${s_cert_pfx}" - echo "------------------------------------------------------------------------------------" - - # Generate: s_key, s_csr - openssl req -new -newkey rsa:3072 -out "${s_csr}" -keyout "${s_key}" -sha384 -nodes -subj "/CN=${s_friendly_name}" || return 1 - - # Generate: self-signed s_cert - openssl x509 -req -in "${s_csr}" -out "${s_cert}" -signkey "${s_key}" -days "${validity}" -sha384 || return 1 - - # output s_cert - echo "------------------------------------------------------------------------------------" - echo "Generated: ${s_cert}" - echo "------------------------------------------------------------------------------------" - openssl x509 -in "${s_cert}" -text -noout - - if [[ "${generate_pfx}" == "true" ]]; then - generate_pfx_files "${s_key}" "${s_cert}" "${s_key_pfx}" "${s_cert_pfx}" "${friendly_name}" - fi - - # remove csr - rm "${s_csr}" - - return 0 -} - -# Generate keys signed by the s-key -function generate_signed_key() { - local n="${1}" - local prefix="${2}" - local s_key="${3}" - local s_cert="${4}" - - - local key_file="${prefix}-private-${n}.pem" - local csr_file="${prefix}-csr-${n}.pem" - local cert_file="${prefix}-public-${n}.pem" - local key_pfx="${prefix}-private-${n}.pfx" - local cert_pfx="${prefix}-public-${n}.pfx" - local friendly_name="${prefix}-${n}" - - echo "------------------------------------------------------------------------------------" - echo "Generating key and cert for node: ${n}" [ "${prefix}"-key ] - echo "friendly_name: ${friendly_name}" - echo "key_file: ${key_file}" - echo "csr_file: ${csr_file}" - echo "cert_file: ${cert_file}" - echo "key_pfx: ${key_pfx}" - echo "cert_pfx: ${cert_pfx}" - echo "s_key: ${s_key}" - echo "s_cert: ${s_cert}" - echo "------------------------------------------------------------------------------------" - - # generate key - openssl ecparam -genkey -name secp384r1 -noout -out "${key_file}" || return 1 - - # generate csr - openssl req -new -out "${csr_file}" -key "${key_file}" -subj "/CN=${friendly_name}" || return 1 - echo "------------------------------------------------------------------------------------" - echo "Generated: ${csr_file}" - echo "------------------------------------------------------------------------------------" - openssl req -text -in "${csr_file}" - - # generate cert and verify - openssl x509 -req -in "${csr_file}" -out "${cert_file}.tmp" -CA "${s_cert}" -CAkey "${s_key}" -days "${validity}" -sha384 || return 1 - cat "${s_cert}" "${cert_file}.tmp" > "${cert_file}" # combine cert chain - openssl verify -verbose -purpose sslserver -CAfile "${s_cert}" "${cert_file}" - rm "${cert_file}.tmp" # remove tmp file - - echo "------------------------------------------------------------------------------------" - echo "Generated: ${cert_file}" [ including certificate chain ] - echo "------------------------------------------------------------------------------------" - openssl storeutl -noout -text -certs "${cert_file}" - - if [[ "${generate_pfx}" == "true" ]]; then - generate_pfx_files "${key_file}" "${cert_file}" "${key_pfx}" "${cert_pfx}" "${friendly_name}" - fi - - # remove csr - rm "${csr_file}" - - return 0 -} - -function generate_pfx_files() { - let key_file="${1}" - let cert_file="${2}" - let key_pfx="${3}" - let cert_pfx="${4}" - let friendly_name="${5}" - - # generate private.pfx - openssl pkcs12 -export -out "${key_pfx}" -inkey "${key_file}" -in "${cert_file}" -iter 10000 \ - -name "${friendly_name}" -macsaltlen 20 -password pass:"${dummy_password}" || return 1 - echo "------------------------------------------------------------------------------------" - echo "Generated: ${key_pfx}" - echo "------------------------------------------------------------------------------------" - openssl pkcs12 -info -in "${key_pfx}" -passin pass:"${dummy_password}" -passout pass:"${dummy_password}" -nokeys # do not output private key - - # generate public.pfx - openssl pkcs12 -export -nokeys -out "${cert_pfx}" -in "${cert_file}" -iter 10000 \ - -name "${friendly_name}" -macsaltlen 20 -password pass:"${dummy_password}" -CAfile "${s_cert}" -chain || return 1 - echo "------------------------------------------------------------------------------------" - echo "Generated: ${cert_pfx}" - echo "------------------------------------------------------------------------------------" - #openssl pkcs12 -info -in a-public-node0.pfx -passin pass:password -passout pass:password -nokeys - openssl pkcs12 -info -in "${cert_pfx}" -passin pass:"${dummy_password}" -passout pass:"${dummy_password}" -nokeys -} - -for nm in "${names[@]}"; do - n="$(echo "${nm}" | tr '[A-Z]' '[a-z]')" - s_key="${s_key_prefix}-private-${n}.pem" - s_cert="${s_key_prefix}-public-${n}.pem" - - generate_signing_key "${n}" "${s_key_prefix}" || exit 1 - generate_signed_key "${n}" "${a_key_prefix}" "${s_key}" "${s_cert}" || exit 1 - - # Generate node mTLS keys - openssl req -new -newkey rsa:3072 -out "hedera-${n}.csr" -keyout "hedera-${n}.key" -sha384 -nodes -subj "/CN=${n}" || exit 1 - openssl x509 -req -in "hedera-${n}.csr" -out "hedera-${n}.crt" -signkey "hedera-${n}.key" -days "${validity}" -sha384 || exit 1 - rm -f "hedera-${n}.csr" -done - -# display backup dir -echo "Backup dir: ${backup_dir}" diff --git a/solo/test/test_util.js b/solo/test/test_util.js deleted file mode 100644 index a75100759..000000000 --- a/solo/test/test_util.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import fs from 'fs' -import os from 'os' -import path from 'path' -import { logging } from '../src/core/index.mjs' - -export const testLogger = logging.NewLogger('debug') - -export function getTestCacheDir (appendDir) { - const baseDir = 'test/data/tmp' - const d = appendDir ? path.join(baseDir, appendDir) : baseDir - - if (!fs.existsSync(d)) { - fs.mkdirSync(d) - } - return d -} - -export function getTmpDir () { - return fs.mkdtempSync(path.join(os.tmpdir(), 'solo-')) -} diff --git a/solo/test/unit/commands/base.test.mjs b/solo/test/unit/commands/base.test.mjs deleted file mode 100644 index 6726f9f26..000000000 --- a/solo/test/unit/commands/base.test.mjs +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { expect, it, describe } from '@jest/globals' -import { - DependencyManager, - ChartManager, - ConfigManager, - Helm, - logging -} from '../../../src/core/index.mjs' -import { BaseCommand } from '../../../src/commands/base.mjs' -import { K8 } from '../../../src/core/k8.mjs' - -const testLogger = logging.NewLogger('debug') - -describe('BaseCommand', () => { - const helm = new Helm(testLogger) - const chartManager = new ChartManager(helm, testLogger) - const configManager = new ConfigManager(testLogger) - const depManager = new DependencyManager(testLogger) - const k8 = new K8(configManager, testLogger) - - const baseCmd = new BaseCommand({ - logger: testLogger, - helm, - k8, - chartManager, - configManager, - depManager - }) - - describe('runShell', () => { - it('should fail during invalid program check', async () => { - await expect(baseCmd.run('INVALID_PROGRAM')).rejects.toThrowError() - }) - it('should succeed during valid program check', async () => { - await expect(baseCmd.run('date')).resolves.not.toBeNull() - }) - }) -}) diff --git a/solo/test/unit/commands/init.test.mjs b/solo/test/unit/commands/init.test.mjs deleted file mode 100644 index 311de9e58..000000000 --- a/solo/test/unit/commands/init.test.mjs +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { InitCommand } from '../../../src/commands/init.mjs' -import { expect, describe, it } from '@jest/globals' -import { - ChartManager, - ConfigManager, - DependencyManager, - Helm, - KeyManager, - logging -} from '../../../src/core/index.mjs' -import { K8 } from '../../../src/core/k8.mjs' - -const testLogger = logging.NewLogger('debug') -describe('InitCommand', () => { - const helm = new Helm(testLogger) - const chartManager = new ChartManager(helm, testLogger) - const configManager = new ConfigManager(testLogger) - const depManager = new DependencyManager(testLogger) - const keyManager = new KeyManager(testLogger) - const k8 = new K8(configManager, testLogger) - - const initCmd = new InitCommand({ - logger: testLogger, - helm, - k8, - chartManager, - configManager, - depManager, - keyManager - }) - - describe('commands', () => { - it('init execution should succeed', async () => { - await expect(initCmd.init({})).resolves.toBe(true) - }, 20000) - }) - - describe('static', () => { - it('command definition should return a valid command def', async () => { - const def = InitCommand.getCommandDefinition(initCmd) - expect(def.name).not.toBeNull() - expect(def.desc).not.toBeNull() - expect(def.handler).not.toBeNull() - }) - }) -}) diff --git a/solo/test/unit/core/config_manager.test.mjs b/solo/test/unit/core/config_manager.test.mjs deleted file mode 100644 index 0c3a8dc8e..000000000 --- a/solo/test/unit/core/config_manager.test.mjs +++ /dev/null @@ -1,269 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { afterAll, describe, expect, it } from '@jest/globals' -import os from 'os' -import path from 'path' -import { ConfigManager } from '../../../src/core/index.mjs' -import * as flags from '../../../src/commands/flags.mjs' -import fs from 'fs' -import { testLogger } from '../../test_util.js' -import * as helpers from '../../../src/core/helpers.mjs' - -describe('ConfigManager', () => { - it('should persist config', () => { - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'config-')) - const tmpFile = path.join(tmpDir, 'test.json') - - expect(fs.existsSync(tmpFile)).toBeFalsy() - const cm = new ConfigManager(testLogger, tmpFile) - cm.persist() - expect(fs.existsSync(tmpFile)).toBeTruthy() - - const configJSON = fs.readFileSync(tmpFile) - const cachedConfig = JSON.parse(configJSON.toString()) - - expect(cachedConfig.version).toStrictEqual(helpers.packageVersion()) - expect(cachedConfig.flags).toStrictEqual({}) - expect(cachedConfig.updatedAt).not.toStrictEqual('') - - expect(cachedConfig.updatedAt).toStrictEqual(cm.getUpdatedAt()) - expect(cachedConfig.version).toStrictEqual(cm.getVersion()) - expect(cachedConfig.flags).toStrictEqual(cm.config.flags) - - fs.rmSync(tmpDir, { recursive: true }) - }) - - describe('update values using argv', () => { - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'config-')) - const tmpFile = path.join(tmpDir, 'test.json') - - it('should update string flag value', () => { - const cm = new ConfigManager(testLogger, tmpFile) - const argv = {} - argv[flags.releaseTag.name] = 'v0.42.5' - - cm.update(argv) - expect(cm.getFlag(flags.releaseTag)).toStrictEqual(argv[flags.releaseTag.name]) - - // ensure non-string values are converted to string - cm.reset() - argv[flags.releaseTag.name] = true - cm.update(argv) - expect(cm.getFlag(flags.releaseTag)).not.toStrictEqual(argv[flags.releaseTag.name]) - expect(cm.getFlag(flags.releaseTag)).toStrictEqual(`${argv[flags.releaseTag.name]}`) - }) - - it('should update number flag value', () => { - const cm = new ConfigManager(testLogger, tmpFile) - const argv = {} - argv[flags.replicaCount.name] = 1 - - cm.update(argv) - expect(cm.getFlag(flags.replicaCount)).toStrictEqual(argv[flags.replicaCount.name]) - - // ensure string values are converted to integer - cm.reset() - argv[flags.replicaCount.name] = '1' - cm.update(argv) - expect(cm.getFlag(flags.replicaCount)).not.toStrictEqual(argv[flags.replicaCount.name]) - expect(cm.getFlag(flags.replicaCount)).toStrictEqual(Number.parseInt(argv[flags.replicaCount.name])) - }) - - it('should update boolean flag value', () => { - const cm = new ConfigManager(testLogger, tmpFile) - - // boolean values should work - const argv = {} - argv[flags.devMode.name] = true - cm.update(argv) - expect(cm.getFlag(flags.devMode)).toStrictEqual(argv[flags.devMode.name]) - - // ensure string "false" is converted to boolean - cm.reset() - argv[flags.devMode.name] = 'false' - cm.update(argv) - expect(cm.getFlag(flags.devMode)).not.toStrictEqual(argv[flags.devMode.name]) - expect(cm.getFlag(flags.devMode)).toStrictEqual(false) - - // ensure string "true" is converted to boolean - cm.reset() - argv[flags.devMode.name] = 'true' - cm.update(argv) - expect(cm.getFlag(flags.devMode)).not.toStrictEqual(argv[flags.devMode.name]) - expect(cm.getFlag(flags.devMode)).toStrictEqual(true) - }) - - afterAll(() => { - fs.rmdirSync(tmpDir, { recursive: true }) - }) - }) - - describe('should apply precedence', () => { - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'config-')) - const tmpFile = path.join(tmpDir, 'test.json') - const aliases = {} - aliases[flags.devMode.name] = [flags.devMode.name, flags.devMode.definition.alias] // mock - - it('should take user input as the first preference', () => { - // Given: config has value, argv has a different value - // Expected: argv should retain the value - const cm = new ConfigManager(testLogger, tmpFile) - cm.setFlag(flags.devMode, false) - expect(cm.getFlag(flags.devMode)).toBeFalsy() - - const argv = {} - argv[flags.devMode.name] = true // devMode flag is set in argv but cached config has it - - const argv2 = cm.applyPrecedence(argv, aliases) - expect(cm.getFlag(flags.devMode)).toBeFalsy() // shouldn't have changed the config yet - expect(argv2[flags.devMode.name]).toBeTruthy() // retain the value - }) - - it('should take cached config as the second preference', () => { - // Given: config has value, argv doesn't have the flag value - // Expected: argv should inherit the flag value from cached config - const cm = new ConfigManager(testLogger, tmpFile) - - cm.setFlag(flags.devMode, false) - expect(cm.getFlag(flags.devMode)).toBeFalsy() - - const argv = {} // devMode flag is not set in argv - const argv2 = cm.applyPrecedence(argv, aliases) - expect(cm.getFlag(flags.devMode)).toBeFalsy() // shouldn't have changed - expect(argv2[flags.devMode.name]).toStrictEqual(cm.getFlag(flags.devMode)) // should inherit from config - }) - - it('should take default as the last preference', () => { - // Given: neither config nor argv has the flag value set - // Expected: argv should inherit the default flag value - const cm = new ConfigManager(testLogger, tmpFile) - expect(cm.hasFlag(flags.devMode)).toBeFalsy() // shouldn't have set - - const argv = {} // devMode flag is not set in argv and cached config doesn't have it either - const argv2 = cm.applyPrecedence(argv, aliases) - expect(cm.hasFlag(flags.devMode)).toBeFalsy() // shouldn't have set - expect(argv2[flags.devMode.name]).toBeFalsy() // should have set from the default - }) - - afterAll(() => { - fs.rmdirSync(tmpDir, { recursive: true }) - }) - }) - - describe('load a cached config file', () => { - const configFilePath = process.cwd() + '/test/data/solo-test-1.config' - const cm = new ConfigManager(testLogger, configFilePath) - cm.load() - - it('config file match: dev=false', () => { - expect(cm.config.flags[flags.devMode.name]).toBeFalsy() - }) - - it('config file match: namespace=solo-user', () => { - expect(cm.config.flags[flags.namespace.name]).toBe('solo-user') - }) - - it('config file match: chartDirectory is empty', () => { - expect(cm.config.flags[flags.chartDirectory.name]).toBe('') - }) - - it('config file match: clusterName=kind-kind', () => { - expect(cm.config.flags[flags.clusterName.name]).toBe('kind-kind') - }) - - it('config file match: deployPrometheusStack=false', () => { - expect(cm.config.flags[flags.deployPrometheusStack.name]).toBeFalsy() - }) - - it('config file match: deployMinio=false', () => { - expect(cm.config.flags[flags.deployMinio.name]).toBeFalsy() - }) - - it('config file match: deployCertManager=false', () => { - expect(cm.config.flags[flags.deployCertManager.name]).toBeFalsy() - }) - - it('config file match: deployCertManagerCrds=false', () => { - expect(cm.config.flags[flags.deployCertManagerCrds.name]).toBeFalsy() - }) - - it('not set, it should be undefined', () => { - expect(cm.config.flags[flags.enablePrometheusSvcMonitor.name]).toBeUndefined() - }) - - it('not set, it should be undefined', () => { - expect(cm.config.flags[flags.enableHederaExplorerTls.name]).toBeUndefined() - }) - - it('not set, it should be undefined', () => { - expect(cm.config.flags[flags.hederaExplorerTlsHostName.name]).toBeUndefined() - }) - - it('not set, it should be undefined', () => { - expect(cm.config.flags[flags.deletePvcs.name]).toBeUndefined() - }) - }) - - describe('handle argv overrides', () => { - const configFilePath = process.cwd() + '/test/data/solo-test-2.config' - const cm = new ConfigManager(testLogger, configFilePath) - const configJSON = fs.readFileSync(process.cwd() + '/test/data/solo-test-2.config') - const cachedConfig = JSON.parse(configJSON.toString()) - - it('override config using argv', () => { - cm.load() - expect(cm.getFlag(flags.clusterName)).toBe(cachedConfig.flags[flags.clusterName.name]) - expect(cm.getFlag(flags.namespace)).toBe(cachedConfig.flags[flags.namespace.name]) - - const argv = {} - argv[flags.clusterName.name] = 'new-cluster' - argv[flags.namespace.name] = 'new-namespace' - cm.update(argv) - - expect(cm.getFlag(flags.clusterName)).toBe(argv[flags.clusterName.name]) - expect(cm.getFlag(flags.namespace)).toBe(argv[flags.namespace.name]) - }) - - it('config file takes precedence over empty namespace', () => { - cm.load() - expect(cm.getFlag(flags.clusterName)).toBe(cachedConfig.flags[flags.clusterName.name]) - expect(cm.getFlag(flags.namespace)).toBe(cachedConfig.flags[flags.namespace.name]) - - const argv = {} - argv[flags.clusterName.name] = 'new-cluster' - argv[flags.namespace.name] = '' - cm.update(argv) - expect(cm.getFlag(flags.clusterName)).toBe(argv[flags.clusterName.name]) - expect(cm.getFlag(flags.namespace)).not.toBe(argv[flags.namespace.name]) - expect(cm.getFlag(flags.namespace)).toBe(cachedConfig.flags[flags.namespace.name]) - }) - - it('config file takes precedence over empty cluster name', () => { - cm.load() - expect(cm.getFlag(flags.clusterName)).toBe(cachedConfig.flags[flags.clusterName.name]) - expect(cm.getFlag(flags.namespace)).toBe(cachedConfig.flags[flags.namespace.name]) - - const argv = {} - argv[flags.clusterName.name] = '' - argv[flags.namespace.name] = 'new-namespace' - cm.update(argv) - expect(cm.getFlag(flags.clusterName)).not.toBe(argv[flags.clusterName.name]) - expect(cm.getFlag(flags.clusterName)).toBe(cachedConfig.flags[flags.clusterName.name]) - expect(cm.getFlag(flags.namespace)).toBe(argv[flags.namespace.name]) - }) - }) -}) diff --git a/solo/test/unit/core/dependency_manager.test.mjs b/solo/test/unit/core/dependency_manager.test.mjs deleted file mode 100644 index 1c35f6a3c..000000000 --- a/solo/test/unit/core/dependency_manager.test.mjs +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { describe, expect, it } from '@jest/globals' -import { DependencyManager } from '../../../src/core/dependency_manager.mjs' -import { FullstackTestingError } from '../../../src/core/errors.mjs' -import { logging, constants } from '../../../src/core/index.mjs' - -const testLogger = logging.NewLogger('debug') -describe('DependencyManager', () => { - const depManager = new DependencyManager(testLogger) - - describe('checks', () => { - it('should succeed with checkHelm', async () => { - await expect(depManager.checkHelm()).resolves.toBe(true) - }) - }) - - describe('checkDependency', () => { - it('should fail during invalid dependency check', async () => { - await expect(depManager.checkDependency('INVALID_PROGRAM')).rejects.toThrowError(new FullstackTestingError('INVALID_PROGRAM:^undefined is not found')) - }) - it('should succeed during kubectl dependency check', async () => { - await expect(depManager.checkDependency(constants.HELM)).resolves.toBe(true) - }) - }) -}) diff --git a/solo/test/unit/core/errors.test.mjs b/solo/test/unit/core/errors.test.mjs deleted file mode 100644 index 518f1e9e0..000000000 --- a/solo/test/unit/core/errors.test.mjs +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { describe, expect, it } from '@jest/globals' -import { - FullstackTestingError, - ResourceNotFoundError, - MissingArgumentError, - IllegalArgumentError, - DataValidationError -} from '../../../src/core/errors.mjs' - -describe('Errors', () => { - const message = 'errorMessage' - const cause = new Error('cause') - - it('should construct correct FullstackTestingError', () => { - const error = new FullstackTestingError(message, cause) - expect(error).toBeInstanceOf(Error) - expect(error.name).toBe('FullstackTestingError') - expect(error.message).toBe(message) - expect(error.cause).toBe(cause) - expect(error.meta).toStrictEqual({}) - }) - - it('should construct correct ResourceNotFoundError', () => { - const resource = 'resource' - const error = new ResourceNotFoundError(message, resource) - expect(error).toBeInstanceOf(FullstackTestingError) - expect(error.name).toBe('ResourceNotFoundError') - expect(error.message).toBe(message) - expect(error.cause).toStrictEqual({}) - expect(error.meta).toStrictEqual({ resource }) - }) - - it('should construct correct MissingArgumentError', () => { - const error = new MissingArgumentError(message) - expect(error).toBeInstanceOf(FullstackTestingError) - expect(error.name).toBe('MissingArgumentError') - expect(error.message).toBe(message) - expect(error.cause).toStrictEqual({}) - expect(error.meta).toStrictEqual({}) - }) - - it('should construct correct IllegalArgumentError', () => { - const value = 'invalid argument' - const error = new IllegalArgumentError(message, value) - expect(error).toBeInstanceOf(FullstackTestingError) - expect(error.name).toBe('IllegalArgumentError') - expect(error.message).toBe(message) - expect(error.cause).toStrictEqual({}) - expect(error.meta).toStrictEqual({ value }) - }) - - it('should construct correct DataValidationError', () => { - const expected = 'expected' - const found = 'found' - const error = new DataValidationError(message, expected, found) - expect(error).toBeInstanceOf(FullstackTestingError) - expect(error.name).toBe('DataValidationError') - expect(error.message).toBe(message) - expect(error.cause).toStrictEqual({}) - expect(error.meta).toStrictEqual({ expected, found }) - }) -}) diff --git a/solo/test/unit/core/helm.test.mjs b/solo/test/unit/core/helm.test.mjs deleted file mode 100644 index c51c3b5bc..000000000 --- a/solo/test/unit/core/helm.test.mjs +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { describe, expect, it, jest } from '@jest/globals' -import { Helm, logging } from '../../../src/core/index.mjs' -import { ShellRunner } from '../../../src/core/shell_runner.mjs' - -describe('Helm', () => { - const logger = logging.NewLogger('debug') - const helm = new Helm(logger) - const shellSpy = jest.spyOn(ShellRunner.prototype, 'run').mockImplementation() - - it('should run helm install', async () => { - await helm.install('arg') - expect(shellSpy).toHaveBeenCalledWith('helm install arg', true) - }) - - it('should run helm uninstall', async () => { - await helm.uninstall('arg') - expect(shellSpy).toHaveBeenCalledWith('helm uninstall arg') - }) - - it('should run helm upgrade', async () => { - await helm.upgrade('release', 'chart') - expect(shellSpy).toHaveBeenCalledWith('helm upgrade release chart') - }) - - it('should run helm list', async () => { - await helm.list() - expect(shellSpy).toHaveBeenCalledWith('helm list') - }) - - it('should run helm dependency', async () => { - await helm.dependency('update', 'chart') - expect(shellSpy).toHaveBeenCalledWith('helm dependency update chart') - }) - - it('should run helm repo', async () => { - await helm.repo('add', 'name', 'url') - expect(shellSpy).toHaveBeenCalledWith('helm repo add name url') - }) - - shellSpy.mockClear() -}) diff --git a/solo/test/unit/core/helpers.test.mjs b/solo/test/unit/core/helpers.test.mjs deleted file mode 100644 index 46c558a83..000000000 --- a/solo/test/unit/core/helpers.test.mjs +++ /dev/null @@ -1,73 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { describe, expect, it } from '@jest/globals' -import { FullstackTestingError } from '../../../src/core/errors.mjs' -import * as helpers from '../../../src/core/helpers.mjs' - -describe('Helpers', () => { - it.each([ - ['v0.42.5', { major: 0, minor: 42, patch: 5 }], - ['v0.42.5-alpha.0', { major: 0, minor: 42, patch: 5 }] - ])('should parse release tag into major, minor and patch numbers', (input, expected) => { - const result = helpers.parseSemver(input) - expect(result).toEqual(expected) - }) - - it.each([ - ['', new FullstackTestingError('invalid version. Expected \'v..\', found \'\'')], - ['0.42.5', new FullstackTestingError('invalid version. Expected \'v..\', found \'0.42.5\'')], - ['v0.42', new FullstackTestingError("version 'v0.42' must have the format MAJOR.MINOR.PATCH")], - ['v0.NEW', new FullstackTestingError("version 'v0.NEW' must have the format MAJOR.MINOR.PATCH")] - ])('should throw error in parsing release tag', (input, expectedError) => { - expect.assertions(1) - try { - helpers.parseSemver(input) // Error(new FullstackTestingError('releaseTag must have the format MAJOR.MINOR.PATCH')) - } catch (e) { - expect(e).toEqual(expectedError) - } - }) - - describe('compareVersion', () => { - it('should succeed with same version', () => { - expect(helpers.compareVersion('v3.14.0', 'v3.14.0')).toBe(0) - }) - - it('should succeed with patch higher than target', () => { - expect(helpers.compareVersion('v3.14.0', 'v3.14.1')).toBe(1) - }) - - it('should succeed with minor version higher than target', () => { - expect(helpers.compareVersion('v3.14.0', 'v3.15.0')).toBe(1) - }) - - it('should succeed with major version higher than target', () => { - expect(helpers.compareVersion('v3.14.0', 'v4.14.0')).toBe(1) - }) - - it('should fail with major version lower than target', () => { - expect(helpers.compareVersion('v3.14.0', 'v2.14.0')).toBe(-1) - }) - - it('should fail with minor version lower than target', () => { - expect(helpers.compareVersion('v3.14.0', 'v3.11.0')).toBe(-1) - }) - - it('should succeed with a later version', () => { - expect(helpers.compareVersion('v3.12.3', 'v3.14.0')).toBe(1) - }) - }) -}) diff --git a/solo/test/unit/core/key_manager.test.mjs b/solo/test/unit/core/key_manager.test.mjs deleted file mode 100644 index cc0527a65..000000000 --- a/solo/test/unit/core/key_manager.test.mjs +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { describe, expect, it } from '@jest/globals' -import fs from 'fs' -import os from 'os' -import path from 'path' -import { constants, logging } from '../../../src/core/index.mjs' -import { KeyManager } from '../../../src/core/key_manager.mjs' - -describe('KeyManager', () => { - const logger = logging.NewLogger('debug') - const keyManager = new KeyManager(logger) - - it('should generate signing key', async () => { - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'keys-')) - const nodeId = 'node0' - const keyPrefix = constants.SIGNING_KEY_PREFIX - - const signingKey = await keyManager.generateSigningKey(nodeId) - - const nodeKeyFiles = keyManager.prepareNodeKeyFilePaths(nodeId, tmpDir, constants.SIGNING_KEY_PREFIX) - const files = await keyManager.storeNodeKey(nodeId, signingKey, tmpDir, nodeKeyFiles, keyPrefix) - expect(files.privateKeyFile).not.toBeNull() - expect(files.certificateFile).not.toBeNull() - - const nodeKey = await keyManager.loadSigningKey(nodeId, tmpDir, KeyManager.SigningKeyAlgo, keyPrefix) - expect(nodeKey.certificate).toStrictEqual(signingKey.certificate) - expect(nodeKey.privateKeyPem).toStrictEqual(signingKey.privateKeyPem) - expect(nodeKey.certificatePem).toStrictEqual(signingKey.certificatePem) - expect(nodeKey.privateKey.algorithm).toStrictEqual(signingKey.privateKey.algorithm) - expect(nodeKey.privateKey.type).toStrictEqual(signingKey.privateKey.type) - - await expect(signingKey.certificate.verify({ - publicKey: signingKey.certificate.publicKey, - signatureOnly: true - })).resolves.toBeTruthy() - - fs.rmSync(tmpDir, { recursive: true }) - }) - - it('should generate agreement key', async () => { - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'keys-')) - const nodeId = 'node0' - - const signingKeyFiles = keyManager.prepareNodeKeyFilePaths(nodeId, 'test/data', constants.SIGNING_KEY_PREFIX) - const signignKey = await keyManager.loadNodeKey(nodeId, 'test/data', KeyManager.SigningKeyAlgo, signingKeyFiles) - const agreementKey = await keyManager.generateAgreementKey(nodeId, signignKey) - - const files = await keyManager.storeAgreementKey(nodeId, agreementKey, tmpDir) - expect(files.privateKeyFile).not.toBeNull() - expect(files.certificateFile).not.toBeNull() - - const nodeKey = await keyManager.loadAgreementKey(nodeId, tmpDir) - expect(nodeKey.certificate).toStrictEqual(agreementKey.certificate) - expect(nodeKey.privateKey.algorithm).toStrictEqual(agreementKey.privateKey.algorithm) - expect(nodeKey.privateKey.type).toStrictEqual(agreementKey.privateKey.type) - - await expect(agreementKey.certificate.verify({ - publicKey: signignKey.certificate.publicKey, - signatureOnly: true - })).resolves.toBeTruthy() - - fs.rmSync(tmpDir, { recursive: true }) - }) - - it('should generate TLS key', async () => { - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'keys-')) - const nodeId = 'node0' - const keyName = 'TLS' - - const tlsKey = await keyManager.generateGrpcTLSKey(nodeId) - expect(tlsKey.certificate.subject).not.toBe('') - expect(tlsKey.certificate.issuer).not.toBe('') - - const files = await keyManager.storeTLSKey(nodeId, tlsKey, tmpDir) - expect(files.privateKeyFile).not.toBeNull() - expect(files.certificateFile).not.toBeNull() - - const nodeKey = await keyManager.loadTLSKey(nodeId, tmpDir, KeyManager.TLSKeyAlgo, keyName) - expect(nodeKey.certificate.subject).toStrictEqual(tlsKey.certificate.subject) - expect(nodeKey.certificate.issuer).toStrictEqual(tlsKey.certificate.issuer) - expect(nodeKey.certificate).toStrictEqual(tlsKey.certificate) - expect(nodeKey.privateKeyPem).toStrictEqual(tlsKey.privateKeyPem) - expect(nodeKey.certificatePem).toStrictEqual(tlsKey.certificatePem) - expect(nodeKey.privateKey.algorithm).toStrictEqual(tlsKey.privateKey.algorithm) - expect(nodeKey.privateKey.type).toStrictEqual(tlsKey.privateKey.type) - - await expect(tlsKey.certificate.verify({ - publicKey: tlsKey.certificate.publicKey, - signatureOnly: true - })).resolves.toBeTruthy() - - fs.rmSync(tmpDir, { recursive: true }) - }, 20000) -}) diff --git a/solo/test/unit/core/logging.test.mjs b/solo/test/unit/core/logging.test.mjs deleted file mode 100644 index 2972c59bd..000000000 --- a/solo/test/unit/core/logging.test.mjs +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { describe, expect, it, jest } from '@jest/globals' -import { NewLogger, Logger } from '../../../src/core/logging.mjs' -import winston from 'winston' - -describe('Logging', () => { - it('should log at correct severity', () => { - const loggerSpy = jest.spyOn(winston.Logger.prototype, 'log').mockImplementation() - const logger = NewLogger('debug') - expect(logger).toBeInstanceOf(Logger) - expect(logger).toBeDefined() - const meta = logger.prepMeta() - - logger.error('Error log') - expect(loggerSpy).toHaveBeenCalledWith('error', 'Error log', meta) - - logger.warn('Warn log') - expect(loggerSpy).toHaveBeenCalledWith('warn', 'Warn log', meta) - - logger.info('Info log') - expect(loggerSpy).toHaveBeenCalledWith('info', 'Info log', meta) - - logger.debug('Debug log') - expect(loggerSpy).toHaveBeenCalledWith('debug', 'Debug log', meta) - - jest.clearAllMocks() - }) -}) diff --git a/solo/test/unit/core/package_downloader.test.mjs b/solo/test/unit/core/package_downloader.test.mjs deleted file mode 100644 index 07a11cd86..000000000 --- a/solo/test/unit/core/package_downloader.test.mjs +++ /dev/null @@ -1,153 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { describe, expect, it } from '@jest/globals' -import * as core from '../../../src/core/index.mjs' -import * as fs from 'fs' -import * as path from 'path' -import * as os from 'os' -import { IllegalArgumentError, MissingArgumentError, ResourceNotFoundError } from '../../../src/core/errors.mjs' - -describe('PackageDownloader', () => { - const testLogger = core.logging.NewLogger('debug') - const downloader = new core.PackageDownloader(testLogger) - - describe('urlExists', () => { - it('should return true if source URL is valid', async () => { - expect.assertions(1) - const url = 'https://builds.hedera.com/node/software/v0.42/build-v0.42.5.sha384' - await expect(downloader.urlExists(url)).resolves.toBe(true) - }) - it('should return false if source URL is valid', async () => { - expect.assertions(1) - const url = 'https://builds.hedera.com/node/software/v0.42/build-v0.42.5.INVALID' - await expect(downloader.urlExists(url)).resolves.toBe(false) - }) - }) - - describe('fetchFile', () => { - it('should fail if source URL is missing', async () => { - expect.assertions(1) - - try { - await downloader.fetchFile('', os.tmpdir()) - } catch (e) { - expect(e.message).toBe('package URL is required') - } - }) - - it('should fail if destination path is missing', async () => { - expect.assertions(1) - - try { - await downloader.fetchFile('https://localhost', '') - } catch (e) { - expect(e.message).toBe('destination path is required') - } - }) - - it('should fail with a malformed URL', async () => { - expect.assertions(2) - - try { - await downloader.fetchFile('INVALID_URL', os.tmpdir()) - } catch (e) { - expect(e).toBeInstanceOf(IllegalArgumentError) - expect(e.message).toBe("package URL 'INVALID_URL' is invalid") - } - }) - - it('should fail with an invalid URL', async () => { - expect.assertions(2) - - try { - await downloader.fetchFile('https://localhost/INVALID_FILE', os.tmpdir()) - } catch (e) { - expect(e).toBeInstanceOf(ResourceNotFoundError) - expect(e.message).toBe("package URL 'https://localhost/INVALID_FILE' does not exist") - } - }) - - it('should succeed with a valid release artifact URL', async () => { - try { - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'downloader-')) - - const tag = 'v0.42.5' - const destPath = `${tmpDir}/build-${tag}.sha384` - - // we use the build-.sha384 file URL to test downloading a small file - const url = `https://builds.hedera.com/node/software/v0.42/build-${tag}.sha384` - await expect(downloader.fetchFile(url, destPath)).resolves.toBe(destPath) - expect(fs.existsSync(destPath)).toBeTruthy() - - // remove the file to reduce disk usage - fs.rmSync(tmpDir, { recursive: true }) - } catch (e) { - expect(e).toBeNull() - } - }) - }) - - describe('fetchPlatform', () => { - it('should fail if platform release tag is missing', async () => { - expect.assertions(2) - - try { - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'downloader-')) - await downloader.fetchPlatform('', tmpDir) - fs.rmSync(tmpDir, { recursive: true }) - } catch (e) { - expect(e.cause).not.toBeNull() - expect(e).toBeInstanceOf(MissingArgumentError) - } - }) - it('should fail if platform release artifact is not found', async () => { - expect.assertions(2) - - const tag = 'v0.40.0-INVALID' - - try { - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'downloader-')) - await downloader.fetchPlatform(tag, tmpDir) - fs.rmSync(tmpDir, { recursive: true }) - } catch (e) { - expect(e.cause).not.toBeNull() - expect(e.cause).toBeInstanceOf(ResourceNotFoundError) - } - }) - - it('should fail if platform release tag is invalid', async () => { - expect.assertions(1) - - try { - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'downloader-')) - await downloader.fetchPlatform('INVALID', os.tmpdir()) - fs.rmSync(tmpDir, { recursive: true }) - } catch (e) { - expect(e.message).toContain('must include major, minor and patch fields') - } - }) - - it('should fail if destination directory is null', async () => { - expect.assertions(1) - try { - await downloader.fetchPlatform('v0.40.0', '') - } catch (e) { - expect(e.message).toContain('destination directory path is required') - } - }) - }) -}) diff --git a/solo/test/unit/core/platform_installer.test.mjs b/solo/test/unit/core/platform_installer.test.mjs deleted file mode 100644 index 47dc93287..000000000 --- a/solo/test/unit/core/platform_installer.test.mjs +++ /dev/null @@ -1,131 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { describe, expect, it } from '@jest/globals' -import * as core from '../../../src/core/index.mjs' -import { ConfigManager, PlatformInstaller } from '../../../src/core/index.mjs' -import * as fs from 'fs' -import * as path from 'path' -import * as os from 'os' -import { - IllegalArgumentError, - MissingArgumentError -} from '../../../src/core/errors.mjs' -describe('PackageInstaller', () => { - const testLogger = core.logging.NewLogger('debug') - const configManager = new ConfigManager(testLogger) - const k8 = new core.K8(configManager, testLogger) - const installer = new PlatformInstaller(testLogger, k8) - - describe('validatePlatformReleaseDir', () => { - it('should fail for missing path', async () => { - expect.assertions(1) - await expect(installer.validatePlatformReleaseDir('')).rejects.toThrow(MissingArgumentError) - }) - - it('should fail for invalid path', async () => { - expect.assertions(1) - await expect(installer.validatePlatformReleaseDir('/INVALID')).rejects.toThrow(IllegalArgumentError) - }) - - it('should fail if directory does not have data/apps directory', async () => { - expect.assertions(1) - - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'installer-')) - fs.mkdirSync(`${tmpDir}/${core.constants.HEDERA_DATA_LIB_DIR}`, { recursive: true }) - await expect(installer.validatePlatformReleaseDir(tmpDir)).rejects.toThrow(IllegalArgumentError) - fs.rmSync(tmpDir, { recursive: true }) - }) - - it('should fail if directory does not have data/libs directory', async () => { - expect.assertions(1) - - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'installer-')) - fs.mkdirSync(`${tmpDir}/${core.constants.HEDERA_DATA_APPS_DIR}`, { recursive: true }) - await expect(installer.validatePlatformReleaseDir(tmpDir)).rejects.toThrow(IllegalArgumentError) - fs.rmSync(tmpDir, { recursive: true }) - }) - - it('should fail if directory does not have data/app directory is empty', async () => { - expect.assertions(1) - - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'installer-')) - fs.mkdirSync(`${tmpDir}/${core.constants.HEDERA_DATA_APPS_DIR}`, { recursive: true }) - fs.mkdirSync(`${tmpDir}/${core.constants.HEDERA_DATA_LIB_DIR}`, { recursive: true }) - fs.writeFileSync(`${tmpDir}/${core.constants.HEDERA_DATA_LIB_DIR}/test.jar`, '') - await expect(installer.validatePlatformReleaseDir()).rejects.toThrow(MissingArgumentError) - fs.rmSync(tmpDir, { recursive: true }) - }) - - it('should fail if directory does not have data/apps directory is empty', async () => { - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'installer-app-')) - fs.mkdirSync(`${tmpDir}/${core.constants.HEDERA_DATA_APPS_DIR}`, { recursive: true }) - fs.writeFileSync(`${tmpDir}/${core.constants.HEDERA_DATA_APPS_DIR}/app.jar`, '') - fs.mkdirSync(`${tmpDir}/${core.constants.HEDERA_DATA_LIB_DIR}`, { recursive: true }) - await expect(installer.validatePlatformReleaseDir()).rejects.toThrow(MissingArgumentError) - fs.rmSync(tmpDir, { recursive: true }) - }) - - it('should succeed with non-empty data/apps and data/libs directory', async () => { - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'installer-lib-')) - fs.mkdirSync(`${tmpDir}/${core.constants.HEDERA_DATA_APPS_DIR}`, { recursive: true }) - fs.writeFileSync(`${tmpDir}/${core.constants.HEDERA_DATA_APPS_DIR}/app.jar`, '') - fs.mkdirSync(`${tmpDir}/${core.constants.HEDERA_DATA_LIB_DIR}`, { recursive: true }) - fs.writeFileSync(`${tmpDir}/${core.constants.HEDERA_DATA_LIB_DIR}/lib-1.jar`, '') - await expect(installer.validatePlatformReleaseDir()).rejects.toThrow(MissingArgumentError) - fs.rmSync(tmpDir, { recursive: true }) - }) - }) - - describe('extractPlatform', () => { - it('should fail for missing pod name', async () => { - expect.assertions(1) - await expect(installer.copyPlatform('', os.tmpdir())).rejects.toThrow(MissingArgumentError) - }) - it('should fail for missing buildZipFile path', async () => { - expect.assertions(1) - await expect(installer.copyPlatform('network-node0-0', '')).rejects.toThrow(MissingArgumentError) - }) - }) - - describe('prepareConfigTxt', () => { - it('should fail for missing nodeIDs', async () => { - await expect(installer.prepareConfigTxt([], './test', '0.42.0')).rejects.toThrow(MissingArgumentError) - }) - - it('should fail for missing destPath', async () => { - await expect(installer.prepareConfigTxt(['node0'], '', '0.42.0')).rejects.toThrow(MissingArgumentError) - }) - - it('should fail for missing release tag', async () => { - await expect(installer.prepareConfigTxt(['node0'], `${os.tmpdir()}/config.txt`, '')).rejects.toThrow(MissingArgumentError) - }) - - it('should fail for invalid destPath', async () => { - await expect(installer.prepareConfigTxt(['node0'], '/INVALID/config.txt', '0.42.0')).rejects.toThrow(IllegalArgumentError) - }) - }) - - describe('copyGossipKeys', () => { - it('should fail for missing podName', async () => { - await expect(installer.copyGossipKeys('', os.tmpdir())).rejects.toThrow(MissingArgumentError) - }) - - it('should fail for missing stagingDir path', async () => { - await expect(installer.copyGossipKeys('network-node0-0', '')).rejects.toThrow(MissingArgumentError) - }) - }) -}) diff --git a/solo/test/unit/core/shell_runner.test.mjs b/solo/test/unit/core/shell_runner.test.mjs deleted file mode 100644 index 8eb6d4973..000000000 --- a/solo/test/unit/core/shell_runner.test.mjs +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { describe, expect, it, jest } from '@jest/globals' -import { ShellRunner } from '../../../src/core/shell_runner.mjs' -import { NewLogger, Logger } from '../../../src/core/logging.mjs' -import { ChildProcess } from 'child_process' -import { Readable } from 'stream' - -describe('ShellRunner', () => { - const logger = NewLogger('debug') - const shellRunner = new ShellRunner(logger) - const loggerSpy = jest.spyOn(Logger.prototype, 'debug').mockImplementation() - const childProcessSpy = jest.spyOn(ChildProcess.prototype, 'on') - const readableSpy = jest.spyOn(Readable.prototype, 'on') - - it('should run command', async () => { - await shellRunner.run('ls -l') - expect(loggerSpy).toHaveBeenNthCalledWith(1, 'Executing command: \'ls -l\'') - expect(loggerSpy).toHaveBeenNthCalledWith(2, 'Finished executing: \'ls -l\'', { - commandExitCode: expect.any(Number), - commandExitSignal: null, - commandOutput: expect.any(Array), - errOutput: expect.any(Array) - }) - expect(readableSpy).toHaveBeenCalledWith('data', expect.anything()) - expect(childProcessSpy).toHaveBeenCalledWith('exit', expect.anything()) - }) - - jest.clearAllMocks() -}) diff --git a/solo/test/unit/core/zippy.test.mjs b/solo/test/unit/core/zippy.test.mjs deleted file mode 100644 index 2bfdfb163..000000000 --- a/solo/test/unit/core/zippy.test.mjs +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Copyright (C) 2024 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the ""License""); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an ""AS IS"" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -import { describe, expect, it } from '@jest/globals' -import * as core from '../../../src/core/index.mjs' -import { FullstackTestingError, IllegalArgumentError, MissingArgumentError } from '../../../src/core/errors.mjs' -import os from 'os' -import fs from 'fs' -import path from 'path' -import { Zippy } from '../../../src/core/zippy.mjs' -describe('Zippy', () => { - const testLogger = core.logging.NewLogger('debug') - const zippy = new Zippy(testLogger) - - describe('unzip', () => { - it('should fail if source file is missing', async () => { - expect.assertions(1) - await expect(zippy.unzip('', '')).rejects.toThrow(MissingArgumentError) - }) - - it('should fail if destination file is missing', async () => { - expect.assertions(1) - await expect(zippy.unzip('', '')).rejects.toThrow(MissingArgumentError) - }) - - it('should fail if source file is invalid', async () => { - expect.assertions(1) - await expect(zippy.unzip('/INVALID', os.tmpdir())).rejects.toThrow(IllegalArgumentError) - }) - - it('should fail for a directory', async () => { - expect.assertions(1) - await expect(zippy.unzip('test/data', os.tmpdir())).rejects.toThrow(FullstackTestingError) - }) - - it('should fail for a non-zip file', async () => { - expect.assertions(1) - await expect(zippy.unzip('test/data/test.txt', os.tmpdir())).rejects.toThrow(FullstackTestingError) - }) - - it('should succeed for valid inputs', async () => { - const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'installer-')) - const zipFile = `${tmpDir}/test.zip` - const unzippedFile = `${tmpDir}/unzipped` - await expect(zippy.zip('test/data/.empty', zipFile)).resolves.toBe(zipFile) - await expect(zippy.unzip(zipFile, unzippedFile, true)).resolves.toBe(unzippedFile) - fs.rmSync(tmpDir, { recursive: true, force: true }) // not very safe! - }) - }) -})