diff --git a/.github/workflows/ci-sdk-wasm.yml b/.github/workflows/ci-sdk-wasm.yml index ae289b9eba..0ad8061bae 100644 --- a/.github/workflows/ci-sdk-wasm.yml +++ b/.github/workflows/ci-sdk-wasm.yml @@ -9,10 +9,14 @@ on: jobs: wasm: - runs-on: ubuntu-20.04 + runs-on: [custom-runner-linux] steps: - uses: actions/checkout@v2 + - uses: actions/setup-node@v3 + with: + node-version: 18 + - uses: actions-rs/toolchain@v1 with: profile: minimal diff --git a/.github/workflows/nightly_build.yml b/.github/workflows/nightly_build.yml index f55c08d0fb..f126348b45 100644 --- a/.github/workflows/nightly_build.yml +++ b/.github/workflows/nightly_build.yml @@ -26,7 +26,7 @@ jobs: - name: Install Dependencies (Linux) run: sudo apt-get update && sudo apt-get install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools protobuf-compiler continue-on-error: true - if: matrix.os == 'ubuntu-20.04' + if: matrix.os == 'custom-linux' - name: Check out repository code uses: actions/checkout@v3 @@ -53,7 +53,7 @@ jobs: - name: Reclaim some disk space uses: actions-rs/cargo@v1 - if: ${{ matrix.os == 'windows-latest' || matrix.os == 'ubuntu-20.04' }} + if: ${{ matrix.os == 'windows-latest' || matrix.os == 'custom-linux' }} with: command: clean @@ -65,7 +65,7 @@ jobs: - name: Reclaim some disk space uses: actions-rs/cargo@v1 - if: ${{ matrix.os == 'windows-latest' || matrix.os == 'ubuntu-20.04' }} + if: ${{ matrix.os == 'windows-latest' || matrix.os == 'custom-linux' }} with: command: clean @@ -77,7 +77,7 @@ jobs: - name: Reclaim some disk space uses: actions-rs/cargo@v1 - if: ${{ matrix.os == 'windows-latest' || matrix.os == 'ubuntu-20.04' }} + if: ${{ matrix.os == 'windows-latest' || matrix.os == 'custom-linux' }} with: command: clean @@ -90,7 +90,7 @@ jobs: - name: Reclaim some disk space uses: actions-rs/cargo@v1 - if: ${{ matrix.os == 'windows-latest' || matrix.os == 'ubuntu-20.04' }} + if: ${{ matrix.os == 'windows-latest' || matrix.os == 'custom-linux' }} with: command: clean @@ -110,7 +110,7 @@ jobs: - name: Reclaim some disk space uses: actions-rs/cargo@v1 - if: ${{ matrix.os == 'windows-latest' || matrix.os == 'ubuntu-20.04' }} + if: ${{ matrix.os == 'windows-latest' || matrix.os == 'custom-linux' }} with: command: clean diff --git a/.github/workflows/nightly_build_matrix_includes.json b/.github/workflows/nightly_build_matrix_includes.json index f276fac8b8..b9a500aaf0 100644 --- a/.github/workflows/nightly_build_matrix_includes.json +++ b/.github/workflows/nightly_build_matrix_includes.json @@ -1,6 +1,6 @@ [ { - "os":"ubuntu-20.04", + "os":"custom-linux", "rust":"stable", "runOnEvent":"schedule" }, @@ -11,13 +11,13 @@ "runOnEvent":"schedule" }, { - "os":"macos-latest", + "os":"custom-runner-mac-m1", "rust":"stable", "runOnEvent":"schedule" }, { - "os":"ubuntu-20.04", + "os":"custom-linux", "rust":"beta", "runOnEvent":"schedule" }, @@ -27,13 +27,13 @@ "runOnEvent":"schedule" }, { - "os":"macos-latest", + "os":"custom-runner-mac-m1", "rust":"beta", "runOnEvent":"schedule" }, { - "os":"ubuntu-20.04", + "os":"custom-linux", "rust":"nightly", "runOnEvent":"schedule" }, @@ -43,7 +43,7 @@ "runOnEvent":"schedule" }, { - "os":"macos-latest", + "os":"custom-runner-mac-m1", "rust":"nightly", "runOnEvent":"schedule" } diff --git a/.github/workflows/nightly_build_matrix_on_dispatch.json b/.github/workflows/nightly_build_matrix_on_dispatch.json new file mode 100644 index 0000000000..fd7dc85315 --- /dev/null +++ b/.github/workflows/nightly_build_matrix_on_dispatch.json @@ -0,0 +1,50 @@ +[ + { + "os":"ubuntu-20.04", + "rust":"stable", + "runOnEvent":"workflow_dispatch" + }, + + { + "os":"windows10", + "rust":"stable", + "runOnEvent":"workflow_dispatch" + }, + { + "os":"custom-runner-mac-m1", + "rust":"stable", + "runOnEvent":"workflow_dispatch" + }, + + { + "os":"ubuntu-20.04", + "rust":"beta", + "runOnEvent":"workflow_dispatch" + }, + { + "os":"windows10", + "rust":"beta", + "runOnEvent":"workflow_dispatch" + }, + { + "os":"custom-runner-mac-m1", + "rust":"beta", + "runOnEvent":"workflow_dispatch" + }, + + { + "os":"ubuntu-20.04", + "rust":"nightly", + "runOnEvent":"workflow_dispatch" + }, + { + "os":"windows10", + "rust":"nightly", + "runOnEvent":"workflow_dispatch" + }, + { + "os":"custom-runner-mac-m1", + "rust":"nightly", + "runOnEvent":"workflow_dispatch" + } +] diff --git a/.github/workflows/nightly_build_release.yml b/.github/workflows/nightly_build_on_dispatch.yml similarity index 85% rename from .github/workflows/nightly_build_release.yml rename to .github/workflows/nightly_build_on_dispatch.yml index 7687035157..f21913ba75 100644 --- a/.github/workflows/nightly_build_release.yml +++ b/.github/workflows/nightly_build_on_dispatch.yml @@ -1,8 +1,6 @@ -name: Nightly builds on latest release +name: Nightly builds on dispatch -on: - schedule: - - cron: '14 2 * * *' +on: workflow_dispatch jobs: matrix_prep: runs-on: ubuntu-20.04 @@ -14,23 +12,10 @@ jobs: - id: set-matrix uses: JoshuaTheMiller/conditional-build-matrix@main with: - inputFile: '.github/workflows/nightly_build_matrix_includes.json' + inputFile: '.github/workflows/nightly_build_matrix_on_dispatch.json' filter: '[?runOnEvent==`${{ github.event_name }}` || runOnEvent==`always`]' - get_release: - runs-on: ubuntu-20.04 - needs: matrix_prep - outputs: - output1: ${{ steps.step2.outputs.latest_release }} - steps: - - name: Check out repository code - uses: actions/checkout@v3 - - name: Fetch all branches - run: git fetch --all - - name: Set output variable to latest release branch - id: step2 - run: echo "latest_release=$(git branch -r | grep -E 'release/v[0-9]+\.[0-9]+\.[0-9]+-' | sort -V | tail -n 1 | sed 's/ origin\///')" >> $GITHUB_OUTPUT build: - needs: [get_release,matrix_prep] + needs: matrix_prep strategy: matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}} runs-on: ${{ matrix.os }} @@ -41,10 +26,8 @@ jobs: continue-on-error: true if: matrix.os == 'ubuntu-20.04' - - name: Check out latest release branch + - name: Check out repository code uses: actions/checkout@v3 - with: - ref: ${{needs.get_release.outputs.output1}} - name: Install rust toolchain uses: actions-rs/toolchain@v1 @@ -156,7 +139,7 @@ jobs: args: --manifest-path nym-wallet/Cargo.toml --workspace --all-targets -- -D warnings notification: - needs: [build,get_release] + needs: build runs-on: custom-runner-linux steps: - name: Collect jobs status @@ -176,10 +159,10 @@ jobs: if: env.WORKFLOW_CONCLUSION == 'failure' env: NYM_NOTIFICATION_KIND: nightly - NYM_PROJECT_NAME: "Nym nightly build on latest release" + NYM_PROJECT_NAME: "Nym nightly build" GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}" - GIT_BRANCH_NAME: "${{needs.get_release.outputs.output1}}" + GIT_BRANCH: "${GITHUB_REF##*/}" IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}" MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}" MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_NIGHTLY }}" diff --git a/.github/workflows/nightly_build_release2.yml b/.github/workflows/nightly_build_release2.yml deleted file mode 100644 index 3c3f962582..0000000000 --- a/.github/workflows/nightly_build_release2.yml +++ /dev/null @@ -1,191 +0,0 @@ -name: Nightly builds on second latest release - -on: - schedule: - - cron: '24 2 * * *' -jobs: - matrix_prep: - runs-on: ubuntu-20.04 - outputs: - matrix: ${{ steps.set-matrix.outputs.matrix }} - steps: - # creates the matrix strategy from nightly_build_matrix_includes.json - - uses: actions/checkout@v3 - - id: set-matrix - uses: JoshuaTheMiller/conditional-build-matrix@main - with: - inputFile: '.github/workflows/nightly_build_matrix_includes.json' - filter: '[?runOnEvent==`${{ github.event_name }}` || runOnEvent==`always`]' - get_release: - runs-on: ubuntu-20.04 - needs: matrix_prep - outputs: - output1: ${{ steps.step2.outputs.latest_release }} - steps: - - name: Check out repository code - uses: actions/checkout@v3 - - name: Fetch all branches - run: git fetch --all - - name: Set output variable to latest release branch - id: step2 - run: echo "latest_release=$(git branch -r | grep -E 'release/v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -n 2 | head -n 1 | sed 's/ origin\///')" >> $GITHUB_OUTPUT - build: - needs: [get_release,matrix_prep] - strategy: - matrix: ${{fromJson(needs.matrix_prep.outputs.matrix)}} - runs-on: ${{ matrix.os }} - continue-on-error: ${{ matrix.rust == 'nightly' || matrix.rust == 'beta' || matrix.rust == 'stable' }} - steps: - - name: Install Dependencies (Linux) - run: sudo apt-get update && sudo apt-get install libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools - continue-on-error: true - if: matrix.os == 'ubuntu-20.04' - - - name: Check out latest release branch - uses: actions/checkout@v3 - with: - ref: ${{needs.get_release.outputs.output1}} - - - name: Install rust toolchain - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: ${{ matrix.rust }} - override: true - components: rustfmt, clippy - - - name: Check formatting - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all -- --check - - - name: Build all binaries - uses: actions-rs/cargo@v1 - with: - command: build - args: --workspace - - - name: Reclaim some disk space (because Windows is being annoying) - uses: actions-rs/cargo@v1 - if: ${{ matrix.os == 'windows-latest' }} - with: - command: clean - - - name: Build all examples - uses: actions-rs/cargo@v1 - with: - command: build - args: --workspace --examples - - - name: Reclaim some disk space (because Windows is being annoying) - uses: actions-rs/cargo@v1 - if: ${{ matrix.os == 'windows-latest' }} - with: - command: clean - - - name: Run all tests - uses: actions-rs/cargo@v1 - with: - command: test - args: --workspace - - - name: Reclaim some disk space (because Windows is being annoying) - uses: actions-rs/cargo@v1 - if: ${{ matrix.os == 'windows-latest' || matrix.os == 'ubuntu-20.04' }} - with: - command: clean - - - name: Run expensive tests - if: github.ref == 'refs/heads/develop' || github.event.pull_request.base.ref == 'develop' || github.event.pull_request.base.ref == 'master' - uses: actions-rs/cargo@v1 - with: - command: test - args: --workspace -- --ignored - - - name: Reclaim some disk space (because Windows is being annoying) - uses: actions-rs/cargo@v1 - if: ${{ matrix.os == 'windows-latest' }} - with: - command: clean - - - uses: actions-rs/clippy-check@v1 - name: Clippy checks - continue-on-error: true - with: - token: ${{ secrets.GITHUB_TOKEN }} - args: --workspace - - - name: Run clippy - uses: actions-rs/cargo@v1 - if: ${{ matrix.rust != 'nightly' }} - with: - command: clippy - args: --workspace --all-targets -- -D warnings - - - name: Reclaim some disk space - uses: actions-rs/cargo@v1 - if: ${{ matrix.os == 'windows-latest' || matrix.os == 'ubuntu-20.04' }} - with: - command: clean - - # nym-wallet (the rust part) - - name: Build nym-wallet rust code - uses: actions-rs/cargo@v1 - with: - command: build - args: --manifest-path nym-wallet/Cargo.toml --workspace - - - name: Run nym-wallet tests - uses: actions-rs/cargo@v1 - with: - command: test - args: --manifest-path nym-wallet/Cargo.toml --workspace - - - name: Check nym-wallet formatting - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --manifest-path nym-wallet/Cargo.toml --all -- --check - - - name: Run clippy for nym-wallet - uses: actions-rs/cargo@v1 - if: ${{ matrix.rust != 'nightly' }} - with: - command: clippy - args: --manifest-path nym-wallet/Cargo.toml --workspace --all-targets -- -D warnings - - notification: - needs: [build,get_release] - runs-on: custom-runner-linux - steps: - - name: Collect jobs status - uses: technote-space/workflow-conclusion-action@v2 - - name: Check out repository code - uses: actions/checkout@v3 - - name: install npm - uses: actions/setup-node@v3 - if: env.WORKFLOW_CONCLUSION == 'failure' - with: - node-version: 18 - - name: Matrix - Node Install - if: env.WORKFLOW_CONCLUSION == 'failure' - run: npm install - working-directory: .github/workflows/support-files - - name: Matrix - Send Notification - if: env.WORKFLOW_CONCLUSION == 'failure' - env: - NYM_NOTIFICATION_KIND: nightly - NYM_PROJECT_NAME: "Nym nightly build on latest release" - GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" - GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}" - GIT_BRANCH_NAME: "${{needs.get_release.outputs.output1}}" - IS_SUCCESS: "${{ env.WORKFLOW_CONCLUSION == 'success' }}" - MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}" - MATRIX_ROOM: "${{ secrets.MATRIX_ROOM_NIGHTLY }}" - MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}" - MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}" - MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}" - uses: docker://keybaseio/client:stable-node - with: - args: .github/workflows/support-files/notifications/entry_point.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 4134fbebda..fe08ef04e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,28 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// ## [Unreleased] +## [2023.1-milka] (2023-09-24) + +- custom Debug impl for mix::Node and gateway::Node ([#3930]) +- added forceTls argument to 'MixFetchOptsSimple' ([#3907]) +- Enable loop cover traffic by default in NR ([#3904]) +- Fix all the cargo warnings ([#3899]) +- [Issue] nym-socks5-client crash on UDP request ([#3898]) +- Feature/gateway inbuilt nr ([#3877]) +- removed queued mixnet migration that was already run ([#3872]) +- [feat] Socks5 and Native client: run with hardcoded topology ([#3866]) +- Introduce a local network requester directly inside a gateway ([#3838]) + +[#3930]: https://github.com/nymtech/nym/pull/3930 +[#3907]: https://github.com/nymtech/nym/pull/3907 +[#3904]: https://github.com/nymtech/nym/pull/3904 +[#3899]: https://github.com/nymtech/nym/pull/3899 +[#3898]: https://github.com/nymtech/nym/issues/3898 +[#3877]: https://github.com/nymtech/nym/pull/3877 +[#3872]: https://github.com/nymtech/nym/pull/3872 +[#3866]: https://github.com/nymtech/nym/pull/3866 +[#3838]: https://github.com/nymtech/nym/issues/3838 + ## [v1.1.31-kitkat] (2023-09-12) - feat: add name to `TaskClient` ([#3844]) diff --git a/Cargo.lock b/Cargo.lock index 4454ef48e4..ac05eb6c74 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -36,7 +36,7 @@ dependencies = [ "actix-service", "actix-utils", "ahash 0.8.3", - "base64 0.21.2", + "base64 0.21.4", "bitflags 1.3.2", "brotli", "bytes", @@ -631,6 +631,17 @@ dependencies = [ "event-listener", ] +[[package]] +name = "async-recursion" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "async-stream" version = "0.3.5" @@ -819,9 +830,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.2" +version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" [[package]] name = "base64ct" @@ -1030,6 +1041,29 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "845141a4fade3f790628b7daaaa298a25b204fb28907eb54febe5142db6ce653" +[[package]] +name = "boringtun" +version = "0.6.0" +source = "git+https://github.com/cloudflare/boringtun?rev=e1d6360d6ab4529fc942a078e4c54df107abe2ba#e1d6360d6ab4529fc942a078e4c54df107abe2ba" +dependencies = [ + "aead 0.5.2", + "base64 0.13.1", + "blake2 0.10.6", + "chacha20poly1305 0.10.1", + "hex", + "hmac 0.12.1", + "ip_network", + "ip_network_table", + "libc", + "nix 0.25.1", + "parking_lot 0.12.1", + "rand_core 0.6.4", + "ring", + "tracing", + "untrusted 0.9.0", + "x25519-dalek 2.0.0", +] + [[package]] name = "brotli" version = "3.3.4" @@ -1096,9 +1130,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" dependencies = [ "serde", ] @@ -2107,18 +2141,31 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.0.0-rc.1" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d4ba9852b42210c7538b75484f9daa0655e9a3ac04f693747bb0f02cf3cfe16" +checksum = "622178105f911d937a42cdb140730ba4a3ed2becd8ae6ce39c7d28b5d75d4588" dependencies = [ "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", "fiat-crypto", - "packed_simd_2", "platforms", + "rustc_version 0.4.0", "subtle 2.4.1", "zeroize", ] +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "curve25519-dalek-ng" version = "4.1.1" @@ -2300,19 +2347,9 @@ dependencies = [ [[package]] name = "dashmap" -version = "4.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" -dependencies = [ - "cfg-if", - "num_cpus", -] - -[[package]] -name = "dashmap" -version = "5.5.0" +version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6943ae99c34386c84a470c499d3414f66502a41340aa895406e0d2e4a207b91d" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", "hashbrown 0.14.0", @@ -2983,7 +3020,7 @@ dependencies = [ [[package]] name = "extension-storage" -version = "1.2.0-rc.2" +version = "1.2.0-rc.9" dependencies = [ "bip39", "console_error_panic_hook", @@ -3085,9 +3122,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.1.20" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" +checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" [[package]] name = "figment" @@ -4214,6 +4251,28 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "ip_network" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2f047c0a98b2f299aa5d6d7088443570faae494e9ae1305e48be000c9e0eb1" + +[[package]] +name = "ip_network_table" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4099b7cfc5c5e2fe8c5edf3f6f7adf7a714c9cc697534f63a5a5da30397cb2c0" +dependencies = [ + "ip_network", + "ip_network_table-deps-treebitmap", +] + +[[package]] +name = "ip_network_table-deps-treebitmap" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e537132deb99c0eb4b752f0346b6a836200eaaa3516dd7e5514b63930a09e5d" + [[package]] name = "ipconfig" version = "0.3.1" @@ -4508,12 +4567,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "libm" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" - [[package]] name = "libm" version = "0.2.7" @@ -4699,7 +4752,7 @@ version = "0.44.0" source = "git+https://github.com/ChainSafe/rust-libp2p.git?rev=e3440d25681df380c9f0f8cfdcfd5ecc0a4f2fb6#e3440d25681df380c9f0f8cfdcfd5ecc0a4f2fb6" dependencies = [ "asynchronous-codec", - "base64 0.21.2", + "base64 0.21.4", "byteorder", "bytes", "fnv", @@ -4729,7 +4782,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70b34b6da8165c0bde35c82db8efda39b824776537e73973549e76cadb3a77c5" dependencies = [ "asynchronous-codec", - "base64 0.21.2", + "base64 0.21.4", "byteorder", "bytes", "either", @@ -5560,7 +5613,7 @@ dependencies = [ [[package]] name = "mix-fetch-wasm" -version = "1.2.0-rc.2" +version = "1.2.0-rc.9" dependencies = [ "futures", "js-sys", @@ -5806,6 +5859,18 @@ dependencies = [ "memoffset 0.6.5", ] +[[package]] +name = "nix" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +dependencies = [ + "autocfg 1.1.0", + "bitflags 1.3.2", + "cfg-if", + "libc", +] + [[package]] name = "no-std-compat" version = "0.4.1" @@ -5913,7 +5978,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg 1.1.0", - "libm 0.2.7", + "libm", ] [[package]] @@ -6187,9 +6252,9 @@ name = "nym-client-core" version = "1.1.15" dependencies = [ "async-trait", - "base64 0.21.2", + "base64 0.21.4", "cfg-if", - "dashmap 5.5.0", + "dashmap", "dirs 4.0.0", "futures", "gloo-timers", @@ -6233,7 +6298,7 @@ dependencies = [ [[package]] name = "nym-client-wasm" -version = "1.2.0-rc.2" +version = "1.2.0-rc.9" dependencies = [ "anyhow", "futures", @@ -6487,7 +6552,7 @@ dependencies = [ "bs58 0.4.0", "clap 4.3.21", "colored", - "dashmap 4.0.2", + "dashmap", "dirs 4.0.0", "dotenvy", "futures", @@ -6504,12 +6569,14 @@ dependencies = [ "nym-mixnet-client", "nym-mixnode-common", "nym-network-defaults", + "nym-network-requester", "nym-pemstore", "nym-sphinx", "nym-statistics-common", "nym-task", "nym-types", "nym-validator-client", + "nym-wireguard", "once_cell", "pretty_env_logger", "rand 0.7.3", @@ -6850,7 +6917,7 @@ dependencies = [ [[package]] name = "nym-node-tester-wasm" -version = "1.2.0-rc.2" +version = "1.2.0-rc.9" dependencies = [ "futures", "js-sys", @@ -7026,6 +7093,7 @@ dependencies = [ "nym-sphinx", "nym-topology", "pretty_env_logger", + "rand 0.7.3", "serde", "serde_json", "tap", @@ -7038,6 +7106,7 @@ dependencies = [ name = "nym-socks5-client-core" version = "0.1.0" dependencies = [ + "anyhow", "dirs 4.0.0", "futures", "log", @@ -7306,6 +7375,7 @@ dependencies = [ "tokio", "wasm-bindgen", "wasm-bindgen-futures", + "wasmtimer", ] [[package]] @@ -7316,6 +7386,7 @@ dependencies = [ "bs58 0.4.0", "log", "nym-bin-common", + "nym-config", "nym-crypto", "nym-mixnet-contract-common", "nym-sphinx-addressing", @@ -7323,7 +7394,12 @@ dependencies = [ "nym-sphinx-types", "rand 0.7.3", "semver 0.11.0", + "serde", + "serde_json", "thiserror", + "tsify", + "wasm-bindgen", + "wasm-utils", ] [[package]] @@ -7435,13 +7511,29 @@ dependencies = [ [[package]] name = "nym-wasm-sdk" -version = "1.2.0-rc.2" +version = "1.2.0-rc.9" dependencies = [ "mix-fetch-wasm", "nym-client-wasm", "nym-node-tester-wasm", ] +[[package]] +name = "nym-wireguard" +version = "0.1.0" +dependencies = [ + "async-recursion", + "base64 0.21.4", + "boringtun", + "bytes", + "futures", + "log", + "nym-task", + "tap", + "thiserror", + "tokio", +] + [[package]] name = "object" version = "0.31.1" @@ -7635,7 +7727,7 @@ checksum = "8b3a2a91fdbfdd4d212c0dcc2ab540de2c2bcbbd90be17de7a7daf8822d010c1" dependencies = [ "async-trait", "crossbeam-channel", - "dashmap 5.5.0", + "dashmap", "fnv", "futures-channel", "futures-executor", @@ -7698,16 +7790,6 @@ dependencies = [ "sha2 0.10.7", ] -[[package]] -name = "packed_simd_2" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1914cd452d8fccd6f9db48147b29fd4ae05bea9dc5d9ad578509f72415de282" -dependencies = [ - "cfg-if", - "libm 0.1.4", -] - [[package]] name = "pairing" version = "0.20.0" @@ -8224,13 +8306,13 @@ dependencies = [ [[package]] name = "prometheus-client-derive-encode" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b6a5217beb0ad503ee7fa752d451c905113d70721b937126158f3106a48cc1" +checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", ] [[package]] @@ -8792,7 +8874,7 @@ version = "0.11.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" dependencies = [ - "base64 0.21.2", + "base64 0.21.4", "bytes", "encoding_rs", "futures-core", @@ -8865,7 +8947,7 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] @@ -9036,7 +9118,7 @@ dependencies = [ "log", "netlink-packet-route", "netlink-proto", - "nix", + "nix 0.24.3", "thiserror", "tokio", ] @@ -9226,7 +9308,7 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ - "base64 0.21.2", + "base64 0.21.4", ] [[package]] @@ -9236,7 +9318,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e98ff011474fa39949b7e5c0428f9b4937eda7da7848bbb947786b7be0b27dab" dependencies = [ "ring", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -9246,7 +9328,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" dependencies = [ "ring", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -9374,7 +9456,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" dependencies = [ "ring", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -9384,7 +9466,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" dependencies = [ "ring", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -9828,14 +9910,14 @@ dependencies = [ [[package]] name = "snow" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ccba027ba85743e09d15c03296797cad56395089b832b48b5a5217880f57733" +checksum = "0c9d1425eb528a21de2755c75af4c9b5d57f50a0d4c3b7f1828a4cd03f8ba155" dependencies = [ "aes-gcm 0.9.4", "blake2 0.10.6", "chacha20poly1305 0.9.1", - "curve25519-dalek 4.0.0-rc.1", + "curve25519-dalek 4.1.0", "rand_core 0.6.4", "ring", "rustc_version 0.4.0", @@ -10874,7 +10956,7 @@ checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" dependencies = [ "async-trait", "axum", - "base64 0.21.2", + "base64 0.21.4", "bytes", "futures-core", "futures-util", @@ -11400,6 +11482,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "unwind_safe" version = "0.1.0" @@ -11412,7 +11500,7 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b11c96ac7ee530603dcdf68ed1557050f374ce55a5a07193ebf8cbc9f8927e9" dependencies = [ - "base64 0.21.2", + "base64 0.21.4", "log", "native-tls", "once_cell", @@ -11805,7 +11893,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" dependencies = [ "ring", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -11815,7 +11903,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" dependencies = [ "ring", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -11938,7 +12026,7 @@ dependencies = [ "tokio", "webpki 0.21.4", "webrtc-util", - "x25519-dalek 2.0.0-pre.1", + "x25519-dalek 2.0.0", "x509-parser 0.13.2", ] @@ -12047,7 +12135,7 @@ dependencies = [ "lazy_static", "libc", "log", - "nix", + "nix 0.24.3", "rand 0.8.5", "thiserror", "tokio", @@ -12347,12 +12435,13 @@ dependencies = [ [[package]] name = "x25519-dalek" -version = "2.0.0-pre.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5da623d8af10a62342bcbbb230e33e58a63255a58012f8653c578e54bab48df" +checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96" dependencies = [ - "curve25519-dalek 3.2.0", + "curve25519-dalek 4.1.0", "rand_core 0.6.4", + "serde", "zeroize", ] diff --git a/Cargo.toml b/Cargo.toml index 5099ec2098..886b9a70f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -77,6 +77,7 @@ members = [ "common/wasm/client-core", "common/wasm/storage", "common/wasm/utils", + "common/wireguard", "explorer-api", "explorer-api/explorer-api-requests", "explorer-api/explorer-client", @@ -145,6 +146,7 @@ cw2 = { version = "=1.1.0" } cw3 = { version = "=1.1.0" } cw4 = { version = "=1.1.0" } cw-controllers = { version = "=1.1.0" } +dashmap = "5.5.3" dotenvy = "0.15.6" futures = "0.3.28" generic-array = "0.14.7" @@ -153,6 +155,7 @@ k256 = "0.13" lazy_static = "1.4.0" log = "0.4" once_cell = "1.7.2" +parking_lot = "0.12.1" rand = "0.8.5" reqwest = "0.11.18" serde = "1.0.152" @@ -174,3 +177,25 @@ wasm-bindgen = "0.2.86" wasm-bindgen-futures = "0.4.37" wasmtimer = "0.2.0" web-sys = "0.3.63" + +# Profile settings for individual crates + +[profile.release.package.nym-socks5-listener] +strip = true +codegen-units = 1 + +[profile.release.package.nym-client-wasm] +# lto = true +opt-level = 'z' + +[profile.release.package.nym-node-tester-wasm] +# lto = true +opt-level = 'z' + +[profile.release.package.nym-wasm-sdk] +# lto = true +opt-level = 'z' + +[profile.release.package.mix-fetch-wasm] +# lto = true +opt-level = 'z' diff --git a/Makefile b/Makefile index a713d6c325..56872e0c8c 100644 --- a/Makefile +++ b/Makefile @@ -109,20 +109,27 @@ sdk-wasm-build: # client $(MAKE) -C wasm/client build + # client (node) + $(MAKE) -C wasm/client build-node + # node-tester $(MAKE) -C wasm/node-tester build # mix-fetch $(MAKE) -C wasm/mix-fetch build + # mix-fetch (node) + $(MAKE) -C wasm/mix-fetch build-node + # full $(MAKE) -C wasm/full-nym-wasm build-full # run this from npm/yarn to ensure tools are in the path, e.g. yarn build:sdk from root of repo sdk-typescript-build: - lerna run --scope @nymproject/sdk build --stream - lerna run --scope @nymproject/mix-fetch build --stream - lerna run --scope @nymproject/node-tester build --stream + npx lerna run --scope @nymproject/sdk build --stream + npx lerna run --scope @nymproject/mix-fetch build --stream + npx lerna run --scope @nymproject/node-tester build --stream + yarn --cwd sdk/typescript/codegen/contract-clients build sdk-wasm-test: # # client diff --git a/clients/native/Cargo.toml b/clients/native/Cargo.toml index 8b7f695260..8e025c7e09 100644 --- a/clients/native/Cargo.toml +++ b/clients/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-client" -version = "1.1.29" +version = "1.1.30" authors = ["Dave Hrycyszyn ", "Jędrzej Stuczyński "] description = "Implementation of the Nym Client" edition = "2021" diff --git a/clients/native/src/client/config/mod.rs b/clients/native/src/client/config/mod.rs index dd819471d8..4f57387ceb 100644 --- a/clients/native/src/client/config/mod.rs +++ b/clients/native/src/client/config/mod.rs @@ -67,7 +67,7 @@ pub struct Config { } impl NymConfigTemplate for Config { - fn template() -> &'static str { + fn template(&self) -> &'static str { CONFIG_TEMPLATE } } diff --git a/clients/native/src/client/config/persistence.rs b/clients/native/src/client/config/persistence.rs index d84c956d8f..a61913a2f7 100644 --- a/clients/native/src/client/config/persistence.rs +++ b/clients/native/src/client/config/persistence.rs @@ -14,7 +14,7 @@ pub struct ClientPaths { impl ClientPaths { pub fn new_default>(base_data_directory: P) -> Self { ClientPaths { - common_paths: CommonClientPaths::new_default(base_data_directory), + common_paths: CommonClientPaths::new_base(base_data_directory), } } } diff --git a/clients/native/src/client/mod.rs b/clients/native/src/client/mod.rs index 6f3982038f..f262d5e26b 100644 --- a/clients/native/src/client/mod.rs +++ b/clients/native/src/client/mod.rs @@ -4,27 +4,19 @@ use crate::client::config::Config; use crate::error::ClientError; use crate::websocket; -use futures::channel::mpsc; use log::*; use nym_client_core::client::base_client::non_wasm_helpers::default_query_dkg_client_from_config; use nym_client_core::client::base_client::storage::OnDiskPersistent; use nym_client_core::client::base_client::{ BaseClientBuilder, ClientInput, ClientOutput, ClientState, }; -use nym_client_core::client::inbound_messages::InputMessage; -use nym_client_core::client::received_buffer::{ - ReceivedBufferMessage, ReceivedBufferRequestSender, ReconstructedMessagesReceiver, -}; -use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag; use nym_sphinx::params::PacketType; -use nym_task::connections::TransmissionLane; -use nym_task::TaskManager; +use nym_task::TaskHandle; use nym_validator_client::QueryHttpRpcNyxdClient; use std::error::Error; -use tokio::sync::watch::error::SendError; +use std::path::PathBuf; pub use nym_sphinx::addressing::clients::Recipient; -pub use nym_sphinx::receiver::ReconstructedMessage; pub mod config; @@ -34,11 +26,17 @@ pub struct SocketClient { /// Client configuration options, including, among other things, packet sending rates, /// key filepaths, etc. config: Config, + + /// Optional path to a .json file containing standalone network details. + custom_mixnet: Option, } impl SocketClient { - pub fn new(config: Config) -> Self { - SocketClient { config } + pub fn new(config: Config, custom_mixnet: Option) -> Self { + SocketClient { + config, + custom_mixnet, + } } fn start_websocket_listener( @@ -85,7 +83,7 @@ impl SocketClient { pub async fn run_socket_forever(self) -> Result<(), Box> { let shutdown = self.start_socket().await?; - let res = shutdown.catch_interrupt().await; + let res = shutdown.wait_for_shutdown().await; log::info!("Stopping nym-client"); res } @@ -109,12 +107,16 @@ impl SocketClient { let storage = self.initialise_storage().await?; - let base_client = BaseClientBuilder::new(&self.config.base, storage, dkg_query_client); + let mut base_client = BaseClientBuilder::new(&self.config.base, storage, dkg_query_client); + + if let Some(custom_mixnet) = &self.custom_mixnet { + base_client = base_client.with_stored_topology(custom_mixnet)?; + } Ok(base_client) } - pub async fn start_socket(self) -> Result { + pub async fn start_socket(self) -> Result { if !self.config.socket.socket_type.is_websocket() { return Err(ClientError::InvalidSocketMode); } @@ -133,141 +135,13 @@ impl SocketClient { client_output, client_state, &self_address, - started_client.task_manager.subscribe(), + started_client.task_handle.get_handle(), packet_type, ); info!("Client startup finished!"); info!("The address of this client is: {self_address}"); - Ok(started_client.task_manager) - } - - pub async fn start_direct(self) -> Result { - if self.config.socket.socket_type.is_websocket() { - return Err(ClientError::InvalidSocketMode); - } - - let base_builder = self.create_base_client_builder().await?; - let packet_type = self.config.base.debug.traffic.packet_type; - let mut started_client = base_builder.start_base().await?; - let address = started_client.address; - let client_input = started_client.client_input.register_producer(); - let client_output = started_client.client_output.register_consumer(); - - // register our receiver - let (reconstructed_sender, reconstructed_receiver) = mpsc::unbounded(); - - // tell the buffer to start sending stuff to us - client_output - .received_buffer_request_sender - .unbounded_send(ReceivedBufferMessage::ReceiverAnnounce( - reconstructed_sender, - )) - .expect("the buffer request failed!"); - - Ok(DirectClient { - client_input, - _received_buffer_request_sender: client_output.received_buffer_request_sender, - reconstructed_receiver, - address, - shutdown_notifier: started_client.task_manager, - packet_type, - }) - } -} - -pub struct DirectClient { - client_input: ClientInput, - // make sure to not drop the channel - _received_buffer_request_sender: ReceivedBufferRequestSender, - reconstructed_receiver: ReconstructedMessagesReceiver, - address: Recipient, - - // we need to keep reference to this guy otherwise things will start dropping - shutdown_notifier: TaskManager, - packet_type: PacketType, -} - -impl DirectClient { - pub fn address(&self) -> &Recipient { - &self.address - } - - pub fn signal_shutdown(&self) -> Result<(), SendError<()>> { - self.shutdown_notifier.signal_shutdown() - } - - pub async fn wait_for_shutdown(&mut self) { - self.shutdown_notifier.wait_for_shutdown().await - } - - /// EXPERIMENTAL DIRECT RUST API - /// It's untested and there are absolutely no guarantees about it (but seems to have worked - /// well enough in local tests) - pub async fn send_regular_message(&mut self, recipient: Recipient, message: Vec) { - let lane = TransmissionLane::General; - let input_msg = InputMessage::new_regular(recipient, message, lane, Some(self.packet_type)); - - self.client_input - .input_sender - .send(input_msg) - .await - .expect("InputMessageReceiver has stopped receiving!"); - } - - /// EXPERIMENTAL DIRECT RUST API - /// It's untested and there are absolutely no guarantees about it (but seems to have worked - /// well enough in local tests) - pub async fn send_anonymous_message( - &mut self, - recipient: Recipient, - message: Vec, - reply_surbs: u32, - ) { - let lane = TransmissionLane::General; - let input_msg = InputMessage::new_anonymous( - recipient, - message, - reply_surbs, - lane, - Some(self.packet_type), - ); - - self.client_input - .input_sender - .send(input_msg) - .await - .expect("InputMessageReceiver has stopped receiving!"); - } - - /// EXPERIMENTAL DIRECT RUST API - /// It's untested and there are absolutely no guarantees about it (but seems to have worked - /// well enough in local tests) - pub async fn send_reply(&mut self, recipient_tag: AnonymousSenderTag, message: Vec) { - let lane = TransmissionLane::General; - let input_msg = - InputMessage::new_reply(recipient_tag, message, lane, Some(self.packet_type)); - - self.client_input - .input_sender - .send(input_msg) - .await - .expect("InputMessageReceiver has stopped receiving!"); - } - - /// EXPERIMENTAL DIRECT RUST API - /// It's untested and there are absolutely no guarantees about it (but seems to have worked - /// well enough in local tests) - /// Note: it waits for the first occurrence of messages being sent to ourselves. If you expect multiple - /// messages, you might have to call this function repeatedly. - // TODO: I guess this should really return something that `impl Stream` - pub async fn wait_for_messages(&mut self) -> Vec { - use futures::StreamExt; - - self.reconstructed_receiver - .next() - .await - .expect("buffer controller seems to have somehow died!") + Ok(started_client.task_handle) } } diff --git a/clients/native/src/commands/init.rs b/clients/native/src/commands/init.rs index d61b31b52d..0fc27590dd 100644 --- a/clients/native/src/commands/init.rs +++ b/clients/native/src/commands/init.rs @@ -15,12 +15,16 @@ use nym_bin_common::output_format::OutputFormat; use nym_client_core::client::base_client::storage::gateway_details::OnDiskGatewayDetails; use nym_client_core::client::key_manager::persistence::OnDiskKeys; use nym_client_core::config::GatewayEndpointConfig; -use nym_client_core::init::GatewaySetup; +use nym_client_core::error::ClientCoreError; +use nym_client_core::init::helpers::current_gateways; +use nym_client_core::init::types::{GatewayDetails, GatewaySelectionSpecification, GatewaySetup}; use nym_crypto::asymmetric::identity; use nym_sphinx::addressing::clients::Recipient; +use nym_topology::NymTopology; use serde::Serialize; use std::fmt::Display; use std::net::IpAddr; +use std::path::PathBuf; use std::{fs, io}; use tap::TapFallible; @@ -49,7 +53,12 @@ pub(crate) struct Init { nyxd_urls: Option>, /// Comma separated list of rest endpoints of the API validators - #[clap(long, alias = "api_validators", value_delimiter = ',')] + #[clap( + long, + alias = "api_validators", + value_delimiter = ',', + group = "network" + )] // the alias here is included for backwards compatibility (1.1.4 and before) nym_apis: Option>, @@ -65,6 +74,10 @@ pub(crate) struct Init { #[clap(long)] host: Option, + /// Path to .json file containing custom network specification. + #[clap(long, group = "network", hide = true)] + custom_mixnet: Option, + /// Mostly debug-related option to increase default traffic rate so that you would not need to /// modify config post init #[clap(long, hide = true)] @@ -102,7 +115,7 @@ impl From for OverrideConfig { #[derive(Debug, Serialize)] pub struct InitResults { #[serde(flatten)] - client_core: nym_client_core::init::InitResults, + client_core: nym_client_core::init::types::InitResults, client_listening_port: u16, client_address: String, } @@ -110,7 +123,11 @@ pub struct InitResults { impl InitResults { fn new(config: &Config, address: &Recipient, gateway: &GatewayEndpointConfig) -> Self { Self { - client_core: nym_client_core::init::InitResults::new(&config.base, address, gateway), + client_core: nym_client_core::init::types::InitResults::new( + &config.base, + address, + gateway, + ), client_listening_port: config.socket.listening_port, client_address: address.to_string(), } @@ -130,7 +147,7 @@ fn init_paths(id: &str) -> io::Result<()> { fs::create_dir_all(default_config_directory(id)) } -pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> { +pub(crate) async fn execute(args: Init) -> Result<(), ClientError> { eprintln!("Initialising client..."); let id = &args.id; @@ -150,7 +167,7 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> { // re-registering if wanted. let user_wants_force_register = args.force_register_gateway; if user_wants_force_register { - eprintln!("Instructed to force registering gateway. This might overwrite keys!"); + eprintln!("Instructed to force registering gateway. This will overwrite keys!"); } // If the client was already initialized, don't generate new keys and don't re-register with @@ -160,9 +177,10 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> { // Attempt to use a user-provided gateway, if possible let user_chosen_gateway_id = args.gateway; - let gateway_setup = GatewaySetup::new_fresh( + let selection_spec = GatewaySelectionSpecification::new( user_chosen_gateway_id.map(|id| id.to_base58_string()), Some(args.latency_based_selection), + false, ); // Load and potentially override config @@ -173,16 +191,29 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> { let key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone()); let details_store = OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details); - let init_details = nym_client_core::init::setup_gateway( - gateway_setup, - &key_store, - &details_store, - register_gateway, - Some(&config.base.client.nym_api_urls), - ) - .await - .tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))? - .details; + + let available_gateways = if let Some(hardcoded_topology) = args + .custom_mixnet + .map(NymTopology::new_from_file) + .transpose()? + { + // hardcoded_topology + hardcoded_topology.get_gateways() + } else { + let mut rng = rand::thread_rng(); + current_gateways(&mut rng, &config.base.client.nym_api_urls).await? + }; + + let gateway_setup = GatewaySetup::New { + specification: selection_spec, + available_gateways, + overwrite_data: register_gateway, + }; + + let init_details = + nym_client_core::init::setup_gateway(gateway_setup, &key_store, &details_store) + .await + .tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?; let config_save_location = config.default_location(); config.save_to_default_location().tap_err(|_| { @@ -197,7 +228,10 @@ pub(crate) async fn execute(args: &Init) -> Result<(), ClientError> { eprintln!("Client configuration completed.\n"); - let init_results = InitResults::new(&config, &address, &init_details.gateway_details); + let GatewayDetails::Configured(gateway_details) = init_details.gateway_details else { + return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails)?; + }; + let init_results = InitResults::new(&config, &address, &gateway_details); println!("{}", args.output.format(&init_results)); Ok(()) diff --git a/clients/native/src/commands/mod.rs b/clients/native/src/commands/mod.rs index e1896bcfb6..3ebe929b16 100644 --- a/clients/native/src/commands/mod.rs +++ b/clients/native/src/commands/mod.rs @@ -84,8 +84,8 @@ pub(crate) async fn execute(args: Cli) -> Result<(), Box init::execute(&m).await?, - Commands::Run(m) => run::execute(&m).await?, + Commands::Init(m) => init::execute(m).await?, + Commands::Run(m) => run::execute(m).await?, Commands::BuildInfo(m) => build_info::execute(m), Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name), Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name), @@ -133,7 +133,7 @@ fn persist_gateway_details( source: Box::new(source), }) })?; - let persisted_details = PersistedGatewayDetails::new(details, &shared_keys); + let persisted_details = PersistedGatewayDetails::new(details.into(), Some(&shared_keys))?; details_store .store_to_disk(&persisted_details) .map_err(|source| { diff --git a/clients/native/src/commands/run.rs b/clients/native/src/commands/run.rs index 23cf54588b..8a61f8147c 100644 --- a/clients/native/src/commands/run.rs +++ b/clients/native/src/commands/run.rs @@ -13,6 +13,7 @@ use nym_bin_common::version_checker::is_minor_version_compatible; use nym_crypto::asymmetric::identity; use std::error::Error; use std::net::IpAddr; +use std::path::PathBuf; #[derive(Args, Clone)] pub(crate) struct Run { @@ -25,7 +26,12 @@ pub(crate) struct Run { nyxd_urls: Option>, /// Comma separated list of rest endpoints of the API validators - #[clap(long, alias = "api_validators", value_delimiter = ',')] + #[clap( + long, + alias = "api_validators", + value_delimiter = ',', + group = "network" + )] // the alias here is included for backwards compatibility (1.1.4 and before) nym_apis: Option>, @@ -46,6 +52,10 @@ pub(crate) struct Run { #[clap(long)] host: Option, + /// Path to .json file containing custom network specification. + #[clap(long, group = "network", hide = true)] + custom_mixnet: Option, + /// Mostly debug-related option to increase default traffic rate so that you would not need to /// modify config post init #[clap(long, hide = true)] @@ -95,7 +105,7 @@ fn version_check(cfg: &Config) -> bool { } } -pub(crate) async fn execute(args: &Run) -> Result<(), Box> { +pub(crate) async fn execute(args: Run) -> Result<(), Box> { eprintln!("Starting client {}...", args.id); let mut config = try_load_current_config(&args.id)?; @@ -106,5 +116,7 @@ pub(crate) async fn execute(args: &Run) -> Result<(), Box()].as_ref().try_into().unwrap()); + let message_len = u64::from_be_bytes(b[2..2 + size_of::()].try_into().unwrap()); let message = &b[2 + size_of::()..]; if message.len() as u64 != message_len { return Err(error::Error::new( diff --git a/clients/socks5/Cargo.toml b/clients/socks5/Cargo.toml index 03b6fcf5e9..7ea0469c74 100644 --- a/clients/socks5/Cargo.toml +++ b/clients/socks5/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-socks5-client" -version = "1.1.29" +version = "1.1.30" authors = ["Dave Hrycyszyn "] description = "A SOCKS5 localhost proxy that converts incoming messages to Sphinx and sends them to a Nym address" edition = "2021" @@ -16,6 +16,7 @@ serde_json = { workspace = true } tap = "1.0.1" thiserror = { workspace = true } tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal"] } +rand = "0.7.3" url = { workspace = true } # internal diff --git a/clients/socks5/src/commands/init.rs b/clients/socks5/src/commands/init.rs index 77782ed262..13d88a6b51 100644 --- a/clients/socks5/src/commands/init.rs +++ b/clients/socks5/src/commands/init.rs @@ -14,11 +14,15 @@ use nym_bin_common::output_format::OutputFormat; use nym_client_core::client::base_client::storage::gateway_details::OnDiskGatewayDetails; use nym_client_core::client::key_manager::persistence::OnDiskKeys; use nym_client_core::config::GatewayEndpointConfig; -use nym_client_core::init::GatewaySetup; +use nym_client_core::error::ClientCoreError; +use nym_client_core::init::helpers::current_gateways; +use nym_client_core::init::types::{GatewayDetails, GatewaySelectionSpecification, GatewaySetup}; use nym_crypto::asymmetric::identity; use nym_sphinx::addressing::clients::Recipient; +use nym_topology::NymTopology; use serde::Serialize; use std::fmt::Display; +use std::path::PathBuf; use std::{fs, io}; use tap::TapFallible; @@ -68,6 +72,10 @@ pub(crate) struct Init { #[clap(short, long)] port: Option, + /// Path to .json file containing custom network specification. + #[clap(long, group = "network", hide = true)] + custom_mixnet: Option, + /// Mostly debug-related option to increase default traffic rate so that you would not need to /// modify config post init #[clap(long, hide = true)] @@ -106,7 +114,7 @@ impl From for OverrideConfig { #[derive(Debug, Serialize)] pub struct InitResults { #[serde(flatten)] - client_core: nym_client_core::init::InitResults, + client_core: nym_client_core::init::types::InitResults, socks5_listening_port: u16, client_address: String, } @@ -114,7 +122,7 @@ pub struct InitResults { impl InitResults { fn new(config: &Config, address: &Recipient, gateway: &GatewayEndpointConfig) -> Self { Self { - client_core: nym_client_core::init::InitResults::new( + client_core: nym_client_core::init::types::InitResults::new( &config.core.base, address, gateway, @@ -138,7 +146,7 @@ fn init_paths(id: &str) -> io::Result<()> { fs::create_dir_all(default_config_directory(id)) } -pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> { +pub(crate) async fn execute(args: Init) -> Result<(), Socks5ClientError> { eprintln!("Initialising client..."); let id = &args.id; @@ -169,9 +177,10 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> { // Attempt to use a user-provided gateway, if possible let user_chosen_gateway_id = args.gateway; - let gateway_setup = GatewaySetup::new_fresh( + let selection_spec = GatewaySelectionSpecification::new( user_chosen_gateway_id.map(|id| id.to_base58_string()), Some(args.latency_based_selection), + false, ); // Load and potentially override config @@ -185,16 +194,29 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> { let key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone()); let details_store = OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details); - let init_details = nym_client_core::init::setup_gateway( - gateway_setup, - &key_store, - &details_store, - register_gateway, - Some(&config.core.base.client.nym_api_urls), - ) - .await - .tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))? - .details; + + let available_gateways = if let Some(hardcoded_topology) = args + .custom_mixnet + .map(NymTopology::new_from_file) + .transpose()? + { + // hardcoded_topology + hardcoded_topology.get_gateways() + } else { + let mut rng = rand::thread_rng(); + current_gateways(&mut rng, &config.core.base.client.nym_api_urls).await? + }; + + let gateway_setup = GatewaySetup::New { + specification: selection_spec, + available_gateways, + overwrite_data: register_gateway, + }; + + let init_details = + nym_client_core::init::setup_gateway(gateway_setup, &key_store, &details_store) + .await + .tap_err(|err| eprintln!("Failed to setup gateway\nError: {err}"))?; // TODO: ask the service provider we specified for its interface version and set it in the config @@ -209,7 +231,10 @@ pub(crate) async fn execute(args: &Init) -> Result<(), Socks5ClientError> { let address = init_details.client_address()?; - let init_results = InitResults::new(&config, &address, &init_details.gateway_details); + let GatewayDetails::Configured(gateway_details) = init_details.gateway_details else { + return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails)?; + }; + let init_results = InitResults::new(&config, &address, &gateway_details); println!("{}", args.output.format(&init_results)); Ok(()) diff --git a/clients/socks5/src/commands/mod.rs b/clients/socks5/src/commands/mod.rs index f9e876015d..1f42cdc905 100644 --- a/clients/socks5/src/commands/mod.rs +++ b/clients/socks5/src/commands/mod.rs @@ -87,8 +87,8 @@ pub(crate) async fn execute(args: Cli) -> Result<(), Box init::execute(&m).await?, - Commands::Run(m) => run::execute(&m).await?, + Commands::Init(m) => init::execute(m).await?, + Commands::Run(m) => run::execute(m).await?, Commands::BuildInfo(m) => build_info::execute(m), Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name), Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name), @@ -175,7 +175,7 @@ fn persist_gateway_details( source: Box::new(source), }) })?; - let persisted_details = PersistedGatewayDetails::new(details, &shared_keys); + let persisted_details = PersistedGatewayDetails::new(details.into(), Some(&shared_keys))?; details_store .store_to_disk(&persisted_details) .map_err(|source| { diff --git a/clients/socks5/src/commands/run.rs b/clients/socks5/src/commands/run.rs index 8dd289e2bf..46bd9cd361 100644 --- a/clients/socks5/src/commands/run.rs +++ b/clients/socks5/src/commands/run.rs @@ -15,6 +15,7 @@ use nym_client_core::client::topology_control::geo_aware_provider::CountryGroup; use nym_crypto::asymmetric::identity; use nym_socks5_client_core::NymClient; use nym_sphinx::addressing::clients::Recipient; +use std::path::PathBuf; #[derive(Args, Clone)] pub(crate) struct Run { @@ -45,13 +46,17 @@ pub(crate) struct Run { nyxd_urls: Option>, /// Comma separated list of rest endpoints of the Nym APIs - #[clap(long, value_delimiter = ',')] + #[clap(long, value_delimiter = ',', group = "network")] nym_apis: Option>, /// Port for the socket to listen on #[clap(short, long)] port: Option, + /// Path to .json file containing custom network specification. + #[clap(long, group = "network", group = "routing", hide = true)] + custom_mixnet: Option, + /// Mostly debug-related option to increase default traffic rate so that you would not need to /// modify config post init #[clap(long, hide = true)] @@ -62,7 +67,7 @@ pub(crate) struct Run { no_cover: bool, /// Set geo-aware mixnode selection when sending mixnet traffic, for experiments only. - #[clap(long, hide = true, value_parser = validate_country_group)] + #[clap(long, hide = true, value_parser = validate_country_group, group="routing")] geo_routing: Option, /// Enable medium mixnet traffic, for experiments only. @@ -124,7 +129,7 @@ fn version_check(cfg: &Config) -> bool { } } -pub(crate) async fn execute(args: &Run) -> Result<(), Box> { +pub(crate) async fn execute(args: Run) -> Result<(), Box> { eprintln!("Starting client {}...", args.id); let mut config = try_load_current_config(&args.id)?; @@ -138,5 +143,7 @@ pub(crate) async fn execute(args: &Run) -> Result<(), Box &'static str { + fn template(&self) -> &'static str { CONFIG_TEMPLATE } } diff --git a/clients/socks5/src/config/persistence.rs b/clients/socks5/src/config/persistence.rs index 6df47997c9..696ae289e0 100644 --- a/clients/socks5/src/config/persistence.rs +++ b/clients/socks5/src/config/persistence.rs @@ -14,7 +14,7 @@ pub struct SocksClientPaths { impl SocksClientPaths { pub fn new_default>(base_data_directory: P) -> Self { SocksClientPaths { - common_paths: CommonClientPaths::new_default(base_data_directory), + common_paths: CommonClientPaths::new_base(base_data_directory), } } } diff --git a/common/bin-common/src/output_format/mod.rs b/common/bin-common/src/output_format/mod.rs index 386cc267a1..d3d57504ec 100644 --- a/common/bin-common/src/output_format/mod.rs +++ b/common/bin-common/src/output_format/mod.rs @@ -32,4 +32,14 @@ impl OutputFormat { OutputFormat::Json => serde_json::to_string(data).unwrap(), } } + + #[cfg(feature = "output_format")] + pub fn to_stdout(&self, data: &T) { + println!("{}", self.format(data)) + } + + #[cfg(feature = "output_format")] + pub fn to_stderr(&self, data: &T) { + eprintln!("{}", self.format(data)) + } } diff --git a/common/client-core/Cargo.toml b/common/client-core/Cargo.toml index 14761acf01..a98eb783ab 100644 --- a/common/client-core/Cargo.toml +++ b/common/client-core/Cargo.toml @@ -11,7 +11,7 @@ rust-version = "1.66" async-trait = { workspace = true } base64 = "0.21.2" cfg-if = "1.0.0" -dashmap = "5.4.0" +dashmap = { workspace = true } dirs = "4.0" futures = { workspace = true } humantime-serde = "1.0" @@ -35,12 +35,11 @@ nym-config = { path = "../config" } nym-crypto = { path = "../crypto" } nym-explorer-client = { path = "../../explorer-api/explorer-client" } nym-gateway-client = { path = "../client-libs/gateway-client" } -#gateway-client = { path = "../../common/client-libs/gateway-client", default-features = false, features = ["wasm", "coconut"] } nym-gateway-requests = { path = "../../gateway/gateway-requests" } nym-nonexhaustive-delayqueue = { path = "../nonexhaustive-delayqueue" } nym-sphinx = { path = "../nymsphinx" } nym-pemstore = { path = "../pemstore" } -nym-topology = { path = "../topology" } +nym-topology = { path = "../topology", features = ["serializable"] } nym-validator-client = { path = "../client-libs/validator-client", default-features = false } nym-task = { path = "../task" } nym-credential-storage = { path = "../credential-storage" } diff --git a/common/client-core/src/client/base_client/mod.rs b/common/client-core/src/client/base_client/mod.rs index ad85157321..07d676a6f3 100644 --- a/common/client-core/src/client/base_client/mod.rs +++ b/common/client-core/src/client/base_client/mod.rs @@ -8,6 +8,7 @@ use crate::client::base_client::storage::MixnetClientStorage; use crate::client::cover_traffic_stream::LoopCoverTrafficStream; use crate::client::inbound_messages::{InputMessage, InputMessageReceiver, InputMessageSender}; use crate::client::key_manager::persistence::KeyStore; +use crate::client::mix_traffic::transceiver::{GatewayReceiver, GatewayTransceiver, RemoteGateway}; use crate::client::mix_traffic::{BatchMixMessageSender, MixTrafficController}; use crate::client::real_messages_control; use crate::client::real_messages_control::RealMessagesController; @@ -25,16 +26,18 @@ use crate::client::topology_control::{ }; use crate::config::{Config, DebugConfig}; use crate::error::ClientCoreError; -use crate::init::{setup_gateway, GatewaySetup, InitialisationDetails, InitialisationResult}; +use crate::init::{ + setup_gateway, + types::{GatewayDetails, GatewaySetup, InitialisationResult}, +}; use crate::{config, spawn_future}; use futures::channel::mpsc; -use log::{debug, info}; +use log::{debug, error, info}; use nym_bandwidth_controller::BandwidthController; use nym_credential_storage::storage::Storage as CredentialStorage; -use nym_crypto::asymmetric::{encryption, identity}; +use nym_crypto::asymmetric::encryption; use nym_gateway_client::{ - AcknowledgementReceiver, AcknowledgementSender, GatewayClient, MixnetMessageReceiver, - MixnetMessageSender, + AcknowledgementReceiver, GatewayClient, MixnetMessageReceiver, PacketRouter, }; use nym_sphinx::acknowledgements::AckKey; use nym_sphinx::addressing::clients::Recipient; @@ -42,9 +45,12 @@ use nym_sphinx::addressing::nodes::NodeIdentity; use nym_sphinx::params::PacketType; use nym_sphinx::receiver::{ReconstructedMessage, SphinxMessageReceiver}; use nym_task::connections::{ConnectionCommandReceiver, ConnectionCommandSender, LaneQueueLengths}; -use nym_task::{TaskClient, TaskManager}; +use nym_task::{TaskClient, TaskHandle}; use nym_topology::provider_trait::TopologyProvider; +use nym_topology::HardcodedTopologyProvider; use nym_validator_client::nyxd::contract_traits::DkgQueryClient; +use std::fmt::Debug; +use std::path::Path; use std::sync::Arc; use url::Url; @@ -155,7 +161,12 @@ pub struct BaseClientBuilder<'a, C, S: MixnetClientStorage> { config: &'a Config, client_store: S, dkg_query_client: Option, + + wait_for_gateway: bool, custom_topology_provider: Option>, + custom_gateway_transceiver: Option>, + shutdown: Option, + setup_method: GatewaySetup, } @@ -173,16 +184,27 @@ where config: base_config, client_store, dkg_query_client, + wait_for_gateway: false, custom_topology_provider: None, + custom_gateway_transceiver: None, + shutdown: None, setup_method: GatewaySetup::MustLoad, } } + #[must_use] pub fn with_gateway_setup(mut self, setup: GatewaySetup) -> Self { self.setup_method = setup; self } + #[must_use] + pub fn with_wait_for_gateway(mut self, wait_for_gateway: bool) -> Self { + self.wait_for_gateway = wait_for_gateway; + self + } + + #[must_use] pub fn with_topology_provider( mut self, provider: Box, @@ -191,15 +213,36 @@ where self } + #[must_use] + pub fn with_gateway_transceiver(mut self, sender: Box) -> Self { + self.custom_gateway_transceiver = Some(sender); + self + } + + #[must_use] + pub fn with_shutdown(mut self, shutdown: TaskClient) -> Self { + self.shutdown = Some(shutdown); + self + } + + pub fn with_stored_topology>( + mut self, + file: P, + ) -> Result { + self.custom_topology_provider = + Some(Box::new(HardcodedTopologyProvider::new_from_file(file)?)); + Ok(self) + } + // note: do **NOT** make this method public as its only valid usage is from within `start_base` // because it relies on the crypto keys being already loaded - fn mix_address(details: &InitialisationDetails) -> Recipient { + fn mix_address(details: &InitialisationResult) -> Recipient { Recipient::new( *details.managed_keys.identity_public_key(), *details.managed_keys.encryption_public_key(), // TODO: below only works under assumption that gateway address == gateway id // (which currently is true) - NodeIdentity::from_base58_string(&details.gateway_details.gateway_id).unwrap(), + NodeIdentity::from_base58_string(details.gateway_details.gateway_id()).unwrap(), ) } @@ -286,50 +329,37 @@ where config: &Config, initialisation_result: InitialisationResult, bandwidth_controller: Option>, - mixnet_message_sender: MixnetMessageSender, - ack_sender: AcknowledgementSender, + packet_router: PacketRouter, shutdown: TaskClient, ) -> Result, ClientCoreError> where ::StorageError: Send + Sync + 'static, ::StorageError: Send + Sync + 'static, { - let managed_keys = initialisation_result.details.managed_keys; + let managed_keys = initialisation_result.managed_keys; + let GatewayDetails::Configured(gateway_config) = initialisation_result.gateway_details + else { + return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails); + }; let mut gateway_client = if let Some(existing_client) = initialisation_result.authenticated_ephemeral_client { - existing_client.upgrade( - mixnet_message_sender, - ack_sender, - config.debug.gateway_connection.gateway_response_timeout, - bandwidth_controller, - shutdown, - ) + existing_client.upgrade(packet_router, bandwidth_controller, shutdown) } else { - let gateway_config = initialisation_result.details.gateway_details; - - let gateway_address = gateway_config.gateway_listener.clone(); - let gateway_id = gateway_config.gateway_id; - - // TODO: in theory, at this point, this should be infallible - let gateway_identity = identity::PublicKey::from_base58_string(gateway_id) - .map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?; - + let cfg = gateway_config.try_into()?; GatewayClient::new( - gateway_address, + cfg, managed_keys.identity_keypair(), - gateway_identity, Some(managed_keys.must_get_gateway_shared_key()), - mixnet_message_sender, - ack_sender, - config.debug.gateway_connection.gateway_response_timeout, + packet_router, bandwidth_controller, shutdown, ) + .with_disabled_credentials_mode(config.client.disabled_credentials_mode) + .with_response_timeout(config.debug.gateway_connection.gateway_response_timeout) }; let gateway_id = gateway_client.gateway_identity(); - gateway_client.set_disabled_credentials_mode(config.client.disabled_credentials_mode); let shared_key = gateway_client .authenticate_and_start() @@ -342,11 +372,48 @@ where } })?; - managed_keys.ensure_gateway_key(shared_key); + managed_keys.ensure_gateway_key(Some(shared_key)); Ok(gateway_client) } + async fn setup_gateway_transceiver( + custom_gateway_transceiver: Option>, + config: &Config, + initialisation_result: InitialisationResult, + bandwidth_controller: Option>, + packet_router: PacketRouter, + mut shutdown: TaskClient, + ) -> Result, ClientCoreError> + where + ::StorageError: Send + Sync + 'static, + ::StorageError: Send + Sync + 'static, + { + // if we have setup custom gateway sender and persisted details agree with it, return it + if let Some(mut custom_gateway_transceiver) = custom_gateway_transceiver { + return if !initialisation_result.gateway_details.is_custom() { + Err(ClientCoreError::CustomGatewaySelectionExpected) + } else { + // and make sure to invalidate the task client so we wouldn't cause premature shutdown + shutdown.mark_as_success(); + custom_gateway_transceiver.set_packet_router(packet_router)?; + Ok(custom_gateway_transceiver) + }; + } + + // otherwise, setup normal gateway client, etc + let gateway_client = Self::start_gateway_client( + config, + initialisation_result, + bandwidth_controller, + packet_router, + shutdown, + ) + .await?; + + Ok(Box::new(RemoteGateway::new(gateway_client))) + } + fn setup_topology_provider( custom_provider: Option>, provider_from_config: config::TopologyStructure, @@ -374,6 +441,8 @@ where topology_provider: Box, topology_config: config::Topology, topology_accessor: TopologyAccessor, + local_gateway: &NodeIdentity, + wait_for_gateway: bool, mut shutdown: TaskClient, ) -> Result<(), ClientCoreError> { let topology_refresher_config = @@ -397,6 +466,32 @@ where return Err(ClientCoreError::InsufficientNetworkTopology(err)); } + let gateway_wait_timeout = if wait_for_gateway { + Some(topology_config.max_startup_gateway_waiting_period) + } else { + None + }; + + if let Err(err) = topology_refresher + .ensure_contains_gateway(local_gateway) + .await + { + if let Some(waiting_timeout) = gateway_wait_timeout { + if let Err(err) = topology_refresher + .wait_for_gateway(local_gateway, waiting_timeout) + .await + { + error!( + "the gateway did not come back online within the specified timeout: {err}" + ); + return Err(err.into()); + } + } else { + error!("the gateway we're supposedly connected to does not exist. We'll not be able to send any packets to ourselves: {err}"); + return Err(err.into()); + } + } + if topology_config.disable_refreshing { // if we're not spawning the refresher, don't cause shutdown immediately info!("The topology refesher is not going to be started"); @@ -411,19 +506,12 @@ where Ok(()) } - // controller for sending packets to mixnet (either real traffic or cover traffic) - // TODO: if we want to send control messages to gateway_client, this CAN'T take the ownership - // over it. Perhaps GatewayClient needs to be thread-shareable or have some channel for - // requests? fn start_mix_traffic_controller( - gateway_client: GatewayClient, + gateway_transceiver: Box, shutdown: TaskClient, - ) -> BatchMixMessageSender - where - ::StorageError: Send + Sync + 'static, - { + ) -> BatchMixMessageSender { info!("Starting mix traffic controller..."); - let (mix_traffic_controller, mix_tx) = MixTrafficController::new(gateway_client); + let (mix_traffic_controller, mix_tx) = MixTrafficController::new(gateway_transceiver); mix_traffic_controller.start_with_shutdown(shutdown); mix_tx } @@ -460,21 +548,12 @@ where setup_method: GatewaySetup, key_store: &S::KeyStore, details_store: &S::GatewayDetailsStore, - overwrite_data: bool, - validator_servers: Option<&[Url]>, ) -> Result where ::StorageError: Sync + Send, ::StorageError: Sync + Send, { - setup_gateway( - setup_method, - key_store, - details_store, - overwrite_data, - validator_servers, - ) - .await + setup_gateway(setup_method, key_store, details_store).await } pub async fn start_base(mut self) -> Result @@ -492,17 +571,11 @@ where self.setup_method, self.client_store.key_store(), self.client_store.gateway_details_store(), - false, - Some(&self.config.client.nym_api_urls), ) .await?; let (reply_storage_backend, credential_store) = self.client_store.into_runtime_stores(); - let bandwidth_controller = self - .dkg_query_client - .map(|client| BandwidthController::new(credential_store, client)); - // channels for inter-component communication // TODO: make the channels be internally created by the relevant components // rather than creating them here, so say for example the buffer controller would create the request channels @@ -523,31 +596,25 @@ where let shared_topology_accessor = TopologyAccessor::new(); // Shutdown notifier for signalling tasks to stop - let task_manager = TaskManager::default(); + let shutdown = self + .shutdown + .map(Into::::into) + .unwrap_or_default() + .name_if_unnamed("BaseNymClient"); // channels responsible for dealing with reply-related fun let (reply_controller_sender, reply_controller_receiver) = reply_controller::requests::new_control_channels(); - let self_address = Self::mix_address(&init_res.details); - let ack_key = init_res.details.managed_keys.ack_key(); - let encryption_keys = init_res.details.managed_keys.encryption_keypair(); + let self_address = Self::mix_address(&init_res); + let ack_key = init_res.managed_keys.ack_key(); + let encryption_keys = init_res.managed_keys.encryption_keypair(); // the components are started in very specific order. Unless you know what you are doing, // do not change that. - let gateway_client = Self::start_gateway_client( - self.config, - init_res, - bandwidth_controller, - mixnet_messages_sender, - ack_sender, - task_manager.subscribe(), - ) - .await?; - - let reply_storage = - Self::setup_persistent_reply_storage(reply_storage_backend, task_manager.subscribe()) - .await?; + let bandwidth_controller = self + .dkg_query_client + .map(|client| BandwidthController::new(credential_store, client)); let topology_provider = Self::setup_topology_provider( self.custom_topology_provider.take(), @@ -555,11 +622,36 @@ where self.config.get_nym_api_endpoints(), ); + // needs to be started as the first thing to block if required waiting for the gateway Self::start_topology_refresher( topology_provider, self.config.debug.topology, shared_topology_accessor.clone(), - task_manager.subscribe(), + self_address.gateway(), + self.wait_for_gateway, + shutdown.fork("topology_refresher"), + ) + .await?; + + let gateway_packet_router = PacketRouter::new( + ack_sender, + mixnet_messages_sender, + shutdown.get_handle().named("gateway-packet-router"), + ); + + let gateway_transceiver = Self::setup_gateway_transceiver( + self.custom_gateway_transceiver, + self.config, + init_res, + bandwidth_controller, + gateway_packet_router, + shutdown.fork("gateway_transceiver"), + ) + .await?; + + let reply_storage = Self::setup_persistent_reply_storage( + reply_storage_backend, + shutdown.fork("persistent_reply_storage"), ) .await?; @@ -569,15 +661,17 @@ where mixnet_messages_receiver, reply_storage.key_storage(), reply_controller_sender.clone(), - task_manager.subscribe(), + shutdown.fork("received_messages_buffer"), ); // The message_sender is the transmitter for any component generating sphinx packets // that are to be sent to the mixnet. They are used by cover traffic stream and real // traffic stream. // The MixTrafficController then sends the actual traffic - let message_sender = - Self::start_mix_traffic_controller(gateway_client, task_manager.subscribe()); + let message_sender = Self::start_mix_traffic_controller( + gateway_transceiver, + shutdown.fork("mix_traffic_controller"), + ); // Channels that the websocket listener can use to signal downstream to the real traffic // controller that connections are closed. @@ -604,7 +698,7 @@ where reply_controller_receiver, shared_lane_queue_lengths.clone(), client_connection_rx, - task_manager.subscribe(), + shutdown.fork("real_traffic_controller"), self.config.debug.traffic.packet_type, ); @@ -620,7 +714,7 @@ where self_address, shared_topology_accessor.clone(), message_sender, - task_manager.subscribe(), + shutdown.fork("cover_traffic_stream"), ); } @@ -645,7 +739,7 @@ where reply_controller_sender, topology_accessor: shared_topology_accessor, }, - task_manager, + task_handle: shutdown, }) } } @@ -656,5 +750,5 @@ pub struct BaseClient { pub client_output: ClientOutputStatus, pub client_state: ClientState, - pub task_manager: TaskManager, + pub task_handle: TaskHandle, } diff --git a/common/client-core/src/client/base_client/storage/gateway_details.rs b/common/client-core/src/client/base_client/storage/gateway_details.rs index bcacdf731e..5493fb93a2 100644 --- a/common/client-core/src/client/base_client/storage/gateway_details.rs +++ b/common/client-core/src/client/base_client/storage/gateway_details.rs @@ -2,8 +2,12 @@ // SPDX-License-Identifier: Apache-2.0 use crate::config::GatewayEndpointConfig; +use crate::error::ClientCoreError; +use crate::init::types::{EmptyCustomDetails, GatewayDetails}; use async_trait::async_trait; +use log::error; use nym_gateway_requests::registration::handshake::SharedKeys; +use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use std::error::Error; @@ -13,19 +17,61 @@ use zeroize::Zeroizing; #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] #[cfg_attr(not(target_arch = "wasm32"), async_trait)] -pub trait GatewayDetailsStore { +pub trait GatewayDetailsStore { type StorageError: Error; - async fn load_gateway_details(&self) -> Result; + async fn load_gateway_details(&self) -> Result, Self::StorageError> + where + T: DeserializeOwned + Send + Sync; async fn store_gateway_details( &self, - details: &PersistedGatewayDetails, - ) -> Result<(), Self::StorageError>; + details: &PersistedGatewayDetails, + ) -> Result<(), Self::StorageError> + where + T: Serialize + Send + Sync; } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct PersistedGatewayDetails { +#[serde(untagged)] +pub enum PersistedGatewayDetails { + /// Standard details of a remote gateway + Default(PersistedGatewayConfig), + + /// Custom gateway setup, such as for a client embedded inside gateway itself + Custom(PersistedCustomGatewayDetails), +} + +impl PersistedGatewayDetails { + // TODO: this should probably allow for custom verification over T + pub fn validate(&self, shared_key: Option<&SharedKeys>) -> Result<(), ClientCoreError> { + match self { + PersistedGatewayDetails::Default(details) => { + if !details.verify( + shared_key + .ok_or(ClientCoreError::UnavailableSharedKey)? + .deref(), + ) { + Err(ClientCoreError::MismatchedGatewayDetails { + gateway_id: details.details.gateway_id.clone(), + }) + } else { + Ok(()) + } + } + PersistedGatewayDetails::Custom(_) => { + if shared_key.is_some() { + error!("using custom persisted gateway setup with shared key present - are you sure that's what you want?"); + // but technically we could still continue. just ignore the key + } + Ok(()) + } + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +pub struct PersistedGatewayConfig { // TODO: should we also verify correctness of the details themselves? // i.e. we could include a checksum or tag (via the shared keys) // counterargument: if we wanted to modify, say, the host information in the stored file on disk, @@ -38,13 +84,16 @@ pub struct PersistedGatewayDetails { pub(crate) details: GatewayEndpointConfig, } -impl From for GatewayEndpointConfig { - fn from(value: PersistedGatewayDetails) -> Self { - value.details - } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct PersistedCustomGatewayDetails { + // whatever custom method is used, gateway's identity must be known + pub gateway_id: String, + + #[serde(flatten)] + pub additional_data: T, } -impl PersistedGatewayDetails { +impl PersistedGatewayConfig { pub fn new(details: GatewayEndpointConfig, shared_key: &SharedKeys) -> Self { let key_bytes = Zeroizing::new(shared_key.to_bytes()); @@ -52,7 +101,7 @@ impl PersistedGatewayDetails { key_hasher.update(&key_bytes); let key_hash = key_hasher.finalize().to_vec(); - PersistedGatewayDetails { key_hash, details } + PersistedGatewayConfig { key_hash, details } } pub fn verify(&self, shared_key: &SharedKeys) -> bool { @@ -66,6 +115,50 @@ impl PersistedGatewayDetails { } } +impl PersistedGatewayDetails { + pub fn new( + details: GatewayDetails, + shared_key: Option<&SharedKeys>, + ) -> Result { + match details { + GatewayDetails::Configured(cfg) => { + let shared_key = shared_key.ok_or(ClientCoreError::UnavailableSharedKey)?; + Ok(PersistedGatewayDetails::Default( + PersistedGatewayConfig::new(cfg, shared_key), + )) + } + GatewayDetails::Custom(custom) => Ok(PersistedGatewayDetails::Custom(custom.into())), + } + } + + pub fn is_custom(&self) -> bool { + matches!(self, PersistedGatewayDetails::Custom(..)) + } + + pub fn matches(&self, other: &GatewayDetails) -> bool + where + T: PartialEq, + { + match self { + PersistedGatewayDetails::Default(default) => { + if let GatewayDetails::Configured(other_configured) = other { + &default.details == other_configured + } else { + false + } + } + PersistedGatewayDetails::Custom(custom) => { + if let GatewayDetails::Custom(other_custom) = other { + custom.gateway_id == other_custom.gateway_id + && custom.additional_data == other_custom.additional_data + } else { + false + } + } + } + } +} + // helper to make Vec serialization use base64 representation to make it human readable // so that it would be easier for users to copy contents from the disk if they wanted to use it elsewhere mod base64 { @@ -116,7 +209,10 @@ impl OnDiskGatewayDetails { } } - pub fn load_from_disk(&self) -> Result { + pub fn load_from_disk(&self) -> Result, OnDiskGatewayDetailsError> + where + T: DeserializeOwned, + { let file = std::fs::File::open(&self.file_location).map_err(|err| { OnDiskGatewayDetailsError::LoadFailure { path: self.file_location.display().to_string(), @@ -127,10 +223,13 @@ impl OnDiskGatewayDetails { Ok(serde_json::from_reader(file)?) } - pub fn store_to_disk( + pub fn store_to_disk( &self, - details: &PersistedGatewayDetails, - ) -> Result<(), OnDiskGatewayDetailsError> { + details: &PersistedGatewayDetails, + ) -> Result<(), OnDiskGatewayDetailsError> + where + T: Serialize, + { // ensure the whole directory structure exists if let Some(parent_dir) = &self.file_location.parent() { std::fs::create_dir_all(parent_dir).map_err(|err| { @@ -170,8 +269,8 @@ impl GatewayDetailsStore for OnDiskGatewayDetails { } #[derive(Default)] -pub struct InMemGatewayDetails { - details: Mutex>, +pub struct InMemGatewayDetails { + details: Mutex>>, } #[derive(Debug, thiserror::Error)] diff --git a/common/client-core/src/client/base_client/storage/mod.rs b/common/client-core/src/client/base_client/storage/mod.rs index 3d05044d4f..60e3ff9a73 100644 --- a/common/client-core/src/client/base_client/storage/mod.rs +++ b/common/client-core/src/client/base_client/storage/mod.rs @@ -38,9 +38,6 @@ pub trait MixnetClientStorage { type CredentialStore: CredentialStorage; type GatewayDetailsStore: GatewayDetailsStore; - // this is a TERRIBLE name... - // fn into_split(self) -> (Self::KeyStore, Self::ReplyStore, Self::CredentialStore, Self::GatewayDetailsStore); - fn into_runtime_stores(self) -> (Self::ReplyStore, Self::CredentialStore); fn key_store(&self) -> &Self::KeyStore; diff --git a/common/client-core/src/client/key_manager/mod.rs b/common/client-core/src/client/key_manager/mod.rs index 4c77f23632..6fb3858eb7 100644 --- a/common/client-core/src/client/key_manager/mod.rs +++ b/common/client-core/src/client/key_manager/mod.rs @@ -103,7 +103,7 @@ impl ManagedKeys { pub fn gateway_shared_key(&self) -> Option> { match self { ManagedKeys::Initial(_) => None, - ManagedKeys::FullyDerived(keys) => Some(keys.gateway_shared_key()), + ManagedKeys::FullyDerived(keys) => keys.gateway_shared_key(), ManagedKeys::Invalidated => unreachable!("the managed keys got invalidated"), } } @@ -124,10 +124,26 @@ impl ManagedKeys { } } - pub fn ensure_gateway_key(&self, gateway_shared_key: Arc) { + pub fn ensure_gateway_key(&self, gateway_shared_key: Option>) { if let ManagedKeys::FullyDerived(key_manager) = &self { - if !Arc::ptr_eq(&key_manager.gateway_shared_key, &gateway_shared_key) - || key_manager.gateway_shared_key != gateway_shared_key + if self.gateway_shared_key().is_none() && gateway_shared_key.is_none() { + // the key doesn't exist in either state + return; + } + + if gateway_shared_key.is_some() && self.gateway_shared_key().is_none() + || gateway_shared_key.is_none() && self.gateway_shared_key().is_some() + { + // if one is provided whilst the other is not... + // TODO: should this actually panic or return an error? would this branch be possible + // under normal operation? + panic!("inconsistent re-derived gateway key") + } + + // here we know both keys MUST exist + let provided = gateway_shared_key.unwrap(); + if !Arc::ptr_eq(key_manager.must_get_gateway_shared_key(), &provided) + || *key_manager.must_get_gateway_shared_key() != provided { // this should NEVER happen thus panic here panic!("derived fresh gateway shared key whilst already holding one!") @@ -137,12 +153,12 @@ impl ManagedKeys { pub async fn deal_with_gateway_key( &mut self, - gateway_shared_key: Arc, + gateway_shared_key: Option>, key_store: &S, ) -> Result<(), S::StorageError> { let key_manager = match std::mem::replace(self, ManagedKeys::Invalidated) { ManagedKeys::Initial(keys) => { - let key_manager = keys.insert_gateway_shared_key(gateway_shared_key); + let key_manager = keys.insert_maybe_gateway_shared_key(gateway_shared_key); key_manager.persist_keys(key_store).await?; key_manager } @@ -184,7 +200,10 @@ impl KeyManagerBuilder { } } - pub fn insert_gateway_shared_key(self, gateway_shared_key: Arc) -> KeyManager { + pub fn insert_maybe_gateway_shared_key( + self, + gateway_shared_key: Option>, + ) -> KeyManager { KeyManager { identity_keypair: self.identity_keypair, encryption_keypair: self.encryption_keypair, @@ -222,7 +241,11 @@ pub struct KeyManager { encryption_keypair: Arc, /// shared key derived with the gateway during "registration handshake" - gateway_shared_key: Arc, + // I'm not a fan of how we broke the nice transition of `KeyManagerBuilder` -> `KeyManager` + // by making this field optional. + // However, it has to be optional for when we use embedded NR inside a gateway, + // since it won't have a shared key (because why would it?) + gateway_shared_key: Option>, /// key used for producing and processing acknowledgement packets. ack_key: Arc, @@ -232,13 +255,13 @@ impl KeyManager { pub fn from_keys( id_keypair: identity::KeyPair, enc_keypair: encryption::KeyPair, - gateway_shared_key: SharedKeys, + gateway_shared_key: Option, ack_key: AckKey, ) -> Self { Self { identity_keypair: Arc::new(id_keypair), encryption_keypair: Arc::new(enc_keypair), - gateway_shared_key: Arc::new(gateway_shared_key), + gateway_shared_key: gateway_shared_key.map(Arc::new), ack_key: Arc::new(ack_key), } } @@ -265,13 +288,23 @@ impl KeyManager { Arc::clone(&self.ack_key) } + fn must_get_gateway_shared_key(&self) -> &Arc { + self.gateway_shared_key + .as_ref() + .expect("gateway shared key is unavailable") + } + + pub fn uses_custom_gateway(&self) -> bool { + self.gateway_shared_key.is_none() + } + /// Gets an atomically reference counted pointer to [`SharedKey`]. - pub fn gateway_shared_key(&self) -> Arc { - Arc::clone(&self.gateway_shared_key) + pub fn gateway_shared_key(&self) -> Option> { + self.gateway_shared_key.as_ref().map(Arc::clone) } pub fn remove_gateway_key(self) -> KeyManagerBuilder { - if Arc::strong_count(&self.gateway_shared_key) > 1 { + if Arc::strong_count(self.must_get_gateway_shared_key()) > 1 { panic!("attempted to remove gateway key whilst still holding multiple references!") } KeyManagerBuilder { diff --git a/common/client-core/src/client/key_manager/persistence.rs b/common/client-core/src/client/key_manager/persistence.rs index 0475de3990..984019eb93 100644 --- a/common/client-core/src/client/key_manager/persistence.rs +++ b/common/client-core/src/client/key_manager/persistence.rs @@ -88,20 +88,20 @@ impl OnDiskKeys { pub fn ephemeral_load_gateway_keys( &self, ) -> Result, OnDiskKeysError> { - self.load_key(self.paths.gateway_shared_key(), "gateway shared keys") + self.load_key(self.paths.gateway_shared_key(), "gateway shared") .map(zeroize::Zeroizing::new) } #[doc(hidden)] pub fn load_encryption_keypair(&self) -> Result { let encryption_paths = self.paths.encryption_key_pair_path(); - self.load_keypair(encryption_paths, "encryption keys") + self.load_keypair(encryption_paths, "encryption") } #[doc(hidden)] pub fn load_identity_keypair(&self) -> Result { let identity_paths = self.paths.identity_key_pair_path(); - self.load_keypair(identity_paths, "identity keys") + self.load_keypair(identity_paths, "identity") } fn load_key( @@ -161,8 +161,9 @@ impl OnDiskKeys { let encryption_keypair = self.load_encryption_keypair()?; let ack_key: AckKey = self.load_key(self.paths.ack_key(), "ack key")?; - let gateway_shared_key: SharedKeys = - self.load_key(self.paths.gateway_shared_key(), "gateway shared keys")?; + let gateway_shared_key: Option = self + .load_key(self.paths.gateway_shared_key(), "gateway shared keys") + .ok(); Ok(KeyManager::from_keys( identity_keypair, @@ -173,6 +174,8 @@ impl OnDiskKeys { } fn store_keys(&self, keys: &KeyManager) -> Result<(), OnDiskKeysError> { + use std::ops::Deref; + let identity_paths = self.paths.identity_key_pair_path(); let encryption_paths = self.paths.encryption_key_pair_path(); @@ -188,11 +191,14 @@ impl OnDiskKeys { )?; self.store_key(keys.ack_key.as_ref(), self.paths.ack_key(), "ack key")?; - self.store_key( - keys.gateway_shared_key.as_ref(), - self.paths.gateway_shared_key(), - "gateway shared keys", - )?; + + if let Some(shared_keys) = &keys.gateway_shared_key { + self.store_key( + shared_keys.deref(), + self.paths.gateway_shared_key(), + "gateway shared keys", + )?; + } Ok(()) } diff --git a/common/client-core/src/client/mix_traffic.rs b/common/client-core/src/client/mix_traffic/mod.rs similarity index 74% rename from common/client-core/src/client/mix_traffic.rs rename to common/client-core/src/client/mix_traffic/mod.rs index cb12a55d85..91c652efba 100644 --- a/common/client-core/src/client/mix_traffic.rs +++ b/common/client-core/src/client/mix_traffic/mod.rs @@ -1,24 +1,26 @@ // Copyright 2021 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::client::mix_traffic::transceiver::GatewayTransceiver; use crate::spawn_future; use log::*; -use nym_credential_storage::storage::Storage; -use nym_gateway_client::GatewayClient; use nym_sphinx::forwarding::packet::MixPacket; -use nym_validator_client::nyxd::contract_traits::DkgQueryClient; pub type BatchMixMessageSender = tokio::sync::mpsc::Sender>; pub type BatchMixMessageReceiver = tokio::sync::mpsc::Receiver>; +pub mod transceiver; + // We remind ourselves that 32 x 32kb = 1024kb, a reasonable size for a network buffer. pub const MIX_MESSAGE_RECEIVER_BUFFER_SIZE: usize = 32; const MAX_FAILURE_COUNT: usize = 100; -pub struct MixTrafficController { - // TODO: most likely to be replaced by some higher level construct as - // later on gateway_client will need to be accessible by other entities - gateway_client: GatewayClient, +// that's also disgusting. +pub struct Empty; + +pub struct MixTrafficController { + gateway_transceiver: Box, + mix_rx: BatchMixMessageReceiver, // TODO: this is temporary work-around. @@ -26,20 +28,31 @@ pub struct MixTrafficController { consecutive_gateway_failure_count: usize, } -impl MixTrafficController -where - C: DkgQueryClient + Sync + Send + 'static, - St: Storage + 'static, - ::StorageError: Send + Sync + 'static, -{ - pub fn new( - gateway_client: GatewayClient, - ) -> (MixTrafficController, BatchMixMessageSender) { +impl MixTrafficController { + pub fn new(gateway_transceiver: T) -> (MixTrafficController, BatchMixMessageSender) + where + T: GatewayTransceiver + Send + 'static, + { + let (message_sender, message_receiver) = + tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE); + ( + MixTrafficController { + gateway_transceiver: Box::new(gateway_transceiver), + mix_rx: message_receiver, + consecutive_gateway_failure_count: 0, + }, + message_sender, + ) + } + + pub fn new_dynamic( + gateway_transceiver: Box, + ) -> (MixTrafficController, BatchMixMessageSender) { let (message_sender, message_receiver) = tokio::sync::mpsc::channel(MIX_MESSAGE_RECEIVER_BUFFER_SIZE); ( MixTrafficController { - gateway_client, + gateway_transceiver, mix_rx: message_receiver, consecutive_gateway_failure_count: 0, }, @@ -52,16 +65,16 @@ where let result = if mix_packets.len() == 1 { let mix_packet = mix_packets.pop().unwrap(); - self.gateway_client.send_mix_packet(mix_packet).await + self.gateway_transceiver.send_mix_packet(mix_packet).await } else { - self.gateway_client + self.gateway_transceiver .batch_send_mix_packets(mix_packets) .await }; match result { Err(err) => { - error!("Failed to send sphinx packet(s) to the gateway! - {err}"); + error!("Failed to send sphinx packet(s) to the gateway: {err}"); self.consecutive_gateway_failure_count += 1; if self.consecutive_gateway_failure_count == MAX_FAILURE_COUNT { // todo: in the future this should initiate a 'graceful' shutdown or try diff --git a/common/client-core/src/client/mix_traffic/transceiver.rs b/common/client-core/src/client/mix_traffic/transceiver.rs new file mode 100644 index 0000000000..b078e02966 --- /dev/null +++ b/common/client-core/src/client/mix_traffic/transceiver.rs @@ -0,0 +1,262 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use async_trait::async_trait; +use log::{debug, error}; +use nym_crypto::asymmetric::identity; +use nym_gateway_client::GatewayClient; +pub use nym_gateway_client::{GatewayPacketRouter, PacketRouter}; +use nym_sphinx::forwarding::packet::MixPacket; +use std::fmt::Debug; +use thiserror::Error; + +#[cfg(not(target_arch = "wasm32"))] +use futures::channel::{mpsc, oneshot}; + +// we need to type erase the error type since we can't have dynamic associated types alongside dynamic dispatch +#[derive(Debug, Error)] +#[error(transparent)] +pub struct ErasedGatewayError(Box); + +fn erase_err(err: E) -> ErasedGatewayError { + ErasedGatewayError(Box::new(err)) +} + +/// This combines combines the functionalities of being able to send and receive mix packets. +pub trait GatewayTransceiver: GatewaySender + GatewayReceiver { + fn gateway_identity(&self) -> identity::PublicKey; +} + +/// This trait defines the functionality of sending `MixPacket` into the mixnet, +/// usually through a gateway. +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +pub trait GatewaySender { + async fn send_mix_packet(&mut self, packet: MixPacket) -> Result<(), ErasedGatewayError>; + + async fn batch_send_mix_packets( + &mut self, + packets: Vec, + ) -> Result<(), ErasedGatewayError> { + // allow for optimisation when sending multiple packets + for packet in packets { + self.send_mix_packet(packet).await?; + } + Ok(()) + } +} + +/// this trait defines the functionality of being able to correctly route +/// packets received from the mixnet, i.e. acks and 'proper' messages. +pub trait GatewayReceiver { + // ughhhh I really dislike this method, but couldn't come up wih anything better + // ideally this would have been an associated type, but heh. we can't. + fn set_packet_router( + &mut self, + _packet_router: PacketRouter, + ) -> Result<(), ErasedGatewayError> { + debug!("no-op packet router setup"); + Ok(()) + } +} + +// to allow for dynamic dispatch +impl GatewayTransceiver for Box { + #[inline] + fn gateway_identity(&self) -> identity::PublicKey { + (**self).gateway_identity() + } +} + +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +impl GatewaySender for Box { + #[inline] + async fn send_mix_packet(&mut self, packet: MixPacket) -> Result<(), ErasedGatewayError> { + (**self).send_mix_packet(packet).await + } + + #[inline] + async fn batch_send_mix_packets( + &mut self, + packets: Vec, + ) -> Result<(), ErasedGatewayError> { + (**self).batch_send_mix_packets(packets).await + } +} + +impl GatewayReceiver for Box { + #[inline] + fn set_packet_router(&mut self, packet_router: PacketRouter) -> Result<(), ErasedGatewayError> { + (**self).set_packet_router(packet_router) + } +} + +/// Gateway to which the client is connected through a socket. +/// Most likely through a websocket. +pub struct RemoteGateway { + gateway_client: GatewayClient, +} + +impl RemoteGateway { + pub fn new(gateway_client: GatewayClient) -> Self { + Self { gateway_client } + } +} + +impl GatewayTransceiver for RemoteGateway +where + C: Send, + St: Send, +{ + fn gateway_identity(&self) -> identity::PublicKey { + self.gateway_client.gateway_identity() + } +} + +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +impl GatewaySender for RemoteGateway +where + C: Send, + St: Send, +{ + async fn send_mix_packet(&mut self, packet: MixPacket) -> Result<(), ErasedGatewayError> { + self.gateway_client + .send_mix_packet(packet) + .await + .map_err(erase_err) + } + + async fn batch_send_mix_packets( + &mut self, + packets: Vec, + ) -> Result<(), ErasedGatewayError> { + self.gateway_client + .batch_send_mix_packets(packets) + .await + .map_err(erase_err) + } +} + +impl GatewayReceiver for RemoteGateway {} + +#[derive(Debug, Error)] +pub enum LocalGatewayError { + #[error("attempted to set the packet router for the second time")] + PacketRouterAlreadySet, + + #[error("failed to setup packet router - has the receiver been dropped?")] + FailedPacketRouterSetup, +} + +/// Gateway running within the same process. +#[cfg(not(target_arch = "wasm32"))] +pub struct LocalGateway { + /// Identity of the locally managed gateway + local_identity: identity::PublicKey, + + // 'sender' part + /// Channel responsible for taking mix packets and forwarding them further into the further mixnet layers. + packet_forwarder: mpsc::UnboundedSender, + + // 'receiver' part + packet_router_tx: Option>, +} + +#[cfg(not(target_arch = "wasm32"))] +impl LocalGateway { + pub fn new( + local_identity: identity::PublicKey, + packet_forwarder: mpsc::UnboundedSender, + packet_router_tx: oneshot::Sender, + ) -> Self { + LocalGateway { + local_identity, + packet_forwarder, + packet_router_tx: Some(packet_router_tx), + } + } +} + +#[cfg(not(target_arch = "wasm32"))] +mod nonwasm_sealed { + use super::*; + + impl GatewayTransceiver for LocalGateway { + fn gateway_identity(&self) -> identity::PublicKey { + self.local_identity + } + } + + #[async_trait] + impl GatewaySender for LocalGateway { + async fn send_mix_packet(&mut self, packet: MixPacket) -> Result<(), ErasedGatewayError> { + self.packet_forwarder + .unbounded_send(packet) + .map_err(|err| err.into_send_error()) + .map_err(erase_err) + } + } + + impl GatewayReceiver for LocalGateway { + fn set_packet_router( + &mut self, + packet_router: PacketRouter, + ) -> Result<(), ErasedGatewayError> { + let Some(packet_routex_tx) = self.packet_router_tx.take() else { + return Err(erase_err(LocalGatewayError::PacketRouterAlreadySet)); + }; + + packet_routex_tx + .send(packet_router) + .map_err(|_| erase_err(LocalGatewayError::FailedPacketRouterSetup)) + } + } +} + +// if we ever decided to start writing unit tests... : ) +pub struct MockGateway { + dummy_identity: identity::PublicKey, + packet_router: Option, + sent: Vec, +} + +impl Default for MockGateway { + fn default() -> Self { + MockGateway { + dummy_identity: "3ebjp1Fb9hdcS1AR6AZihgeJiMHkB5jjJUsvqNnfQwU7" + .parse() + .unwrap(), + packet_router: None, + sent: vec![], + } + } +} + +#[derive(Debug, Error)] +#[error("mock gateway error")] +pub struct MockGatewayError; + +impl GatewayReceiver for MockGateway { + // TODO: that's frustrating. can't do anything about the behaviour here since all the routing is in the `PacketRouter`... + fn set_packet_router(&mut self, packet_router: PacketRouter) -> Result<(), ErasedGatewayError> { + self.packet_router = Some(packet_router); + Ok(()) + } +} + +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +impl GatewaySender for MockGateway { + async fn send_mix_packet(&mut self, packet: MixPacket) -> Result<(), ErasedGatewayError> { + self.sent.push(packet); + Ok(()) + } +} + +impl GatewayTransceiver for MockGateway { + fn gateway_identity(&self) -> identity::PublicKey { + self.dummy_identity + } +} diff --git a/common/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs b/common/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs index 18d2959181..0034e00567 100644 --- a/common/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs +++ b/common/client-core/src/client/real_messages_control/acknowledgement_control/acknowledgement_listener.rs @@ -71,7 +71,7 @@ impl AcknowledgementListener { while !shutdown.is_shutdown() { tokio::select! { acks = self.ack_receiver.next() => match acks { - Some(acks) => {self.handle_ack_receiver_item(acks).await} + Some(acks) => self.handle_ack_receiver_item(acks).await, None => { log::trace!("AcknowledgementListener: Stopping since channel closed"); break; diff --git a/common/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs b/common/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs index 5f2bf6f80d..acf0f54ca9 100644 --- a/common/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs +++ b/common/client-core/src/client/real_messages_control/acknowledgement_control/mod.rs @@ -260,7 +260,7 @@ where let mut sent_notification_listener = self.sent_notification_listener; let mut action_controller = self.action_controller; - let shutdown_handle = shutdown.clone(); + let shutdown_handle = shutdown.fork("acknowledgement_listener"); spawn_future(async move { acknowledgement_listener .run_with_shutdown(shutdown_handle) @@ -268,7 +268,7 @@ where debug!("The acknowledgement listener has finished execution!"); }); - let shutdown_handle = shutdown.clone(); + let shutdown_handle = shutdown.fork("input_message_listener"); spawn_future(async move { input_message_listener .run_with_shutdown(shutdown_handle) @@ -276,7 +276,7 @@ where debug!("The input listener has finished execution!"); }); - let shutdown_handle = shutdown.clone(); + let shutdown_handle = shutdown.fork("retransmission_request_listener"); spawn_future(async move { retransmission_request_listener .run_with_shutdown(shutdown_handle, packet_type) @@ -284,7 +284,7 @@ where debug!("The retransmission request listener has finished execution!"); }); - let shutdown_handle = shutdown.clone(); + let shutdown_handle = shutdown.fork("sent_notification_listener"); spawn_future(async move { sent_notification_listener .run_with_shutdown(shutdown_handle) @@ -293,7 +293,9 @@ where }); spawn_future(async move { - action_controller.run_with_shutdown(shutdown).await; + action_controller + .run_with_shutdown(shutdown.with_suffix("action_controller")) + .await; debug!("The controller has finished execution!"); }); } diff --git a/common/client-core/src/client/real_messages_control/mod.rs b/common/client-core/src/client/real_messages_control/mod.rs index 32c913006d..9c57798fe7 100644 --- a/common/client-core/src/client/real_messages_control/mod.rs +++ b/common/client-core/src/client/real_messages_control/mod.rs @@ -213,17 +213,17 @@ impl RealMessagesController { let ack_control = self.ack_control; let mut reply_control = self.reply_control; - let shutdown_handle = shutdown.clone(); + let shutdown_handle = shutdown.fork("out_queue_control"); spawn_future(async move { out_queue_control.run_with_shutdown(shutdown_handle).await; debug!("The out queue controller has finished execution!"); }); - let shutdown_handle = shutdown.clone(); + let shutdown_handle = shutdown.fork("reply_control"); spawn_future(async move { reply_control.run_with_shutdown(shutdown_handle).await; debug!("The reply controller has finished execution!"); }); - ack_control.start_with_shutdown(shutdown, packet_type); + ack_control.start_with_shutdown(shutdown.with_suffix("ack_control"), packet_type); } } diff --git a/common/client-core/src/client/received_buffer.rs b/common/client-core/src/client/received_buffer.rs index b9c93d8922..3421ed86ff 100644 --- a/common/client-core/src/client/received_buffer.rs +++ b/common/client-core/src/client/received_buffer.rs @@ -500,7 +500,7 @@ impl ReceivedMessagesBufferControll let mut fragmented_message_receiver = self.fragmented_message_receiver; let mut request_receiver = self.request_receiver; - let shutdown_handle = shutdown.clone(); + let shutdown_handle = shutdown.fork("fragmented_message_receiver"); spawn_future(async move { match fragmented_message_receiver .run_with_shutdown(shutdown_handle) @@ -511,7 +511,9 @@ impl ReceivedMessagesBufferControll } }); spawn_future(async move { - request_receiver.run_with_shutdown(shutdown).await; + request_receiver + .run_with_shutdown(shutdown.with_suffix("request_receiver")) + .await; }); } } diff --git a/common/client-core/src/client/topology_control/mod.rs b/common/client-core/src/client/topology_control/mod.rs index ed426dde50..ae50128942 100644 --- a/common/client-core/src/client/topology_control/mod.rs +++ b/common/client-core/src/client/topology_control/mod.rs @@ -5,10 +5,17 @@ use crate::spawn_future; pub(crate) use accessor::{TopologyAccessor, TopologyReadPermit}; use futures::StreamExt; use log::*; +use nym_sphinx::addressing::nodes::NodeIdentity; use nym_topology::provider_trait::TopologyProvider; use nym_topology::NymTopologyError; use std::time::Duration; +#[cfg(not(target_arch = "wasm32"))] +use tokio::time::sleep; + +#[cfg(target_arch = "wasm32")] +use wasmtimer::tokio::sleep; + mod accessor; pub mod geo_aware_provider; pub(crate) mod nym_api_provider; @@ -86,6 +93,54 @@ impl TopologyRefresher { self.topology_accessor.ensure_is_routable().await } + pub async fn ensure_contains_gateway( + &self, + gateway: &NodeIdentity, + ) -> Result<(), NymTopologyError> { + let topology = self + .topology_accessor + .current_topology() + .await + .ok_or(NymTopologyError::EmptyNetworkTopology)?; + if !topology.gateway_exists(gateway) { + return Err(NymTopologyError::NonExistentGatewayError { + identity_key: gateway.to_base58_string(), + }); + } + + Ok(()) + } + + pub async fn wait_for_gateway( + &mut self, + gateway: &NodeIdentity, + timeout_duration: Duration, + ) -> Result<(), NymTopologyError> { + info!( + "going to wait for at most {timeout_duration:?} for gateway '{gateway}' to come online" + ); + + let deadline = sleep(timeout_duration); + tokio::pin!(deadline); + + loop { + tokio::select! { + _ = &mut deadline => { + return Err(NymTopologyError::TimedOutWaitingForGateway { + identity_key: gateway.to_base58_string() + }) + } + _ = self.try_refresh() => { + if self.ensure_contains_gateway(gateway).await.is_ok() { + return Ok(()) + } + info!("gateway '{gateway}' is still not online..."); + sleep(self.refresh_rate).await + } + } + } + } + pub fn start_with_shutdown(mut self, mut shutdown: nym_task::TaskClient) { spawn_future(async move { debug!("Started TopologyRefresher with graceful shutdown support"); diff --git a/common/client-core/src/config/disk_persistence/keys_paths.rs b/common/client-core/src/config/disk_persistence/keys_paths.rs index 3ae1400a19..aeab0359ea 100644 --- a/common/client-core/src/config/disk_persistence/keys_paths.rs +++ b/common/client-core/src/config/disk_persistence/keys_paths.rs @@ -35,7 +35,7 @@ pub struct ClientKeysPaths { } impl ClientKeysPaths { - pub fn new_default>(base_data_directory: P) -> Self { + pub fn new_base>(base_data_directory: P) -> Self { let base_dir = base_data_directory.as_ref(); ClientKeysPaths { diff --git a/common/client-core/src/config/disk_persistence/mod.rs b/common/client-core/src/config/disk_persistence/mod.rs index 6527283117..b323d059dc 100644 --- a/common/client-core/src/config/disk_persistence/mod.rs +++ b/common/client-core/src/config/disk_persistence/mod.rs @@ -29,14 +29,14 @@ pub struct CommonClientPaths { } impl CommonClientPaths { - pub fn new_default>(base_data_directory: P) -> Self { + pub fn new_base>(base_data_directory: P) -> Self { let base_dir = base_data_directory.as_ref(); CommonClientPaths { credentials_database: base_dir.join(DEFAULT_CREDENTIALS_DB_FILENAME), reply_surb_database: base_dir.join(DEFAULT_REPLY_SURB_DB_FILENAME), gateway_details: base_dir.join(DEFAULT_GATEWAY_DETAILS_FILENAME), - keys: ClientKeysPaths::new_default(base_data_directory), + keys: ClientKeysPaths::new_base(base_data_directory), } } } diff --git a/common/client-core/src/config/mod.rs b/common/client-core/src/config/mod.rs index e11f523276..b3e8afabff 100644 --- a/common/client-core/src/config/mod.rs +++ b/common/client-core/src/config/mod.rs @@ -3,6 +3,7 @@ use nym_config::defaults::NymNetworkDetails; use nym_crypto::asymmetric::identity; +use nym_gateway_client::client::GatewayConfig; use nym_sphinx::{ addressing::clients::Recipient, params::{PacketSize, PacketType}, @@ -29,6 +30,8 @@ const DEFAULT_MESSAGE_STREAM_AVERAGE_DELAY: Duration = Duration::from_millis(20) const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(50); const DEFAULT_TOPOLOGY_REFRESH_RATE: Duration = Duration::from_secs(5 * 60); // every 5min const DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT: Duration = Duration::from_millis(5_000); +const DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD: Duration = Duration::from_secs(70 * 60); // 70min -> full epoch (1h) + a bit of overhead + // Set this to a high value for now, so that we don't risk sporadic timeouts that might cause // bought bandwidth tokens to not have time to be spent; Once we remove the gateway from the // bandwidth bridging protocol, we can come back to a smaller timeout value @@ -137,6 +140,17 @@ impl Config { self.debug.traffic.message_sending_average_delay = Duration::from_millis(4); } + pub fn with_disabled_poisson_process(mut self, disabled: bool) -> Self { + if disabled { + self.set_no_poisson_process() + } + self + } + + pub fn set_no_poisson_process(&mut self) { + self.debug.traffic.disable_main_poisson_packet_distribution = true; + } + pub fn with_disabled_cover_traffic(mut self, disabled: bool) -> Self { if disabled { self.set_no_cover_traffic() @@ -230,6 +244,19 @@ pub struct GatewayEndpointConfig { pub gateway_listener: String, } +impl TryFrom for GatewayConfig { + type Error = ClientCoreError; + + fn try_from(value: GatewayEndpointConfig) -> Result { + Ok(GatewayConfig { + gateway_identity: identity::PublicKey::from_base58_string(value.gateway_id) + .map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?, + gateway_owner: Some(value.gateway_owner), + gateway_listener: value.gateway_listener, + }) + } +} + #[cfg_attr(target_arch = "wasm32", wasm_bindgen)] impl GatewayEndpointConfig { #[cfg_attr(target_arch = "wasm32", wasm_bindgen(constructor))] @@ -252,15 +279,29 @@ impl GatewayEndpointConfig { identity::PublicKey::from_base58_string(&self.gateway_id) .map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId) } -} -impl From for GatewayEndpointConfig { - fn from(node: nym_topology::gateway::Node) -> GatewayEndpointConfig { - let gateway_listener = node.clients_address(); + pub fn from_node(node: nym_topology::gateway::Node, use_tls: bool) -> Self { + // TODO: in the future this shall return a Result and explicit `use_tls` will be removed in favour of the tls info being available on the struct + if use_tls { + Self::from_topology_node_tls(node) + } else { + Self::from_topology_node_no_tls(node) + } + } + + pub fn from_topology_node_no_tls(node: nym_topology::gateway::Node) -> Self { GatewayEndpointConfig { gateway_id: node.identity_key.to_base58_string(), + gateway_listener: node.clients_address(), + gateway_owner: node.owner, + } + } + + pub fn from_topology_node_tls(node: nym_topology::gateway::Node) -> Self { + GatewayEndpointConfig { + gateway_id: node.identity_key.to_base58_string(), + gateway_listener: node.clients_address_tls(), gateway_owner: node.owner, - gateway_listener, } } } @@ -487,6 +528,11 @@ pub struct Topology { /// Supersedes `topology_refresh_rate_ms`. pub disable_refreshing: bool, + /// Defines how long the client is going to wait on startup for its gateway to come online, + /// before abandoning the procedure. + #[serde(with = "humantime_serde")] + pub max_startup_gateway_waiting_period: Duration, + /// Specifies the mixnode topology to be used for sending packets. pub topology_structure: TopologyStructure, } @@ -521,6 +567,7 @@ impl Default for Topology { topology_refresh_rate: DEFAULT_TOPOLOGY_REFRESH_RATE, topology_resolution_timeout: DEFAULT_TOPOLOGY_RESOLUTION_TIMEOUT, disable_refreshing: false, + max_startup_gateway_waiting_period: DEFAULT_MAX_STARTUP_GATEWAY_WAITING_PERIOD, topology_structure: TopologyStructure::default(), } } diff --git a/common/client-core/src/config/old_config_v1_1_20_2.rs b/common/client-core/src/config/old_config_v1_1_20_2.rs index a097b55f2a..afb6536192 100644 --- a/common/client-core/src/config/old_config_v1_1_20_2.rs +++ b/common/client-core/src/config/old_config_v1_1_20_2.rs @@ -267,7 +267,7 @@ impl From for Topology { topology_refresh_rate: value.topology_refresh_rate, topology_resolution_timeout: value.topology_resolution_timeout, disable_refreshing: value.disable_refreshing, - topology_structure: Default::default(), + ..Default::default() } } } diff --git a/common/client-core/src/error.rs b/common/client-core/src/error.rs index 0c30c149cb..15b6c1a1bf 100644 --- a/common/client-core/src/error.rs +++ b/common/client-core/src/error.rs @@ -1,6 +1,7 @@ -// Copyright 2022 - Nym Technologies SA +// Copyright 2022-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::client::mix_traffic::transceiver::ErasedGatewayError; use nym_crypto::asymmetric::identity::Ed25519RecoveryError; use nym_gateway_client::error::GatewayClientError; use nym_topology::gateway::GatewayConversionError; @@ -19,6 +20,12 @@ pub enum ClientCoreError { source: GatewayClientError, }, + #[error("Custom gateway client error: {source}")] + ErasedGatewayClientError { + #[from] + source: ErasedGatewayError, + }, + #[error("Ed25519 error: {0}")] Ed25519RecoveryError(#[from] Ed25519RecoveryError), @@ -31,15 +38,9 @@ pub enum ClientCoreError { #[error("No gateways on network")] NoGatewaysOnNetwork, - #[error("Failed to setup gateway")] - FailedToSetupGateway, - #[error("List of nym apis is empty")] ListOfNymApisIsEmpty, - #[error("Could not load existing gateway configuration: {0}")] - CouldNotLoadExistingGatewayConfiguration(std::io::Error), - #[error("The current network topology seem to be insufficient to route any packets through")] InsufficientNetworkTopology(#[from] NymTopologyError), @@ -61,15 +62,6 @@ pub enum ClientCoreError { #[error("The gateway id is invalid - {0}")] UnableToCreatePublicKeyFromGatewayId(Ed25519RecoveryError), - #[error("The identity of the gateway is unknown - did you run init?")] - GatewayIdUnknown, - - #[error("The owner of the gateway is unknown - did you run init?")] - GatewayOwnerUnknown, - - #[error("The address of the gateway is unknown - did you run init?")] - GatewayAddressUnknown, - #[error("The gateway is malformed: {source}")] MalformedGateway { #[from] @@ -122,6 +114,18 @@ pub enum ClientCoreError { #[error("unable to upgrade config file to `{new_version}`")] UnableToUpgradeConfigFile { new_version: String }, + + #[error("the provided gateway details don't much the stored data")] + MismatchedStoredGatewayDetails, + + #[error("custom selection of gateway was expected")] + CustomGatewaySelectionExpected, + + #[error("the persisted gateway details were set for a custom setup")] + UnexpectedPersistedCustomGatewayDetails, + + #[error("this client has performed gateway initialisation in another session")] + NoInitClientPresent, } /// Set of messages that the client can send to listeners via the task manager diff --git a/common/client-core/src/init/helpers.rs b/common/client-core/src/init/helpers.rs index 9d54130576..27516e7750 100644 --- a/common/client-core/src/init/helpers.rs +++ b/common/client-core/src/init/helpers.rs @@ -3,12 +3,12 @@ use crate::config::GatewayEndpointConfig; use crate::error::ClientCoreError; -use crate::init::RegistrationResult; +use crate::init::types::RegistrationResult; use futures::{SinkExt, StreamExt}; use log::{debug, info, trace, warn}; use nym_crypto::asymmetric::identity; use nym_gateway_client::GatewayClient; -use nym_topology::{filter::VersionFilterable, gateway}; +use nym_topology::{filter::VersionFilterable, gateway, mix}; use rand::{seq::SliceRandom, Rng}; use std::{sync::Arc, time::Duration}; use tungstenite::Message; @@ -24,6 +24,7 @@ use tokio_tungstenite::connect_async; use tokio_tungstenite::{MaybeTlsStream, WebSocketStream}; #[cfg(not(target_arch = "wasm32"))] type WsConn = WebSocketStream>; +use nym_validator_client::client::IdentityKeyRef; #[cfg(not(target_arch = "wasm32"))] use tokio::time::sleep; @@ -77,6 +78,28 @@ pub async fn current_gateways( Ok(filtered_gateways) } +pub async fn current_mixnodes( + rng: &mut R, + nym_apis: &[Url], +) -> Result, ClientCoreError> { + let nym_api = nym_apis + .choose(rng) + .ok_or(ClientCoreError::ListOfNymApisIsEmpty)?; + let client = nym_validator_client::client::NymApiClient::new(nym_api.clone()); + + log::trace!("Fetching list of mixnodes from: {nym_api}"); + + let mixnodes = client.get_cached_mixnodes().await?; + let valid_mixnodes = mixnodes + .into_iter() + .filter_map(|mixnode| (&mixnode.bond_information).try_into().ok()) + .collect::>(); + + // we were always filtering by version so I'm not removing that 'feature' + let filtered_mixnodes = valid_mixnodes.filter_by_version(env!("CARGO_PKG_VERSION")); + Ok(filtered_mixnodes) +} + #[cfg(not(target_arch = "wasm32"))] async fn connect(endpoint: &str) -> Result { match tokio::time::timeout(CONN_TIMEOUT, connect_async(endpoint)).await { @@ -197,17 +220,27 @@ pub(super) fn uniformly_random_gateway( .cloned() } +pub(super) fn get_specified_gateway( + gateway_identity: IdentityKeyRef, + gateways: &[gateway::Node], +) -> Result { + let user_gateway = identity::PublicKey::from_base58_string(gateway_identity) + .map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?; + + gateways + .iter() + .find(|gateway| gateway.identity_key == user_gateway) + .ok_or_else(|| ClientCoreError::NoGatewayWithId(gateway_identity.to_string())) + .cloned() +} + pub(super) async fn register_with_gateway( gateway: &GatewayEndpointConfig, our_identity: Arc, ) -> Result { - let timeout = Duration::from_millis(1500); - let mut gateway_client = GatewayClient::new_init( - gateway.gateway_listener.clone(), - gateway.try_get_gateway_identity_key()?, - our_identity.clone(), - timeout, - ); + let mut gateway_client = + GatewayClient::new_init(gateway.to_owned().try_into()?, our_identity.clone()); + gateway_client.establish_connection().await.map_err(|err| { log::warn!("Failed to establish connection with gateway!"); ClientCoreError::GatewayClientError { @@ -230,6 +263,6 @@ pub(super) async fn register_with_gateway( })?; Ok(RegistrationResult { shared_keys, - authenticated_ephemeral_client: Some(gateway_client), + authenticated_ephemeral_client: gateway_client, }) } diff --git a/common/client-core/src/init/mod.rs b/common/client-core/src/init/mod.rs index 1f8e10bcc9..27279cfadb 100644 --- a/common/client-core/src/init/mod.rs +++ b/common/client-core/src/init/mod.rs @@ -8,246 +8,34 @@ use crate::client::base_client::storage::gateway_details::{ }; use crate::client::key_manager::persistence::KeyStore; use crate::client::key_manager::ManagedKeys; -use crate::init::helpers::{choose_gateway_by_latency, current_gateways, uniformly_random_gateway}; -use crate::{ - config::{Config, GatewayEndpointConfig}, - error::ClientCoreError, +use crate::config::GatewayEndpointConfig; +use crate::error::ClientCoreError; +use crate::init::helpers::{ + choose_gateway_by_latency, get_specified_gateway, uniformly_random_gateway, }; -use nym_crypto::asymmetric::identity; -use nym_gateway_client::client::InitOnly; -use nym_gateway_client::GatewayClient; -use nym_gateway_requests::registration::handshake::SharedKeys; -use nym_sphinx::addressing::{clients::Recipient, nodes::NodeIdentity}; +use crate::init::types::{ + CustomGatewayDetails, GatewayDetails, GatewaySelectionSpecification, GatewaySetup, + InitialisationResult, +}; +use nym_gateway_client::client::InitGatewayClient; use nym_topology::gateway; -use nym_validator_client::client::IdentityKey; use rand::rngs::OsRng; +use serde::de::DeserializeOwned; use serde::Serialize; -use std::fmt::{Debug, Display}; use std::sync::Arc; -use url::Url; pub mod helpers; - -pub struct RegistrationResult { - pub shared_keys: Arc, - pub authenticated_ephemeral_client: Option>, -} - -pub struct InitialisationResult { - pub details: InitialisationDetails, - pub authenticated_ephemeral_client: Option>, -} - -impl From for InitialisationResult { - fn from(details: InitialisationDetails) -> Self { - InitialisationResult { - details, - authenticated_ephemeral_client: None, - } - } -} - -// TODO: rename to something better... -#[derive(Debug)] -pub struct InitialisationDetails { - pub gateway_details: GatewayEndpointConfig, - pub managed_keys: ManagedKeys, -} - -impl InitialisationDetails { - pub fn new(gateway_details: GatewayEndpointConfig, managed_keys: ManagedKeys) -> Self { - InitialisationDetails { - gateway_details, - managed_keys, - } - } - - pub async fn try_load(key_store: &K, details_store: &D) -> Result - where - K: KeyStore, - D: GatewayDetailsStore, - K::StorageError: Send + Sync + 'static, - D::StorageError: Send + Sync + 'static, - { - let loaded_details = _load_gateway_details(details_store).await?; - let loaded_keys = _load_managed_keys(key_store).await?; - - if !loaded_details.verify(&loaded_keys.must_get_gateway_shared_key()) { - return Err(ClientCoreError::MismatchedGatewayDetails { - gateway_id: loaded_details.details.gateway_id, - }); - } - - Ok(InitialisationDetails { - gateway_details: loaded_details.into(), - managed_keys: loaded_keys, - }) - } - - pub fn client_address(&self) -> Result { - let client_recipient = Recipient::new( - *self.managed_keys.identity_public_key(), - *self.managed_keys.encryption_public_key(), - // TODO: below only works under assumption that gateway address == gateway id - // (which currently is true) - NodeIdentity::from_base58_string(&self.gateway_details.gateway_id)?, - ); - - Ok(client_recipient) - } -} - -pub enum GatewaySetup { - /// The gateway specification MUST BE loaded from the underlying storage. - MustLoad, - - /// Specifies usage of a new, random, gateway. - New { - /// Should the new gateway be selected based on latency. - by_latency: bool, - }, - - Specified { - /// Identity key of the gateway we want to try to use. - gateway_identity: IdentityKey, - }, - - Predefined { - /// Full gateway configuration - details: PersistedGatewayDetails, - }, - - ReuseConnection { - /// The authenticated ephemeral client that was created during `init` - authenticated_ephemeral_client: GatewayClient, - - /// Details of this pre-initialised client - details: InitialisationDetails, - }, -} - -impl From for GatewaySetup { - fn from(details: PersistedGatewayDetails) -> Self { - GatewaySetup::Predefined { details } - } -} - -impl From for GatewaySetup { - fn from(gateway_identity: IdentityKey) -> Self { - GatewaySetup::Specified { gateway_identity } - } -} - -impl Default for GatewaySetup { - fn default() -> Self { - GatewaySetup::New { by_latency: false } - } -} - -impl GatewaySetup { - pub fn new_fresh( - gateway_identity: Option, - latency_based_selection: Option, - ) -> Self { - if let Some(gateway_identity) = gateway_identity { - GatewaySetup::Specified { gateway_identity } - } else { - GatewaySetup::New { - by_latency: latency_based_selection.unwrap_or_default(), - } - } - } - - pub fn is_must_load(&self) -> bool { - matches!(self, GatewaySetup::MustLoad) - } - - pub fn has_full_details(&self) -> bool { - matches!(self, GatewaySetup::Predefined { .. }) || self.is_must_load() - } - - pub async fn choose_gateway( - &self, - gateways: &[gateway::Node], - ) -> Result { - match self { - GatewaySetup::New { by_latency } => { - let mut rng = OsRng; - if *by_latency { - choose_gateway_by_latency(&mut rng, gateways).await - } else { - uniformly_random_gateway(&mut rng, gateways) - } - } - .map(Into::into), - GatewaySetup::Specified { gateway_identity } => { - let user_gateway = identity::PublicKey::from_base58_string(gateway_identity) - .map_err(ClientCoreError::UnableToCreatePublicKeyFromGatewayId)?; - - gateways - .iter() - .find(|gateway| gateway.identity_key == user_gateway) - .ok_or_else(|| ClientCoreError::NoGatewayWithId(gateway_identity.to_string())) - .cloned() - } - .map(Into::into), - _ => Err(ClientCoreError::UnexpectedGatewayDetails), - } - } - - pub async fn try_get_new_gateway_details( - &self, - validator_servers: &[Url], - ) -> Result { - let mut rng = OsRng; - let gateways = current_gateways(&mut rng, validator_servers).await?; - self.choose_gateway(&gateways).await - } -} - -/// Struct describing the results of the client initialization procedure. -#[derive(Debug, Serialize)] -pub struct InitResults { - version: String, - id: String, - identity_key: String, - encryption_key: String, - gateway_id: String, - gateway_listener: String, -} - -impl InitResults { - pub fn new(config: &Config, address: &Recipient, gateway: &GatewayEndpointConfig) -> Self { - Self { - version: config.client.version.clone(), - id: config.client.id.clone(), - identity_key: address.identity().to_base58_string(), - encryption_key: address.encryption_key().to_base58_string(), - gateway_id: gateway.gateway_id.clone(), - gateway_listener: gateway.gateway_listener.clone(), - } - } -} - -impl Display for InitResults { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - writeln!(f, "Version: {}", self.version)?; - writeln!(f, "ID: {}", self.id)?; - writeln!(f, "Identity key: {}", self.identity_key)?; - writeln!(f, "Encryption: {}", self.encryption_key)?; - writeln!(f, "Gateway ID: {}", self.gateway_id)?; - write!(f, "Gateway: {}", self.gateway_listener) - } -} +pub mod types; // helpers for error wrapping -async fn _store_gateway_details( +async fn _store_gateway_details( details_store: &D, - details: &PersistedGatewayDetails, + details: &PersistedGatewayDetails, ) -> Result<(), ClientCoreError> where - D: GatewayDetailsStore, + D: GatewayDetailsStore, D::StorageError: Send + Sync + 'static, + T: Serialize + Send + Sync, { details_store .store_gateway_details(details) @@ -257,12 +45,13 @@ where }) } -async fn _load_gateway_details( +async fn _load_gateway_details( details_store: &D, -) -> Result +) -> Result, ClientCoreError> where - D: GatewayDetailsStore, + D: GatewayDetailsStore, D::StorageError: Send + Sync + 'static, + T: DeserializeOwned + Send + Sync, { details_store .load_gateway_details() @@ -284,190 +73,168 @@ where }) } -fn ensure_valid_details( - details: &PersistedGatewayDetails, +fn ensure_valid_details( + details: &PersistedGatewayDetails, loaded_keys: &ManagedKeys, ) -> Result<(), ClientCoreError> { - if !details.verify(&loaded_keys.must_get_gateway_shared_key()) { - Err(ClientCoreError::MismatchedGatewayDetails { - gateway_id: details.details.gateway_id.clone(), - }) - } else { - Ok(()) - } + details.validate(loaded_keys.gateway_shared_key().as_deref()) } -pub async fn setup_gateway_from( - setup: GatewaySetup, +async fn setup_new_gateway( key_store: &K, details_store: &D, overwrite_data: bool, - gateways: Option<&[gateway::Node]>, -) -> Result + selection_specification: GatewaySelectionSpecification, + available_gateways: Vec, +) -> Result, ClientCoreError> where K: KeyStore, - D: GatewayDetailsStore, + D: GatewayDetailsStore, K::StorageError: Send + Sync + 'static, D::StorageError: Send + Sync + 'static, + T: DeserializeOwned + Serialize + Send + Sync, { - // I don't like how we can't deal with this variant in the match below, but we need to take ownership of internal values. - if let GatewaySetup::ReuseConnection { - authenticated_ephemeral_client, - details, - } = setup - { - // if we have already performed the full setup, forward the details. - // it's up to the caller to ensure persistence - return Ok(InitialisationResult { - details, - authenticated_ephemeral_client: Some(authenticated_ephemeral_client), - }); + // if we're setting up new gateway, failing to load existing information is fine. + // as a matter of fact, it's only potentially a problem if we DO succeed + if _load_gateway_details(details_store).await.is_ok() && !overwrite_data { + return Err(ClientCoreError::ForbiddenKeyOverwrite); + } + if _load_managed_keys(key_store).await.is_ok() && !overwrite_data { + return Err(ClientCoreError::ForbiddenKeyOverwrite); } let mut rng = OsRng; + let mut new_keys = ManagedKeys::generate_new(&mut rng); - // try load gateway details - let loaded_details = _load_gateway_details(details_store).await; - - // try load keys and decide what to do based on the GatewaySetup - let mut managed_keys = match ManagedKeys::try_load(key_store).await { - Ok(loaded_keys) => { - match &setup { - GatewaySetup::MustLoad => { - // get EVERYTHING from the storage - let details = loaded_details?; - ensure_valid_details(&details, &loaded_keys)?; - - // no need to persist anything as we got everything from the storage - return Ok(InitialisationDetails::new(details.into(), loaded_keys).into()); - } - GatewaySetup::Predefined { details } => { - // we already have defined gateway details AND a shared key - ensure_valid_details(details, &loaded_keys)?; - - // if nothing was stored or we're allowed to overwrite what's there, just persist the passed data - if overwrite_data || loaded_details.is_err() { - _store_gateway_details(details_store, details).await?; - } - - return Ok( - InitialisationDetails::new(details.clone().into(), loaded_keys).into(), - ); - } - GatewaySetup::Specified { gateway_identity } => { - // if that data was already stored... - if let Ok(existing_gateway) = loaded_details { - ensure_valid_details(&existing_gateway, &loaded_keys)?; - if &existing_gateway.details.gateway_id != gateway_identity - && !overwrite_data - { - // if our loaded details don't match requested value and we CANT overwrite it... - return Err(ClientCoreError::UnexpectedGatewayDetails); - } else if &existing_gateway.details.gateway_id == gateway_identity { - // if they do match up, just return it - return Ok(InitialisationDetails::new( - existing_gateway.into(), - loaded_keys, - ) - .into()); - } - } - - // we didn't get full details from the store and we have loaded some keys - // so we can only continue if we're allowed to overwrite keys - if overwrite_data { - ManagedKeys::generate_new(&mut rng) - } else { - return Err(ClientCoreError::ForbiddenKeyOverwrite); - } - } - GatewaySetup::New { .. } => { - if let Ok(existing_gateway) = loaded_details { - ensure_valid_details(&existing_gateway, &loaded_keys)?; - return Ok(InitialisationDetails::new( - existing_gateway.into(), - loaded_keys, - ) - .into()); - } - - // we didn't get full details from the store and we have loaded some keys - // so we can only continue if we're allowed to overwrite keys - if overwrite_data { - ManagedKeys::generate_new(&mut rng) - } else { - return Err(ClientCoreError::ForbiddenKeyOverwrite); - } - } - GatewaySetup::ReuseConnection { .. } => { - unreachable!("the reuse connection variant was already manually covered") - } - } + let gateway_details = match selection_specification { + GatewaySelectionSpecification::UniformRemote { must_use_tls } => { + let gateway = uniformly_random_gateway(&mut rng, &available_gateways)?; + GatewayDetails::Configured(GatewayEndpointConfig::from_node(gateway, must_use_tls)) } - Err(_) => { - // if we failed to load the keys, ensure we didn't provide gateway details in some form - // (in that case we CAN'T generate new keys - if setup.has_full_details() { - return Err(ClientCoreError::UnavailableSharedKey); - } - ManagedKeys::generate_new(&mut rng) + GatewaySelectionSpecification::RemoteByLatency { must_use_tls } => { + let gateway = choose_gateway_by_latency(&mut rng, &available_gateways).await?; + GatewayDetails::Configured(GatewayEndpointConfig::from_node(gateway, must_use_tls)) } + GatewaySelectionSpecification::Specified { + must_use_tls, + identity, + } => { + let gateway = get_specified_gateway(&identity, &available_gateways)?; + GatewayDetails::Configured(GatewayEndpointConfig::from_node(gateway, must_use_tls)) + } + GatewaySelectionSpecification::Custom { + gateway_identity, + additional_data, + } => GatewayDetails::Custom(CustomGatewayDetails::new(gateway_identity, additional_data)), }; - // choose gateway - let gateway_details = setup.choose_gateway(gateways.unwrap_or_default()).await?; - - // get our identity key - let our_identity = managed_keys.identity_keypair(); + let registration_result = if let GatewayDetails::Configured(gateway_cfg) = &gateway_details { + // if we're using a 'normal' gateway setup, do register + let our_identity = new_keys.identity_keypair(); + Some(helpers::register_with_gateway(gateway_cfg, our_identity).await?) + } else { + None + }; - // Establish connection, authenticate and generate keys for talking with the gateway - let registration_result = - helpers::register_with_gateway(&gateway_details, our_identity).await?; - let shared_keys = registration_result.shared_keys; + let maybe_shared_keys = registration_result + .as_ref() + .map(|r| Arc::clone(&r.shared_keys)); - let persisted_details = PersistedGatewayDetails::new(gateway_details, &shared_keys); + let persisted_details = + PersistedGatewayDetails::new(gateway_details, maybe_shared_keys.as_deref())?; - // persist gateway keys - managed_keys - .deal_with_gateway_key(shared_keys, key_store) + // persist the keys + new_keys + .deal_with_gateway_key(maybe_shared_keys, key_store) .await .map_err(|source| ClientCoreError::KeyStoreError { source: Box::new(source), })?; - // persist gateway config + // persist gateway configs _store_gateway_details(details_store, &persisted_details).await?; Ok(InitialisationResult { - details: InitialisationDetails::new(persisted_details.into(), managed_keys), - authenticated_ephemeral_client: registration_result.authenticated_ephemeral_client, + gateway_details: persisted_details.into(), + managed_keys: new_keys, + authenticated_ephemeral_client: registration_result + .map(|r| r.authenticated_ephemeral_client), }) } -pub async fn setup_gateway( - setup: GatewaySetup, +async fn use_loaded_gateway_details( key_store: &K, details_store: &D, - overwrite_data: bool, - validator_servers: Option<&[Url]>, -) -> Result +) -> Result, ClientCoreError> where K: KeyStore, - D: GatewayDetailsStore, + D: GatewayDetailsStore, K::StorageError: Send + Sync + 'static, D::StorageError: Send + Sync + 'static, + T: DeserializeOwned + Send + Sync, { - let mut rng = OsRng; - let gateways = current_gateways(&mut rng, validator_servers.unwrap_or_default()).await?; + let loaded_details = _load_gateway_details(details_store).await?; + let loaded_keys = _load_managed_keys(key_store).await?; + + ensure_valid_details(&loaded_details, &loaded_keys)?; - setup_gateway_from( - setup, - key_store, - details_store, - overwrite_data, - Some(&gateways), - ) - .await + // no need to persist anything as we got everything from the storage + Ok(InitialisationResult::new_loaded( + loaded_details.into(), + loaded_keys, + )) +} + +fn reuse_gateway_connection( + authenticated_ephemeral_client: InitGatewayClient, + gateway_details: GatewayDetails, + managed_keys: ManagedKeys, +) -> InitialisationResult { + InitialisationResult { + gateway_details, + managed_keys, + authenticated_ephemeral_client: Some(authenticated_ephemeral_client), + } +} + +pub async fn setup_gateway( + setup: GatewaySetup, + key_store: &K, + details_store: &D, +) -> Result, ClientCoreError> +where + K: KeyStore, + D: GatewayDetailsStore, + K::StorageError: Send + Sync + 'static, + D::StorageError: Send + Sync + 'static, + T: DeserializeOwned + Serialize + Send + Sync, +{ + match setup { + GatewaySetup::MustLoad => use_loaded_gateway_details(key_store, details_store).await, + GatewaySetup::New { + specification, + available_gateways, + overwrite_data, + } => { + setup_new_gateway( + key_store, + details_store, + overwrite_data, + specification, + available_gateways, + ) + .await + } + GatewaySetup::ReuseConnection { + authenticated_ephemeral_client, + gateway_details, + managed_keys, + } => Ok(reuse_gateway_connection( + authenticated_ephemeral_client, + gateway_details, + managed_keys, + )), + } } pub fn output_to_json(init_results: &T, output_file: &str) { diff --git a/common/client-core/src/init/types.rs b/common/client-core/src/init/types.rs new file mode 100644 index 0000000000..3e8a88d133 --- /dev/null +++ b/common/client-core/src/init/types.rs @@ -0,0 +1,329 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::client::base_client::storage::gateway_details::{ + GatewayDetailsStore, PersistedCustomGatewayDetails, PersistedGatewayDetails, +}; +use crate::client::key_manager::persistence::KeyStore; +use crate::client::key_manager::ManagedKeys; +use crate::config::{Config, GatewayEndpointConfig}; +use crate::error::ClientCoreError; +use crate::init::{_load_gateway_details, _load_managed_keys, setup_gateway}; +use nym_gateway_client::client::InitGatewayClient; +use nym_gateway_requests::registration::handshake::SharedKeys; +use nym_sphinx::addressing::clients::Recipient; +use nym_sphinx::addressing::nodes::NodeIdentity; +use nym_topology::gateway; +use nym_validator_client::client::IdentityKey; +use serde::de::DeserializeOwned; +use serde::{Deserialize, Serialize}; +use std::fmt::Display; +use std::sync::Arc; + +/// Result of registering with a gateway: +/// - shared keys derived between ourselves and the node +/// - an authenticated handle of an ephemeral handle created for the purposes of registration +pub struct RegistrationResult { + pub shared_keys: Arc, + pub authenticated_ephemeral_client: InitGatewayClient, +} + +/// Result of fully initialising a client: +/// - details of the associated gateway +/// - all loaded (or derived) keys +/// - an optional authenticated handle of an ephemeral gateway handle created for the purposes of registration, +/// if this was the first time this client registered +pub struct InitialisationResult { + pub gateway_details: GatewayDetails, + pub managed_keys: ManagedKeys, + pub authenticated_ephemeral_client: Option, +} + +impl InitialisationResult { + pub fn new_loaded(gateway_details: GatewayDetails, managed_keys: ManagedKeys) -> Self { + InitialisationResult { + gateway_details, + managed_keys, + authenticated_ephemeral_client: None, + } + } + + pub async fn try_load(key_store: &K, details_store: &D) -> Result + where + K: KeyStore, + D: GatewayDetailsStore, + K::StorageError: Send + Sync + 'static, + D::StorageError: Send + Sync + 'static, + T: DeserializeOwned + Send + Sync, + { + let loaded_details = _load_gateway_details(details_store).await?; + let loaded_keys = _load_managed_keys(key_store).await?; + + match &loaded_details { + PersistedGatewayDetails::Default(loaded_default) => { + if !loaded_default.verify(&loaded_keys.must_get_gateway_shared_key()) { + return Err(ClientCoreError::MismatchedGatewayDetails { + gateway_id: loaded_default.details.gateway_id.clone(), + }); + } + } + PersistedGatewayDetails::Custom(_) => {} + } + + Ok(InitialisationResult { + gateway_details: loaded_details.into(), + managed_keys: loaded_keys, + authenticated_ephemeral_client: None, + }) + } + + pub fn client_address(&self) -> Result { + let client_recipient = Recipient::new( + *self.managed_keys.identity_public_key(), + *self.managed_keys.encryption_public_key(), + // TODO: below only works under assumption that gateway address == gateway id + // (which currently is true) + NodeIdentity::from_base58_string(self.gateway_details.gateway_id())?, + ); + + Ok(client_recipient) + } +} + +/// Details of particular gateway client got registered with +#[derive(Debug, Clone)] +pub enum GatewayDetails { + /// Standard details of a remote gateway + Configured(GatewayEndpointConfig), + + /// Custom gateway setup, such as for a client embedded inside gateway itself + Custom(CustomGatewayDetails), +} + +#[derive(Debug, Default, Copy, Clone, Serialize, Deserialize, Eq, PartialEq)] +#[serde(rename_all = "snake_case")] +pub struct EmptyCustomDetails {} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CustomGatewayDetails { + // whatever custom method is used, gateway's identity must be known + pub gateway_id: String, + + #[serde(flatten)] + pub additional_data: T, +} + +impl CustomGatewayDetails { + pub fn new(gateway_id: String, additional_data: T) -> Self { + Self { + gateway_id, + additional_data, + } + } +} + +impl GatewayDetails { + pub fn try_get_configured_endpoint(&self) -> Option<&GatewayEndpointConfig> { + if let GatewayDetails::Configured(endpoint) = &self { + Some(endpoint) + } else { + None + } + } + + pub fn is_custom(&self) -> bool { + matches!(self, GatewayDetails::Custom(_)) + } + + pub fn gateway_id(&self) -> &str { + match self { + GatewayDetails::Configured(cfg) => &cfg.gateway_id, + GatewayDetails::Custom(custom) => &custom.gateway_id, + } + } +} + +impl From for GatewayDetails { + fn from(value: GatewayEndpointConfig) -> Self { + GatewayDetails::Configured(value) + } +} + +impl From> for CustomGatewayDetails { + fn from(value: PersistedCustomGatewayDetails) -> Self { + CustomGatewayDetails { + gateway_id: value.gateway_id, + additional_data: value.additional_data, + } + } +} + +impl From> for PersistedCustomGatewayDetails { + fn from(value: CustomGatewayDetails) -> Self { + PersistedCustomGatewayDetails { + gateway_id: value.gateway_id, + additional_data: value.additional_data, + } + } +} + +impl From> for GatewayDetails { + fn from(value: PersistedGatewayDetails) -> Self { + match value { + PersistedGatewayDetails::Default(default) => { + GatewayDetails::Configured(default.details) + } + PersistedGatewayDetails::Custom(custom) => GatewayDetails::Custom(custom.into()), + } + } +} + +#[derive(Clone)] +pub enum GatewaySelectionSpecification { + /// Uniformly choose a random remote gateway. + UniformRemote { must_use_tls: bool }, + + /// Should the new, remote, gateway be selected based on latency. + RemoteByLatency { must_use_tls: bool }, + + /// Gateway with this specific identity should be chosen. + // JS: I don't really like the name of this enum variant but couldn't think of anything better at the time + Specified { + must_use_tls: bool, + identity: IdentityKey, + }, + + // TODO: this doesn't really fit in here..., but where else to put it? + /// This client has handled the selection by itself + Custom { + gateway_identity: String, + additional_data: T, + }, +} + +impl Default for GatewaySelectionSpecification { + fn default() -> Self { + GatewaySelectionSpecification::UniformRemote { + must_use_tls: false, + } + } +} + +impl GatewaySelectionSpecification { + pub fn new( + gateway_identity: Option, + latency_based_selection: Option, + must_use_tls: bool, + ) -> Self { + if let Some(identity) = gateway_identity { + GatewaySelectionSpecification::Specified { + identity, + must_use_tls, + } + } else if let Some(true) = latency_based_selection { + GatewaySelectionSpecification::RemoteByLatency { must_use_tls } + } else { + GatewaySelectionSpecification::UniformRemote { must_use_tls } + } + } +} + +pub enum GatewaySetup { + /// The gateway specification (details + keys) MUST BE loaded from the underlying storage. + MustLoad, + + /// Specifies usage of a new gateway + New { + specification: GatewaySelectionSpecification, + + // TODO: seems to be a bit inefficient to pass them by value + available_gateways: Vec, + + /// Specifies whether old data should be overwritten whilst setting up new gateway client. + overwrite_data: bool, + }, + + ReuseConnection { + /// The authenticated ephemeral client that was created during `init` + authenticated_ephemeral_client: InitGatewayClient, + + // Details of this pre-initialised client (i.e. gateway and keys) + gateway_details: GatewayDetails, + + managed_keys: ManagedKeys, + }, +} + +impl GatewaySetup { + pub fn try_reuse_connection( + init_res: InitialisationResult, + ) -> Result { + if let Some(authenticated_ephemeral_client) = init_res.authenticated_ephemeral_client { + Ok(GatewaySetup::ReuseConnection { + authenticated_ephemeral_client, + gateway_details: init_res.gateway_details, + managed_keys: init_res.managed_keys, + }) + } else { + Err(ClientCoreError::NoInitClientPresent) + } + } + + pub async fn try_setup( + self, + key_store: &K, + details_store: &D, + ) -> Result, ClientCoreError> + where + K: KeyStore, + D: GatewayDetailsStore, + K::StorageError: Send + Sync + 'static, + D::StorageError: Send + Sync + 'static, + T: DeserializeOwned + Serialize + Send + Sync, + { + setup_gateway(self, key_store, details_store).await + } + + pub fn is_must_load(&self) -> bool { + matches!(self, GatewaySetup::MustLoad) + } + + pub fn has_full_details(&self) -> bool { + self.is_must_load() + } +} + +/// Struct describing the results of the client initialization procedure. +#[derive(Debug, Serialize)] +pub struct InitResults { + version: String, + id: String, + identity_key: String, + encryption_key: String, + gateway_id: String, + gateway_listener: String, +} + +impl InitResults { + pub fn new(config: &Config, address: &Recipient, gateway: &GatewayEndpointConfig) -> Self { + Self { + version: config.client.version.clone(), + id: config.client.id.clone(), + identity_key: address.identity().to_base58_string(), + encryption_key: address.encryption_key().to_base58_string(), + gateway_id: gateway.gateway_id.clone(), + gateway_listener: gateway.gateway_listener.clone(), + } + } +} + +impl Display for InitResults { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "Version: {}", self.version)?; + writeln!(f, "ID: {}", self.id)?; + writeln!(f, "Identity key: {}", self.identity_key)?; + writeln!(f, "Encryption: {}", self.encryption_key)?; + writeln!(f, "Gateway ID: {}", self.gateway_id)?; + write!(f, "Gateway: {}", self.gateway_listener) + } +} diff --git a/common/client-core/src/lib.rs b/common/client-core/src/lib.rs index 04e215daec..386e498e53 100644 --- a/common/client-core/src/lib.rs +++ b/common/client-core/src/lib.rs @@ -5,6 +5,11 @@ pub mod config; pub mod error; pub mod init; +pub use nym_topology::{ + HardcodedTopologyProvider, NymTopology, NymTopologyError, SerializableNymTopology, + SerializableTopologyError, TopologyProvider, +}; + #[cfg(target_arch = "wasm32")] pub(crate) fn spawn_future(future: F) where diff --git a/common/client-libs/gateway-client/src/client.rs b/common/client-libs/gateway-client/src/client.rs index 3cd75b1b5f..a95fee0bf7 100644 --- a/common/client-libs/gateway-client/src/client.rs +++ b/common/client-libs/gateway-client/src/client.rs @@ -7,6 +7,7 @@ pub use crate::packet_router::{ AcknowledgementReceiver, AcknowledgementSender, MixnetMessageReceiver, MixnetMessageSender, }; use crate::socket_state::{PartiallyDelegated, SocketState}; +use crate::traits::GatewayPacketRouter; use crate::{cleanup_socket_message, try_decrypt_binary_message}; use futures::{SinkExt, StreamExt}; use log::*; @@ -39,9 +40,23 @@ use wasm_utils::websocket::JSWebsocket; #[cfg(target_arch = "wasm32")] use wasmtimer::tokio::sleep; +// Set this to a high value for now, so that we don't risk sporadic timeouts that might cause +// bought bandwidth tokens to not have time to be spent; Once we remove the gateway from the +// bandwidth bridging protocol, we can come back to a smaller timeout value +const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_secs(5 * 60); const DEFAULT_RECONNECTION_ATTEMPTS: usize = 10; const DEFAULT_RECONNECTION_BACKOFF: Duration = Duration::from_secs(5); +pub struct GatewayConfig { + pub gateway_identity: identity::PublicKey, + + // currently a dead field + pub gateway_owner: Option, + + pub gateway_listener: String, +} + +// TODO: this should be refactored into a state machine that keeps track of its authentication state pub struct GatewayClient { authenticated: bool, disabled_credentials_mode: bool, @@ -69,17 +84,12 @@ pub struct GatewayClient { } impl GatewayClient { - // TODO: put it all in a Config struct - #[allow(clippy::too_many_arguments)] pub fn new( - gateway_address: String, + config: GatewayConfig, local_identity: Arc, - gateway_identity: identity::PublicKey, // TODO: make it mandatory. if you don't want to pass it, use `new_init` shared_key: Option>, - mixnet_message_sender: MixnetMessageSender, - ack_sender: AcknowledgementSender, - response_timeout_duration: Duration, + packet_router: PacketRouter, bandwidth_controller: Option>, shutdown: TaskClient, ) -> Self { @@ -87,13 +97,13 @@ impl GatewayClient { authenticated: false, disabled_credentials_mode: true, bandwidth_remaining: 0, - gateway_address, - gateway_identity, + gateway_address: config.gateway_listener, + gateway_identity: config.gateway_identity, local_identity, shared_key, connection: SocketState::NotConnected, - packet_router: PacketRouter::new(ack_sender, mixnet_message_sender, shutdown.clone()), - response_timeout_duration, + packet_router, + response_timeout_duration: DEFAULT_GATEWAY_RESPONSE_TIMEOUT, bandwidth_controller, should_reconnect_on_failure: true, reconnection_attempts: DEFAULT_RECONNECTION_ATTEMPTS, @@ -102,21 +112,34 @@ impl GatewayClient { } } - pub fn set_disabled_credentials_mode(&mut self, disabled_credentials_mode: bool) { + #[must_use] + pub fn with_disabled_credentials_mode(mut self, disabled_credentials_mode: bool) -> Self { self.disabled_credentials_mode = disabled_credentials_mode; + self } - // TODO: later convert into proper builder methods - pub fn with_reconnection_on_failure(&mut self, should_reconnect_on_failure: bool) { - self.should_reconnect_on_failure = should_reconnect_on_failure + #[must_use] + pub fn with_reconnection_on_failure(mut self, should_reconnect_on_failure: bool) -> Self { + self.should_reconnect_on_failure = should_reconnect_on_failure; + self } - pub fn with_reconnection_attempts(&mut self, reconnection_attempts: usize) { - self.reconnection_attempts = reconnection_attempts + #[must_use] + pub fn with_response_timeout(mut self, response_timeout_duration: Duration) -> Self { + self.response_timeout_duration = response_timeout_duration; + self } - pub fn with_reconnection_backoff(&mut self, backoff: Duration) { - self.reconnection_backoff = backoff + #[must_use] + pub fn with_reconnection_attempts(mut self, reconnection_attempts: usize) -> Self { + self.reconnection_attempts = reconnection_attempts; + self + } + + #[must_use] + pub fn with_reconnection_backoff(mut self, backoff: Duration) -> Self { + self.reconnection_backoff = backoff; + self } pub fn gateway_identity(&self) -> identity::PublicKey { @@ -761,16 +784,14 @@ impl GatewayClient { } } +// type alias for an ease of use +pub type InitGatewayClient = GatewayClient; + pub struct InitOnly; impl GatewayClient { // for initialisation we do not need credential storage. Though it's still a bit weird we have to set the generic... - pub fn new_init( - gateway_address: String, - gateway_identity: identity::PublicKey, - local_identity: Arc, - response_timeout_duration: Duration, - ) -> Self { + pub fn new_init(config: GatewayConfig, local_identity: Arc) -> Self { use futures::channel::mpsc; // note: this packet_router is completely invalid in normal circumstances, but "works" @@ -784,13 +805,13 @@ impl GatewayClient { authenticated: false, disabled_credentials_mode: true, bandwidth_remaining: 0, - gateway_address, - gateway_identity, + gateway_address: config.gateway_listener, + gateway_identity: config.gateway_identity, local_identity, shared_key: None, connection: SocketState::NotConnected, packet_router, - response_timeout_duration, + response_timeout_duration: DEFAULT_GATEWAY_RESPONSE_TIMEOUT, bandwidth_controller: None, should_reconnect_on_failure: false, reconnection_attempts: DEFAULT_RECONNECTION_ATTEMPTS, @@ -801,9 +822,7 @@ impl GatewayClient { pub fn upgrade( self, - mixnet_message_sender: MixnetMessageSender, - ack_sender: AcknowledgementSender, - response_timeout_duration: Duration, + packet_router: PacketRouter, bandwidth_controller: Option>, shutdown: TaskClient, ) -> GatewayClient { @@ -822,8 +841,8 @@ impl GatewayClient { local_identity: self.local_identity, shared_key: self.shared_key, connection: self.connection, - packet_router: PacketRouter::new(ack_sender, mixnet_message_sender, shutdown.clone()), - response_timeout_duration, + packet_router, + response_timeout_duration: self.response_timeout_duration, bandwidth_controller, should_reconnect_on_failure: self.should_reconnect_on_failure, reconnection_attempts: self.reconnection_attempts, diff --git a/common/client-libs/gateway-client/src/error.rs b/common/client-libs/gateway-client/src/error.rs index 8ac387b43f..081ea3f999 100644 --- a/common/client-libs/gateway-client/src/error.rs +++ b/common/client-libs/gateway-client/src/error.rs @@ -13,17 +13,17 @@ pub enum GatewayClientError { #[error("Connection to the gateway is not established")] ConnectionNotEstablished, - #[error("Gateway returned an error response - {0}")] + #[error("Gateway returned an error response: {0}")] GatewayError(String), - #[error("There was a network error - {0}")] + #[error("There was a network error: {0}")] NetworkError(#[from] WsError), #[cfg(target_arch = "wasm32")] - #[error("There was a network error")] + #[error("There was a network error: {0}")] NetworkErrorWasm(#[from] JsError), - #[error("Invalid URL - {0}")] + #[error("Invalid URL: {0}")] InvalidURL(String), #[error("No shared key was provided or obtained")] @@ -32,7 +32,7 @@ pub enum GatewayClientError { #[error("No bandwidth controller provided")] NoBandwidthControllerAvailable, - #[error("Bandwidth controller error - {0}")] + #[error("Bandwidth controller error: {0}")] BandwidthControllerError(#[from] nym_bandwidth_controller::error::BandwidthControllerError), #[error("Connection was abruptly closed")] @@ -62,7 +62,7 @@ pub enum GatewayClientError { #[error("Connection is in an invalid state - please send a bug report")] ConnectionInInvalidState, - #[error("Failed to finish registration handshake - {0}")] + #[error("Failed to finish registration handshake: {0}")] RegistrationFailure(HandshakeError), #[error("Authentication failure")] @@ -76,6 +76,16 @@ pub enum GatewayClientError { #[error("Attempted to negotiate connection with gateway using incompatible protocol version. Ours is {current} and the gateway reports {gateway:?}")] IncompatibleProtocol { gateway: Option, current: u8 }, + + #[error( + "The packet router hasn't been set - are you sure you started up the client correctly?" + )] + PacketRouterUnavailable, + + #[error( + "this operation couldn't be completed as the program is in the process of shutting down" + )] + ShutdownInProgress, } impl GatewayClientError { diff --git a/common/client-libs/gateway-client/src/lib.rs b/common/client-libs/gateway-client/src/lib.rs index aea81dcda9..bc1b22b887 100644 --- a/common/client-libs/gateway-client/src/lib.rs +++ b/common/client-libs/gateway-client/src/lib.rs @@ -2,20 +2,23 @@ // SPDX-License-Identifier: Apache-2.0 use crate::error::GatewayClientError; -pub use client::GatewayClient; use log::warn; use nym_gateway_requests::BinaryResponse; -pub use packet_router::{ - AcknowledgementReceiver, AcknowledgementSender, MixnetMessageReceiver, MixnetMessageSender, -}; use tungstenite::{protocol::Message, Error as WsError}; +pub use client::{GatewayClient, GatewayConfig}; pub use nym_gateway_requests::registration::handshake::SharedKeys; +pub use packet_router::{ + AcknowledgementReceiver, AcknowledgementSender, MixnetMessageReceiver, MixnetMessageSender, + PacketRouter, +}; +pub use traits::GatewayPacketRouter; pub mod client; pub mod error; pub mod packet_router; pub mod socket_state; +pub mod traits; /// Helper method for reading from websocket stream. Helps to flatten the structure. pub(crate) fn cleanup_socket_message( diff --git a/common/client-libs/gateway-client/src/packet_router.rs b/common/client-libs/gateway-client/src/packet_router.rs index 385d8bf333..bf73ecb8ca 100644 --- a/common/client-libs/gateway-client/src/packet_router.rs +++ b/common/client-libs/gateway-client/src/packet_router.rs @@ -5,10 +5,8 @@ // I will gladly take any suggestions on how to rename this. use crate::error::GatewayClientError; +use crate::GatewayPacketRouter; use futures::channel::mpsc; -use log::*; -use nym_sphinx::addressing::nodes::MAX_NODE_ADDRESS_UNPADDED_LEN; -use nym_sphinx::params::packet_sizes::PacketSize; use nym_task::TaskClient; pub type MixnetMessageSender = mpsc::UnboundedSender>>; @@ -37,77 +35,52 @@ impl PacketRouter { } } - pub fn route_received( - &mut self, - unwrapped_packets: Vec>, + pub fn route_mixnet_messages( + &self, + received_messages: Vec>, ) -> Result<(), GatewayClientError> { - let mut received_messages = Vec::new(); - let mut received_acks = Vec::new(); - - // remember: gateway removes final layer of sphinx encryption and from the unwrapped - // data he takes the SURB-ACK and first hop address. - // currently SURB-ACKs are attached in EVERY packet, even cover, so this is always true - let ack_overhead = PacketSize::AckPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN; - let outfox_ack_overhead = - PacketSize::OutfoxAckPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN; - - for received_packet in unwrapped_packets { - if received_packet.len() == PacketSize::AckPacket.plaintext_size() - // we don't know the real size of the payload, it could be anything <= 48 bytes - || received_packet.len() <= PacketSize::OutfoxAckPacket.plaintext_size() - { - received_acks.push(received_packet); - } else if received_packet.len() - == PacketSize::RegularPacket.plaintext_size() - ack_overhead - || received_packet.len() - == PacketSize::OutfoxRegularPacket.plaintext_size() - outfox_ack_overhead - || received_packet.len() - == PacketSize::OutfoxRegularPacket.size() - outfox_ack_overhead - { - trace!("routing regular packet"); - received_messages.push(received_packet); - } else if received_packet.len() - == PacketSize::ExtendedPacket8.plaintext_size() - ack_overhead - { - trace!("routing extended8 packet"); - received_messages.push(received_packet); - } else if received_packet.len() - == PacketSize::ExtendedPacket16.plaintext_size() - ack_overhead - { - trace!("routing extended16 packet"); - received_messages.push(received_packet); - } else if received_packet.len() - == PacketSize::ExtendedPacket32.plaintext_size() - ack_overhead - { - trace!("routing extended32 packet"); - received_messages.push(received_packet); - } else { - // this can happen if other clients are not padding their messages - warn!("Received message of unexpected size. Probably from an outdated client... len: {}", received_packet.len()); - received_messages.push(received_packet); + if let Err(err) = self.mixnet_message_sender.unbounded_send(received_messages) { + // check if the failure is due to the shutdown being in progress and thus the receiver channel + // having already been dropped + if self.shutdown.is_shutdown_poll() || self.shutdown.is_dummy() { + // This should ideally not happen, but it's ok + log::warn!("Failed to send mixnet messages due to receiver task shutdown"); + return Err(GatewayClientError::ShutdownInProgress); } + // This should never happen during ordinary operation the way it's currently used. + // Abort to be on the safe side + panic!("Failed to send mixnet message: {err}"); } + Ok(()) + } - if !received_messages.is_empty() { - trace!("routing 'real'"); - if let Err(err) = self.mixnet_message_sender.unbounded_send(received_messages) { - if self.shutdown.is_shutdown_poll() || self.shutdown.is_dummy() { - // This should ideally not happen, but it's ok - log::warn!("Failed to send mixnet message due to receiver task shutdown"); - return Err(GatewayClientError::MixnetMsgSenderFailedToSend); - } - // This should never happen during ordinary operation the way it's currently used. - // Abort to be on the safe side - panic!("Failed to send mixnet message: {err}"); + pub fn route_acks(&self, received_acks: Vec>) -> Result<(), GatewayClientError> { + if let Err(err) = self.ack_sender.unbounded_send(received_acks) { + // check if the failure is due to the shutdown being in progress and thus the receiver channel + // having already been dropped + if self.shutdown.is_shutdown_poll() || self.shutdown.is_dummy() { + // This should ideally not happen, but it's ok + log::warn!("Failed to send acks due to receiver task shutdown"); + return Err(GatewayClientError::ShutdownInProgress); } - } - - if !received_acks.is_empty() { - trace!("routing acks"); - if let Err(err) = self.ack_sender.unbounded_send(received_acks) { - error!("failed to send ack: {err}"); - }; + // This should never happen during ordinary operation the way it's currently used. + // Abort to be on the safe side + panic!("Failed to send acks: {err}"); } Ok(()) } } + +impl GatewayPacketRouter for PacketRouter { + type Error = GatewayClientError; + + // note: this trait tries to decide whether a given message is an ack or a data message + + fn route_mixnet_messages(&self, received_messages: Vec>) -> Result<(), Self::Error> { + self.route_mixnet_messages(received_messages) + } + + fn route_acks(&self, received_acks: Vec>) -> Result<(), Self::Error> { + self.route_acks(received_acks) + } +} diff --git a/common/client-libs/gateway-client/src/socket_state.rs b/common/client-libs/gateway-client/src/socket_state.rs index 0ffbcea034..6f82ef4939 100644 --- a/common/client-libs/gateway-client/src/socket_state.rs +++ b/common/client-libs/gateway-client/src/socket_state.rs @@ -3,6 +3,7 @@ use crate::error::GatewayClientError; use crate::packet_router::PacketRouter; +use crate::traits::GatewayPacketRouter; use crate::{cleanup_socket_messages, try_decrypt_binary_message}; use futures::channel::oneshot; use futures::stream::{SplitSink, SplitStream}; diff --git a/common/client-libs/gateway-client/src/traits.rs b/common/client-libs/gateway-client/src/traits.rs new file mode 100644 index 0000000000..54b53ffc81 --- /dev/null +++ b/common/client-libs/gateway-client/src/traits.rs @@ -0,0 +1,96 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use log::{error, trace, warn}; +use nym_sphinx::addressing::nodes::MAX_NODE_ADDRESS_UNPADDED_LEN; +use nym_sphinx::params::PacketSize; + +pub trait GatewayPacketRouter { + type Error: std::error::Error; + + fn route_received(&self, unwrapped_packets: Vec>) -> Result<(), Self::Error> { + let mut received_messages = Vec::new(); + let mut received_acks = Vec::new(); + + // remember: gateway removes final layer of sphinx encryption and from the unwrapped + // data he takes the SURB-ACK and first hop address. + // currently SURB-ACKs are attached in EVERY packet, even cover, so this is always true + let sphinx_ack_overhead = PacketSize::AckPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN; + let outfox_ack_overhead = + PacketSize::OutfoxAckPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN; + + for received_packet in unwrapped_packets { + // note: if we ever fail to route regular outfox, it might be because I've removed a match on + // `size == PacketSize::OutfoxRegularPacket.size() - outfox_ack_overhead` since it seemed + // redundant given we have `size == PacketSize::OutfoxRegularPacket.plaintext_size() - outfox_ack_overhead` + // and all the headers should have already be stripped at this point + match received_packet.len() { + n if n == PacketSize::AckPacket.plaintext_size() => { + trace!("received sphinx ack"); + received_acks.push(received_packet); + } + + n if n <= PacketSize::OutfoxAckPacket.plaintext_size() => { + // we don't know the real size of the payload, it could be anything <= 48 bytes + trace!("received outfox ack"); + received_acks.push(received_packet); + } + + n if n == PacketSize::RegularPacket.plaintext_size() - sphinx_ack_overhead => { + trace!("received regular sphinx packet"); + received_messages.push(received_packet); + } + + n if n + == PacketSize::OutfoxRegularPacket.plaintext_size() - outfox_ack_overhead => + { + trace!("received regular outfox packet"); + received_messages.push(received_packet); + } + + n if n == PacketSize::ExtendedPacket8.plaintext_size() - sphinx_ack_overhead => { + trace!("received extended8 packet"); + received_messages.push(received_packet); + } + + n if n == PacketSize::ExtendedPacket16.plaintext_size() - sphinx_ack_overhead => { + trace!("received extended16 packet"); + received_messages.push(received_packet); + } + + n if n == PacketSize::ExtendedPacket32.plaintext_size() - sphinx_ack_overhead => { + trace!("received extended32 packet"); + received_messages.push(received_packet); + } + + n => { + // this can happen if other clients are not padding their messages + warn!("Received message of unexpected size. Probably from an outdated client... len: {n}"); + received_messages.push(received_packet); + } + } + } + + if !received_messages.is_empty() { + trace!("routing {} received packets", received_messages.len()); + if let Err(err) = self.route_mixnet_messages(received_messages) { + error!("failed to route received messages: {err}"); + return Err(err); + } + } + + if !received_acks.is_empty() { + trace!("routing {} received acks", received_acks.len()); + if let Err(err) = self.route_acks(received_acks) { + error!("failed to route received acks: {err}"); + return Err(err); + } + } + + Ok(()) + } + + fn route_mixnet_messages(&self, received_messages: Vec>) -> Result<(), Self::Error>; + + fn route_acks(&self, received_acks: Vec>) -> Result<(), Self::Error>; +} diff --git a/common/client-libs/mixnet-client/src/forwarder.rs b/common/client-libs/mixnet-client/src/forwarder.rs index 8bbf5a47f6..630cc95663 100644 --- a/common/client-libs/mixnet-client/src/forwarder.rs +++ b/common/client-libs/mixnet-client/src/forwarder.rs @@ -56,7 +56,7 @@ impl PacketForwarder { log::trace!("PacketForwarder: Received shutdown"); } Some(mix_packet) = self.packet_receiver.next() => { - trace!("Going to forward packet to {:?}", mix_packet.next_hop()); + trace!("Going to forward packet to {}", mix_packet.next_hop()); let next_hop = mix_packet.next_hop(); let packet_type = mix_packet.packet_type(); diff --git a/common/config/src/lib.rs b/common/config/src/lib.rs index a751ba2414..d3e4dbf6b5 100644 --- a/common/config/src/lib.rs +++ b/common/config/src/lib.rs @@ -33,18 +33,17 @@ pub fn may_get_home() -> Option { } pub trait NymConfigTemplate: Serialize { - fn template() -> &'static str; + fn template(&self) -> &'static str; fn format_to_string(&self) -> String { // it is responsibility of whoever is implementing the trait to ensure the template is valid Handlebars::new() - .render_template(Self::template(), &self) + .render_template(self.template(), &self) .unwrap() } fn format_to_writer(&self, writer: W) -> io::Result<()> { - if let Err(err) = - Handlebars::new().render_template_to_write(Self::template(), &self, writer) + if let Err(err) = Handlebars::new().render_template_to_write(self.template(), &self, writer) { match err { TemplateRenderError::IOError(err, _) => return Err(err), @@ -64,7 +63,7 @@ where C: NymConfigTemplate, P: AsRef, { - log::trace!("trying to save config file to {}", path.as_ref().display()); + log::debug!("trying to save config file to {}", path.as_ref().display()); let file = File::create(path.as_ref())?; // TODO: check for whether any of our configs stores anything sensitive @@ -108,7 +107,7 @@ where // // // pub trait NymConfig: Default + Serialize + DeserializeOwned { -// fn template() -> &'static str; +// fn template(&self) -> &'static str; // // fn config_file_name() -> String { // "config.toml".to_string() diff --git a/common/credential-utils/src/utils.rs b/common/credential-utils/src/utils.rs index 2f92b53c90..b58211eba0 100644 --- a/common/credential-utils/src/utils.rs +++ b/common/credential-utils/src/utils.rs @@ -71,7 +71,7 @@ pub async fn setup_recovery_storage(recovery_dir: PathBuf) -> RecoveryStorage { pub async fn setup_persistent_storage(client_home_directory: PathBuf) -> PersistentStorage { let data_dir = client_home_directory.join(DEFAULT_DATA_DIR); - let paths = CommonClientPaths::new_default(data_dir); + let paths = CommonClientPaths::new_base(data_dir); let db_path = paths.credentials_database; nym_credential_storage::initialise_persistent_storage(db_path).await diff --git a/common/crypto/src/asymmetric/identity/mod.rs b/common/crypto/src/asymmetric/identity/mod.rs index efe11acf4f..ae001c2df6 100644 --- a/common/crypto/src/asymmetric/identity/mod.rs +++ b/common/crypto/src/asymmetric/identity/mod.rs @@ -150,6 +150,13 @@ impl PublicKey { } } +#[cfg(feature = "sphinx")] +impl From for DestinationAddressBytes { + fn from(value: PublicKey) -> Self { + value.derive_destination_address() + } +} + impl FromStr for PublicKey { type Err = Ed25519RecoveryError; @@ -242,8 +249,7 @@ impl PrivateKey { /// Signs text with the provided Ed25519 private key, returning a base58 signature pub fn sign_text(&self, text: &str) -> String { let signature_bytes = self.sign(text.as_ref()).to_bytes(); - let signature = bs58::encode(signature_bytes).into_string(); - signature + bs58::encode(signature_bytes).into_string() } } diff --git a/common/network-defaults/src/mainnet.rs b/common/network-defaults/src/mainnet.rs index bfb3f42531..fd002d4db7 100644 --- a/common/network-defaults/src/mainnet.rs +++ b/common/network-defaults/src/mainnet.rs @@ -4,9 +4,9 @@ use crate::var_names; use crate::{DenomDetails, ValidatorDetails}; -pub(crate) const NETWORK_NAME: &str = "mainnet"; +pub const NETWORK_NAME: &str = "mainnet"; -pub(crate) const BECH32_PREFIX: &str = "n"; +pub const BECH32_PREFIX: &str = "n"; pub const MIX_DENOM: DenomDetails = DenomDetails::new("unym", "nym", 6); pub const STAKE_DENOM: DenomDetails = DenomDetails::new("unyx", "nyx", 6); @@ -15,13 +15,12 @@ pub const MIXNET_CONTRACT_ADDRESS: &str = "n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr"; pub const VESTING_CONTRACT_ADDRESS: &str = "n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw"; -pub(crate) const COCONUT_BANDWIDTH_CONTRACT_ADDRESS: &str = - "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0"; -pub(crate) const GROUP_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0"; -pub(crate) const MULTISIG_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0"; -pub(crate) const COCONUT_DKG_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0"; -pub(crate) const EPHEMERA_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0"; -pub(crate) const REWARDING_VALIDATOR_ADDRESS: &str = "n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy"; +pub const COCONUT_BANDWIDTH_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0"; +pub const GROUP_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0"; +pub const MULTISIG_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0"; +pub const COCONUT_DKG_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0"; +pub const EPHEMERA_CONTRACT_ADDRESS: &str = "n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0"; +pub const REWARDING_VALIDATOR_ADDRESS: &str = "n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy"; pub const STATISTICS_SERVICE_DOMAIN_ADDRESS: &str = "https://mainnet-stats.nymte.ch:8090/"; pub const NYXD_URL: &str = "https://rpc.nymtech.net"; diff --git a/common/socks5-client-core/Cargo.toml b/common/socks5-client-core/Cargo.toml index 6a5221bba0..ca4c53023d 100644 --- a/common/socks5-client-core/Cargo.toml +++ b/common/socks5-client-core/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +anyhow = { workspace = true } dirs = "4.0" futures = { workspace = true } log = { workspace = true } diff --git a/common/socks5-client-core/src/config/old_config_v1_1_13.rs b/common/socks5-client-core/src/config/old_config_v1_1_13.rs index 095b4b21d0..dc51308120 100644 --- a/common/socks5-client-core/src/config/old_config_v1_1_13.rs +++ b/common/socks5-client-core/src/config/old_config_v1_1_13.rs @@ -17,7 +17,7 @@ use std::path::PathBuf; // // // // // impl NymConfig for OldConfigV1_1_13 { -// // fn template() -> &'static str { +// // fn template(&self) -> &'static str { // // // not intended to be used // // unimplemented!() // // } diff --git a/common/socks5-client-core/src/lib.rs b/common/socks5-client-core/src/lib.rs index 74d27b69ed..bbf9b7ed72 100644 --- a/common/socks5-client-core/src/lib.rs +++ b/common/socks5-client-core/src/lib.rs @@ -19,13 +19,15 @@ use nym_client_core::client::base_client::{ use nym_client_core::client::key_manager::persistence::KeyStore; use nym_client_core::client::replies::reply_storage::ReplyStorageBackend; use nym_client_core::config::DebugConfig; -use nym_client_core::init::GatewaySetup; +use nym_client_core::init::types::GatewaySetup; use nym_credential_storage::storage::Storage as CredentialStorage; use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::params::PacketType; -use nym_task::{TaskClient, TaskManager}; +use nym_task::{TaskClient, TaskHandle}; +use anyhow::anyhow; use std::error::Error; +use std::path::PathBuf; pub mod config; pub mod error; @@ -43,7 +45,7 @@ pub enum Socks5ControlMessage { pub struct StartedSocks5Client { /// Handle for managing graceful shutdown of this client. If dropped, the client will be stopped. - pub shutdown_handle: TaskManager, + pub shutdown_handle: TaskHandle, /// Address of the started client pub address: Recipient, @@ -57,6 +59,9 @@ pub struct NymClient { storage: S, setup_method: GatewaySetup, + + /// Optional path to a .json file containing standalone network details. + custom_mixnet: Option, } impl NymClient @@ -68,11 +73,12 @@ where ::StorageError: Sync + Send, ::StorageError: Send + Sync, { - pub fn new(config: Config, storage: S) -> Self { + pub fn new(config: Config, storage: S, custom_mixnet: Option) -> Self { NymClient { config, storage, setup_method: GatewaySetup::MustLoad, + custom_mixnet, } } @@ -150,7 +156,7 @@ where pub async fn run_forever(self) -> Result<(), Box> { let started = self.start().await?; - let res = started.shutdown_handle.catch_interrupt().await; + let res = started.shutdown_handle.wait_for_shutdown().await; log::info!("Stopping nym-socks5-client"); res } @@ -163,7 +169,12 @@ where ) -> Result<(), Box> { // Start the main task let started = self.start().await?; - let mut shutdown = started.shutdown_handle; + let mut shutdown = started + .shutdown_handle + .try_into_task_manager() + .ok_or(anyhow!( + "attempted to use `run_and_listen` without owning shutdown handle" + ))?; // Listen to status messages from task, that we forward back to the caller shutdown.start_status_listener(sender).await; @@ -210,10 +221,14 @@ where Some(default_query_dkg_client_from_config(&self.config.base)) }; - let base_builder = + let mut base_builder = BaseClientBuilder::new(&self.config.base, self.storage, dkg_query_client) .with_gateway_setup(self.setup_method); + if let Some(custom_mixnet) = &self.custom_mixnet { + base_builder = base_builder.with_stored_topology(custom_mixnet)?; + } + let packet_type = self.config.base.debug.traffic.packet_type; let mut started_client = base_builder.start_base().await?; let self_address = started_client.address; @@ -230,7 +245,7 @@ where client_output, client_state, self_address, - started_client.task_manager.subscribe(), + started_client.task_handle.get_handle(), packet_type, ); @@ -238,7 +253,7 @@ where info!("The address of this client is: {self_address}"); Ok(StartedSocks5Client { - shutdown_handle: started_client.task_manager, + shutdown_handle: started_client.task_handle, address: self_address, }) } diff --git a/common/socks5-client-core/src/socks/client.rs b/common/socks5-client-core/src/socks/client.rs index a1ef3f72ef..eb1e2db2f6 100644 --- a/common/socks5-client-core/src/socks/client.rs +++ b/common/socks5-client-core/src/socks/client.rs @@ -507,8 +507,8 @@ impl SocksClient { ); } - SocksCommand::Bind => unimplemented!(), // not handled - SocksCommand::UdpAssociate => unimplemented!(), // not handled + SocksCommand::Bind => return Err(SocksProxyError::BindNotSupported), // not handled + SocksCommand::UdpAssociate => return Err(SocksProxyError::UdpNotSupported), }; Ok(()) diff --git a/common/socks5-client-core/src/socks/types.rs b/common/socks5-client-core/src/socks/types.rs index 964377bdc6..86ea1bbe56 100644 --- a/common/socks5-client-core/src/socks/types.rs +++ b/common/socks5-client-core/src/socks/types.rs @@ -83,6 +83,12 @@ pub enum SocksProxyError { #[from] source: Socks5RequestError, }, + + #[error("SOCKS5 UDP not (yet) supported")] + UdpNotSupported, + + #[error("SOCKS5 BIND not (yet) supported")] + BindNotSupported, } /// DST.addr variant types diff --git a/common/socks5/proxy-helpers/src/connection_controller.rs b/common/socks5/proxy-helpers/src/connection_controller.rs index 416b88770f..71ee35dafd 100644 --- a/common/socks5/proxy-helpers/src/connection_controller.rs +++ b/common/socks5/proxy-helpers/src/connection_controller.rs @@ -132,7 +132,7 @@ impl Controller { } else { // check if there were any pending messages if let Some(pending) = self.pending_messages.remove(&conn_id) { - debug!("There were some pending messages for {}", conn_id); + debug!("There were some pending messages for {conn_id}"); for data in pending { self.send_to_connection(data) } @@ -141,12 +141,9 @@ impl Controller { } fn remove_connection(&mut self, conn_id: ConnectionId) { - debug!("Removing {} from controller", conn_id); + debug!("Removing {conn_id} from controller"); if self.active_connections.remove(&conn_id).is_none() { - error!( - "tried to remove non-existing connection with id: {:?}", - conn_id - ) + error!("tried to remove non-existing connection with id: {conn_id}",) } self.recently_closed.insert(conn_id); diff --git a/common/task/Cargo.toml b/common/task/Cargo.toml index 500cdb2a53..6f0f6b7579 100644 --- a/common/task/Cargo.toml +++ b/common/task/Cargo.toml @@ -14,14 +14,18 @@ thiserror = { workspace = true } tokio = { workspace = true, features = ["macros", "sync"] } [target."cfg(not(target_arch = \"wasm32\"))".dependencies.tokio] -version = "1.24.1" +workspace = true features = ["signal", "time", "rt"] [target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen-futures] -version = "0.4" +workspace = true [target."cfg(target_arch = \"wasm32\")".dependencies.wasm-bindgen] -version = "0.2.83" +workspace = true + +[target."cfg(target_arch = \"wasm32\")".dependencies.wasmtimer] +workspace = true +features = ["tokio"] [dev-dependencies] -tokio = { version = "1.24.1", features = ["rt-multi-thread", "net", "signal", "test-util", "macros"] } +tokio = { workspace = true, features = ["rt-multi-thread", "net", "signal", "test-util", "macros"] } diff --git a/common/task/src/lib.rs b/common/task/src/lib.rs index 00bcb8b0bd..6615bc86e0 100644 --- a/common/task/src/lib.rs +++ b/common/task/src/lib.rs @@ -7,7 +7,7 @@ pub mod manager; pub mod signal; pub mod spawn; -pub use manager::{StatusReceiver, StatusSender, TaskClient, TaskManager}; +pub use manager::{StatusReceiver, StatusSender, TaskClient, TaskHandle, TaskManager}; #[cfg(not(target_arch = "wasm32"))] pub use signal::wait_for_signal_and_error; diff --git a/common/task/src/manager.rs b/common/task/src/manager.rs index e9147776b7..a59ae545d9 100644 --- a/common/task/src/manager.rs +++ b/common/task/src/manager.rs @@ -1,19 +1,22 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use std::future::Future; -use std::{error::Error, time::Duration}; - use futures::{future::pending, FutureExt, SinkExt, StreamExt}; use log::{log, Level}; -use tokio::{ - sync::{ - mpsc, - watch::{self, error::SendError}, - }, - time::sleep, +use std::future::Future; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::{error::Error, time::Duration}; +use tokio::sync::{ + mpsc, + watch::{self, error::SendError}, }; +#[cfg(not(target_arch = "wasm32"))] +use tokio::time::{sleep, timeout}; + +#[cfg(target_arch = "wasm32")] +use wasmtimer::tokio::{sleep, timeout}; + const DEFAULT_SHUTDOWN_TIMER_SECS: u64 = 5; pub(crate) type SentError = Box; @@ -143,6 +146,17 @@ impl TaskManager { } } + pub fn subscribe_named>(&self, suffix: S) -> TaskClient { + let task_client = self.subscribe(); + let suffix = suffix.into(); + let child_name = if let Some(base) = &self.name { + format!("{base}-{suffix}") + } else { + format!("unknown-{suffix}") + }; + task_client.named(child_name) + } + pub fn signal_shutdown(&self) -> Result<(), SendError<()>> { self.notify_tx.send(()) } @@ -159,9 +173,9 @@ impl TaskManager { crate::spawn::spawn(async move { loop { if let Some(msg) = task_status_rx.next().await { - log::trace!("Got msg: {}", msg); + log::trace!("Got msg: {msg}"); if let Err(msg) = sender.send(msg).await { - log::error!("Error sending status message: {}", msg); + log::error!("Error sending status message: {msg}"); } } else { log::trace!("Stopping since channel closed"); @@ -205,16 +219,10 @@ impl TaskManager { #[cfg(not(target_arch = "wasm32"))] let interrupt_future = tokio::signal::ctrl_c(); - // in wasm we'll never get our shutdown anyway... #[cfg(target_arch = "wasm32")] let interrupt_future = futures::future::pending::<()>(); - #[cfg(not(target_arch = "wasm32"))] - let wait_future = tokio::time::sleep(Duration::from_secs(self.shutdown_timer_secs)); - - // TODO: we should be using a `Delay` here for wasm - #[cfg(target_arch = "wasm32")] - let wait_future = futures::future::pending::<()>(); + let wait_future = sleep(Duration::from_secs(self.shutdown_timer_secs)); tokio::select! { _ = self.notify_tx.closed() => { @@ -238,7 +246,10 @@ pub struct TaskClient { name: Option, // If a shutdown notification has been registered - shutdown: bool, + // the reason for having an atomic here is to be able to cheat and modify that value whilst + // holding an immutable reference to the `TaskClient`. + // note: using `Relaxed` ordering everywhere is fine since it's not shared between threads + shutdown: AtomicBool, // Listen for shutdown notifications, as well as a mechanism to report back that we have // finished (the receiver is closed). @@ -272,7 +283,7 @@ impl Clone for TaskClient { TaskClient { name, - shutdown: self.shutdown, + shutdown: AtomicBool::new(self.shutdown.load(Ordering::Relaxed)), notify: self.notify.clone(), return_error: self.return_error.clone(), drop_error: self.drop_error.clone(), @@ -286,7 +297,6 @@ impl TaskClient { const MAX_NAME_LENGTH: usize = 128; const OVERFLOW_NAME: &'static str = "reached maximum TaskClient children name depth"; - #[cfg(not(target_arch = "wasm32"))] const SHUTDOWN_TIMEOUT_WAITING_FOR_SIGNAL_ON_EXIT: Duration = Duration::from_secs(5); fn new( @@ -297,7 +307,7 @@ impl TaskClient { ) -> TaskClient { TaskClient { name: None, - shutdown: false, + shutdown: AtomicBool::new(false), notify, return_error, drop_error, @@ -341,6 +351,17 @@ impl TaskClient { self } + #[must_use] + pub fn with_suffix>(self, suffix: S) -> Self { + let suffix = suffix.into(); + let name = if let Some(base) = &self.name { + format!("{base}-{suffix}") + } else { + format!("unknown-{suffix}") + }; + self.named(name) + } + pub async fn run_future(&mut self, fut: Fut) -> Option where Fut: Future, @@ -360,7 +381,7 @@ impl TaskClient { let (task_status_tx, _task_status_rx) = futures::channel::mpsc::channel(128); TaskClient { name: None, - shutdown: false, + shutdown: AtomicBool::new(false), notify: notify_rx, return_error: task_halt_tx, drop_error: task_drop_tx, @@ -377,7 +398,7 @@ impl TaskClient { if self.mode.is_dummy() { false } else { - self.shutdown + self.shutdown.load(Ordering::Relaxed) } } @@ -385,11 +406,11 @@ impl TaskClient { if self.mode.is_dummy() { return pending().await; } - if self.shutdown { + if self.shutdown.load(Ordering::Relaxed) { return; } let _ = self.notify.changed().await; - self.shutdown = true; + self.shutdown.store(true, Ordering::Relaxed); } pub async fn recv_with_delay(&mut self) { @@ -403,29 +424,31 @@ impl TaskClient { pub async fn recv_timeout(&mut self) { if self.mode.is_dummy() { - #[cfg_attr(target_arch = "wasm32", allow(clippy::needless_return))] return pending().await; } - #[cfg(not(target_arch = "wasm32"))] - tokio::time::timeout( + + if let Err(timeout) = timeout( Self::SHUTDOWN_TIMEOUT_WAITING_FOR_SIGNAL_ON_EXIT, self.recv(), ) .await - .expect("Task stopped without shutdown called"); + { + self.log(Level::Error, "Task stopped without shutdown called"); + panic!("{timeout}") + } } - pub fn is_shutdown_poll(&mut self) -> bool { + pub fn is_shutdown_poll(&self) -> bool { if self.mode.is_dummy() { return false; } - if self.shutdown { + if self.shutdown.load(Ordering::Relaxed) { return true; } match self.notify.has_changed() { Ok(has_changed) => { if has_changed { - self.shutdown = true; + self.shutdown.store(true, Ordering::Relaxed); } has_changed } @@ -520,6 +543,95 @@ impl ClientOperatingMode { } } +#[derive(Debug)] +pub enum TaskHandle { + /// Full [`TaskManager`] that was created by the underlying task. + Internal(TaskManager), + + /// `[TaskClient]` that was passed from an external task, that controls the shutdown process. + External(TaskClient), +} + +impl From for TaskHandle { + fn from(value: TaskManager) -> Self { + TaskHandle::Internal(value) + } +} + +impl From for TaskHandle { + fn from(value: TaskClient) -> Self { + TaskHandle::External(value) + } +} + +impl Default for TaskHandle { + fn default() -> Self { + TaskHandle::Internal(TaskManager::default()) + } +} + +impl TaskHandle { + #[must_use] + pub fn name_if_unnamed>(self, name: S) -> Self { + match self { + TaskHandle::Internal(task_manager) => { + if task_manager.name.is_none() { + TaskHandle::Internal(task_manager.named(name)) + } else { + TaskHandle::Internal(task_manager) + } + } + TaskHandle::External(task_client) => { + if task_client.name.is_none() { + TaskHandle::External(task_client.named(name)) + } else { + TaskHandle::External(task_client) + } + } + } + } + + #[must_use] + pub fn named>(self, name: S) -> Self { + match self { + TaskHandle::Internal(task_manager) => TaskHandle::Internal(task_manager.named(name)), + TaskHandle::External(task_client) => TaskHandle::External(task_client.named(name)), + } + } + + pub fn fork>(&self, child_suffix: S) -> TaskClient { + match self { + TaskHandle::External(shutdown) => shutdown.fork(child_suffix), + TaskHandle::Internal(shutdown) => shutdown.subscribe_named(child_suffix), + } + } + + pub fn get_handle(&self) -> TaskClient { + match self { + TaskHandle::External(shutdown) => shutdown.clone(), + TaskHandle::Internal(shutdown) => shutdown.subscribe(), + } + } + + pub fn try_into_task_manager(self) -> Option { + match self { + TaskHandle::External(_) => None, + TaskHandle::Internal(shutdown) => Some(shutdown), + } + } + + #[cfg(not(target_arch = "wasm32"))] + pub async fn wait_for_shutdown(self) -> Result<(), SentError> { + match self { + TaskHandle::Internal(task_manager) => task_manager.catch_interrupt().await, + TaskHandle::External(mut task_client) => { + task_client.recv().await; + Ok(()) + } + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/common/topology/Cargo.toml b/common/topology/Cargo.toml index e6d35a509c..079429cc69 100644 --- a/common/topology/Cargo.toml +++ b/common/topology/Cargo.toml @@ -19,6 +19,14 @@ thiserror = "1.0.37" async-trait = { workspace = true, optional = true } semver = "0.11" +# 'serializable' feature +serde = { workspace = true, features = ["derive"], optional = true } +serde_json = { workspace = true, optional = true } + +# 'wasm-serde-types' feature +tsify = { workspace = true, features = ["js"], optional = true } +wasm-bindgen = { workspace = true, optional = true } + ## internal nym-crypto = { path = "../crypto", features = ["sphinx", "outfox"] } nym-mixnet-contract-common = { path = "../cosmwasm-smart-contracts/mixnet-contract" } @@ -27,6 +35,14 @@ nym-sphinx-types = { path = "../nymsphinx/types", features = ["sphinx", "outfox" nym-sphinx-routing = { path = "../nymsphinx/routing" } nym-bin-common = { path = "../bin-common" } +# 'serializable' feature +nym-config = { path = "../config", optional = true } + +# 'wasm-serde-types' feature +wasm-utils = { path = "../wasm/utils", default-features = false, optional = true } + [features] default = ["provider-trait"] -provider-trait = ["async-trait"] \ No newline at end of file +provider-trait = ["async-trait"] +wasm-serde-types = ["tsify", "wasm-bindgen", "wasm-utils"] +serializable = ["serde", "nym-config", "serde_json"] \ No newline at end of file diff --git a/common/topology/src/error.rs b/common/topology/src/error.rs index 3f2523576f..4c8714c0d6 100644 --- a/common/topology/src/error.rs +++ b/common/topology/src/error.rs @@ -21,6 +21,9 @@ pub enum NymTopologyError { #[error("Gateway with identity key {identity_key} doesn't exist")] NonExistentGatewayError { identity_key: String }, + #[error("timed out while waiting for gateway '{identity_key}' to come online")] + TimedOutWaitingForGateway { identity_key: String }, + #[error("Wanted to create a mix route with {requested} hops, while only {available} layers are available")] InvalidNumberOfHopsError { available: usize, requested: usize }, diff --git a/common/topology/src/gateway.rs b/common/topology/src/gateway.rs index 04e7d6f45a..ce5acc7638 100644 --- a/common/topology/src/gateway.rs +++ b/common/topology/src/gateway.rs @@ -8,6 +8,7 @@ use nym_sphinx_addressing::nodes::{NodeIdentity, NymNodeRoutingAddress}; use nym_sphinx_types::Node as SphinxNode; use std::convert::{TryFrom, TryInto}; use std::fmt; +use std::fmt::Formatter; use std::io; use std::net::SocketAddr; use thiserror::Error; @@ -28,7 +29,7 @@ pub enum GatewayConversionError { }, } -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct Node { pub owner: String, pub host: NetworkAddress, @@ -41,6 +42,20 @@ pub struct Node { pub version: NodeVersion, } +impl std::fmt::Debug for Node { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_struct("gateway::Node") + .field("host", &self.host) + .field("owner", &self.owner) + .field("mix_host", &self.mix_host) + .field("clients_port", &self.clients_port) + .field("identity_key", &self.identity_key.to_base58_string()) + .field("sphinx_key", &self.sphinx_key.to_base58_string()) + .field("version", &self.version) + .finish() + } +} + impl Node { pub fn parse_host(raw: &str) -> Result { raw.parse() @@ -69,6 +84,10 @@ impl Node { pub fn clients_address(&self) -> String { format!("ws://{}:{}", self.host, self.clients_port) } + + pub fn clients_address_tls(&self) -> String { + format!("wss://{}:443", self.host) + } } impl fmt::Display for Node { diff --git a/common/topology/src/lib.rs b/common/topology/src/lib.rs index 8c2a06cbfa..0273cf4a3a 100644 --- a/common/topology/src/lib.rs +++ b/common/topology/src/lib.rs @@ -17,6 +17,9 @@ use std::io; use std::net::{IpAddr, SocketAddr, ToSocketAddrs}; use std::str::FromStr; +#[cfg(feature = "serializable")] +use ::serde::{Deserialize, Deserializer, Serialize, Serializer}; + pub mod error; pub mod filter; pub mod gateway; @@ -26,6 +29,14 @@ pub mod random_route_provider; #[cfg(feature = "provider-trait")] pub mod provider_trait; +#[cfg(feature = "serializable")] +pub(crate) mod serde; + +#[cfg(feature = "serializable")] +pub use crate::serde::{ + SerializableGateway, SerializableMixNode, SerializableNymTopology, SerializableTopologyError, +}; + #[cfg(feature = "provider-trait")] pub use provider_trait::{HardcodedTopologyProvider, TopologyProvider}; @@ -110,6 +121,23 @@ impl NymTopology { NymTopology { mixes, gateways } } + pub fn new_unordered(unordered_mixes: Vec, gateways: Vec) -> Self { + let mut mixes = BTreeMap::new(); + for node in unordered_mixes.into_iter() { + let layer = node.layer as MixLayer; + let layer_entry = mixes.entry(layer).or_insert_with(Vec::new); + layer_entry.push(node) + } + + NymTopology { mixes, gateways } + } + + #[cfg(feature = "serializable")] + pub fn new_from_file>(path: P) -> std::io::Result { + let file = std::fs::File::open(path)?; + serde_json::from_reader(file).map_err(Into::into) + } + pub fn from_detailed( mix_details: Vec, gateway_bonds: Vec, @@ -171,6 +199,10 @@ impl NymTopology { &self.gateways } + pub fn get_gateways(&self) -> Vec { + self.gateways.clone() + } + pub fn get_gateway(&self, gateway_identity: &NodeIdentity) -> Option<&gateway::Node> { self.gateways .iter() @@ -350,6 +382,27 @@ impl NymTopology { } } +#[cfg(feature = "serializable")] +impl Serialize for NymTopology { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + crate::serde::SerializableNymTopology::from(self.clone()).serialize(serializer) + } +} + +#[cfg(feature = "serializable")] +impl<'de> Deserialize<'de> for NymTopology { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let serializable = crate::serde::SerializableNymTopology::deserialize(deserializer)?; + serializable.try_into().map_err(::serde::de::Error::custom) + } +} + pub fn nym_topology_from_detailed( mix_details: Vec, gateway_bonds: Vec, @@ -362,8 +415,8 @@ pub fn nym_topology_from_detailed( let layer = bond.layer as MixLayer; if layer == 0 || layer > 3 { warn!( - "{} says it's on invalid layer {}!", - bond.mix_node.identity_key, layer + "{} says it's on invalid layer {layer}!", + bond.mix_node.identity_key ); continue; } @@ -374,7 +427,7 @@ pub fn nym_topology_from_detailed( match bond.try_into() { Ok(mix) => layer_entry.push(mix), Err(err) => { - warn!("Mix {} / {} is malformed - {err}", mix_id, mix_identity); + warn!("Mix {mix_id} / {mix_identity} is malformed: {err}"); continue; } } @@ -386,7 +439,7 @@ pub fn nym_topology_from_detailed( match bond.try_into() { Ok(gate) => gateways.push(gate), Err(err) => { - warn!("Gateway {} is malformed - {err}", gate_id); + warn!("Gateway {gate_id} is malformed: {err}"); continue; } } diff --git a/common/topology/src/mix.rs b/common/topology/src/mix.rs index bfc4b90344..0481d5bc16 100644 --- a/common/topology/src/mix.rs +++ b/common/topology/src/mix.rs @@ -8,6 +8,7 @@ use nym_mixnet_contract_common::{MixId, MixNodeBond}; use nym_sphinx_addressing::nodes::NymNodeRoutingAddress; use nym_sphinx_types::Node as SphinxNode; use std::convert::{TryFrom, TryInto}; +use std::fmt::Formatter; use std::io; use std::net::SocketAddr; use thiserror::Error; @@ -28,7 +29,7 @@ pub enum MixnodeConversionError { }, } -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct Node { pub mix_id: MixId, pub owner: String, @@ -42,6 +43,21 @@ pub struct Node { pub version: NodeVersion, } +impl std::fmt::Debug for Node { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("mix::Node") + .field("mix_id", &self.mix_id) + .field("owner", &self.owner) + .field("host", &self.host) + .field("mix_host", &self.mix_host) + .field("identity_key", &self.identity_key.to_base58_string()) + .field("sphinx_key", &self.sphinx_key.to_base58_string()) + .field("layer", &self.layer) + .field("version", &self.version) + .finish() + } +} + impl Node { pub fn parse_host(raw: &str) -> Result { raw.parse() diff --git a/common/topology/src/provider_trait.rs b/common/topology/src/provider_trait.rs index 562cfaa5f7..0dddecf2cb 100644 --- a/common/topology/src/provider_trait.rs +++ b/common/topology/src/provider_trait.rs @@ -22,6 +22,11 @@ pub struct HardcodedTopologyProvider { } impl HardcodedTopologyProvider { + #[cfg(feature = "serializable")] + pub fn new_from_file>(path: P) -> std::io::Result { + NymTopology::new_from_file(path).map(Self::new) + } + pub fn new(topology: NymTopology) -> Self { HardcodedTopologyProvider { topology } } diff --git a/common/topology/src/serde.rs b/common/topology/src/serde.rs new file mode 100644 index 0000000000..89e943e03e --- /dev/null +++ b/common/topology/src/serde.rs @@ -0,0 +1,250 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::gateway::GatewayConversionError; +use crate::mix::MixnodeConversionError; +use crate::{gateway, mix, MixLayer, NymTopology}; +use nym_config::defaults::{DEFAULT_CLIENT_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT}; +use nym_crypto::asymmetric::{encryption, identity}; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; +use std::net::{IpAddr, SocketAddr}; +use thiserror::Error; + +#[cfg(feature = "wasm-serde-types")] +use tsify::Tsify; + +#[cfg(feature = "wasm-serde-types")] +use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; + +#[cfg(feature = "wasm-serde-types")] +use wasm_utils::error::simple_js_error; + +#[derive(Debug, Error)] +pub enum SerializableTopologyError { + #[error("got invalid mix layer {value}. Expected 1, 2 or 3.")] + InvalidMixLayer { value: u8 }, + + #[error(transparent)] + GatewayConversion(#[from] GatewayConversionError), + + #[error(transparent)] + MixnodeConversion(#[from] MixnodeConversionError), + + #[error("The provided mixnode map was malformed: {msg}")] + MalformedMixnodeMap { msg: String }, + + #[error("The provided gateway list was malformed: {msg}")] + MalformedGatewayList { msg: String }, +} + +#[cfg(feature = "wasm-serde-types")] +impl From for JsValue { + fn from(value: SerializableTopologyError) -> Self { + simple_js_error(value.to_string()) + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "wasm-serde-types", derive(Tsify))] +#[cfg_attr(feature = "wasm-serde-types", tsify(into_wasm_abi, from_wasm_abi))] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +pub struct SerializableNymTopology { + pub mixnodes: BTreeMap>, + pub gateways: Vec, +} + +impl TryFrom for NymTopology { + type Error = SerializableTopologyError; + + fn try_from(value: SerializableNymTopology) -> Result { + let mut converted_mixes = BTreeMap::new(); + + for (layer, nodes) in value.mixnodes { + let layer_nodes = nodes + .into_iter() + .map(TryInto::try_into) + .collect::>()?; + + converted_mixes.insert(layer, layer_nodes); + } + + let gateways = value + .gateways + .into_iter() + .map(TryInto::try_into) + .collect::>()?; + + Ok(NymTopology::new(converted_mixes, gateways)) + } +} + +impl From for SerializableNymTopology { + fn from(value: NymTopology) -> Self { + SerializableNymTopology { + mixnodes: value + .mixes() + .iter() + .map(|(&l, nodes)| (l, nodes.iter().map(Into::into).collect())) + .collect(), + gateways: value.gateways().iter().map(Into::into).collect(), + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "wasm-serde-types", derive(Tsify))] +#[cfg_attr(feature = "wasm-serde-types", tsify(into_wasm_abi, from_wasm_abi))] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +pub struct SerializableMixNode { + // this is a `MixId` but due to typescript issue, we're using u32 directly. + #[serde(alias = "mix_id")] + pub mix_id: u32, + + pub owner: String, + + pub host: String, + + #[cfg_attr(feature = "wasm-serde-types", tsify(optional))] + #[serde(alias = "mix_port")] + pub mix_port: Option, + + #[serde(alias = "identity_key")] + pub identity_key: String, + + #[serde(alias = "sphinx_key")] + pub sphinx_key: String, + + // this is a `MixLayer` but due to typescript issue, we're using u8 directly. + pub layer: u8, + + #[cfg_attr(feature = "wasm-serde-types", tsify(optional))] + pub version: Option, +} + +impl TryFrom for mix::Node { + type Error = SerializableTopologyError; + + fn try_from(value: SerializableMixNode) -> Result { + let host = mix::Node::parse_host(&value.host)?; + + let mix_port = value.mix_port.unwrap_or(DEFAULT_MIX_LISTENING_PORT); + let version = value.version.map(|v| v.as_str().into()).unwrap_or_default(); + + // try to completely resolve the host in the mix situation to avoid doing it every + // single time we want to construct a path + let mix_host = mix::Node::extract_mix_host(&host, mix_port)?; + + Ok(mix::Node { + mix_id: value.mix_id, + owner: value.owner, + host, + mix_host, + identity_key: identity::PublicKey::from_base58_string(&value.identity_key) + .map_err(MixnodeConversionError::from)?, + sphinx_key: encryption::PublicKey::from_base58_string(&value.sphinx_key) + .map_err(MixnodeConversionError::from)?, + layer: mix::Layer::try_from(value.layer) + .map_err(|_| SerializableTopologyError::InvalidMixLayer { value: value.layer })?, + version, + }) + } +} + +impl<'a> From<&'a mix::Node> for SerializableMixNode { + fn from(value: &'a mix::Node) -> Self { + SerializableMixNode { + mix_id: value.mix_id, + owner: value.owner.clone(), + host: value.host.to_string(), + mix_port: Some(value.mix_host.port()), + identity_key: value.identity_key.to_base58_string(), + sphinx_key: value.sphinx_key.to_base58_string(), + layer: value.layer.into(), + version: Some(value.version.to_string()), + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "wasm-serde-types", derive(Tsify))] +#[cfg_attr(feature = "wasm-serde-types", tsify(into_wasm_abi, from_wasm_abi))] +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +pub struct SerializableGateway { + pub owner: String, + + pub host: String, + + // optional ip address in the case of host being a hostname that can't be resolved + // (thank you wasm) + #[cfg_attr(feature = "wasm-serde-types", tsify(optional))] + #[serde(alias = "explicit_ip")] + pub explicit_ip: Option, + + #[cfg_attr(feature = "wasm-serde-types", tsify(optional))] + #[serde(alias = "mix_port")] + pub mix_port: Option, + + #[cfg_attr(feature = "wasm-serde-types", tsify(optional))] + #[serde(alias = "clients_port")] + pub clients_port: Option, + + #[serde(alias = "identity_key")] + pub identity_key: String, + + #[serde(alias = "sphinx_key")] + pub sphinx_key: String, + + #[cfg_attr(feature = "wasm-serde-types", tsify(optional))] + pub version: Option, +} + +impl TryFrom for gateway::Node { + type Error = SerializableTopologyError; + + fn try_from(value: SerializableGateway) -> Result { + let host = gateway::Node::parse_host(&value.host)?; + + let mix_port = value.mix_port.unwrap_or(DEFAULT_MIX_LISTENING_PORT); + let clients_port = value.clients_port.unwrap_or(DEFAULT_CLIENT_LISTENING_PORT); + let version = value.version.map(|v| v.as_str().into()).unwrap_or_default(); + + // try to completely resolve the host in the mix situation to avoid doing it every + // single time we want to construct a path + let mix_host = if let Some(explicit_ip) = value.explicit_ip { + SocketAddr::new(explicit_ip, mix_port) + } else { + gateway::Node::extract_mix_host(&host, mix_port)? + }; + + Ok(gateway::Node { + owner: value.owner, + host, + mix_host, + clients_port, + identity_key: identity::PublicKey::from_base58_string(&value.identity_key) + .map_err(GatewayConversionError::from)?, + sphinx_key: encryption::PublicKey::from_base58_string(&value.sphinx_key) + .map_err(GatewayConversionError::from)?, + version, + }) + } +} + +impl<'a> From<&'a gateway::Node> for SerializableGateway { + fn from(value: &'a gateway::Node) -> Self { + SerializableGateway { + owner: value.owner.clone(), + host: value.host.to_string(), + explicit_ip: Some(value.mix_host.ip()), + mix_port: Some(value.mix_host.port()), + clients_port: Some(value.clients_port), + identity_key: value.identity_key.to_base58_string(), + sphinx_key: value.sphinx_key.to_base58_string(), + version: Some(value.version.to_string()), + } + } +} diff --git a/common/types/src/gateway.rs b/common/types/src/gateway.rs index 125cf4ba03..a26fea053f 100644 --- a/common/types/src/gateway.rs +++ b/common/types/src/gateway.rs @@ -82,23 +82,67 @@ pub struct GatewayNodeDetailsResponse { pub identity_key: String, pub sphinx_key: String, pub bind_address: String, - pub version: String, pub mix_port: u16, pub clients_port: u16, + pub config_path: String, pub data_store: String, + + pub network_requester: Option, } impl fmt::Display for GatewayNodeDetailsResponse { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - writeln!(f, "Identity Key: {}", self.identity_key)?; - writeln!(f, "Sphinx Key: {}", self.sphinx_key)?; - writeln!(f, "Version: {}", self.version)?; + writeln!(f, "config path: {}", self.config_path)?; + writeln!(f, "identity key: {}", self.identity_key)?; + writeln!(f, "sphinx key: {}", self.sphinx_key)?; + writeln!(f, "bind address: {}", self.bind_address)?; writeln!( f, - "Mix Port: {}, Clients port: {}", + "mix Port: {}, clients port: {}", self.mix_port, self.clients_port )?; - writeln!(f, "Data store is at: {}", self.data_store) + writeln!(f, "data store is at: {}", self.data_store)?; + + if let Some(nr) = &self.network_requester { + nr.fmt(f)?; + } + Ok(()) + } +} + +#[derive(Serialize, Deserialize)] +pub struct GatewayNetworkRequesterDetails { + pub enabled: bool, + + pub identity_key: String, + pub encryption_key: String, + + pub open_proxy: bool, + pub enabled_statistics: bool, + + // just a convenience wrapper around all the keys + pub address: String, + + pub config_path: String, + pub allow_list_path: String, + pub unknown_list_path: String, +} + +impl fmt::Display for GatewayNetworkRequesterDetails { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "Network requester:")?; + writeln!(f, "\tenabled: {}", self.enabled)?; + writeln!(f, "\tconfig path: {}", self.config_path)?; + + writeln!(f, "\tidentity key: {}", self.identity_key)?; + writeln!(f, "\tencryption key: {}", self.encryption_key)?; + writeln!(f, "\taddress: {}", self.address)?; + + writeln!(f, "\tuses open proxy: {}", self.open_proxy)?; + writeln!(f, "\tsends statistics: {}", self.enabled_statistics)?; + + writeln!(f, "\tallow list path: {}", self.allow_list_path)?; + writeln!(f, "\tunknown list path: {}", self.allow_list_path) } } diff --git a/common/wasm/client-core/Cargo.toml b/common/wasm/client-core/Cargo.toml index 82f03573ba..38a9e3f5f9 100644 --- a/common/wasm/client-core/Cargo.toml +++ b/common/wasm/client-core/Cargo.toml @@ -30,7 +30,7 @@ nym-gateway-client = { path = "../../client-libs/gateway-client", default-featur nym-sphinx = { path = "../../nymsphinx" } nym-sphinx-acknowledgements = { path = "../../nymsphinx/acknowledgements", features = ["serde"]} nym-task = { path = "../../task" } -nym-topology = { path = "../../topology" } +nym-topology = { path = "../../topology", features = ["serializable", "wasm-serde-types"] } nym-validator-client = { path = "../../client-libs/validator-client", default-features = false } wasm-utils = { path = "../utils" } wasm-storage = { path = "../storage" } diff --git a/common/wasm/client-core/src/config/mod.rs b/common/wasm/client-core/src/config/mod.rs index 429fae6400..77dad1da5c 100644 --- a/common/wasm/client-core/src/config/mod.rs +++ b/common/wasm/client-core/src/config/mod.rs @@ -356,6 +356,10 @@ pub struct TopologyWasm { /// did not reach its destination. pub topology_resolution_timeout_ms: u32, + /// Defines how long the client is going to wait on startup for its gateway to come online, + /// before abandoning the procedure. + pub max_startup_gateway_waiting_period_ms: u32, + /// Specifies whether the client should not refresh the network topology after obtaining /// the first valid instance. /// Supersedes `topology_refresh_rate_ms`. @@ -376,6 +380,9 @@ impl From for ConfigTopology { topology.topology_resolution_timeout_ms as u64, ), disable_refreshing: topology.disable_refreshing, + max_startup_gateway_waiting_period: Duration::from_millis( + topology.max_startup_gateway_waiting_period_ms as u64, + ), topology_structure: Default::default(), } } @@ -386,6 +393,9 @@ impl From for TopologyWasm { TopologyWasm { topology_refresh_rate_ms: topology.topology_refresh_rate.as_millis() as u32, topology_resolution_timeout_ms: topology.topology_resolution_timeout.as_millis() as u32, + max_startup_gateway_waiting_period_ms: topology + .max_startup_gateway_waiting_period + .as_millis() as u32, disable_refreshing: topology.disable_refreshing, } } diff --git a/common/wasm/client-core/src/config/override.rs b/common/wasm/client-core/src/config/override.rs index 20f3f0cf2a..147584f3d4 100644 --- a/common/wasm/client-core/src/config/override.rs +++ b/common/wasm/client-core/src/config/override.rs @@ -228,6 +228,11 @@ pub struct TopologyWasmOverride { #[tsify(optional)] pub topology_resolution_timeout_ms: Option, + /// Defines how long the client is going to wait on startup for its gateway to come online, + /// before abandoning the procedure. + #[tsify(optional)] + pub max_startup_gateway_waiting_period_ms: Option, + /// Specifies whether the client should not refresh the network topology after obtaining /// the first valid instance. /// Supersedes `topology_refresh_rate_ms`. @@ -246,6 +251,9 @@ impl From for TopologyWasm { topology_resolution_timeout_ms: value .topology_resolution_timeout_ms .unwrap_or(def.topology_resolution_timeout_ms), + max_startup_gateway_waiting_period_ms: value + .max_startup_gateway_waiting_period_ms + .unwrap_or(def.max_startup_gateway_waiting_period_ms), disable_refreshing: value.disable_refreshing.unwrap_or(def.disable_refreshing), } } diff --git a/common/wasm/client-core/src/helpers.rs b/common/wasm/client-core/src/helpers.rs index e6aacfe2b7..6b59d30d80 100644 --- a/common/wasm/client-core/src/helpers.rs +++ b/common/wasm/client-core/src/helpers.rs @@ -4,15 +4,18 @@ use crate::error::WasmCoreError; use crate::storage::wasm_client_traits::WasmClientStorage; use crate::storage::ClientStorage; -use crate::topology::WasmNymTopology; use js_sys::Promise; use nym_client_core::client::replies::reply_storage::browser_backend; use nym_client_core::config; use nym_client_core::init::helpers::current_gateways; -use nym_client_core::init::{setup_gateway_from, GatewaySetup, InitialisationResult}; +use nym_client_core::init::types::GatewaySelectionSpecification; +use nym_client_core::init::{ + self, + types::{GatewaySetup, InitialisationResult}, +}; use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag; -use nym_topology::{gateway, NymTopology}; +use nym_topology::{gateway, NymTopology, SerializableNymTopology}; use nym_validator_client::client::IdentityKey; use nym_validator_client::NymApiClient; use rand::thread_rng; @@ -52,7 +55,7 @@ pub fn parse_sender_tag(tag: &str) -> Result pub async fn current_network_topology_async( nym_api_url: String, -) -> Result { +) -> Result { let url: Url = match nym_api_url.parse() { Ok(url) => url, Err(source) => { @@ -81,37 +84,47 @@ pub fn current_network_topology(nym_api_url: String) -> Promise { }) } -async fn setup_gateway( +pub async fn setup_gateway_wasm( client_store: &ClientStorage, + force_tls: bool, chosen_gateway: Option, gateways: &[gateway::Node], ) -> Result { let setup = if client_store.has_full_gateway_info().await? { GatewaySetup::MustLoad } else { - GatewaySetup::new_fresh(chosen_gateway.clone(), None) + let selection_spec = + GatewaySelectionSpecification::new(chosen_gateway.clone(), None, force_tls); + + GatewaySetup::New { + specification: selection_spec, + available_gateways: gateways.to_vec(), + overwrite_data: false, + } }; - setup_gateway_from(setup, client_store, client_store, false, Some(gateways)) + init::setup_gateway(setup, client_store, client_store) .await .map_err(Into::into) } pub async fn setup_gateway_from_api( client_store: &ClientStorage, + force_tls: bool, chosen_gateway: Option, nym_apis: &[Url], ) -> Result { let mut rng = thread_rng(); let gateways = current_gateways(&mut rng, nym_apis).await?; - setup_gateway(client_store, chosen_gateway, &gateways).await + setup_gateway_wasm(client_store, force_tls, chosen_gateway, &gateways).await } pub async fn setup_from_topology( explicit_gateway: Option, + force_tls: bool, topology: &NymTopology, client_store: &ClientStorage, ) -> Result { let gateways = topology.gateways(); - setup_gateway(client_store, explicit_gateway, gateways).await + setup_gateway_wasm(client_store, force_tls, explicit_gateway, gateways).await } diff --git a/common/wasm/client-core/src/lib.rs b/common/wasm/client-core/src/lib.rs index 95ce12ad3c..568b2b459e 100644 --- a/common/wasm/client-core/src/lib.rs +++ b/common/wasm/client-core/src/lib.rs @@ -16,11 +16,9 @@ pub mod topology; pub use nym_bandwidth_controller::BandwidthController; pub use nym_client_core::*; pub use nym_client_core::{ - client::key_manager::ManagedKeys, - error::ClientCoreError, - init::{InitialisationDetails, InitialisationResult}, + client::key_manager::ManagedKeys, error::ClientCoreError, init::types::InitialisationResult, }; -pub use nym_gateway_client::{error::GatewayClientError, GatewayClient}; +pub use nym_gateway_client::{error::GatewayClientError, GatewayClient, GatewayConfig}; pub use nym_sphinx::{ addressing::{clients::Recipient, nodes::NodeIdentity}, params::PacketType, diff --git a/common/wasm/client-core/src/storage/core_client_traits.rs b/common/wasm/client-core/src/storage/core_client_traits.rs index 0a0114d55c..b017bb3914 100644 --- a/common/wasm/client-core/src/storage/core_client_traits.rs +++ b/common/wasm/client-core/src/storage/core_client_traits.rs @@ -80,7 +80,7 @@ impl KeyStore for ClientStorage { Ok(KeyManager::from_keys( identity_keypair, encryption_keypair, - gateway_shared_key, + Some(gateway_shared_key), ack_keypair, )) } @@ -93,8 +93,11 @@ impl KeyStore for ClientStorage { self.store_encryption_keypair(&keys.encryption_keypair()) .await?; self.store_ack_key(&keys.ack_key()).await?; - self.store_gateway_shared_key(&keys.gateway_shared_key()) - .await + + if let Some(shared_keys) = keys.gateway_shared_key() { + self.store_gateway_shared_key(&shared_keys).await?; + } + Ok(()) } } diff --git a/common/wasm/client-core/src/topology.rs b/common/wasm/client-core/src/topology.rs index ab6ee353d3..8c84dee4a1 100644 --- a/common/wasm/client-core/src/topology.rs +++ b/common/wasm/client-core/src/topology.rs @@ -2,55 +2,30 @@ // SPDX-License-Identifier: Apache-2.0 use nym_client_core::config::GatewayEndpointConfig; -use nym_config::defaults::{DEFAULT_CLIENT_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT}; -use nym_crypto::asymmetric::{encryption, identity}; -use nym_topology::gateway::GatewayConversionError; -use nym_topology::mix::{Layer, MixnodeConversionError}; -use nym_topology::{gateway, mix, MixLayer, NymTopology}; +use nym_topology::SerializableTopologyError; use nym_validator_client::client::IdentityKeyRef; -use serde::{Deserialize, Serialize}; -use std::collections::BTreeMap; -use thiserror::Error; -use tsify::Tsify; -use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; use wasm_utils::console_log; -use wasm_utils::error::simple_js_error; -#[derive(Debug, Error)] -pub enum WasmTopologyError { - #[error("got invalid mix layer {value}. Expected 1, 2 or 3.")] - InvalidMixLayer { value: u8 }, +pub use nym_topology::{ + gateway, mix, SerializableGateway, SerializableMixNode, SerializableNymTopology, +}; - #[error(transparent)] - GatewayConversion(#[from] GatewayConversionError), +// redeclare this as a type alias for easy of use +pub type WasmTopologyError = SerializableTopologyError; - #[error(transparent)] - MixnodeConversion(#[from] MixnodeConversionError), +// helper trait to define extra functionality on the external type that we used to have here before +pub trait SerializableTopologyExt { + fn print(&self); - #[error("The provided mixnode map was malformed: {msg}")] - MalformedMixnodeMap { msg: String }, - - #[error("The provided gateway list was malformed: {msg}")] - MalformedGatewayList { msg: String }, -} - -impl From for JsValue { - fn from(value: WasmTopologyError) -> Self { - simple_js_error(value.to_string()) + fn ensure_contains(&self, gateway_config: &GatewayEndpointConfig) -> bool { + self.ensure_contains_gateway_id(&gateway_config.gateway_id) } -} -// serde helper, not intended to be used directly -#[derive(Tsify, Debug, Clone, Serialize, Deserialize)] -#[tsify(into_wasm_abi, from_wasm_abi)] -#[serde(rename_all = "camelCase")] -pub struct WasmNymTopology { - mixnodes: BTreeMap>, - gateways: Vec, + fn ensure_contains_gateway_id(&self, gateway_id: IdentityKeyRef) -> bool; } -impl WasmNymTopology { - pub fn print(&self) { +impl SerializableTopologyExt for SerializableNymTopology { + fn print(&self) { if !self.mixnodes.is_empty() { console_log!("mixnodes:"); for (layer, nodes) in &self.mixnodes { @@ -74,178 +49,8 @@ impl WasmNymTopology { console_log!("NO GATEWAYS") } } -} - -impl TryFrom for NymTopology { - type Error = WasmTopologyError; - fn try_from(value: WasmNymTopology) -> Result { - let mut converted_mixes = BTreeMap::new(); - - for (layer, nodes) in value.mixnodes { - let layer_nodes = nodes - .into_iter() - .map(TryInto::try_into) - .collect::>()?; - - converted_mixes.insert(layer, layer_nodes); - } - - let gateways = value - .gateways - .into_iter() - .map(TryInto::try_into) - .collect::>()?; - - Ok(NymTopology::new(converted_mixes, gateways)) - } -} - -impl WasmNymTopology { - pub fn ensure_contains(&self, gateway_config: &GatewayEndpointConfig) -> bool { - self.ensure_contains_gateway_id(&gateway_config.gateway_id) - } - - pub fn ensure_contains_gateway_id(&self, gateway_id: IdentityKeyRef) -> bool { + fn ensure_contains_gateway_id(&self, gateway_id: IdentityKeyRef) -> bool { self.gateways.iter().any(|g| g.identity_key == gateway_id) } } - -impl From for WasmNymTopology { - fn from(value: NymTopology) -> Self { - WasmNymTopology { - mixnodes: value - .mixes() - .iter() - .map(|(&l, nodes)| (l, nodes.iter().map(Into::into).collect())) - .collect(), - gateways: value.gateways().iter().map(Into::into).collect(), - } - } -} - -#[derive(Tsify, Debug, Clone, Serialize, Deserialize)] -#[tsify(into_wasm_abi, from_wasm_abi)] -#[serde(rename_all = "camelCase")] -pub struct WasmMixNode { - // this is a `MixId` but due to typescript issue, we're using u32 directly. - pub mix_id: u32, - pub owner: String, - pub host: String, - - #[tsify(optional)] - pub mix_port: Option, - pub identity_key: String, - pub sphinx_key: String, - - // this is a `MixLayer` but due to typescript issue, we're using u8 directly. - pub layer: u8, - - #[tsify(optional)] - pub version: Option, -} - -impl TryFrom for mix::Node { - type Error = WasmTopologyError; - - fn try_from(value: WasmMixNode) -> Result { - let host = mix::Node::parse_host(&value.host)?; - - let mix_port = value.mix_port.unwrap_or(DEFAULT_MIX_LISTENING_PORT); - let version = value.version.map(|v| v.as_str().into()).unwrap_or_default(); - - // try to completely resolve the host in the mix situation to avoid doing it every - // single time we want to construct a path - let mix_host = mix::Node::extract_mix_host(&host, mix_port)?; - - Ok(mix::Node { - mix_id: value.mix_id, - owner: value.owner, - host, - mix_host, - identity_key: identity::PublicKey::from_base58_string(&value.identity_key) - .map_err(MixnodeConversionError::from)?, - sphinx_key: encryption::PublicKey::from_base58_string(&value.sphinx_key) - .map_err(MixnodeConversionError::from)?, - layer: Layer::try_from(value.layer) - .map_err(|_| WasmTopologyError::InvalidMixLayer { value: value.layer })?, - version, - }) - } -} - -impl<'a> From<&'a mix::Node> for WasmMixNode { - fn from(value: &'a mix::Node) -> Self { - WasmMixNode { - mix_id: value.mix_id, - owner: value.owner.clone(), - host: value.host.to_string(), - mix_port: Some(value.mix_host.port()), - identity_key: value.identity_key.to_base58_string(), - sphinx_key: value.sphinx_key.to_base58_string(), - layer: value.layer.into(), - version: Some(value.version.to_string()), - } - } -} - -#[derive(Tsify, Debug, Clone, Serialize, Deserialize)] -#[tsify(into_wasm_abi, from_wasm_abi)] -#[serde(rename_all = "camelCase")] -pub struct WasmGateway { - pub owner: String, - pub host: String, - - #[tsify(optional)] - pub mix_port: Option, - - #[tsify(optional)] - pub clients_port: Option, - pub identity_key: String, - pub sphinx_key: String, - - #[tsify(optional)] - pub version: Option, -} - -impl TryFrom for gateway::Node { - type Error = WasmTopologyError; - - fn try_from(value: WasmGateway) -> Result { - let host = gateway::Node::parse_host(&value.host)?; - - let mix_port = value.mix_port.unwrap_or(DEFAULT_MIX_LISTENING_PORT); - let clients_port = value.clients_port.unwrap_or(DEFAULT_CLIENT_LISTENING_PORT); - let version = value.version.map(|v| v.as_str().into()).unwrap_or_default(); - - // try to completely resolve the host in the mix situation to avoid doing it every - // single time we want to construct a path - let mix_host = gateway::Node::extract_mix_host(&host, mix_port)?; - - Ok(gateway::Node { - owner: value.owner, - host, - mix_host, - clients_port, - identity_key: identity::PublicKey::from_base58_string(&value.identity_key) - .map_err(GatewayConversionError::from)?, - sphinx_key: encryption::PublicKey::from_base58_string(&value.sphinx_key) - .map_err(GatewayConversionError::from)?, - version, - }) - } -} - -impl<'a> From<&'a gateway::Node> for WasmGateway { - fn from(value: &'a gateway::Node) -> Self { - WasmGateway { - owner: value.owner.clone(), - host: value.host.to_string(), - mix_port: Some(value.mix_host.port()), - clients_port: Some(value.clients_port), - identity_key: value.identity_key.to_base58_string(), - sphinx_key: value.sphinx_key.to_base58_string(), - version: Some(value.version.to_string()), - } - } -} diff --git a/common/wireguard/Cargo.toml b/common/wireguard/Cargo.toml new file mode 100644 index 0000000000..ac54018cc1 --- /dev/null +++ b/common/wireguard/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "nym-wireguard" +version = "0.1.0" +authors.workspace = true +repository.workspace = true +homepage.workspace = true +documentation.workspace = true +edition.workspace = true +license.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +async-recursion = "1.0.4" +base64 = "0.21.3" +# The latest version on crates.io at the time of writing this (6.0.0) has a +# version mismatch with x25519-dalek/curve25519-dalek that is resolved in the +# latest commit. So pick that for now. +#boringtun = "0.6.0" +boringtun = { git = "https://github.com/cloudflare/boringtun", rev = "e1d6360d6ab4529fc942a078e4c54df107abe2ba" } +bytes = "1.5.0" +futures = "0.3.28" +log.workspace = true +nym-task = { path = "../task" } +tap.workspace = true +thiserror.workspace = true +tokio = { workspace = true, features = ["rt-multi-thread", "net"]} diff --git a/common/wireguard/src/error.rs b/common/wireguard/src/error.rs new file mode 100644 index 0000000000..d46d10c5ac --- /dev/null +++ b/common/wireguard/src/error.rs @@ -0,0 +1,7 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum WgError { + #[error("unable to get tunnel")] + UnableToGetTunnel, +} diff --git a/common/wireguard/src/event.rs b/common/wireguard/src/event.rs new file mode 100644 index 0000000000..4808517434 --- /dev/null +++ b/common/wireguard/src/event.rs @@ -0,0 +1,33 @@ +use std::fmt::{Display, Formatter}; + +use bytes::Bytes; + +#[allow(unused)] +#[derive(Debug, Clone)] +pub enum Event { + /// Dumb event with no data. + Dumb, + /// IP packet received from the WireGuard tunnel that should be passed through to the corresponding virtual device/internet. + /// Original implementation also has protocol here since it understands it, but we'll have to infer it downstream + WgPacket(Bytes), + /// IP packet to be sent through the WireGuard tunnel as crafted by the virtual device. + IpPacket(Bytes), +} + +impl Display for Event { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + Event::Dumb => { + write!(f, "Dumb{{}}") + } + Event::WgPacket(data) => { + let size = data.len(); + write!(f, "WgPacket{{ size={size} }}") + } + Event::IpPacket(data) => { + let size = data.len(); + write!(f, "IpPacket{{ size={size} }}") + } + } + } +} diff --git a/common/wireguard/src/lib.rs b/common/wireguard/src/lib.rs new file mode 100644 index 0000000000..75119c723f --- /dev/null +++ b/common/wireguard/src/lib.rs @@ -0,0 +1,140 @@ +use std::{collections::HashMap, net::SocketAddr, sync::Arc}; + +use base64::{engine::general_purpose, Engine as _}; +use boringtun::x25519; +use futures::StreamExt; +use log::{error, info}; +use nym_task::TaskClient; +use tap::TapFallible; +use tokio::{net::UdpSocket, sync::mpsc, task::JoinHandle}; +use tun::WireGuardTunnel; + +use crate::event::Event; + +pub use error::WgError; + +mod error; +mod event; +mod tun; + +//const WG_ADDRESS = "0.0.0.0:51820"; +const WG_ADDRESS: &str = "0.0.0.0:51822"; + +// The private key of the listener +// Corresponding public key: "WM8s8bYegwMa0TJ+xIwhk+dImk2IpDUKslDBCZPizlE=" +const PRIVATE_KEY: &str = "AEqXrLFT4qjYq3wmX0456iv94uM6nDj5ugp6Jedcflg="; + +// The public keys of the registered peers (clients) +const PEERS: &[&str; 1] = &[ + // Corresponding private key: "ILeN6gEh6vJ3Ju8RJ3HVswz+sPgkcKtAYTqzQRhTtlo=" + "NCIhkgiqxFx1ckKl3Zuh595DzIFl8mxju1Vg995EZhI=", // "mxV/mw7WZTe+0Msa0kvJHMHERDA/cSskiZWQce+TdEs=", +]; + +const MAX_PACKET: usize = 65535; + +fn init_static_dev_keys() -> (x25519::StaticSecret, x25519::PublicKey) { + // TODO: this is a temporary solution for development + let static_private_bytes: [u8; 32] = general_purpose::STANDARD + .decode(PRIVATE_KEY) + .unwrap() + .try_into() + .unwrap(); + let static_private = x25519::StaticSecret::try_from(static_private_bytes).unwrap(); + let static_public = x25519::PublicKey::from(&static_private); + info!( + "wg public key: {}", + general_purpose::STANDARD.encode(static_public) + ); + + // TODO: A single static public key is used for all peers during development + let peer_static_public_bytes: [u8; 32] = general_purpose::STANDARD + .decode(PEERS[0]) + .unwrap() + .try_into() + .unwrap(); + let peer_static_public = x25519::PublicKey::try_from(peer_static_public_bytes).unwrap(); + + (static_private, peer_static_public) +} + +fn start_wg_tunnel( + addr: SocketAddr, + udp: Arc, + static_private: x25519::StaticSecret, + peer_static_public: x25519::PublicKey, +) -> (JoinHandle, mpsc::UnboundedSender) { + let (mut tunnel, peer_tx) = WireGuardTunnel::new(udp, addr, static_private, peer_static_public); + let join_handle = tokio::spawn(async move { + tunnel.spin_off().await; + addr + }); + (join_handle, peer_tx) +} + +pub async fn start_wg_listener( + mut task_client: TaskClient, +) -> Result<(), Box> { + log::info!("Starting wireguard listener on {}", WG_ADDRESS); + let udp_socket = Arc::new(UdpSocket::bind(WG_ADDRESS).await?); + + // Setup some static keys for development + let (static_private, peer_static_public) = init_static_dev_keys(); + + tokio::spawn(async move { + // The set of active tunnels indexed by the peer's address + let mut active_peers: HashMap> = HashMap::new(); + // Each tunnel is run in its own task, and the task handle is stored here so we can remove + // it from `active_peers` when the tunnel is closed + let mut active_peers_task_handles = futures::stream::FuturesUnordered::new(); + let mut buf = [0u8; MAX_PACKET]; + + while !task_client.is_shutdown() { + tokio::select! { + _ = task_client.recv() => { + log::trace!("WireGuard listener: received shutdown"); + break; + } + // Handle tunnel closing + Some(addr) = active_peers_task_handles.next() => { + match addr { + Ok(addr) => { + info!("WireGuard listener: closed {addr:?}"); + active_peers.remove(&addr); + } + Err(err) => { + error!("WireGuard listener: error receiving shutdown from peer: {err}"); + } + } + } + // Handle incoming packets + Ok((len, addr)) = udp_socket.recv_from(&mut buf) => { + log::info!("Received {} bytes from {}", len, addr); + + if let Some(peer_tx) = active_peers.get_mut(&addr) { + log::info!("WireGuard listener: received packet from known peer"); + peer_tx.send(Event::WgPacket(buf[..len].to_vec().into())) + .tap_err(|err| log::error!("{err}")) + .unwrap(); + } else { + log::info!("WireGuard listener: received packet from unknown peer, starting tunnel"); + let (join_handle, peer_tx) = start_wg_tunnel( + addr, + udp_socket.clone(), + static_private.clone(), + peer_static_public + ); + peer_tx.send(Event::WgPacket(buf[..len].to_vec().into())) + .tap_err(|err| log::error!("{err}")) + .unwrap(); + + active_peers.insert(addr, peer_tx); + active_peers_task_handles.push(join_handle); + } + } + } + } + log::info!("WireGuard listener: shutting down"); + }); + + Ok(()) +} diff --git a/common/wireguard/src/tun.rs b/common/wireguard/src/tun.rs new file mode 100644 index 0000000000..ae1819b6fa --- /dev/null +++ b/common/wireguard/src/tun.rs @@ -0,0 +1,221 @@ +use std::{net::SocketAddr, sync::Arc, time::Duration}; + +use async_recursion::async_recursion; +use boringtun::{ + noise::{errors::WireGuardError, Tunn, TunnResult}, + x25519, +}; +use bytes::Bytes; +use log::{debug, error, info, warn}; +use tap::TapFallible; +use tokio::{ + net::UdpSocket, + sync::{broadcast, mpsc}, + time::timeout, +}; + +use crate::{event::Event, WgError}; + +const MAX_PACKET: usize = 65535; + +pub struct WireGuardTunnel { + // Incoming data from the UDP socket received in the main event loop + udp_rx: mpsc::UnboundedReceiver, + + // UDP socket used for sending data + udp: Arc, + + // Peer endpoint + addr: SocketAddr, + + // `boringtun` tunnel, used for crypto & WG protocol + wg_tunnel: Arc>, + + // Signal close + close_tx: broadcast::Sender<()>, + close_rx: broadcast::Receiver<()>, +} + +impl Drop for WireGuardTunnel { + fn drop(&mut self) { + info!("WireGuard tunnel: dropping"); + self.close(); + } +} + +impl WireGuardTunnel { + fn close(&self) { + let _ = self.close_tx.send(()); + } + + pub fn new( + udp: Arc, + addr: SocketAddr, + static_private: x25519::StaticSecret, + peer_static_public: x25519::PublicKey, + ) -> (Self, mpsc::UnboundedSender) { + let preshared_key = None; + let persistent_keepalive = None; + let index = 0; + let rate_limiter = None; + + let wg_tunnel = Arc::new(tokio::sync::Mutex::new( + Tunn::new( + static_private, + peer_static_public, + preshared_key, + persistent_keepalive, + index, + rate_limiter, + ) + .unwrap(), + )); + + // Channels with incoming data that is received by the main event loop + let (udp_tx, udp_rx) = mpsc::unbounded_channel(); + + // Signal close tunnel + let (close_tx, close_rx) = broadcast::channel(1); + + let tunnel = WireGuardTunnel { + udp_rx, + udp, + addr, + wg_tunnel, + close_tx, + close_rx, + }; + + (tunnel, udp_tx) + } + + pub async fn spin_off(&mut self) { + loop { + tokio::select! { + _ = self.close_rx.recv() => { + info!("WireGuard tunnel: received msg to close"); + break; + }, + packet = self.udp_rx.recv() => match packet { + Some(packet) => { + info!("WireGuard tunnel received: {packet}"); + match packet { + Event::WgPacket(data) => { + let _ = self.consume_wg(&data) + .await + .tap_err(|err| error!("WireGuard tunnel: consume_wg error: {err}")); + }, + Event::IpPacket(data) => self.consume_eth(&data).await, + _ => {}, + } + }, + None => { + info!("WireGuard tunnel: incoming UDP stream closed, closing tunnel"); + break; + }, + }, + _ = tokio::time::sleep(Duration::from_millis(250)) => { + let _ = self.update_wg_timers() + .await + .map_err(|err| error!("WireGuard tunnel: update_wg_timers error: {err}")); + }, + } + } + info!("WireGuard tunnel ({}): closed", self.addr); + } + + async fn wg_tunnel_lock(&self) -> Result, WgError> { + timeout(Duration::from_millis(100), self.wg_tunnel.lock()) + .await + .map_err(|_| WgError::UnableToGetTunnel) + } + + async fn consume_wg(&self, data: &[u8]) -> Result<(), WgError> { + let mut send_buf = [0u8; MAX_PACKET]; + let mut peer = self.wg_tunnel_lock().await?; + match peer.decapsulate(None, data, &mut send_buf) { + TunnResult::WriteToNetwork(packet) => { + debug!("WireGuard: writing to network"); + if let Err(err) = self.udp.send_to(packet, self.addr).await { + error!("Failed to send decapsulation-instructed packet to WireGuard endpoint: {err:?}"); + }; + // Flush pending queue + loop { + let mut send_buf = [0u8; MAX_PACKET]; + match peer.decapsulate(None, &[], &mut send_buf) { + TunnResult::WriteToNetwork(packet) => { + if let Err(err) = self.udp.send_to(packet, self.addr).await { + error!("Failed to send decapsulation-instructed packet to WireGuard endpoint: {err:?}"); + break; + }; + } + _ => { + break; + } + } + } + } + TunnResult::WriteToTunnelV4(packet, _) | TunnResult::WriteToTunnelV6(packet, _) => { + debug!("WireGuard: writing to tunnel"); + info!( + "WireGuard endpoint sent IP packet of {} bytes (not yet implemented)", + packet.len() + ); + // TODO + } + TunnResult::Done => { + debug!("WireGuard: decapsulate done"); + } + TunnResult::Err(err) => { + error!("WireGuard: decapsulate error: {err:?}"); + } + } + Ok(()) + } + + async fn consume_eth(&self, _data: &Bytes) { + info!("WireGuard tunnel: consume_eth"); + todo!(); + } + + async fn update_wg_timers(&mut self) -> Result<(), WgError> { + let mut send_buf = [0u8; MAX_PACKET]; + let mut tun = self.wg_tunnel_lock().await?; + let tun_result = tun.update_timers(&mut send_buf); + self.handle_routine_tun_result(tun_result).await; + Ok(()) + } + + #[async_recursion] + async fn handle_routine_tun_result<'a: 'async_recursion>(&self, result: TunnResult<'a>) { + match result { + TunnResult::WriteToNetwork(packet) => { + info!( + "Sending routine packet of {} bytes to WireGuard endpoint", + packet.len() + ); + if let Err(err) = self.udp.send_to(packet, self.addr).await { + error!("Failed to send routine packet to WireGuard endpoint: {err:?}",); + }; + } + TunnResult::Err(WireGuardError::ConnectionExpired) => { + warn!("Wireguard handshake has expired!"); + let mut buf = vec![0u8; MAX_PACKET]; + let Ok(mut peer) = self.wg_tunnel_lock().await else { + warn!("Failed to lock WireGuard peer, closing tunnel"); + self.close(); + return; + }; + peer.format_handshake_initiation(&mut buf[..], false); + self.handle_routine_tun_result(result).await + } + TunnResult::Err(err) => { + error!("Failed to prepare routine packet for WireGuard endpoint: {err:?}"); + } + TunnResult::Done => {} + other => { + warn!("Unexpected WireGuard routine task state: {other:?}"); + } + }; + } +} diff --git a/contracts/Cargo.lock b/contracts/Cargo.lock index 812afbaa8d..cfe8bc7e30 100644 --- a/contracts/Cargo.lock +++ b/contracts/Cargo.lock @@ -1302,7 +1302,7 @@ dependencies = [ [[package]] name = "nym-mixnet-contract" -version = "1.5.0" +version = "1.5.1" dependencies = [ "bs58", "cosmwasm-derive", diff --git a/contracts/Cargo.toml b/contracts/Cargo.toml index 8063d2f543..9ec0049b20 100644 --- a/contracts/Cargo.toml +++ b/contracts/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +resolver = "2" members = [ "coconut-bandwidth", "coconut-dkg", diff --git a/contracts/mixnet/Cargo.toml b/contracts/mixnet/Cargo.toml index a50d9c789a..6824f2e309 100644 --- a/contracts/mixnet/Cargo.toml +++ b/contracts/mixnet/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-mixnet-contract" -version = "1.5.0" +version = "1.5.1" description = "Nym mixnet contract" edition = { workspace = true } authors = { workspace = true } @@ -54,8 +54,3 @@ vergen = { version = "=7.4.3", default-features = false, features = ["build", "g default = [] contract-testing = ["mixnet-contract-common/contract-testing"] schema-gen = ["mixnet-contract-common/schema", "cosmwasm-schema"] - -[profile.release] -overflow-checks = true - - diff --git a/contracts/mixnet/schema/nym-mixnet-contract.json b/contracts/mixnet/schema/nym-mixnet-contract.json index 37cbc9ba65..829a510d1b 100644 --- a/contracts/mixnet/schema/nym-mixnet-contract.json +++ b/contracts/mixnet/schema/nym-mixnet-contract.json @@ -1,6 +1,6 @@ { "contract_name": "nym-mixnet-contract", - "contract_version": "1.5.0", + "contract_version": "1.5.1", "idl_version": "1.0.0", "instantiate": { "$schema": "http://json-schema.org/draft-07/schema#", diff --git a/contracts/mixnet/src/contract.rs b/contracts/mixnet/src/contract.rs index 892f4d2298..0e8a75df39 100644 --- a/contracts/mixnet/src/contract.rs +++ b/contracts/mixnet/src/contract.rs @@ -606,7 +606,7 @@ pub fn query( #[entry_point] pub fn migrate( - mut deps: DepsMut<'_>, + deps: DepsMut<'_>, _env: Env, msg: MigrateMsg, ) -> Result { @@ -632,7 +632,6 @@ pub fn migrate( // If state structure changed in any contract version in the way migration is needed, it // should occur here, for example anything from `crate::queued_migrations::` - crate::queued_migrations::insert_pending_pledge_changes(deps.branch())?; } // due to circular dependency on contract addresses (i.e. mixnet contract requiring vesting contract address diff --git a/contracts/mixnet/src/queued_migrations.rs b/contracts/mixnet/src/queued_migrations.rs index 732c4c3be2..8df3ef5d86 100644 --- a/contracts/mixnet/src/queued_migrations.rs +++ b/contracts/mixnet/src/queued_migrations.rs @@ -1,42 +1,2 @@ // Copyright 2022-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 - -use crate::interval::storage as interval_storage; -use crate::mixnodes::storage as mixnodes_storage; -use cosmwasm_std::DepsMut; -use mixnet_contract_common::error::MixnetContractError; -use mixnet_contract_common::mixnode::PendingMixNodeChanges; -use mixnet_contract_common::PendingEpochEventKind; -use std::collections::BTreeMap; - -pub fn insert_pending_pledge_changes(deps: DepsMut<'_>) -> Result<(), MixnetContractError> { - let last_executed = interval_storage::LAST_PROCESSED_EPOCH_EVENT.load(deps.storage)?; - let last_inserted = interval_storage::EPOCH_EVENT_ID_COUNTER.load(deps.storage)?; - - let mut new_pending = BTreeMap::new(); - - for event_id in last_executed + 1..=last_inserted { - let event = interval_storage::PENDING_EPOCH_EVENTS.load(deps.storage, event_id)?; - match event.kind { - PendingEpochEventKind::PledgeMore { mix_id, .. } - | PendingEpochEventKind::DecreasePledge { mix_id, .. } => { - if new_pending.insert(mix_id, event_id).is_some() { - return Err(MixnetContractError::FailedMigration { comment: format!("mixnode {mix_id} has more than a single pledge change pending for this epoch. Run this migration again after the epoch has finished.") }); - } - } - _ => (), - } - } - - for (mix_id, event_id) in new_pending { - mixnodes_storage::PENDING_MIXNODE_CHANGES.save( - deps.storage, - mix_id, - &PendingMixNodeChanges { - pledge_change: Some(event_id), - }, - )?; - } - - Ok(()) -} diff --git a/contracts/vesting/Cargo.toml b/contracts/vesting/Cargo.toml index 053aeedd15..f9a4f53d2a 100644 --- a/contracts/vesting/Cargo.toml +++ b/contracts/vesting/Cargo.toml @@ -48,8 +48,5 @@ cosmwasm-crypto = { workspace = true } [build-dependencies] vergen = { version = "=7.4.3", default-features = false, features = ["build", "git", "rustc"] } -[profile.release] -overflow-checks = true - [features] -schema-gen = ["vesting-contract-common/schema", "cosmwasm-schema"] \ No newline at end of file +schema-gen = ["vesting-contract-common/schema", "cosmwasm-schema"] diff --git a/documentation/build_all_to_dist.sh b/documentation/build_all_to_dist.sh index b414e92df6..76c58f5e6d 100755 --- a/documentation/build_all_to_dist.sh +++ b/documentation/build_all_to_dist.sh @@ -1,4 +1,9 @@ -#!/bin/bash +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + # this is a script called by the github CI and CD workflows to build all 3 docs projects # and move them to /dist/ in the root of the monorepo. They are rsynced to various servers # from there by subsequent workflow tasks. diff --git a/documentation/bump_versions.sh b/documentation/bump_versions.sh index 2ff1c2c882..8b1f68e1f8 100755 --- a/documentation/bump_versions.sh +++ b/documentation/bump_versions.sh @@ -1,4 +1,9 @@ #!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + # takes one manadatory arg and one optional arg: wallet release and minimum rust versions # it then uses sed to bump them in the three book.toml files. # diff --git a/documentation/dev-portal/src/integrations/integration-options.md b/documentation/dev-portal/src/integrations/integration-options.md index 6b9071b17c..56f00a33da 100644 --- a/documentation/dev-portal/src/integrations/integration-options.md +++ b/documentation/dev-portal/src/integrations/integration-options.md @@ -3,7 +3,7 @@ If you've already gone through the different [Quick Start](../quickstart/overvie This section assumes you wish to integrate with Nym into your application code. -The [integrations FAQ](./faq.md) has a list of common questions regarding integrating with Nym and Nyx, as well as commonly required links. _This is a good place to start to get an overall idea of the tools and software avaliable to you_. +The [integrations FAQ](../faq/integrations-faq.md) has a list of common questions regarding integrating with Nym and Nyx, as well as commonly required links. _This is a good place to start to get an overall idea of the tools and software avaliable to you_. If you wish to integrate with Nym to use the mixnet for application traffic, start with the [mixnet integration](./mixnet-integration.md) page. diff --git a/documentation/dev-portal/src/integrations/payment-integration.md b/documentation/dev-portal/src/integrations/payment-integration.md index 26e40bca6f..937702a3bd 100644 --- a/documentation/dev-portal/src/integrations/payment-integration.md +++ b/documentation/dev-portal/src/integrations/payment-integration.md @@ -5,7 +5,7 @@ If you want to integrate with Nym in order to send `NYM` tokens (for instance, i Nyx is the blockchain supporting the Nym network, hosting both the `NYM` and `NYX` cryptocurrencies, the CosmWasm smart contracts keeping track of the network, and (coming soon) facilitating zk-Nym credential generation. It is built with the [Cosmos SDK](https://tendermint.com/sdk/). ### Interacting with the Nyx blockchain -Check out the integration options in the [Integration FAQ](./faq.md#how-can-i-use-json-rpc-methods-to-interact-with-the-nyx-blockchain). +Check out the integration options in the [Integration FAQ](../faq/integrations-faq.md#how-can-i-use-json-rpc-methods-to-interact-with-the-nyx-blockchain). ### Chain information and RPC endpoints You can find most information required for integration in the [Cosmos Chain Registry](https://github.com/cosmos/chain-registry/blob/master/nyx/chain.json) and [Keplr Chain Registry](https://github.com/chainapsis/keplr-chain-registry/blob/main/cosmos/nyx.json) repositories. diff --git a/documentation/dev-portal/src/tutorials/cosmos-service/lib.md b/documentation/dev-portal/src/tutorials/cosmos-service/lib.md index 77236ea11e..9982403657 100644 --- a/documentation/dev-portal/src/tutorials/cosmos-service/lib.md +++ b/documentation/dev-portal/src/tutorials/cosmos-service/lib.md @@ -100,7 +100,6 @@ pub async fn create_client(config_path: PathBuf) -> MixnetClient { .await .unwrap() .build() - .await .unwrap(); client.connect_to_mixnet().await.unwrap() diff --git a/documentation/docs/src/sdk/rust.md b/documentation/docs/src/sdk/rust.md index bb89a7dbc1..b62353a9d6 100644 --- a/documentation/docs/src/sdk/rust.md +++ b/documentation/docs/src/sdk/rust.md @@ -82,10 +82,11 @@ If you're integrating mixnet functionality into an existing app and want to inte ### Anonymous replies with SURBs Both functions used to send messages through the mixnet (`send_message` and `send_plain_message`) send a pre-determined number of SURBs along with their messages by default. -The number of SURBs is set [here](https://github.com/nymtech/nym/blob/master/sdk/rust/nym-sdk/src/mixnet/client.rs#L33): +The number of SURBs is set [here](https://github.com/nymtech/nym/blob/master/sdk/rust/nym-sdk/src/mixnet/client.rs#L33). + ```rust,noplayground -{{#include ../../../../sdk/rust/nym-sdk/src/mixnet/client.rs:34}} +{{#include ../../../../sdk/rust/nym-sdk/src/mixnet/client.rs:33}} ``` You can read more about how SURBs function under the hood [here](../architecture/traffic-flow.md#private-replies-using-surbs). diff --git a/documentation/docs/src/sdk/typescript.md b/documentation/docs/src/sdk/typescript.md index 49bc816738..1e03c74677 100644 --- a/documentation/docs/src/sdk/typescript.md +++ b/documentation/docs/src/sdk/typescript.md @@ -47,7 +47,7 @@ There are multiple example projects in [`nym/sdk/typescript/examples/`](https:// The best place to start if you just want to quickly get a basic frontend up and running with which to experiment is `examples/plain-html`: ```typescript -{{#include ../../../../sdk/typescript/examples/chat-app/plain-html/src/index.ts}} +{{#include ../../../../sdk/typescript/examples/shared/index.ts}} ``` As you can see, all that is required to create an ephemeral keypair and connect to the mixnet is creating a client and then subscribing to the mixnet events coming down the websocket, and adding logic to deal with them. diff --git a/documentation/operators/src/faq/smoosh-faq.md b/documentation/operators/src/faq/smoosh-faq.md index ca413cd4e3..5284b901a0 100644 --- a/documentation/operators/src/faq/smoosh-faq.md +++ b/documentation/operators/src/faq/smoosh-faq.md @@ -1,9 +1,10 @@ # Project Smoosh - FAQ > We aim on purpose to make minimal changes to reward scheme and software. We're just 'smooshing' together stuff we already debugged and know works. -> -- Harry Halpin, Nym CEO +> -- Harry Halpin, Nym CEO +

This page refer to the changes which are planned to take place over Q3 and Q4 2023. As this is a transition period in the beginning (Q3 2023) the [Mix Nodes FAQ page](./mixnodes-faq.md) holds more answers to the current setup as project Smoosh refers to the eventual setup. As project Smoosh gets progressively implemented the answers on this page will become to be more relevant to the current state and eventually this FAQ page will be merged with the still relevant parts of the main Mix Nodes FAQ page. - +

If any questions are not answered or it's not clear for you in which stage project Smoosh is right now, please reach out in Node Operators [Matrix room](https://matrix.to/#/#operators:nymtech.chat). ## Overview @@ -33,7 +34,7 @@ The operators running `gateways` would have to “open” their nodes to a wider ### Can I run a mix node only? -Yes, to run a mix node only is an option. However it will be less rewarded as nodes providing option for `gateway` - meaning the *new smooshed gateway* (previously `gateway` and `network requester`)- due to the work and risk the operators have in comparison to running a `mixnode` only. +Yes, to run a mix node only is an option. However it will be less rewarded as nodes providing option for `gateway` - meaning the *new smooshed gateway* (previously `gateway` and `network requester`) - due to the work and risk the operators have in comparison to running a `mixnode` only. ## Token Economics & Rewards diff --git a/documentation/post_process.sh b/documentation/post_process.sh index bbc866a66b..b9abb4f9bb 100755 --- a/documentation/post_process.sh +++ b/documentation/post_process.sh @@ -1,4 +1,9 @@ -#!/bin/bash +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + # this is a script called by the github CI and CD workflows to post process CSS/image/href links for serving # several mdbooks from a subdirectory diff --git a/explorer-api/Cargo.toml b/explorer-api/Cargo.toml index 79323fe3fe..ffb2138321 100644 --- a/explorer-api/Cargo.toml +++ b/explorer-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "explorer-api" -version = "1.1.29" +version = "1.1.30" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/explorer/src/pages/MixnodeDetail/index.tsx b/explorer/src/pages/MixnodeDetail/index.tsx index 288c1bd8c0..5ceaa36867 100644 --- a/explorer/src/pages/MixnodeDetail/index.tsx +++ b/explorer/src/pages/MixnodeDetail/index.tsx @@ -36,7 +36,7 @@ const columns: ColumnsType[] = [ title: 'Stake Saturation', width: '12.5%', tooltipInfo: - 'Level of stake saturation for this node. Nodes receive more rewards the higher their saturation level, up to 100%. Beyond 100% no additional rewards are granted. The current stake saturation level is 730k NYM, computed as S/K where S is target amount of tokens staked in the network and K is the number of nodes in the reward set.', + 'Level of stake saturation for this node. Nodes receive more rewards the higher their saturation level, up to 100%. Beyond 100% no additional rewards are granted. The current stake saturation level is 940k NYMs, computed as S/K where S is target amount of tokens staked in the network and K is the number of nodes in the reward set.', }, { field: 'self_percentage', diff --git a/explorer/src/pages/Mixnodes/index.tsx b/explorer/src/pages/Mixnodes/index.tsx index d42b99efef..afd6bdd234 100644 --- a/explorer/src/pages/Mixnodes/index.tsx +++ b/explorer/src/pages/Mixnodes/index.tsx @@ -153,7 +153,7 @@ export const PageMixnodes: FCWithChildren = () => { renderHeader: () => ( ), headerClassName: 'MuiDataGrid-header-override', diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml index d54d8e1ee7..1dd1531099 100644 --- a/gateway/Cargo.toml +++ b/gateway/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-gateway" -version = "1.1.29" +version = "1.1.30" authors = [ "Dave Hrycyszyn ", "Jędrzej Stuczyński ", @@ -15,14 +15,14 @@ rust-version = "1.56" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -anyhow = "1.0.53" +anyhow = { workspace = true } async-trait = { workspace = true } atty = "0.2" bip39 = { workspace = true } bs58 = "0.4.0" clap = { version = "4.0", features = ["cargo", "derive"] } colored = "2.0" -dashmap = "4.0" +dashmap = { workspace = true } dirs = "4.0" dotenvy = { workspace = true } futures = { workspace = true } @@ -55,12 +55,14 @@ nym-gateway-requests = { path = "gateway-requests" } nym-mixnet-client = { path = "../common/client-libs/mixnet-client" } nym-mixnode-common = { path = "../common/mixnode-common" } nym-network-defaults = { path = "../common/network-defaults" } +nym-network-requester = { path = "../service-providers/network-requester" } nym-pemstore = { path = "../common/pemstore" } nym-sphinx = { path = "../common/nymsphinx" } nym-statistics-common = { path = "../common/statistics" } nym-task = { path = "../common/task" } nym-types = { path = "../common/types" } nym-validator-client = { path = "../common/client-libs/validator-client" } +nym-wireguard = { path = "../common/wireguard" } [build-dependencies] tokio = { version = "1.24.1", features = ["rt-multi-thread", "macros"] } @@ -70,3 +72,6 @@ sqlx = { version = "0.5", features = [ "macros", "migrate", ] } + +[features] +wireguard = [] diff --git a/gateway/src/commands/helpers.rs b/gateway/src/commands/helpers.rs new file mode 100644 index 0000000000..f8b9e326bd --- /dev/null +++ b/gateway/src/commands/helpers.rs @@ -0,0 +1,282 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::commands::upgrade_helpers; +use crate::config::default_config_filepath; +use crate::config::persistence::paths::default_network_requester_data_dir; +use crate::config::Config; +use crate::error::GatewayError; +use log::{error, info}; +use nym_bin_common::version_checker; +use nym_config::{save_formatted_config_to_file, OptionalSet}; +use nym_crypto::asymmetric::identity; +use nym_network_defaults::mainnet; +use nym_network_defaults::var_names::NYXD; +use nym_network_defaults::var_names::{BECH32_PREFIX, NYM_API, STATISTICS_SERVICE_DOMAIN_ADDRESS}; +use nym_network_requester::config::BaseClientConfig; +use nym_network_requester::{ + setup_gateway, GatewaySelectionSpecification, GatewaySetup, OnDiskGatewayDetails, OnDiskKeys, +}; +use nym_types::gateway::GatewayNetworkRequesterDetails; +use nym_validator_client::nyxd::AccountId; +use std::net::IpAddr; +use std::path::PathBuf; + +// Configuration that can be overridden. +#[derive(Default)] +pub(crate) struct OverrideConfig { + pub(crate) host: Option, + pub(crate) mix_port: Option, + pub(crate) clients_port: Option, + pub(crate) datastore: Option, + pub(crate) enabled_statistics: Option, + pub(crate) statistics_service_url: Option, + pub(crate) nym_apis: Option>, + pub(crate) mnemonic: Option, + pub(crate) nyxd_urls: Option>, + pub(crate) only_coconut_credentials: Option, + pub(crate) with_network_requester: Option, +} + +impl OverrideConfig { + pub(crate) fn do_override(self, mut config: Config) -> Result { + config = config + .with_optional(Config::with_listening_address, self.host) + .with_optional(Config::with_mix_port, self.mix_port) + .with_optional(Config::with_clients_port, self.clients_port) + .with_optional_custom_env( + Config::with_custom_nym_apis, + self.nym_apis, + NYM_API, + nym_config::parse_urls, + ) + .with_optional(Config::with_enabled_statistics, self.enabled_statistics) + .with_optional_env( + Config::with_custom_statistics_service_url, + self.statistics_service_url, + STATISTICS_SERVICE_DOMAIN_ADDRESS, + ) + .with_optional(Config::with_custom_persistent_store, self.datastore) + .with_optional(Config::with_cosmos_mnemonic, self.mnemonic) + .with_optional_custom_env( + Config::with_custom_validator_nyxd, + self.nyxd_urls, + NYXD, + nym_config::parse_urls, + ) + .with_optional( + Config::with_only_coconut_credentials, + self.only_coconut_credentials, + ) + .with_optional( + Config::with_enabled_network_requester, + self.with_network_requester, + ); + + if config.network_requester.enabled + && config.storage_paths.network_requester_config.is_none() + { + Ok(config.with_default_network_requester_config_path()) + } else { + Ok(config) + } + } +} + +#[derive(Default)] +pub(crate) struct OverrideNetworkRequesterConfig { + pub(crate) fastmode: bool, + pub(crate) no_cover: bool, + pub(crate) medium_toggle: bool, + + pub(crate) open_proxy: Option, + pub(crate) enable_statistics: Option, + pub(crate) statistics_recipient: Option, +} + +/// Ensures that a given bech32 address is valid +pub(crate) fn ensure_correct_bech32_prefix(address: &AccountId) -> Result<(), GatewayError> { + let expected_prefix = + std::env::var(BECH32_PREFIX).unwrap_or(mainnet::BECH32_PREFIX.to_string()); + let actual_prefix = address.prefix(); + + if expected_prefix != actual_prefix { + return Err(GatewayError::InvalidBech32AccountPrefix { + account: address.to_owned(), + expected_prefix, + actual_prefix: actual_prefix.to_owned(), + }); + } + + Ok(()) +} + +// this only checks compatibility between config the binary. It does not take into consideration +// network version. It might do so in the future. +pub(crate) fn ensure_config_version_compatibility(cfg: &Config) -> Result<(), GatewayError> { + let binary_version = env!("CARGO_PKG_VERSION"); + let config_version = &cfg.gateway.version; + + if binary_version == config_version { + Ok(()) + } else if version_checker::is_minor_version_compatible(binary_version, config_version) { + log::warn!( + "The gateway binary has different version than what is specified in config file! {binary_version} and {config_version}. \ + But, they are still semver compatible. However, consider running the `upgrade` command."); + Ok(()) + } else { + log::error!( + "The gateway binary has different version than what is specified in config file! {binary_version} and {config_version}. \ + And they are semver incompatible! - please run the `upgrade` command before attempting `run` again"); + Err(GatewayError::LocalVersionCheckFailure { + binary_version: binary_version.to_owned(), + config_version: config_version.to_owned(), + }) + } +} + +pub(crate) fn try_load_current_config(id: &str) -> Result { + upgrade_helpers::try_upgrade_config(id)?; + + Config::read_from_default_path(id).map_err(|err| { + error!( + "Failed to load config for {id}. Are you sure you have run `init` before? (Error was: {err})", + ); + GatewayError::ConfigLoadFailure { + path: default_config_filepath(id), + id: id.to_string(), + source: err, + } + }) +} + +fn make_nr_id(gateway_id: &str) -> String { + format!("{gateway_id}-network-requester") +} + +// NOTE: make sure this is in sync with service-providers/network-requester/src/cli/mod.rs::override_config +pub(crate) fn override_network_requester_config( + mut cfg: nym_network_requester::Config, + opts: Option, +) -> nym_network_requester::Config { + let Some(opts) = opts else { return cfg }; + + // as of 12.09.23 the below is true (not sure how this comment will rot in the future) + // medium_toggle: + // - sets secondary packet size to 16kb + // - disables poisson distribution of the main traffic stream + // - sets the cover traffic stream to 1 packet / 5s (on average) + // - disables per hop delay + // + // fastmode (to be renamed to `fast-poisson`): + // - sets average per hop delay to 10ms + // - sets the cover traffic stream to 1 packet / 2000s (on average); for all intents and purposes it disables the stream + // - sets the poisson distribution of the main traffic stream to 4ms, i.e. 250 packets / s on average + // + // no_cover: + // - disables poisson distribution of the main traffic stream + // - disables the secondary cover traffic stream + + // disable poisson rate in the BASE client if the NR option is enabled + if cfg.network_requester.disable_poisson_rate { + cfg.set_no_poisson_process(); + } + + // those should be enforced by `clap` when parsing the arguments + if opts.medium_toggle { + assert!(!opts.fastmode); + assert!(!opts.no_cover); + + cfg.set_medium_toggle(); + } + + cfg.with_base( + BaseClientConfig::with_high_default_traffic_volume, + opts.fastmode, + ) + .with_base(BaseClientConfig::with_disabled_cover_traffic, opts.no_cover) + .with_optional( + nym_network_requester::Config::with_open_proxy, + opts.open_proxy, + ) + .with_optional( + nym_network_requester::Config::with_enabled_statistics, + opts.enable_statistics, + ) + .with_optional( + nym_network_requester::Config::with_statistics_recipient, + opts.statistics_recipient, + ) +} + +pub(crate) async fn initialise_local_network_requester( + gateway_config: &Config, + opts: OverrideNetworkRequesterConfig, + identity: identity::PublicKey, +) -> Result { + info!("initialising network requester..."); + let Some(nr_cfg_path) = gateway_config.storage_paths.network_requester_config() else { + return Err(GatewayError::UnspecifiedNetworkRequesterConfig); + }; + + let id = &gateway_config.gateway.id; + let nr_id = make_nr_id(id); + let nr_data_dir = default_network_requester_data_dir(id); + let mut nr_cfg = nym_network_requester::Config::new(&nr_id).with_data_directory(nr_data_dir); + nr_cfg = override_network_requester_config(nr_cfg, Some(opts)); + + let key_store = OnDiskKeys::new(nr_cfg.storage_paths.common_paths.keys.clone()); + let details_store = + OnDiskGatewayDetails::new(&nr_cfg.storage_paths.common_paths.gateway_details); + + // gateway setup here is way simpler as we're 'connecting' to ourselves + let init_res = setup_gateway( + GatewaySetup::New { + specification: GatewaySelectionSpecification::Custom { + gateway_identity: identity.to_base58_string(), + additional_data: Default::default(), + }, + available_gateways: vec![], + overwrite_data: false, + }, + &key_store, + &details_store, + ) + .await?; + + let address = init_res.client_address()?; + + if let Err(err) = save_formatted_config_to_file(&nr_cfg, nr_cfg_path) { + log::error!("Failed to save the network requester config file: {err}"); + return Err(GatewayError::ConfigSaveFailure { + id: nr_id, + path: nr_cfg_path.to_path_buf(), + source: err, + }); + } else { + eprintln!( + "Saved network requester configuration file to {}", + nr_cfg_path.display() + ) + } + + Ok(GatewayNetworkRequesterDetails { + enabled: gateway_config.network_requester.enabled, + identity_key: address.identity().to_string(), + encryption_key: address.encryption_key().to_string(), + open_proxy: nr_cfg.network_requester.open_proxy, + enabled_statistics: nr_cfg.network_requester.enabled_statistics, + address: address.to_string(), + config_path: nr_cfg_path.display().to_string(), + allow_list_path: nr_cfg + .storage_paths + .allowed_list_location + .display() + .to_string(), + unknown_list_path: nr_cfg + .storage_paths + .unknown_list_location + .display() + .to_string(), + }) +} diff --git a/gateway/src/commands/init.rs b/gateway/src/commands/init.rs index 2901e116ef..c5123703ab 100644 --- a/gateway/src/commands/init.rs +++ b/gateway/src/commands/init.rs @@ -1,15 +1,15 @@ // Copyright 2020-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::config::{default_config_directory, default_config_filepath, default_data_directory}; -use crate::{ - commands::{override_config, OverrideConfig}, - config::Config, - OutputFormat, +use crate::commands::helpers::{ + initialise_local_network_requester, OverrideNetworkRequesterConfig, }; +use crate::config::{default_config_directory, default_config_filepath, default_data_directory}; +use crate::node::helpers::node_details; +use crate::{commands::helpers::OverrideConfig, config::Config, OutputFormat}; +use anyhow::bail; use clap::Args; use nym_crypto::asymmetric::{encryption, identity}; -use std::error::Error; use std::net::IpAddr; use std::path::PathBuf; use std::{fs, io}; @@ -17,32 +17,32 @@ use std::{fs, io}; #[derive(Args, Clone)] pub struct Init { /// Id of the gateway we want to create config for - #[clap(long)] + #[arg(long)] id: String, /// The custom host on which the gateway will be running for receiving sphinx packets - #[clap(long)] + #[arg(long)] host: IpAddr, /// The port on which the gateway will be listening for sphinx packets - #[clap(long)] + #[arg(long)] mix_port: Option, /// The port on which the gateway will be listening for clients gateway-requests - #[clap(long)] + #[arg(long)] clients_port: Option, /// Path to sqlite database containing all gateway persistent data - #[clap(long)] + #[arg(long)] datastore: Option, /// Comma separated list of endpoints of nym APIs - #[clap(long, alias = "validator_apis", value_delimiter = ',')] + #[arg(long, alias = "validator_apis", value_delimiter = ',')] // the alias here is included for backwards compatibility (1.1.4 and before) nym_apis: Option>, /// Comma separated list of endpoints of the validator - #[clap( + #[arg( long, alias = "validators", alias = "nyxd_validators", @@ -53,23 +53,71 @@ pub struct Init { nyxd_urls: Option>, /// Cosmos wallet mnemonic needed for double spending protection - #[clap(long)] + #[arg(long)] mnemonic: Option, /// Set this gateway to work only with coconut credentials; that would disallow clients to /// bypass bandwidth credential requirement - #[clap(long, hide = true)] + #[arg(long, hide = true)] only_coconut_credentials: Option, /// Enable/disable gateway anonymized statistics that get sent to a statistics aggregator server - #[clap(long)] + #[arg(long)] enabled_statistics: Option, /// URL where a statistics aggregator is running. The default value is a Nym aggregator server - #[clap(long)] + #[arg(long)] statistics_service_url: Option, - #[clap(short, long, default_value_t = OutputFormat::default())] + /// Allows this gateway to run an embedded network requester for minimal network overhead + #[arg(long)] + with_network_requester: bool, + + // ##### NETWORK REQUESTER FLAGS ##### + /// Specifies whether this network requester should run in 'open-proxy' mode + #[arg(long, requires = "with_network_requester")] + open_proxy: Option, + + /// Enable service anonymized statistics that get sent to a statistics aggregator server + #[arg(long, requires = "with_network_requester")] + enable_statistics: Option, + + /// Mixnet client address where a statistics aggregator is running. The default value is a Nym + /// aggregator client + #[arg(long, requires = "with_network_requester")] + statistics_recipient: Option, + + /// Mostly debug-related option to increase default traffic rate so that you would not need to + /// modify config post init + #[arg( + long, + hide = true, + conflicts_with = "medium_toggle", + requires = "with_network_requester" + )] + fastmode: bool, + + /// Disable loop cover traffic and the Poisson rate limiter (for debugging only) + #[arg( + long, + hide = true, + conflicts_with = "medium_toggle", + requires = "with_network_requester" + )] + no_cover: bool, + + /// Enable medium mixnet traffic, for experiments only. + /// This includes things like disabling cover traffic, no per hop delays, etc. + #[arg( + long, + hide = true, + conflicts_with = "no_cover", + conflicts_with = "fastmode", + requires = "with_network_requester" + )] + medium_toggle: bool, + + #[arg(short, long, default_value_t = OutputFormat::default())] output: OutputFormat, } @@ -88,6 +136,20 @@ impl From for OverrideConfig { nyxd_urls: init_config.nyxd_urls, only_coconut_credentials: init_config.only_coconut_credentials, + with_network_requester: Some(init_config.with_network_requester), + } + } +} + +impl<'a> From<&'a Init> for OverrideNetworkRequesterConfig { + fn from(value: &'a Init) -> Self { + OverrideNetworkRequesterConfig { + fastmode: value.fastmode, + no_cover: value.no_cover, + medium_toggle: value.medium_toggle, + open_proxy: value.open_proxy, + enable_statistics: value.enable_statistics, + statistics_recipient: value.statistics_recipient.clone(), } } } @@ -97,8 +159,9 @@ fn init_paths(id: &str) -> io::Result<()> { fs::create_dir_all(default_config_directory(id)) } -pub async fn execute(args: Init) -> Result<(), Box> { +pub async fn execute(args: Init) -> anyhow::Result<()> { eprintln!("Initialising gateway {}...", args.id); + let output = args.output; let already_init = if default_config_filepath(&args.id).exists() { eprintln!( @@ -112,52 +175,60 @@ pub async fn execute(args: Init) -> Result<(), Box> { false }; - let override_config_fields = OverrideConfig::from(args.clone()); - // Initialising the config structure is just overriding a default constructed one - let config = override_config(Config::new(&args.id), override_config_fields)?; + let fresh_config = Config::new(&args.id); + let nr_opts = (&args).into(); + let mut config = OverrideConfig::from(args).do_override(fresh_config)?; - // if gateway was already initialised, don't generate new keys + // if gateway was already initialised, don't generate new keys, et al. if !already_init { let mut rng = rand::rngs::OsRng; let identity_keys = identity::KeyPair::new(&mut rng); let sphinx_keys = encryption::KeyPair::new(&mut rng); - nym_pemstore::store_keypair( + if let Err(err) = nym_pemstore::store_keypair( &identity_keys, &nym_pemstore::KeyPairPath::new( config.storage_paths.private_identity_key(), config.storage_paths.public_identity_key(), ), - ) - .expect("Failed to save identity keys"); + ) { + bail!("failed to save the identity keys: {err}") + } - nym_pemstore::store_keypair( + if let Err(err) = nym_pemstore::store_keypair( &sphinx_keys, &nym_pemstore::KeyPairPath::new( config.storage_paths.private_encryption_key(), config.storage_paths.public_encryption_key(), ), - ) - .expect("Failed to save sphinx keys"); + ) { + bail!("failed to save the sphinx keys: {err}") + } + + if config.network_requester.enabled { + initialise_local_network_requester(&config, nr_opts, *identity_keys.public_key()) + .await?; + } eprintln!("Saved identity and mixnet sphinx keypairs"); } let config_save_location = config.default_location(); - config - .save_to_default_location() - .expect("Failed to save the config file"); + if let Err(err) = config.save_to_default_location() { + bail!("failed to save the config file: {err}") + } + config.save_path = Some(config_save_location.clone()); + eprintln!( "Saved configuration file to {}", config_save_location.display() ); eprintln!("Gateway configuration completed.\n\n\n"); - crate::node::create_gateway(config) - .await - .print_node_details(args.output); + output.to_stdout(&node_details(&config)?); + Ok(()) } @@ -184,11 +255,20 @@ mod tests { nyxd_urls: None, only_coconut_credentials: None, output: Default::default(), + with_network_requester: false, + open_proxy: None, + enable_statistics: None, + statistics_recipient: None, + fastmode: false, + no_cover: false, + medium_toggle: false, }; std::env::set_var(BECH32_PREFIX, "n"); - let config = Config::new(&args.id); - let config = override_config(config, OverrideConfig::from(args.clone())).unwrap(); + let fresh_config = Config::new(&args.id); + let config = OverrideConfig::from(args) + .do_override(fresh_config) + .unwrap(); let (identity_keys, sphinx_keys) = { let mut rng = rand::rngs::OsRng; @@ -199,8 +279,13 @@ mod tests { }; // The test is really if this instantiates with InMemStorage without panics - let _gateway = - Gateway::new_from_keys_and_storage(config, identity_keys, sphinx_keys, InMemStorage) - .await; + let _gateway = Gateway::new_from_keys_and_storage( + config, + None, + identity_keys, + sphinx_keys, + InMemStorage, + ) + .await; } } diff --git a/gateway/src/commands/mod.rs b/gateway/src/commands/mod.rs index ed70c8b203..0df249edb1 100644 --- a/gateway/src/commands/mod.rs +++ b/gateway/src/commands/mod.rs @@ -1,28 +1,20 @@ // Copyright 2020-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::config::default_config_filepath; -use crate::config::old_config_v1_1_20::ConfigV1_1_20; -use crate::error::GatewayError; -use crate::{config::Config, Cli}; +use crate::Cli; use clap::CommandFactory; use clap::Subcommand; -use log::{error, info}; use nym_bin_common::completions::{fig_generate, ArgShell}; -use nym_bin_common::version_checker; -use nym_config::OptionalSet; -use nym_network_defaults::var_names::NYXD; -use nym_network_defaults::var_names::{BECH32_PREFIX, NYM_API, STATISTICS_SERVICE_DOMAIN_ADDRESS}; -use nym_validator_client::nyxd::AccountId; use std::error::Error; -use std::net::IpAddr; -use std::path::PathBuf; pub(crate) mod build_info; +pub(crate) mod helpers; pub(crate) mod init; pub(crate) mod node_details; pub(crate) mod run; +pub(crate) mod setup_network_requester; pub(crate) mod sign; +mod upgrade_helpers; #[derive(Subcommand)] pub(crate) enum Commands { @@ -35,6 +27,10 @@ pub(crate) enum Commands { /// Starts the gateway Run(run::Run), + /// Add network requester support to this gateway + // essentially an option to include NR without having to setup fresh gateway + SetupNetworkRequester(setup_network_requester::CmdArgs), + /// Sign text to prove ownership of this mixnode Sign(sign::Sign), @@ -48,21 +44,6 @@ pub(crate) enum Commands { GenerateFigSpec, } -// Configuration that can be overridden. -#[derive(Default)] -pub(crate) struct OverrideConfig { - host: Option, - mix_port: Option, - clients_port: Option, - datastore: Option, - enabled_statistics: Option, - statistics_service_url: Option, - nym_apis: Option>, - mnemonic: Option, - nyxd_urls: Option>, - only_coconut_credentials: Option, -} - pub(crate) async fn execute(args: Cli) -> Result<(), Box> { let bin_name = "nym-gateway"; @@ -70,6 +51,7 @@ pub(crate) async fn execute(args: Cli) -> Result<(), Box init::execute(m).await?, Commands::NodeDetails(m) => node_details::execute(m).await?, Commands::Run(m) => run::execute(m).await?, + Commands::SetupNetworkRequester(m) => setup_network_requester::execute(m).await?, Commands::Sign(m) => sign::execute(m)?, Commands::BuildInfo(m) => build_info::execute(m), Commands::Completions(s) => s.generate(&mut crate::Cli::command(), bin_name), @@ -78,118 +60,6 @@ pub(crate) async fn execute(args: Cli) -> Result<(), Box Result { - config = config - .with_optional(Config::with_listening_address, args.host) - .with_optional(Config::with_mix_port, args.mix_port) - .with_optional(Config::with_clients_port, args.clients_port) - .with_optional_custom_env( - Config::with_custom_nym_apis, - args.nym_apis, - NYM_API, - nym_config::parse_urls, - ) - .with_optional(Config::with_enabled_statistics, args.enabled_statistics) - .with_optional_env( - Config::with_custom_statistics_service_url, - args.statistics_service_url, - STATISTICS_SERVICE_DOMAIN_ADDRESS, - ) - .with_optional(Config::with_custom_persistent_store, args.datastore) - .with_optional(Config::with_cosmos_mnemonic, args.mnemonic) - .with_optional_custom_env( - Config::with_custom_validator_nyxd, - args.nyxd_urls, - NYXD, - nym_config::parse_urls, - ) - .with_optional( - Config::with_only_coconut_credentials, - args.only_coconut_credentials, - ); - - Ok(config) -} - -/// Ensures that a given bech32 address is valid -pub(crate) fn ensure_correct_bech32_prefix(address: &AccountId) -> Result<(), GatewayError> { - let expected_prefix = std::env::var(BECH32_PREFIX).expect("bech32 prefix not set"); - let actual_prefix = address.prefix(); - if expected_prefix != actual_prefix { - return Err(GatewayError::InvalidBech32AccountPrefix { - account: address.to_owned(), - expected_prefix, - actual_prefix: actual_prefix.to_owned(), - }); - } - - Ok(()) -} - -// this only checks compatibility between config the binary. It does not take into consideration -// network version. It might do so in the future. -pub(crate) fn ensure_config_version_compatibility(cfg: &Config) -> Result<(), GatewayError> { - let binary_version = env!("CARGO_PKG_VERSION"); - let config_version = &cfg.gateway.version; - - if binary_version == config_version { - Ok(()) - } else if version_checker::is_minor_version_compatible(binary_version, config_version) { - log::warn!( - "The gateway binary has different version than what is specified in config file! {binary_version} and {config_version}. \ - But, they are still semver compatible. However, consider running the `upgrade` command."); - Ok(()) - } else { - log::error!( - "The gateway binary has different version than what is specified in config file! {binary_version} and {config_version}. \ - And they are semver incompatible! - please run the `upgrade` command before attempting `run` again"); - Err(GatewayError::LocalVersionCheckFailure { - binary_version: binary_version.to_owned(), - config_version: config_version.to_owned(), - }) - } -} - -fn try_upgrade_v1_1_20_config(id: &str) -> Result<(), GatewayError> { - use nym_config::legacy_helpers::nym_config::MigrationNymConfig; - - // explicitly load it as v1.1.20 (which is incompatible with the current, i.e. 1.1.21+) - let Ok(old_config) = ConfigV1_1_20::load_from_file(id) else { - // if we failed to load it, there might have been nothing to upgrade - // or maybe it was an even older file. in either way. just ignore it and carry on with our day - return Ok(()); - }; - info!("It seems the gateway is using <= v1.1.20 config template."); - info!("It is going to get updated to the current specification."); - - let updated: Config = old_config.into(); - updated - .save_to_default_location() - .map_err(|err| GatewayError::ConfigSaveFailure { - path: default_config_filepath(id), - id: id.to_string(), - source: err, - }) -} - -pub(crate) fn try_load_current_config(id: &str) -> Result { - try_upgrade_v1_1_20_config(id)?; - - Config::read_from_default_path(id).map_err(|err| { - error!( - "Failed to load config for {id}. Are you sure you have run `init` before? (Error was: {err})", - ); - GatewayError::ConfigLoadFailure { - path: default_config_filepath(id), - id: id.to_string(), - source: err, - } - }) -} - #[cfg(test)] mod tests { use super::*; diff --git a/gateway/src/commands/node_details.rs b/gateway/src/commands/node_details.rs index 11c855ace5..2d37617338 100644 --- a/gateway/src/commands/node_details.rs +++ b/gateway/src/commands/node_details.rs @@ -1,11 +1,10 @@ // Copyright 2021-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::commands::OverrideConfig; -use crate::support::config::build_config; +use crate::commands::helpers::try_load_current_config; +use crate::node::helpers::node_details; use clap::Args; use nym_bin_common::output_format::OutputFormat; -use std::error::Error; #[derive(Args, Clone)] pub struct NodeDetails { @@ -17,11 +16,9 @@ pub struct NodeDetails { output: OutputFormat, } -pub async fn execute(args: NodeDetails) -> Result<(), Box> { - let config = build_config(args.id.clone(), OverrideConfig::default())?; +pub async fn execute(args: NodeDetails) -> anyhow::Result<()> { + let config = try_load_current_config(&args.id)?; + args.output.to_stdout(&node_details(&config)?); - crate::node::create_gateway(config) - .await - .print_node_details(args.output); Ok(()) } diff --git a/gateway/src/commands/run.rs b/gateway/src/commands/run.rs index d60e66c7b5..6dd01e90bc 100644 --- a/gateway/src/commands/run.rs +++ b/gateway/src/commands/run.rs @@ -1,12 +1,14 @@ // Copyright 2020-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::commands::{ensure_config_version_compatibility, OverrideConfig}; +use crate::commands::helpers::{ + ensure_config_version_compatibility, OverrideConfig, OverrideNetworkRequesterConfig, +}; +use crate::node::helpers::node_details; use crate::support::config::build_config; use clap::Args; use nym_bin_common::output_format::OutputFormat; use nym_config::helpers::SPECIAL_ADDRESSES; -use std::error::Error; use std::net::IpAddr; use std::path::PathBuf; @@ -33,7 +35,12 @@ pub struct Run { datastore: Option, /// Comma separated list of endpoints of nym APIs - #[clap(long, alias = "validator_apis", value_delimiter = ',')] + #[clap( + long, + alias = "validator_apis", + value_delimiter = ',', + group = "network" + )] // the alias here is included for backwards compatibility (1.1.4 and before) nym_apis: Option>, @@ -65,6 +72,48 @@ pub struct Run { #[clap(long)] statistics_service_url: Option, + /// Allows this gateway to run an embedded network requester for minimal network overhead + #[clap(long)] + with_network_requester: Option, + + // ##### NETWORK REQUESTER FLAGS ##### + /// Specifies whether this network requester should run in 'open-proxy' mode + #[arg(long)] + open_proxy: Option, + + /// Enable service anonymized statistics that get sent to a statistics aggregator server + #[arg(long)] + enable_statistics: Option, + + /// Mixnet client address where a statistics aggregator is running. The default value is a Nym + /// aggregator client + #[arg(long)] + statistics_recipient: Option, + + /// Mostly debug-related option to increase default traffic rate so that you would not need to + /// modify config post init + #[arg(long, hide = true, conflicts_with = "medium_toggle")] + fastmode: bool, + + /// Disable loop cover traffic and the Poisson rate limiter (for debugging only) + #[arg(long, hide = true, conflicts_with = "medium_toggle")] + no_cover: bool, + + /// Enable medium mixnet traffic, for experiments only. + /// This includes things like disabling cover traffic, no per hop delays, etc. + #[arg( + long, + hide = true, + conflicts_with = "no_cover", + conflicts_with = "fastmode" + )] + medium_toggle: bool, + + /// Path to .json file containing custom network specification. + /// Only usable when local network requester is enabled. + #[clap(long, group = "network", hide = true)] + custom_mixnet: Option, + #[clap(short, long, default_value_t = OutputFormat::default())] output: OutputFormat, } @@ -83,6 +132,20 @@ impl From for OverrideConfig { statistics_service_url: run_config.statistics_service_url, nyxd_urls: run_config.nyxd_urls, only_coconut_credentials: run_config.only_coconut_credentials, + with_network_requester: run_config.with_network_requester, + } + } +} + +impl<'a> From<&'a Run> for OverrideNetworkRequesterConfig { + fn from(value: &'a Run) -> Self { + OverrideNetworkRequesterConfig { + fastmode: value.fastmode, + no_cover: value.no_cover, + medium_toggle: value.medium_toggle, + open_proxy: value.open_proxy, + enable_statistics: value.enable_statistics, + statistics_recipient: value.statistics_recipient.clone(), } } } @@ -97,11 +160,14 @@ fn show_binding_warning(address: &str) { eprintln!("\n\n"); } -pub async fn execute(args: Run) -> Result<(), Box> { +pub async fn execute(args: Run) -> anyhow::Result<()> { let id = args.id.clone(); eprintln!("Starting gateway {id}..."); let output = args.output; + let custom_mixnet = args.custom_mixnet.clone(); + let nr_opts = (&args).into(); + let config = build_config(id, args)?; ensure_config_version_compatibility(&config)?; @@ -109,11 +175,12 @@ pub async fn execute(args: Run) -> Result<(), Box> { show_binding_warning(&config.gateway.listening_address.to_string()); } - let mut gateway = crate::node::create_gateway(config).await; + let node_details = node_details(&config)?; + let gateway = crate::node::create_gateway(config, Some(nr_opts), custom_mixnet).await?; eprintln!( "\nTo bond your gateway you will need to install the Nym wallet, go to https://nymtech.net/get-involved and select the Download button.\n\ Select the correct version and install it to your machine. You will need to provide the following: \n "); - gateway.print_node_details(output); + output.to_stdout(&node_details); gateway.run().await } diff --git a/gateway/src/commands/setup_network_requester.rs b/gateway/src/commands/setup_network_requester.rs new file mode 100644 index 0000000000..f59f37dbd5 --- /dev/null +++ b/gateway/src/commands/setup_network_requester.rs @@ -0,0 +1,109 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::commands::helpers::{ + initialise_local_network_requester, try_load_current_config, OverrideNetworkRequesterConfig, +}; +use crate::node::helpers::load_public_key; +use clap::Args; +use nym_bin_common::output_format::OutputFormat; +use std::path::PathBuf; + +#[derive(Args, Clone)] +pub struct CmdArgs { + /// The id of the gateway you want to initialise local network requester for. + #[arg(long)] + id: String, + + /// Path to custom location for network requester's config. + #[arg(long)] + custom_config_path: Option, + + /// Specify whether the network requester should be enabled. + // (you might want to create all the configs, generate keys, etc. but not actually run the NR just yet) + #[arg(long)] + enabled: Option, + + // note: those flags are set as bools as we want to explicitly override any settings values + // so say `open_proxy` was set to true in the config.toml. youd have to explicitly state `open-proxy=false` + // as an argument here to override it as opposed to not providing the value at all. + /// Specifies whether this network requester should run in 'open-proxy' mode + #[arg(long)] + open_proxy: Option, + + /// Enable service anonymized statistics that get sent to a statistics aggregator server + #[arg(long)] + enable_statistics: Option, + + /// Mixnet client address where a statistics aggregator is running. The default value is a Nym + /// aggregator client + #[arg(long)] + statistics_recipient: Option, + + /// Mostly debug-related option to increase default traffic rate so that you would not need to + /// modify config post init + #[arg(long, hide = true, conflicts_with = "medium_toggle")] + fastmode: bool, + + /// Disable loop cover traffic and the Poisson rate limiter (for debugging only) + #[arg(long, hide = true, conflicts_with = "medium_toggle")] + no_cover: bool, + + /// Enable medium mixnet traffic, for experiments only. + /// This includes things like disabling cover traffic, no per hop delays, etc. + #[arg( + long, + hide = true, + conflicts_with = "no_cover", + conflicts_with = "fastmode" + )] + medium_toggle: bool, + + #[clap(short, long, default_value_t = OutputFormat::default())] + output: OutputFormat, +} + +impl<'a> From<&'a CmdArgs> for OverrideNetworkRequesterConfig { + fn from(value: &'a CmdArgs) -> Self { + OverrideNetworkRequesterConfig { + fastmode: value.fastmode, + no_cover: value.no_cover, + medium_toggle: value.medium_toggle, + open_proxy: value.open_proxy, + enable_statistics: value.enable_statistics, + statistics_recipient: value.statistics_recipient.clone(), + } + } +} + +pub async fn execute(args: CmdArgs) -> anyhow::Result<()> { + let mut config = try_load_current_config(&args.id)?; + let opts = (&args).into(); + + // if somebody provided config file of a custom NR, that's fine + // but in 90% cases, I'd assume, it won't work due to invalid gateway configuration + // but it might be nice to be able to move files around. + if let Some(custom_config_path) = args.custom_config_path { + // if you specified anything as the argument, overwrite whatever was already in the config file + config.storage_paths.network_requester_config = Some(custom_config_path); + } + + if let Some(override_enabled) = args.enabled { + config.network_requester.enabled = override_enabled; + } + + if config.storage_paths.network_requester_config.is_none() { + config = config.with_default_network_requester_config_path() + } + + let identity_public_key = load_public_key( + &config.storage_paths.keys.public_identity_key_file, + "gateway identity", + )?; + let details = initialise_local_network_requester(&config, opts, identity_public_key).await?; + config.try_save()?; + + args.output.to_stdout(&details); + + Ok(()) +} diff --git a/gateway/src/commands/sign.rs b/gateway/src/commands/sign.rs index c8a7a1a728..ad8061e597 100644 --- a/gateway/src/commands/sign.rs +++ b/gateway/src/commands/sign.rs @@ -1,19 +1,18 @@ // Copyright 2020-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::commands::{ensure_correct_bech32_prefix, OverrideConfig}; +use crate::commands::helpers::{ + ensure_config_version_compatibility, ensure_correct_bech32_prefix, OverrideConfig, +}; use crate::error::GatewayError; +use crate::node::helpers::load_identity_keys; use crate::support::config::build_config; -use crate::{ - commands::ensure_config_version_compatibility, config::persistence::paths::GatewayPaths, -}; use anyhow::{bail, Result}; use clap::{ArgGroup, Args}; use nym_bin_common::output_format::OutputFormat; use nym_crypto::asymmetric::identity; use nym_types::helpers::ConsoleSigningOutput; use nym_validator_client::nyxd; -use std::error::Error; #[derive(Args, Clone)] #[clap(group(ArgGroup::new("sign").required(true).args(&["wallet_address", "text", "contract_msg"])))] @@ -64,16 +63,6 @@ impl TryFrom for SignedTarget { } } -pub fn load_identity_keys(paths: &GatewayPaths) -> identity::KeyPair { - let identity_keypair: identity::KeyPair = - nym_pemstore::load_keypair(&nym_pemstore::KeyPairPath::new( - paths.private_identity_key().to_owned(), - paths.public_identity_key().to_owned(), - )) - .expect("Failed to read stored identity key files"); - identity_keypair -} - fn print_signed_address( private_key: &identity::PrivateKey, wallet_address: nyxd::AccountId, @@ -90,14 +79,11 @@ fn print_signed_text( text: &str, output: OutputFormat, ) -> Result<(), GatewayError> { - eprintln!( - "Signing the text {:?} using your mixnode's Ed25519 identity key...", - text - ); + eprintln!("Signing the text {text:?} using your mixnode's Ed25519 identity key...",); let signature = private_key.sign_text(text); let sign_output = ConsoleSigningOutput::new(text, signature); - println!("{}", output.format(&sign_output)); + output.to_stdout(&sign_output); Ok(()) } @@ -125,6 +111,7 @@ fn print_signed_contract_msg( }; // if this is a valid json, it MUST be a valid string + #[allow(clippy::unwrap_used)] let decoded_string = String::from_utf8(decoded.clone()).unwrap(); let signature = private_key.sign(&decoded).to_base58_string(); @@ -132,14 +119,14 @@ fn print_signed_contract_msg( println!("{}", output.format(&sign_output)); } -pub fn execute(args: Sign) -> Result<(), Box> { +pub fn execute(args: Sign) -> anyhow::Result<()> { let config = build_config(args.id.clone(), OverrideConfig::default())?; ensure_config_version_compatibility(&config)?; let output = args.output; let signed_target = SignedTarget::try_from(args)?; - let identity_keypair = load_identity_keys(&config.storage_paths); + let identity_keypair = load_identity_keys(&config)?; match signed_target { SignedTarget::Text(text) => { diff --git a/gateway/src/commands/upgrade_helpers.rs b/gateway/src/commands/upgrade_helpers.rs new file mode 100644 index 0000000000..d8555ca215 --- /dev/null +++ b/gateway/src/commands/upgrade_helpers.rs @@ -0,0 +1,66 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::config::old_config_v1_1_20::ConfigV1_1_20; +use crate::config::old_config_v1_1_28::ConfigV1_1_28; +use crate::config::{default_config_filepath, Config}; +use crate::error::GatewayError; +use log::info; + +fn try_upgrade_v1_1_20_config(id: &str) -> Result { + use nym_config::legacy_helpers::nym_config::MigrationNymConfig; + + // explicitly load it as v1.1.20 (which is incompatible with the current, i.e. 1.1.21+) + let Ok(old_config) = ConfigV1_1_20::load_from_file(id) else { + // if we failed to load it, there might have been nothing to upgrade + // or maybe it was an even older file. in either way. just ignore it and carry on with our day + return Ok(false); + }; + info!("It seems the gateway is using <= v1.1.20 config template."); + info!("It is going to get updated to the current specification."); + + let updated_step1: ConfigV1_1_28 = old_config.into(); + let updated: Config = updated_step1.into(); + updated + .save_to_default_location() + .map_err(|err| GatewayError::ConfigSaveFailure { + path: default_config_filepath(id), + id: id.to_string(), + source: err, + })?; + + Ok(true) +} + +fn try_upgrade_v1_1_28_config(id: &str) -> Result { + // explicitly load it as v1.1.28 (which is incompatible with the current, i.e. 1.1.29+) + let Ok(old_config) = ConfigV1_1_28::read_from_default_path(id) else { + // if we failed to load it, there might have been nothing to upgrade + // or maybe it was an even older file. in either way. just ignore it and carry on with our day + return Ok(false); + }; + info!("It seems the gateway is using <= v1.1.28 config template."); + info!("It is going to get updated to the current specification."); + + let updated: Config = old_config.into(); + updated + .save_to_default_location() + .map_err(|err| GatewayError::ConfigSaveFailure { + path: default_config_filepath(id), + id: id.to_string(), + source: err, + })?; + + Ok(true) +} + +pub(crate) fn try_upgrade_config(id: &str) -> Result<(), GatewayError> { + if try_upgrade_v1_1_20_config(id)? { + return Ok(()); + } + if try_upgrade_v1_1_28_config(id)? { + return Ok(()); + } + + Ok(()) +} diff --git a/gateway/src/config/mod.rs b/gateway/src/config/mod.rs index 40dd27249e..23620953d6 100644 --- a/gateway/src/config/mod.rs +++ b/gateway/src/config/mod.rs @@ -3,6 +3,7 @@ use crate::config::persistence::paths::GatewayPaths; use crate::config::template::CONFIG_TEMPLATE; +use log::{debug, warn}; use nym_bin_common::logging::LoggingSettings; use nym_config::defaults::{DEFAULT_CLIENT_LISTENING_PORT, DEFAULT_MIX_LISTENING_PORT}; use nym_config::helpers::inaddr_any; @@ -20,6 +21,7 @@ use url::Url; use zeroize::{Zeroize, ZeroizeOnDrop}; pub(crate) mod old_config_v1_1_20; +pub(crate) mod old_config_v1_1_28; pub mod persistence; mod template; @@ -65,10 +67,16 @@ pub fn default_data_directory>(id: P) -> PathBuf { #[derive(Debug, Deserialize, PartialEq, Serialize)] #[serde(deny_unknown_fields)] pub struct Config { + // additional metadata holding on-disk location of this config file + #[serde(skip)] + pub(crate) save_path: Option, + pub gateway: Gateway, pub storage_paths: GatewayPaths, + pub network_requester: NetworkRequester, + #[serde(default)] pub logging: LoggingSettings, @@ -77,7 +85,7 @@ pub struct Config { } impl NymConfigTemplate for Config { - fn template() -> &'static str { + fn template(&self) -> &'static str { CONFIG_TEMPLATE } } @@ -85,19 +93,33 @@ impl NymConfigTemplate for Config { impl Config { pub fn new>(id: S) -> Self { Config { + save_path: None, gateway: Gateway::new_default(id.as_ref()), storage_paths: GatewayPaths::new_default(id.as_ref()), + network_requester: Default::default(), logging: Default::default(), debug: Default::default(), } } + // simple wrapper that reads config file and assigns path location + fn read_from_path>(path: P) -> io::Result { + let path = path.as_ref(); + let mut loaded: Config = read_config_from_toml_file(path)?; + loaded.save_path = Some(path.to_path_buf()); + debug!("loaded config file from {}", path.display()); + Ok(loaded) + } + + // currently this is dead code, but once we allow loading configs from custom paths + // well, we will have to be using it + #[allow(dead_code)] pub fn read_from_toml_file>(path: P) -> io::Result { - read_config_from_toml_file(path) + Self::read_from_path(path) } pub fn read_from_default_path>(id: P) -> io::Result { - Self::read_from_toml_file(default_config_filepath(id)) + Self::read_from_path(default_config_filepath(id)) } pub fn default_location(&self) -> PathBuf { @@ -109,6 +131,27 @@ impl Config { save_formatted_config_to_file(self, config_save_location) } + pub fn try_save(&self) -> io::Result<()> { + if let Some(save_location) = &self.save_path { + save_formatted_config_to_file(self, save_location) + } else { + warn!("config file save location is unknown. falling back to the default"); + self.save_to_default_location() + } + } + + pub fn with_enabled_network_requester(mut self, enabled_network_requester: bool) -> Self { + self.network_requester.enabled = enabled_network_requester; + self + } + + pub fn with_default_network_requester_config_path(mut self) -> Self { + self.storage_paths = self + .storage_paths + .with_default_network_requester_config(&self.gateway.id); + self + } + pub fn with_only_coconut_credentials(mut self, only_coconut_credentials: bool) -> Self { self.gateway.only_coconut_credentials = only_coconut_credentials; self @@ -227,6 +270,8 @@ pub struct Gateway { impl Gateway { pub fn new_default>(id: S) -> Self { + // allow usage of `expect` here as our default mainnet values should have been well-formed. + #[allow(clippy::expect_used)] Gateway { version: env!("CARGO_PKG_VERSION").to_string(), id: id.into(), @@ -240,11 +285,26 @@ impl Gateway { .expect("Invalid default statistics service URL"), nym_api_urls: vec![mainnet::NYM_API.parse().expect("Invalid default API URL")], nyxd_urls: vec![mainnet::NYXD_URL.parse().expect("Invalid default nyxd URL")], - cosmos_mnemonic: bip39::Mnemonic::generate(24).unwrap(), + cosmos_mnemonic: bip39::Mnemonic::generate(24) + .expect("failed to generate fresh mnemonic"), } } } +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(default)] +pub struct NetworkRequester { + /// Specifies whether network requester service is enabled in this process. + pub enabled: bool, +} + +#[allow(clippy::derivable_impls)] +impl Default for NetworkRequester { + fn default() -> Self { + NetworkRequester { enabled: false } + } +} + #[derive(Debug, Deserialize, PartialEq, Serialize)] #[serde(default)] pub struct Debug { diff --git a/gateway/src/config/old_config_v1_1_20.rs b/gateway/src/config/old_config_v1_1_20.rs index 594043b8a7..f7a83fc2c0 100644 --- a/gateway/src/config/old_config_v1_1_20.rs +++ b/gateway/src/config/old_config_v1_1_20.rs @@ -1,13 +1,14 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::config::persistence::paths::{GatewayPaths, KeysPaths}; -use crate::config::{Config, Debug, Gateway}; -use nym_bin_common::logging::LoggingSettings; +use crate::config::old_config_v1_1_28::{ + ConfigV1_1_28, DebugV1_1_28, GatewayPathsV1_1_28, GatewayV1_1_28, KeysPathsV1_1_28, + LoggingSettingsV1_1_28, +}; use nym_config::legacy_helpers::nym_config::MigrationNymConfig; use nym_validator_client::nyxd; use serde::{Deserialize, Serialize}; -use std::net::IpAddr; +use std::net::{IpAddr, Ipv4Addr}; use std::path::PathBuf; use std::str::FromStr; use std::time::Duration; @@ -28,8 +29,9 @@ const DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE: usize = 2000; const DEFAULT_STORED_MESSAGE_FILENAME_LENGTH: u16 = 16; const DEFAULT_MESSAGE_RETRIEVAL_LIMIT: i64 = 100; +/// returns a `0.0.0.0` / INADDR_ANY fn bind_all_address() -> IpAddr { - "0.0.0.0".parse().unwrap() + IpAddr::V4(Ipv4Addr::UNSPECIFIED) } #[derive(Debug, Default, Deserialize, PartialEq, Serialize)] @@ -42,10 +44,10 @@ pub struct ConfigV1_1_20 { debug: DebugV1_1_20, } -impl From for Config { +impl From for ConfigV1_1_28 { fn from(value: ConfigV1_1_20) -> Self { - Config { - gateway: Gateway { + ConfigV1_1_28 { + gateway: GatewayV1_1_28 { version: value.gateway.version, id: value.gateway.id, only_coconut_credentials: value.gateway.only_coconut_credentials, @@ -58,8 +60,8 @@ impl From for Config { statistics_service_url: value.gateway.statistics_service_url, cosmos_mnemonic: value.gateway.cosmos_mnemonic, }, - storage_paths: GatewayPaths { - keys: KeysPaths { + storage_paths: GatewayPathsV1_1_28 { + keys: KeysPathsV1_1_28 { private_identity_key_file: value.gateway.private_identity_key_file, public_identity_key_file: value.gateway.public_identity_key_file, private_sphinx_key_file: value.gateway.private_sphinx_key_file, @@ -75,6 +77,8 @@ impl From for Config { impl MigrationNymConfig for ConfigV1_1_20 { fn default_root_directory() -> PathBuf { + // unless this is run on some esoteric system, it should not fail thus the expect is fine + #[allow(clippy::expect_used)] dirs::home_dir() .expect("Failed to evaluate $HOME value") .join(".nym") @@ -112,6 +116,8 @@ pub struct GatewayV1_1_20 { impl Default for GatewayV1_1_20 { fn default() -> Self { + // allow usage of `expect` here as our default mainnet values should have been well-formed. + #[allow(clippy::expect_used)] GatewayV1_1_20 { version: env!("CARGO_PKG_VERSION").to_string(), id: "".to_string(), @@ -129,7 +135,8 @@ impl Default for GatewayV1_1_20 { .expect("Invalid default statistics service URL"), nym_api_urls: vec![Url::from_str(NYM_API).expect("Invalid default API URL")], nyxd_urls: vec![Url::from_str(NYXD_URL).expect("Invalid default nyxd URL")], - cosmos_mnemonic: bip39::Mnemonic::generate(24).unwrap(), + cosmos_mnemonic: bip39::Mnemonic::generate(24) + .expect("failed to generate fresh mnemonic"), nym_root_directory: ConfigV1_1_20::default_root_directory(), persistent_storage: Default::default(), wallet_address: None, @@ -141,9 +148,9 @@ impl Default for GatewayV1_1_20 { #[serde(deny_unknown_fields)] struct LoggingV1_1_20 {} -impl From for LoggingSettings { +impl From for LoggingSettingsV1_1_28 { fn from(_value: LoggingV1_1_20) -> Self { - LoggingSettings {} + LoggingSettingsV1_1_28 {} } } @@ -164,9 +171,9 @@ struct DebugV1_1_20 { use_legacy_framed_packet_version: bool, } -impl From for Debug { +impl From for DebugV1_1_28 { fn from(value: DebugV1_1_20) -> Self { - Debug { + DebugV1_1_28 { packet_forwarding_initial_backoff: value.packet_forwarding_initial_backoff, packet_forwarding_maximum_backoff: value.packet_forwarding_maximum_backoff, initial_connection_timeout: value.initial_connection_timeout, diff --git a/gateway/src/config/old_config_v1_1_28.rs b/gateway/src/config/old_config_v1_1_28.rs new file mode 100644 index 0000000000..7639d860f9 --- /dev/null +++ b/gateway/src/config/old_config_v1_1_28.rs @@ -0,0 +1,224 @@ +// Copyright 2020-2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::config::persistence::paths::{GatewayPaths, KeysPaths}; +use crate::config::{Config, Debug, Gateway}; +use nym_bin_common::logging::LoggingSettings; +use nym_config::{ + must_get_home, read_config_from_toml_file, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, NYM_DIR, +}; +use serde::{Deserialize, Serialize}; +use std::io; +use std::net::IpAddr; +use std::path::{Path, PathBuf}; +use std::time::Duration; +use url::Url; + +const DEFAULT_GATEWAYS_DIR: &str = "gateways"; + +// 'DEBUG' +// where applicable, the below are defined in milliseconds +const DEFAULT_PRESENCE_SENDING_DELAY: Duration = Duration::from_millis(10_000); +const DEFAULT_PACKET_FORWARDING_INITIAL_BACKOFF: Duration = Duration::from_millis(10_000); +const DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF: Duration = Duration::from_millis(300_000); +const DEFAULT_INITIAL_CONNECTION_TIMEOUT: Duration = Duration::from_millis(1_500); +const DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE: usize = 2000; + +const DEFAULT_STORED_MESSAGE_FILENAME_LENGTH: u16 = 16; +const DEFAULT_MESSAGE_RETRIEVAL_LIMIT: i64 = 100; + +/// Derive default path to gateway's config directory. +/// It should get resolved to `$HOME/.nym/gateways//config` +pub fn default_config_directory>(id: P) -> PathBuf { + must_get_home() + .join(NYM_DIR) + .join(DEFAULT_GATEWAYS_DIR) + .join(id) + .join(DEFAULT_CONFIG_DIR) +} + +/// Derive default path to gateways's config file. +/// It should get resolved to `$HOME/.nym/gateways//config/config.toml` +pub fn default_config_filepath>(id: P) -> PathBuf { + default_config_directory(id).join(DEFAULT_CONFIG_FILENAME) +} + +#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct KeysPathsV1_1_28 { + pub private_identity_key_file: PathBuf, + pub public_identity_key_file: PathBuf, + pub private_sphinx_key_file: PathBuf, + pub public_sphinx_key_file: PathBuf, +} + +#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct GatewayPathsV1_1_28 { + pub keys: KeysPathsV1_1_28, + #[serde(alias = "persistent_storage")] + pub clients_storage: PathBuf, +} + +#[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct LoggingSettingsV1_1_28 {} + +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(deny_unknown_fields)] +pub struct ConfigV1_1_28 { + pub gateway: GatewayV1_1_28, + + pub storage_paths: GatewayPathsV1_1_28, + + #[serde(default)] + pub logging: LoggingSettingsV1_1_28, + + #[serde(default)] + pub debug: DebugV1_1_28, +} + +impl ConfigV1_1_28 { + pub fn read_from_default_path>(id: P) -> io::Result { + read_config_from_toml_file(default_config_filepath(id)) + } +} + +impl From for Config { + fn from(value: ConfigV1_1_28) -> Self { + Config { + save_path: None, + gateway: Gateway { + version: value.gateway.version, + id: value.gateway.id, + only_coconut_credentials: value.gateway.only_coconut_credentials, + listening_address: value.gateway.listening_address, + mix_port: value.gateway.mix_port, + clients_port: value.gateway.clients_port, + enabled_statistics: value.gateway.enabled_statistics, + nym_api_urls: value.gateway.nym_api_urls, + nyxd_urls: value.gateway.nyxd_urls, + statistics_service_url: value.gateway.statistics_service_url, + cosmos_mnemonic: value.gateway.cosmos_mnemonic, + }, + storage_paths: GatewayPaths { + keys: KeysPaths { + private_identity_key_file: value.storage_paths.keys.private_identity_key_file, + public_identity_key_file: value.storage_paths.keys.public_identity_key_file, + private_sphinx_key_file: value.storage_paths.keys.private_sphinx_key_file, + public_sphinx_key_file: value.storage_paths.keys.public_sphinx_key_file, + }, + clients_storage: value.storage_paths.clients_storage, + network_requester_config: None, + }, + network_requester: Default::default(), + logging: LoggingSettings {}, + debug: Debug { + packet_forwarding_initial_backoff: value.debug.packet_forwarding_initial_backoff, + packet_forwarding_maximum_backoff: value.debug.packet_forwarding_maximum_backoff, + initial_connection_timeout: value.debug.initial_connection_timeout, + maximum_connection_buffer_size: value.debug.maximum_connection_buffer_size, + presence_sending_delay: value.debug.presence_sending_delay, + stored_messages_filename_length: value.debug.stored_messages_filename_length, + message_retrieval_limit: value.debug.message_retrieval_limit, + use_legacy_framed_packet_version: value.debug.use_legacy_framed_packet_version, + }, + } + } +} + +#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)] +pub struct GatewayV1_1_28 { + /// Version of the gateway for which this configuration was created. + pub version: String, + + /// ID specifies the human readable ID of this particular gateway. + pub id: String, + + /// Indicates whether this gateway is accepting only coconut credentials for accessing the + /// the mixnet, or if it also accepts non-paying clients + #[serde(default)] + pub only_coconut_credentials: bool, + + /// Address to which this mixnode will bind to and will be listening for packets. + pub listening_address: IpAddr, + + /// Port used for listening for all mixnet traffic. + /// (default: 1789) + pub mix_port: u16, + + /// Port used for listening for all client-related traffic. + /// (default: 9000) + pub clients_port: u16, + + /// Whether gateway collects and sends anonymized statistics + pub enabled_statistics: bool, + + /// Domain address of the statistics service + pub statistics_service_url: Url, + + /// Addresses to APIs from which the node gets the view of the network. + #[serde(alias = "validator_api_urls")] + pub nym_api_urls: Vec, + + /// Addresses to validators which the node uses to check for double spending of ERC20 tokens. + #[serde(alias = "validator_nymd_urls")] + pub nyxd_urls: Vec, + + /// Mnemonic of a cosmos wallet used in checking for double spending. + // #[deprecated(note = "move to storage")] + // TODO: I don't think this should be stored directly in the config... + pub cosmos_mnemonic: bip39::Mnemonic, +} + +#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[serde(default)] +pub struct DebugV1_1_28 { + /// Initial value of an exponential backoff to reconnect to dropped TCP connection when + /// forwarding sphinx packets. + #[serde(with = "humantime_serde")] + pub packet_forwarding_initial_backoff: Duration, + + /// Maximum value of an exponential backoff to reconnect to dropped TCP connection when + /// forwarding sphinx packets. + #[serde(with = "humantime_serde")] + pub packet_forwarding_maximum_backoff: Duration, + + /// Timeout for establishing initial connection when trying to forward a sphinx packet. + #[serde(with = "humantime_serde")] + pub initial_connection_timeout: Duration, + + /// Maximum number of packets that can be stored waiting to get sent to a particular connection. + pub maximum_connection_buffer_size: usize, + + /// Delay between each subsequent presence data being sent. + #[serde(with = "humantime_serde")] + pub presence_sending_delay: Duration, + + /// Length of filenames for new client messages. + pub stored_messages_filename_length: u16, + + /// Number of messages from offline client that can be pulled at once from the storage. + pub message_retrieval_limit: i64, + + /// Specifies whether the mixnode should be using the legacy framing for the sphinx packets. + // it's set to true by default. The reason for that decision is to preserve compatibility with the + // existing nodes whilst everyone else is upgrading and getting the code for handling the new field. + // It shall be disabled in the subsequent releases. + pub use_legacy_framed_packet_version: bool, +} + +impl Default for DebugV1_1_28 { + fn default() -> Self { + DebugV1_1_28 { + packet_forwarding_initial_backoff: DEFAULT_PACKET_FORWARDING_INITIAL_BACKOFF, + packet_forwarding_maximum_backoff: DEFAULT_PACKET_FORWARDING_MAXIMUM_BACKOFF, + initial_connection_timeout: DEFAULT_INITIAL_CONNECTION_TIMEOUT, + presence_sending_delay: DEFAULT_PRESENCE_SENDING_DELAY, + maximum_connection_buffer_size: DEFAULT_MAXIMUM_CONNECTION_BUFFER_SIZE, + stored_messages_filename_length: DEFAULT_STORED_MESSAGE_FILENAME_LENGTH, + message_retrieval_limit: DEFAULT_MESSAGE_RETRIEVAL_LIMIT, + use_legacy_framed_packet_version: false, + } + } +} diff --git a/gateway/src/config/persistence/paths.rs b/gateway/src/config/persistence/paths.rs index b5f44b6cd4..8d3be49335 100644 --- a/gateway/src/config/persistence/paths.rs +++ b/gateway/src/config/persistence/paths.rs @@ -1,8 +1,8 @@ // Copyright 2020-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::config::default_data_directory; -use serde::{Deserialize, Serialize}; +use crate::config::{default_config_directory, default_data_directory}; +use serde::{Deserialize, Deserializer, Serialize}; use std::path::{Path, PathBuf}; pub const DEFAULT_PRIVATE_IDENTITY_KEY_FILENAME: &str = "private_identity.pem"; @@ -12,8 +12,28 @@ pub const DEFAULT_PUBLIC_SPHINX_KEY_FILENAME: &str = "public_sphinx.pem"; pub const DEFAULT_CLIENTS_STORAGE_FILENAME: &str = "db.sqlite"; +pub const DEFAULT_NETWORK_REQUESTER_CONFIG_FILENAME: &str = "network_requester_config.toml"; +pub const DEFAULT_NETWORK_REQUESTER_DATA_DIR: &str = "network-requester-data"; + // pub const DEFAULT_DESCRIPTION_FILENAME: &str = "description.toml"; +pub fn default_network_requester_data_dir>(id: P) -> PathBuf { + default_data_directory(id).join(DEFAULT_NETWORK_REQUESTER_DATA_DIR) +} + +/// makes sure that an empty path is converted into a `None` as opposed to `Some("")` +fn de_maybe_path<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let path = PathBuf::deserialize(deserializer)?; + if path.as_os_str().is_empty() { + Ok(None) + } else { + Ok(Some(path)) + } +} + #[derive(Debug, Clone, Deserialize, PartialEq, Eq, Serialize)] #[serde(deny_unknown_fields)] pub struct GatewayPaths { @@ -23,6 +43,10 @@ pub struct GatewayPaths { /// derived shared keys and available client bandwidths. #[serde(alias = "persistent_storage")] pub clients_storage: PathBuf, + + /// Path to the configuration of the embedded network requester. + #[serde(deserialize_with = "de_maybe_path")] + pub network_requester_config: Option, // pub node_description: PathBuf, // pub cosmos_bip39_mnemonic: PathBuf, @@ -34,9 +58,27 @@ impl GatewayPaths { keys: KeysPaths::new_default(id.as_ref()), clients_storage: default_data_directory(id).join(DEFAULT_CLIENTS_STORAGE_FILENAME), // node_description: default_config_filepath(id).join(DEFAULT_DESCRIPTION_FILENAME), + network_requester_config: None, } } + #[must_use] + pub fn with_network_requester_config>(mut self, path: P) -> Self { + self.network_requester_config = Some(path.as_ref().into()); + self + } + + #[must_use] + pub fn with_default_network_requester_config>(self, id: P) -> Self { + self.with_network_requester_config( + default_config_directory(id).join(DEFAULT_NETWORK_REQUESTER_CONFIG_FILENAME), + ) + } + + pub fn network_requester_config(&self) -> &Option { + &self.network_requester_config + } + pub fn private_identity_key(&self) -> &Path { self.keys.private_identity_key() } diff --git a/gateway/src/config/template.rs b/gateway/src/config/template.rs index e8543b8f44..7e7563edf9 100644 --- a/gateway/src/config/template.rs +++ b/gateway/src/config/template.rs @@ -53,7 +53,11 @@ nyxd_urls = [ {{/each}} ] -cosmos_mnemonic = "{{ gateway.cosmos_mnemonic }}" +cosmos_mnemonic = '{{ gateway.cosmos_mnemonic }}' + +[network_requester] +# Specifies whether network requester service is enabled in this process. +enabled = {{ network_requester.enabled }} [storage_paths] @@ -73,6 +77,9 @@ keys.public_sphinx_key_file = '{{ storage_paths.keys.public_sphinx_key_file }}' # derived shared keys and available client bandwidths. clients_storage = '{{ storage_paths.clients_storage }}' +# Path to the configuration of the embedded network requester. +network_requester_config = '{{ storage_paths.network_requester_config }}' + ##### logging configuration options ##### [logging] diff --git a/gateway/src/error.rs b/gateway/src/error.rs index 5786bd26fb..dde0690979 100644 --- a/gateway/src/error.rs +++ b/gateway/src/error.rs @@ -1,6 +1,9 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::node::storage::error::StorageError; +use nym_network_requester::error::{ClientCoreError, NetworkRequesterError}; +use nym_validator_client::nyxd::error::NyxdError; use nym_validator_client::nyxd::AccountId; use nym_validator_client::ValidatorClientError; use std::io; @@ -9,8 +12,24 @@ use thiserror::Error; #[derive(Debug, Error)] pub(crate) enum GatewayError { + #[error("failed to load {keys} keys from '{}' (private key) and '{}' (public key): {err}", .paths.private_key_path.display(), .paths.public_key_path.display())] + KeyPairLoadFailure { + keys: String, + paths: nym_pemstore::KeyPairPath, + #[source] + err: io::Error, + }, + + #[error("failed to load {key} public key from '{}': {err}", .path.display())] + PublicKeyLoadFailure { + key: String, + path: PathBuf, + #[source] + err: io::Error, + }, + #[error( - "failed to load config file for id {id} using path {path}. detailed message: {source}" + "failed to load config file for id {id} using path '{}'. detailed message: {source}", path.display() )] ConfigLoadFailure { id: String, @@ -20,7 +39,17 @@ pub(crate) enum GatewayError { }, #[error( - "failed to save config file for id {id} using path {path}. detailed message: {source}" + "failed to load config file for network requester (gateway-id: '{id}') using path '{}'. detailed message: {source}", path.display() + )] + NetworkRequesterConfigLoadFailure { + id: String, + path: PathBuf, + #[source] + source: io::Error, + }, + + #[error( + "failed to save config file for id {id} using path '{}'. detailed message: {source}", path.display() )] ConfigSaveFailure { id: String, @@ -47,4 +76,43 @@ pub(crate) enum GatewayError { expected_prefix: String, actual_prefix: String, }, + + #[error("storage failure: {source}")] + StorageError { + #[from] + source: StorageError, + }, + + #[error("Path to network requester configuration file hasn't been specified. Perhaps try to run `setup-network-requester`?")] + UnspecifiedNetworkRequesterConfig, + + #[error("there was an issue with the local network requester: {source}")] + NetworkRequesterFailure { + #[from] + source: NetworkRequesterError, + }, + + #[error("failed to startup local network requester")] + NetworkRequesterStartupFailure, + + #[error("there are no nym API endpoints available")] + NoNymApisAvailable, + + #[error("there are no nyxd endpoints available")] + NoNyxdAvailable, + + #[error("there was an issue attempting to use the validator [nyxd]: {source}")] + ValidatorFailure { + #[from] + source: NyxdError, + }, +} + +impl From for GatewayError { + fn from(value: ClientCoreError) -> Self { + // if we ever get a client core error, it must have come from the network requester + GatewayError::NetworkRequesterFailure { + source: value.into(), + } + } } diff --git a/gateway/src/main.rs b/gateway/src/main.rs index 5290037266..1f3f54b398 100644 --- a/gateway/src/main.rs +++ b/gateway/src/main.rs @@ -1,6 +1,9 @@ // Copyright 2020-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +#![warn(clippy::expect_used)] +#![warn(clippy::unwrap_used)] + use clap::{crate_name, crate_version, Parser}; use colored::Colorize; use lazy_static::lazy_static; diff --git a/gateway/src/node/client_handling/active_clients.rs b/gateway/src/node/client_handling/active_clients.rs index 280027dacd..a44de399ba 100644 --- a/gateway/src/node/client_handling/active_clients.rs +++ b/gateway/src/node/client_handling/active_clients.rs @@ -1,14 +1,41 @@ -// Copyright 2021 - Nym Technologies SA +// Copyright 2021-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use super::websocket::message_receiver::{IsActiveRequestSender, MixMessageSender}; +use crate::node::client_handling::embedded_network_requester::LocalNetworkRequesterHandle; use dashmap::DashMap; +use log::warn; use nym_sphinx::DestinationAddressBytes; use std::sync::Arc; -use super::websocket::message_receiver::{IsActiveRequestSender, MixMessageSender}; +enum ActiveClient { + /// Handle to a remote client connected via a network socket. + Remote(ClientIncomingChannels), + + /// Handle to a locally (inside the same process) running network requester client. + Embedded(LocalNetworkRequesterHandle), +} + +impl ActiveClient { + fn get_sender_ref(&self) -> &MixMessageSender { + match self { + ActiveClient::Remote(remote) => &remote.mix_message_sender, + ActiveClient::Embedded(embedded) => &embedded.mix_message_sender, + } + } + + fn get_sender(&self) -> MixMessageSender { + match self { + ActiveClient::Remote(remote) => remote.mix_message_sender.clone(), + ActiveClient::Embedded(embedded) => embedded.mix_message_sender.clone(), + } + } +} #[derive(Clone)] -pub(crate) struct ActiveClientsStore(Arc>); +pub(crate) struct ActiveClientsStore { + inner: Arc>, +} #[derive(Clone)] pub(crate) struct ClientIncomingChannels { @@ -22,7 +49,9 @@ pub(crate) struct ClientIncomingChannels { impl ActiveClientsStore { /// Creates new instance of `ActiveClientsStore` to store in-memory handles to all currently connected clients. pub(crate) fn new() -> Self { - ActiveClientsStore(Arc::new(DashMap::new())) + ActiveClientsStore { + inner: Arc::new(DashMap::new()), + } } /// Tries to obtain sending channel to specified client. Note that if stale entry existed, it is @@ -31,29 +60,72 @@ impl ActiveClientsStore { /// # Arguments /// /// * `client`: address of the client for which to obtain the handle. - pub(crate) fn get(&self, client: DestinationAddressBytes) -> Option { - let entry = self.0.get(&client)?; - let handle = entry.value(); + pub(crate) fn get_sender(&self, client: DestinationAddressBytes) -> Option { + let entry = self.inner.get(&client)?; + let handle = entry.value().get_sender(); // if the entry is stale, remove it from the map // if handle.is_valid() { - if !handle.mix_message_sender.is_closed() { - Some(handle.clone()) + if !handle.is_closed() { + Some(handle) + } else { + // drop the reference to the map to prevent deadlocks + drop(entry); + self.inner.remove(&client); + None + } + } + + /// Attempts to get full handle to a remotely connected client + pub(crate) fn get_remote_client( + &self, + address: DestinationAddressBytes, + ) -> Option { + let entry = self.inner.get(&address)?; + let handle = entry.value(); + + let ActiveClient::Remote(channels) = handle else { + warn!("attempted to get a remote handle to a embedded network requester"); + return None; + }; + + // if the entry is stale, remove it from the map + if !channels.mix_message_sender.is_closed() { + Some(channels.clone()) } else { // drop the reference to the map to prevent deadlocks drop(entry); - self.0.remove(&client); + self.inner.remove(&address); None } } + /// Checks whether there's already an active connection to this client. + /// It will also remove the entry from the map if its stale. + pub(crate) fn is_active(&self, client: DestinationAddressBytes) -> bool { + let Some(entry) = self.inner.get(&client) else { + return false; + }; + let handle = entry.value().get_sender_ref(); + + // if the entry is stale, remove it from the map + if !handle.is_closed() { + true + } else { + // drop the reference to the map to prevent deadlocks + drop(entry); + self.inner.remove(&client); + false + } + } + /// Indicates particular client has disconnected from the gateway and its handle should get removed. /// /// # Arguments /// /// * `client`: address of the client for which to remove the handle. pub(crate) fn disconnect(&self, client: DestinationAddressBytes) { - self.0.remove(&client); + self.inner.remove(&client); } /// Insert new client handle into the store. @@ -62,23 +134,33 @@ impl ActiveClientsStore { /// /// * `client`: address of the client for which to insert the handle. /// * `handle`: the sender channel for all mix packets to be pushed back onto the websocket - pub(crate) fn insert( + pub(crate) fn insert_remote( &self, client: DestinationAddressBytes, handle: MixMessageSender, is_active_request_sender: IsActiveRequestSender, ) { - self.0.insert( - client, - ClientIncomingChannels { - mix_message_sender: handle, - is_active_request_sender, - }, - ); + let entry = ActiveClient::Remote(ClientIncomingChannels { + mix_message_sender: handle, + is_active_request_sender, + }); + if self.inner.insert(client, entry).is_some() { + panic!("inserted a duplicate remote client") + } + } + + /// Inserts a handle to the embedded network requester + pub(crate) fn insert_embedded(&self, local_nr_handle: LocalNetworkRequesterHandle) { + let key = local_nr_handle.client_destination(); + let entry = ActiveClient::Embedded(local_nr_handle); + if self.inner.insert(key, entry).is_some() { + // this is literally impossible since we're starting local NR before even spawning the websocket listener task + panic!("somehow we already had a client with the same address as our local NR!") + } } /// Get number of active clients in store pub(crate) fn size(&self) -> usize { - self.0.len() + self.inner.len() } } diff --git a/gateway/src/node/client_handling/embedded_network_requester/mod.rs b/gateway/src/node/client_handling/embedded_network_requester/mod.rs new file mode 100644 index 0000000000..7d2d612aa0 --- /dev/null +++ b/gateway/src/node/client_handling/embedded_network_requester/mod.rs @@ -0,0 +1,89 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::node::client_handling::websocket::message_receiver::{ + MixMessageReceiver, MixMessageSender, +}; +use futures::StreamExt; +use log::{debug, error}; +use nym_network_requester::core::OnStartData; +use nym_network_requester::{GatewayPacketRouter, PacketRouter}; +use nym_sphinx::addressing::clients::Recipient; +use nym_sphinx::DestinationAddressBytes; +use nym_task::TaskClient; + +#[derive(Debug)] +pub(crate) struct LocalNetworkRequesterHandle { + /// Nym address of the embedded network requester. + pub(crate) address: Recipient, + + /// Message channel used internally to forward any received mix packets to the network requester. + pub(crate) mix_message_sender: MixMessageSender, +} + +impl LocalNetworkRequesterHandle { + pub(crate) fn new(start_data: OnStartData, mix_message_sender: MixMessageSender) -> Self { + Self { + address: start_data.address, + mix_message_sender, + } + } + + pub(crate) fn client_destination(&self) -> DestinationAddressBytes { + self.address.identity().derive_destination_address() + } +} + +// we could have just passed a `PacketRouter` around instead of creating a dedicated task for +// calling the method. however, this would have caused slightly more complexity and more overhead +// (due to more data being copied to every [mix] connection) +// +/// task responsible for receiving messages for locally NR requester from multiple mix connections +/// and forwarding them via the router. kinda equivalent of a client socket handler +pub(crate) struct MessageRouter { + mix_receiver: MixMessageReceiver, + packet_router: PacketRouter, +} + +impl MessageRouter { + pub(crate) fn new(mix_receiver: MixMessageReceiver, packet_router: PacketRouter) -> Self { + Self { + mix_receiver, + packet_router, + } + } + + pub(crate) fn start_with_shutdown(self, shutdown: TaskClient) { + tokio::spawn(self.run_with_shutdown(shutdown)); + } + + fn handle_received_messages(&self, messages: Vec>) { + if let Err(err) = self.packet_router.route_received(messages) { + // TODO: what should we do here? I don't think this could/should ever fail. + // is panicking the appropriate thing to do then? + error!("failed to route packets to local NR: {err}") + } + } + + pub(crate) async fn run_with_shutdown(mut self, mut shutdown: TaskClient) { + debug!("Started embedded network requester message router with graceful shutdown support"); + while !shutdown.is_shutdown() { + tokio::select! { + messages = self.mix_receiver.next() => match messages { + Some(messages) => self.handle_received_messages(messages), + None => { + log::trace!("embedded_network_requester::MessageRouter: Stopping since channel closed"); + break; + } + }, + _ = shutdown.recv_with_delay() => { + log::trace!("embedded_network_requester::MessageRouter: Received shutdown"); + debug_assert!(shutdown.is_shutdown()); + break + } + } + } + + debug!("embedded_network_requester::MessageRouter: Exiting") + } +} diff --git a/gateway/src/node/client_handling/mod.rs b/gateway/src/node/client_handling/mod.rs index 671ac5a1c7..bc63605d58 100644 --- a/gateway/src/node/client_handling/mod.rs +++ b/gateway/src/node/client_handling/mod.rs @@ -3,6 +3,7 @@ pub(crate) mod active_clients; mod bandwidth; +pub(crate) mod embedded_network_requester; pub(crate) mod websocket; pub(crate) const FREE_TESTNET_BANDWIDTH_VALUE: i64 = 64 * 1024 * 1024 * 1024; // 64GB diff --git a/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs b/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs index 1bbd85b5f1..ff779cad36 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/authenticated.rs @@ -375,21 +375,24 @@ where async fn handle_pong(&mut self, msg: Vec) { if let Ok(msg) = msg.try_into() { let msg = u64::from_be_bytes(msg); - trace!("Received pong from client: {}", msg); + trace!("Received pong from client: {msg}"); if let Some((tag, _)) = &self.is_active_ping_pending_reply { if tag == &msg { debug!("Reporting back to the handler that the client is still active"); + // safety: + // the unwrap here is fine as we can only enter this if branch if `self.is_active_ping_pending_reply` + // was a `Some` + #[allow(clippy::unwrap_used)] let tx = self.is_active_ping_pending_reply.take().unwrap().1; if let Err(err) = tx.send(IsActive::Active) { warn!("Failed to send pong reply back to the requesting handler: {err:?}"); } } else { - warn!( - "Received pong reply from the client with unexpected tag: {}", - msg - ); + warn!("Received pong reply from the client with unexpected tag: {msg}",); } } + } else { + warn!("the received pong message was not a valid u64") } } diff --git a/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs b/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs index 349cf4200b..f4389fb433 100644 --- a/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs +++ b/gateway/src/node/client_handling/websocket/connection_handler/fresh.rs @@ -1,4 +1,4 @@ -// Copyright 2021 - Nym Technologies SA +// Copyright 2021-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 use futures::{ @@ -10,6 +10,7 @@ use nym_crypto::asymmetric::identity; use nym_gateway_requests::authentication::encrypted_address::{ EncryptedAddressBytes, EncryptedAddressConversionError, }; +use nym_gateway_requests::registration::handshake::shared_key::SharedKeyConversionError; use nym_gateway_requests::{ iv::{IVConversionError, IV}, registration::handshake::{error::HandshakeError, gateway_handshake, SharedKeys}, @@ -43,26 +44,35 @@ pub(crate) enum InitialAuthenticationError { #[error("Internal gateway storage error")] StorageError(#[from] StorageError), - #[error("Failed to perform registration handshake - {0}")] + #[error( + "our datastore is corrupted. the stored key for client {client_id} is malformed: {source}" + )] + MalformedStoredSharedKey { + client_id: String, + #[source] + source: SharedKeyConversionError, + }, + + #[error("Failed to perform registration handshake: {0}")] HandshakeError(#[from] HandshakeError), - #[error("Provided client address is malformed - {0}")] - // sphinx error is not used here directly as it's messaging might be confusing to people + #[error("Provided client address is malformed: {0}")] + // sphinx error is not used here directly as its messaging might be confusing to people MalformedClientAddress(String), - #[error("Provided encrypted client address is malformed - {0}")] + #[error("Provided encrypted client address is malformed: {0}")] MalformedEncryptedAddress(#[from] EncryptedAddressConversionError), #[error("There is already an open connection to this client")] DuplicateConnection, - #[error("Provided authentication IV is malformed - {0}")] + #[error("Provided authentication IV is malformed: {0}")] MalformedIV(#[from] IVConversionError), #[error("Only 'Register' or 'Authenticate' requests are allowed")] InvalidRequest, - #[error("Experienced connection error - {0}")] + #[error("Experienced connection error: {0}")] ConnectionError(#[from] WsError), #[error("Attempted to negotiate connection with client using incompatible protocol version. Ours is {current} and the client reports {client:?}")] @@ -316,13 +326,19 @@ where let shared_keys = self.storage.get_shared_keys(client_address).await?; if let Some(shared_keys) = shared_keys { - // the unwrap here is fine as we only ever construct persisted shared keys ourselves when inserting + // this should never fail as we only ever construct persisted shared keys ourselves when inserting // data to the storage. The only way it could fail is if we somehow changed implementation without // performing proper migration let keys = SharedKeys::try_from_base58_string( shared_keys.derived_aes128_ctr_blake3_hmac_keys_bs58, ) - .unwrap(); + .map_err(|source| { + InitialAuthenticationError::MalformedStoredSharedKey { + client_id: client_address.as_base58_string(), + source, + } + })?; + // TODO: SECURITY: // this is actually what we have been doing in the past, however, // after looking deeper into implementation it seems that only checks the encryption @@ -482,8 +498,8 @@ where let iv = IV::try_from_base58_string(iv)?; // Check for duplicate clients - if let Some(client_tx) = self.active_clients_store.get(address) { - log::warn!("Detected duplicate connection for client: {}", address); + if let Some(client_tx) = self.active_clients_store.get_remote_client(address) { + log::warn!("Detected duplicate connection for client: {address}"); self.handle_duplicate_client(address, client_tx.is_active_request_sender) .await?; } @@ -569,7 +585,7 @@ where let remote_identity = Self::extract_remote_identity_from_register_init(&init_data)?; let remote_address = remote_identity.derive_destination_address(); - if self.active_clients_store.get(remote_address).is_some() { + if self.active_clients_store.is_active(remote_address) { return Err(InitialAuthenticationError::DuplicateConnection); } @@ -675,7 +691,7 @@ where // Channel for handlers to ask other handlers if they are still active. let (is_active_request_sender, is_active_request_receiver) = mpsc::unbounded(); - self.active_clients_store.insert( + self.active_clients_store.insert_remote( client_details.address, mix_sender, is_active_request_sender, diff --git a/gateway/src/node/client_handling/websocket/listener.rs b/gateway/src/node/client_handling/websocket/listener.rs index 8811105b2e..01463e12c6 100644 --- a/gateway/src/node/client_handling/websocket/listener.rs +++ b/gateway/src/node/client_handling/websocket/listener.rs @@ -78,7 +78,7 @@ impl Listener { active_clients_store.clone(), Arc::clone(&self.coconut_verifier), ); - let shutdown = shutdown.clone(); + let shutdown = shutdown.clone().named(format!("ClientConnectionHandler_{remote_addr}")); tokio::spawn(async move { handle.start_handling(shutdown).await }); } Err(err) => warn!("failed to get client: {err}"), diff --git a/gateway/src/node/helpers.rs b/gateway/src/node/helpers.rs new file mode 100644 index 0000000000..9535519fce --- /dev/null +++ b/gateway/src/node/helpers.rs @@ -0,0 +1,148 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::config::Config; +use crate::error::GatewayError; +use crate::node::storage::PersistentStorage; +use nym_crypto::asymmetric::{encryption, identity}; +use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair}; +use nym_pemstore::KeyPairPath; +use nym_sphinx::addressing::clients::Recipient; +use nym_types::gateway::{GatewayNetworkRequesterDetails, GatewayNodeDetailsResponse}; +use std::path::Path; + +fn display_maybe_path>(path: Option

) -> String { + path.as_ref() + .map(|p| p.as_ref().display().to_string()) + .unwrap_or_default() +} + +fn display_path>(path: P) -> String { + path.as_ref().display().to_string() +} + +pub(crate) fn node_details(config: &Config) -> Result { + let gateway_identity_public_key: identity::PublicKey = load_public_key( + &config.storage_paths.keys.public_identity_key_file, + "gateway identity", + )?; + + let gateway_sphinx_public_key: encryption::PublicKey = load_public_key( + &config.storage_paths.keys.public_sphinx_key_file, + "gateway sphinx", + )?; + + let network_requester = + if let Some(nr_cfg_path) = &config.storage_paths.network_requester_config { + let cfg = load_network_requester_config(&config.gateway.id, nr_cfg_path)?; + + let nr_identity_public_key: identity::PublicKey = load_public_key( + &cfg.storage_paths.common_paths.keys.public_identity_key_file, + "network requester identity", + )?; + + let nr_encryption_key: encryption::PublicKey = load_public_key( + &cfg.storage_paths + .common_paths + .keys + .public_encryption_key_file, + "network requester encryption", + )?; + + let address = Recipient::new( + nr_identity_public_key, + nr_encryption_key, + gateway_identity_public_key, + ); + + Some(GatewayNetworkRequesterDetails { + enabled: config.network_requester.enabled, + identity_key: nr_identity_public_key.to_base58_string(), + encryption_key: nr_encryption_key.to_base58_string(), + open_proxy: cfg.network_requester.open_proxy, + enabled_statistics: cfg.network_requester.enabled_statistics, + address: address.to_string(), + config_path: display_path(nr_cfg_path), + allow_list_path: display_path(&cfg.storage_paths.allowed_list_location), + unknown_list_path: display_path(&cfg.storage_paths.unknown_list_location), + }) + } else { + None + }; + + Ok(GatewayNodeDetailsResponse { + identity_key: gateway_identity_public_key.to_base58_string(), + sphinx_key: gateway_sphinx_public_key.to_base58_string(), + bind_address: config.gateway.listening_address.to_string(), + mix_port: config.gateway.mix_port, + clients_port: config.gateway.clients_port, + config_path: display_maybe_path(config.save_path.as_ref()), + data_store: display_path(&config.storage_paths.clients_storage), + network_requester, + }) +} + +pub(crate) fn load_network_requester_config>( + id: &str, + path: P, +) -> Result { + let path = path.as_ref(); + nym_network_requester::Config::read_from_toml_file(path).map_err(|err| { + GatewayError::NetworkRequesterConfigLoadFailure { + id: id.to_string(), + path: path.to_path_buf(), + source: err, + } + }) +} + +pub(crate) async fn initialise_main_storage( + config: &Config, +) -> Result { + let path = &config.storage_paths.clients_storage; + let retrieval_limit = config.debug.message_retrieval_limit; + + Ok(PersistentStorage::init(path, retrieval_limit).await?) +} + +pub(crate) fn load_keypair( + paths: KeyPairPath, + name: impl Into, +) -> Result { + nym_pemstore::load_keypair(&paths).map_err(|err| GatewayError::KeyPairLoadFailure { + keys: name.into(), + paths, + err, + }) +} + +pub(crate) fn load_public_key(path: P, name: S) -> Result +where + T: PemStorableKey, + P: AsRef, + S: Into, +{ + nym_pemstore::load_key(path.as_ref()).map_err(|err| GatewayError::PublicKeyLoadFailure { + key: name.into(), + path: path.as_ref().to_path_buf(), + err, + }) +} + +/// Loads identity keys stored on disk +pub(crate) fn load_identity_keys(config: &Config) -> Result { + let identity_paths = KeyPairPath::new( + config.storage_paths.keys.private_identity_key(), + config.storage_paths.keys.public_identity_key(), + ); + load_keypair(identity_paths, "gateway identity") +} + +/// Loads Sphinx keys stored on disk +pub(crate) fn load_sphinx_keys(config: &Config) -> Result { + let sphinx_paths = KeyPairPath::new( + config.storage_paths.keys.private_encryption_key(), + config.storage_paths.keys.public_encryption_key(), + ); + load_keypair(sphinx_paths, "gateway sphinx") +} diff --git a/gateway/src/node/mixnet_handling/receiver/connection_handler.rs b/gateway/src/node/mixnet_handling/receiver/connection_handler.rs index e6071b8035..00fd98033b 100644 --- a/gateway/src/node/mixnet_handling/receiver/connection_handler.rs +++ b/gateway/src/node/mixnet_handling/receiver/connection_handler.rs @@ -6,6 +6,7 @@ use crate::node::client_handling::websocket::message_receiver::MixMessageSender; use crate::node::mixnet_handling::receiver::packet_processing::PacketProcessor; use crate::node::storage::error::StorageError; use crate::node::storage::Storage; +use futures::channel::mpsc::SendError; use futures::StreamExt; use log::*; use nym_mixnet_client::forwarder::MixForwardingSender; @@ -17,9 +18,17 @@ use nym_sphinx::DestinationAddressBytes; use nym_task::TaskClient; use std::collections::HashMap; use std::net::SocketAddr; +use thiserror::Error; use tokio::net::TcpStream; use tokio_util::codec::Framed; +// defines errors that warrant a panic if not thrown in the context of a shutdown +#[derive(Debug, Error)] +enum CriticalPacketProcessingError { + #[error("failed to forward an ack")] + AckForwardingFailure { source: SendError }, +} + pub(crate) struct ConnectionHandler { packet_processor: PacketProcessor, @@ -70,9 +79,9 @@ impl ConnectionHandler { } fn update_clients_store_cache_entry(&mut self, client_address: DestinationAddressBytes) { - if let Some(client_senders) = self.active_clients_store.get(client_address) { + if let Some(client_senders) = self.active_clients_store.get_sender(client_address) { self.clients_store_cache - .insert(client_address, client_senders.mix_message_sender); + .insert(client_address, client_senders); } } @@ -97,11 +106,14 @@ impl ConnectionHandler { match self.clients_store_cache.get(&client_address) { None => Err(message), Some(sender_channel) => { - sender_channel - .unbounded_send(vec![message]) - // right now it's a "simpler" case here as we're only ever sending 1 message - // at the time, but the channel itself could accept arbitrary many messages at once - .map_err(|try_send_err| try_send_err.into_inner().pop().unwrap()) + if let Err(unsent) = sender_channel.unbounded_send(vec![message]) { + // the unwrap here is fine as the original message got returned; + // plus we're only ever sending 1 message at the time (for now) + #[allow(clippy::unwrap_used)] + return Err(unsent.into_inner().pop().unwrap()); + } else { + Ok(()) + } } } } @@ -111,27 +123,35 @@ impl ConnectionHandler { client_address: DestinationAddressBytes, message: Vec, ) -> Result<(), StorageError> { - debug!( - "Storing received message for {} on the disk...", - client_address - ); + debug!("Storing received message for {client_address} on the disk...",); self.storage.store_message(client_address, message).await } - fn forward_ack(&self, forward_ack: Option, client_address: DestinationAddressBytes) { + fn forward_ack( + &self, + forward_ack: Option, + client_address: DestinationAddressBytes, + ) -> Result<(), CriticalPacketProcessingError> { if let Some(forward_ack) = forward_ack { - trace!( - "Sending ack from packet for {} to {}", - client_address, - forward_ack.next_hop() - ); - - self.ack_sender.unbounded_send(forward_ack).unwrap(); + let next_hop = forward_ack.next_hop(); + trace!("Sending ack from packet for {client_address} to {next_hop}",); + + self.ack_sender + .unbounded_send(forward_ack) + .map_err( + |source| CriticalPacketProcessingError::AckForwardingFailure { + source: source.into_send_error(), + }, + )?; } + Ok(()) } - async fn handle_processed_packet(&mut self, processed_final_hop: ProcessedFinalHop) { + async fn handle_processed_packet( + &mut self, + processed_final_hop: ProcessedFinalHop, + ) -> Result<(), CriticalPacketProcessingError> { let client_address = processed_final_hop.destination; let message = processed_final_hop.message; let forward_ack = processed_final_hop.forward_ack; @@ -144,18 +164,21 @@ impl ConnectionHandler { .await { Err(err) => error!("Failed to store client data - {err}"), - Ok(_) => trace!("Stored packet for {}", client_address), + Ok(_) => trace!("Stored packet for {client_address}"), }, - Ok(_) => trace!("Pushed received packet to {}", client_address), + Ok(_) => trace!("Pushed received packet to {client_address}"), } // if we managed to either push message directly to the [online] client or store it at // its inbox, it means that it must exist at this gateway, hence we can send the // received ack back into the network - self.forward_ack(forward_ack, client_address); + self.forward_ack(forward_ack, client_address) } - async fn handle_received_packet(&mut self, framed_sphinx_packet: FramedNymPacket) { + async fn handle_received_packet( + &mut self, + framed_sphinx_packet: FramedNymPacket, + ) -> Result<(), CriticalPacketProcessingError> { // // TODO: here be replay attack detection - it will require similar key cache to the one in // packet processor for vpn packets, @@ -166,7 +189,7 @@ impl ConnectionHandler { { Err(err) => { debug!("We failed to process received sphinx packet - {err}"); - return; + return Ok(()); } Ok(processed_final_hop) => processed_final_hop, }; @@ -198,7 +221,11 @@ impl ConnectionHandler { // in theory we could process multiple sphinx packet from the same connection in parallel, // but we already handle multiple concurrent connections so if anything, making // that change would only slow things down - self.handle_received_packet(framed_sphinx_packet).await; + if let Err(critical_err) = self.handle_received_packet(framed_sphinx_packet).await { + if !shutdown.is_shutdown() { + panic!("experienced critical failure when processing received packet: {critical_err}") + } + } } Some(Err(err)) => { error!( @@ -212,9 +239,13 @@ impl ConnectionHandler { } } - info!( - "Closing connection from {:?}", - framed_conn.into_inner().peer_addr() - ); + match framed_conn.into_inner().peer_addr() { + Ok(peer_addr) => { + debug!("closing connection from {peer_addr}") + } + Err(err) => { + warn!("closing connection from an unknown peer: {err}") + } + } } } diff --git a/gateway/src/node/mixnet_handling/receiver/listener.rs b/gateway/src/node/mixnet_handling/receiver/listener.rs index 38fd8ef43b..6714906ed7 100644 --- a/gateway/src/node/mixnet_handling/receiver/listener.rs +++ b/gateway/src/node/mixnet_handling/receiver/listener.rs @@ -43,7 +43,7 @@ impl Listener { match connection { Ok((socket, remote_addr)) => { let handler = connection_handler.clone(); - tokio::spawn(handler.handle_connection(socket, remote_addr, self.shutdown.clone())); + tokio::spawn(handler.handle_connection(socket, remote_addr, self.shutdown.clone().named(format!("MixnetConnectionHandler_{remote_addr}")))); } Err(err) => warn!("failed to get client: {err}"), } diff --git a/gateway/src/node/mod.rs b/gateway/src/node/mod.rs index 93bce3a6fd..80bd505ccf 100644 --- a/gateway/src/node/mod.rs +++ b/gateway/src/node/mod.rs @@ -2,19 +2,26 @@ // SPDX-License-Identifier: Apache-2.0 use self::storage::PersistentStorage; +use crate::commands::helpers::{override_network_requester_config, OverrideNetworkRequesterConfig}; use crate::config::Config; use crate::error::GatewayError; use crate::node::client_handling::active_clients::ActiveClientsStore; +use crate::node::client_handling::embedded_network_requester::{ + LocalNetworkRequesterHandle, MessageRouter, +}; use crate::node::client_handling::websocket; use crate::node::client_handling::websocket::connection_handler::coconut::CoconutVerifier; +use crate::node::helpers::{initialise_main_storage, load_network_requester_config}; use crate::node::mixnet_handling::receiver::connection_handler::ConnectionHandler; use crate::node::statistics::collector::GatewayStatisticsCollector; use crate::node::storage::Storage; +use anyhow::bail; +use futures::channel::{mpsc, oneshot}; use log::*; -use nym_bin_common::output_format::OutputFormat; use nym_crypto::asymmetric::{encryption, identity}; use nym_mixnet_client::forwarder::{MixForwardingSender, PacketForwarder}; use nym_network_defaults::NymNetworkDetails; +use nym_network_requester::{LocalGateway, NRServiceProviderBuilder}; use nym_statistics_common::collector::StatisticsSender; use nym_task::{TaskClient, TaskManager}; use nym_validator_client::{nyxd, DirectSigningHttpRpcNyxdClient}; @@ -22,32 +29,59 @@ use rand::seq::SliceRandom; use rand::thread_rng; use std::error::Error; use std::net::SocketAddr; +use std::path::PathBuf; use std::sync::Arc; pub(crate) mod client_handling; +pub(crate) mod helpers; pub(crate) mod mixnet_handling; pub(crate) mod statistics; pub(crate) mod storage; /// Wire up and create Gateway instance -pub(crate) async fn create_gateway(config: Config) -> Gateway { - let storage = initialise_storage(&config).await; - Gateway::new(config, storage).await +pub(crate) async fn create_gateway( + config: Config, + nr_config_override: Option, + custom_nr_mixnet: Option, +) -> Result { + // don't attempt to read config if NR is disabled + let network_requester_config = if config.network_requester.enabled { + if let Some(path) = &config.storage_paths.network_requester_config { + let cfg = load_network_requester_config(&config.gateway.id, path)?; + Some(override_network_requester_config(cfg, nr_config_override)) + } else { + // if NR is enabled, the config path must be specified + return Err(GatewayError::UnspecifiedNetworkRequesterConfig); + } + } else { + None + }; + + let storage = initialise_main_storage(&config).await?; + + let nr_opts = network_requester_config.map(|config| LocalNetworkRequesterOpts { + config, + custom_mixnet_path: custom_nr_mixnet, + }); + + Gateway::new(config, nr_opts, storage) } -async fn initialise_storage(config: &Config) -> PersistentStorage { - let path = &config.storage_paths.clients_storage; - let retrieval_limit = config.debug.message_retrieval_limit; - match PersistentStorage::init(path, retrieval_limit).await { - Err(err) => panic!("failed to initialise gateway storage: {err}"), - Ok(storage) => storage, - } +#[derive(Debug, Clone)] +pub struct LocalNetworkRequesterOpts { + config: nym_network_requester::Config, + + custom_mixnet_path: Option, } -pub(crate) struct Gateway { +pub(crate) struct Gateway { config: Config, + + network_requester_opts: Option, + /// ed25519 keypair used to assert one's identity. identity_keypair: Arc, + /// x25519 keypair used for Diffie-Hellman. Currently only used for sphinx key derivation. sphinx_keypair: Arc, storage: St, @@ -55,71 +89,37 @@ pub(crate) struct Gateway { impl Gateway { /// Construct from the given `Config` instance. - pub async fn new(config: Config, storage: St) -> Self { - Gateway { + pub fn new( + config: Config, + network_requester_opts: Option, + storage: St, + ) -> Result { + Ok(Gateway { storage, - identity_keypair: Arc::new(Self::load_identity_keys(&config)), - sphinx_keypair: Arc::new(Self::load_sphinx_keys(&config)), + identity_keypair: Arc::new(helpers::load_identity_keys(&config)?), + sphinx_keypair: Arc::new(helpers::load_sphinx_keys(&config)?), config, - } + network_requester_opts, + }) } #[cfg(test)] pub async fn new_from_keys_and_storage( config: Config, + network_requester_opts: Option, identity_keypair: identity::KeyPair, sphinx_keypair: encryption::KeyPair, storage: St, ) -> Self { Gateway { config, + network_requester_opts, identity_keypair: Arc::new(identity_keypair), sphinx_keypair: Arc::new(sphinx_keypair), storage, } } - /// Loads identity keys stored on disk - pub(crate) fn load_identity_keys(config: &Config) -> identity::KeyPair { - let identity_keypair: identity::KeyPair = - nym_pemstore::load_keypair(&nym_pemstore::KeyPairPath::new( - config.storage_paths.keys.private_identity_key(), - config.storage_paths.keys.public_identity_key(), - )) - .expect("Failed to read stored identity key files"); - identity_keypair - } - - /// Loads Sphinx keys stored on disk - fn load_sphinx_keys(config: &Config) -> encryption::KeyPair { - let sphinx_keypair: encryption::KeyPair = - nym_pemstore::load_keypair(&nym_pemstore::KeyPairPath::new( - config.storage_paths.keys.private_encryption_key(), - config.storage_paths.keys.public_encryption_key(), - )) - .expect("Failed to read stored sphinx key files"); - sphinx_keypair - } - - pub(crate) fn print_node_details(&self, output: OutputFormat) { - let node_details = nym_types::gateway::GatewayNodeDetailsResponse { - identity_key: self.identity_keypair.public_key().to_base58_string(), - sphinx_key: self.sphinx_keypair.public_key().to_base58_string(), - bind_address: self.config.gateway.listening_address.to_string(), - version: self.config.gateway.version.clone(), - mix_port: self.config.gateway.mix_port, - clients_port: self.config.gateway.clients_port, - data_store: self - .config - .storage_paths - .clients_storage - .display() - .to_string(), - }; - - println!("{}", output.format(&node_details)); - } - fn start_mix_socket_listener( &self, ack_sender: MixForwardingSender, @@ -194,46 +194,106 @@ impl Gateway { packet_sender } - async fn wait_for_interrupt( + // TODO: rethink the logic in this function... + async fn start_network_requester( &self, - shutdown: TaskManager, - ) -> Result<(), Box> { + forwarding_channel: MixForwardingSender, + shutdown: TaskClient, + ) -> Result { + info!("Starting network requester..."); + + // if network requester is enabled, configuration file must be provided! + let Some(nr_opts) = &self.network_requester_opts else { + return Err(GatewayError::UnspecifiedNetworkRequesterConfig); + }; + + // this gateway, whenever it has anything to send to its local NR will use fake_client_tx + let (nr_mix_sender, nr_mix_receiver) = mpsc::unbounded(); + let router_shutdown = shutdown.fork("message_router"); + + let (router_tx, mut router_rx) = oneshot::channel(); + + let transceiver = LocalGateway::new( + *self.identity_keypair.public_key(), + forwarding_channel, + router_tx, + ); + + // TODO: well, wire it up internally to gateway traffic, shutdowns, etc. + let (on_start_tx, on_start_rx) = oneshot::channel(); + let mut nr_builder = NRServiceProviderBuilder::new(nr_opts.config.clone()) + .with_shutdown(shutdown) + .with_custom_gateway_transceiver(Box::new(transceiver)) + .with_wait_for_gateway(true) + .with_on_start(on_start_tx); + + if let Some(custom_mixnet) = &nr_opts.custom_mixnet_path { + nr_builder = nr_builder.with_stored_topology(custom_mixnet)? + } + + tokio::spawn(async move { + if let Err(err) = nr_builder.run_service_provider().await { + // no need to panic as we have passed a task client to the NR so we're most likely + // already in the process of shutting down + error!("network requester has failed: {err}") + } + }); + + let start_data = on_start_rx + .await + .map_err(|_| GatewayError::NetworkRequesterStartupFailure)?; + + // this should be instantaneous since the data is sent on this channel before the on start is called; + // the failure should be impossible + let Ok(Some(packet_router)) = router_rx.try_recv() else { + return Err(GatewayError::NetworkRequesterStartupFailure); + }; + + MessageRouter::new(nr_mix_receiver, packet_router).start_with_shutdown(router_shutdown); + info!( + "the local network requester is running on {}", + start_data.address + ); + + Ok(LocalNetworkRequesterHandle::new(start_data, nr_mix_sender)) + } + + async fn wait_for_interrupt(shutdown: TaskManager) -> Result<(), Box> { let res = shutdown.catch_interrupt().await; log::info!("Stopping nym gateway"); res } - fn random_api_client(&self) -> nym_validator_client::NymApiClient { + fn random_api_client(&self) -> Result { let endpoints = self.config.get_nym_api_endpoints(); let nym_api = endpoints .choose(&mut thread_rng()) - .expect("The list of validator apis is empty"); + .ok_or(GatewayError::NoNymApisAvailable)?; - nym_validator_client::NymApiClient::new(nym_api.clone()) + Ok(nym_validator_client::NymApiClient::new(nym_api.clone())) } - fn random_nyxd_client(&self) -> DirectSigningHttpRpcNyxdClient { + fn random_nyxd_client(&self) -> Result { let endpoints = self.config.get_nyxd_urls(); let validator_nyxd = endpoints .choose(&mut thread_rng()) - .expect("The list of validators is empty"); + .ok_or(GatewayError::NoNyxdAvailable)?; let network_details = NymNetworkDetails::new_from_env(); - let client_config = nyxd::Config::try_from_nym_network_details(&network_details) - .expect("failed to construct valid validator client config with the provided network"); + let client_config = nyxd::Config::try_from_nym_network_details(&network_details)?; DirectSigningHttpRpcNyxdClient::connect_with_mnemonic( client_config, validator_nyxd.as_ref(), self.config.get_cosmos_mnemonic(), ) - .expect("Could not connect with mnemonic") + .map_err(Into::into) } async fn check_if_bonded(&self) -> Result { // TODO: if anything, this should be getting data directly from the contract // as opposed to the validator API - let validator_client = self.random_api_client(); + let validator_client = self.random_api_client()?; let existing_nodes = match validator_client.get_cached_gateways().await { Ok(nodes) => nodes, Err(err) => { @@ -247,7 +307,7 @@ impl Gateway { })) } - pub async fn run(&mut self) -> Result<(), Box> + pub async fn run(self) -> anyhow::Result<()> where St: Storage + Clone + 'static, { @@ -260,17 +320,18 @@ impl Gateway { let shutdown = TaskManager::new(10); let coconut_verifier = { - let nyxd_client = self.random_nyxd_client(); + let nyxd_client = self.random_nyxd_client()?; CoconutVerifier::new(nyxd_client) }; - let mix_forwarding_channel = self.start_packet_forwarder(shutdown.subscribe()); + let mix_forwarding_channel = + self.start_packet_forwarder(shutdown.subscribe().named("PacketForwarder")); let active_clients_store = ActiveClientsStore::new(); self.start_mix_socket_listener( mix_forwarding_channel.clone(), active_clients_store.clone(), - shutdown.subscribe(), + shutdown.subscribe().named("mixnet_handling::Listener"), ); if self.config.gateway.enabled_statistics { @@ -286,15 +347,40 @@ impl Gateway { }); } + if self.config.network_requester.enabled { + let embedded_nr = self + .start_network_requester( + mix_forwarding_channel.clone(), + shutdown.subscribe().named("NetworkRequester"), + ) + .await?; + // insert information about embedded NR to the active clients store + active_clients_store.insert_embedded(embedded_nr) + } else { + info!("embedded network requester is disabled"); + } + self.start_client_websocket_listener( mix_forwarding_channel, active_clients_store, - shutdown.subscribe(), + shutdown.subscribe().named("websocket::Listener"), Arc::new(coconut_verifier), ); + // Once this is a bit more mature, make this a commandline flag instead of a compile time + // flag + #[cfg(feature = "wireguard")] + if let Err(err) = nym_wireguard::start_wg_listener(shutdown.subscribe()).await { + // that's a nasty workaround, but anyhow errors are generally nicer, especially on exit + bail!("{err}") + } + info!("Finished nym gateway startup procedure - it should now be able to receive mix and client traffic!"); - self.wait_for_interrupt(shutdown).await + if let Err(err) = Self::wait_for_interrupt(shutdown).await { + // that's a nasty workaround, but anyhow errors are generally nicer, especially on exit + bail!("{err}") + } + Ok(()) } } diff --git a/gateway/src/node/storage/error.rs b/gateway/src/node/storage/error.rs index 7f6d023bab..306dafa557 100644 --- a/gateway/src/node/storage/error.rs +++ b/gateway/src/node/storage/error.rs @@ -5,9 +5,9 @@ use thiserror::Error; #[derive(Error, Debug)] pub(crate) enum StorageError { - #[error("Database experienced an internal error - {0}")] + #[error("Database experienced an internal error: {0}")] InternalDatabaseError(#[from] sqlx::Error), - #[error("Failed to perform database migration - {0}")] + #[error("Failed to perform database migration: {0}")] MigrationError(#[from] sqlx::migrate::MigrateError), } diff --git a/gateway/src/node/storage/inboxes.rs b/gateway/src/node/storage/inboxes.rs index d40ae5681f..f67fac94b4 100644 --- a/gateway/src/node/storage/inboxes.rs +++ b/gateway/src/node/storage/inboxes.rs @@ -18,7 +18,12 @@ impl InboxManager { /// # Arguments /// /// * `connection_pool`: database connection pool to use. - pub(crate) fn new(connection_pool: sqlx::SqlitePool, retrieval_limit: i64) -> Self { + pub(crate) fn new(connection_pool: sqlx::SqlitePool, mut retrieval_limit: i64) -> Self { + // TODO: make this into a hard error instead + if retrieval_limit == 0 { + retrieval_limit = 100; + } + InboxManager { connection_pool, retrieval_limit, @@ -99,7 +104,8 @@ impl InboxManager { if res.len() > self.retrieval_limit as usize { res.truncate(self.retrieval_limit as usize); - // assuming retrieval_limit > 0, unwrap will not fail + // given retrieval_limit > 0, unwrap will not fail + #[allow(clippy::unwrap_used)] let start_after = res.last().unwrap().id; Ok((res, Some(start_after))) // diff --git a/gateway/src/support/config.rs b/gateway/src/support/config.rs index cbbd4dd798..ff6cc91789 100644 --- a/gateway/src/support/config.rs +++ b/gateway/src/support/config.rs @@ -1,7 +1,7 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::commands::{override_config, try_load_current_config, OverrideConfig}; +use crate::commands::helpers::{try_load_current_config, OverrideConfig}; use crate::config::Config; use crate::error::GatewayError; @@ -10,6 +10,5 @@ pub(crate) fn build_config>( override_args: O, ) -> Result { let config = try_load_current_config(&id)?; - - override_config(config, override_args.into()) + override_args.into().do_override(config) } diff --git a/lerna.json b/lerna.json index 851bdf0b54..053f72e27e 100644 --- a/lerna.json +++ b/lerna.json @@ -1,4 +1,3 @@ { - "version": "0.0.0", - "useWorkspaces": true + "version": "independent" } diff --git a/mixnode/Cargo.toml b/mixnode/Cargo.toml index 9efff54500..37268c654d 100644 --- a/mixnode/Cargo.toml +++ b/mixnode/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-mixnode" -version = "1.1.30" +version = "1.1.31" authors = [ "Dave Hrycyszyn ", "Jędrzej Stuczyński ", diff --git a/mixnode/src/config/mod.rs b/mixnode/src/config/mod.rs index eeb8582ff4..7a6a73e06a 100644 --- a/mixnode/src/config/mod.rs +++ b/mixnode/src/config/mod.rs @@ -88,7 +88,7 @@ pub struct Config { } impl NymConfigTemplate for Config { - fn template() -> &'static str { + fn template(&self) -> &'static str { CONFIG_TEMPLATE } } diff --git a/nym-api/Cargo.toml b/nym-api/Cargo.toml index 5f5f6a9bd6..4389d27de8 100644 --- a/nym-api/Cargo.toml +++ b/nym-api/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-api" -version = "1.1.30" +version = "1.1.31" authors = [ "Dave Hrycyszyn ", "Jędrzej Stuczyński ", diff --git a/nym-api/nym-api-requests/Cargo.toml b/nym-api/nym-api-requests/Cargo.toml index e890aa8e44..2d39074adb 100644 --- a/nym-api/nym-api-requests/Cargo.toml +++ b/nym-api/nym-api-requests/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" [dependencies] bs58 = "0.4.0" cosmrs = { workspace = true } -cosmwasm-std = { workspace = true, default-features = false } +cosmwasm-std = { workspace = true } getset = "0.1.1" schemars = { version = "0.8", features = ["preserve_order"] } serde = { version = "1.0", features = ["derive"] } diff --git a/nym-api/src/network_monitor/monitor/sender.rs b/nym-api/src/network_monitor/monitor/sender.rs index bbf40e6f72..ef3bda31af 100644 --- a/nym-api/src/network_monitor/monitor/sender.rs +++ b/nym-api/src/network_monitor/monitor/sender.rs @@ -16,8 +16,11 @@ use nym_bandwidth_controller::BandwidthController; use nym_config::defaults::REMAINING_BANDWIDTH_THRESHOLD; use nym_credential_storage::persistent_storage::PersistentStorage; use nym_crypto::asymmetric::identity::{self, PUBLIC_KEY_LENGTH}; +use nym_gateway_client::client::GatewayConfig; use nym_gateway_client::error::GatewayClientError; -use nym_gateway_client::{AcknowledgementReceiver, GatewayClient, MixnetMessageReceiver}; +use nym_gateway_client::{ + AcknowledgementReceiver, GatewayClient, MixnetMessageReceiver, PacketRouter, +}; use nym_sphinx::forwarding::packet::MixPacket; use nym_task::TaskClient; use pin_project::pin_project; @@ -55,6 +58,14 @@ impl GatewayPackets { } } + pub(crate) fn gateway_config(&self) -> GatewayConfig { + GatewayConfig { + gateway_identity: self.pub_key, + gateway_owner: None, + gateway_listener: self.clients_address.clone(), + } + } + pub(crate) fn empty(clients_address: String, pub_key: identity::PublicKey) -> Self { GatewayPackets { clients_address, @@ -169,13 +180,16 @@ impl PacketSender { } fn new_gateway_client_handle( - address: String, - identity: identity::PublicKey, + config: GatewayConfig, fresh_gateway_client_data: &FreshGatewayClientData, ) -> ( GatewayClientHandle, (MixnetMessageReceiver, AcknowledgementReceiver), ) { + // I think the proper one should be passed around instead... + let task_client = + nym_task::TaskClient::dummy().named(format!("gateway-{}", config.gateway_identity)); + // TODO: future optimization: if we're remaking client for a gateway to which we used to be connected in the past, // use old shared keys let (message_sender, message_receiver) = mpsc::unbounded(); @@ -184,20 +198,22 @@ impl PacketSender { // so that the gateway client would not crash let (ack_sender, ack_receiver) = mpsc::unbounded(); - let mut gateway_client = GatewayClient::new( - address, - Arc::clone(&fresh_gateway_client_data.local_identity), - identity, - None, - message_sender, + let gateway_packet_router = PacketRouter::new( ack_sender, - fresh_gateway_client_data.gateway_response_timeout, - Some(fresh_gateway_client_data.bandwidth_controller.clone()), - nym_task::TaskClient::dummy(), + message_sender, + task_client.fork("packet-router"), ); - gateway_client - .set_disabled_credentials_mode(fresh_gateway_client_data.disabled_credentials_mode); + let gateway_client = GatewayClient::new( + config, + Arc::clone(&fresh_gateway_client_data.local_identity), + None, + gateway_packet_router, + Some(fresh_gateway_client_data.bandwidth_controller.clone()), + task_client, + ) + .with_disabled_credentials_mode(fresh_gateway_client_data.disabled_credentials_mode) + .with_response_timeout(fresh_gateway_client_data.gateway_response_timeout); ( GatewayClientHandle::new(gateway_client), @@ -265,16 +281,16 @@ impl PacketSender { } async fn create_new_gateway_client_handle_and_authenticate( - address: String, - identity: identity::PublicKey, + config: GatewayConfig, fresh_gateway_client_data: &FreshGatewayClientData, gateway_connection_timeout: Duration, ) -> Option<( GatewayClientHandle, (MixnetMessageReceiver, AcknowledgementReceiver), )> { + let gateway_identity = config.gateway_identity; let (new_client, (message_receiver, ack_receiver)) = - Self::new_gateway_client_handle(address, identity, fresh_gateway_client_data); + Self::new_gateway_client_handle(config, fresh_gateway_client_data); // Put this in timeout in case the gateway has incorrectly set their ulimit and our connection // gets stuck in their TCP queue and just hangs on our end but does not terminate @@ -295,19 +311,12 @@ impl PacketSender { Some((new_client, (message_receiver, ack_receiver))) } Ok(Err(err)) => { - warn!( - "failed to authenticate with new gateway ({}) - {}", - identity.to_base58_string(), - err - ); + warn!("failed to authenticate with new gateway ({gateway_identity}): {err}",); // we failed to create a client, can't do much here None } Err(_) => { - warn!( - "timed out while trying to authenticate with new gateway ({})", - identity.to_base58_string() - ); + warn!("timed out while trying to authenticate with new gateway {gateway_identity}",); None } } @@ -349,8 +358,7 @@ impl PacketSender { } else { let (client, gateway_channels) = Self::create_new_gateway_client_handle_and_authenticate( - packets.clients_address, - packets.pub_key, + packets.gateway_config(), &fresh_gateway_client_data, gateway_connection_timeout, ) diff --git a/nym-api/src/support/config/mod.rs b/nym-api/src/support/config/mod.rs index a66c5ce8a7..9cf1404b38 100644 --- a/nym-api/src/support/config/mod.rs +++ b/nym-api/src/support/config/mod.rs @@ -110,7 +110,7 @@ impl<'a> From<&'a Config> for NymNetworkDetails { } impl NymConfigTemplate for Config { - fn template() -> &'static str { + fn template(&self) -> &'static str { CONFIG_TEMPLATE } } diff --git a/nym-browser-extension/storage/Cargo.toml b/nym-browser-extension/storage/Cargo.toml index 5d88f1a4a8..9ec0066330 100644 --- a/nym-browser-extension/storage/Cargo.toml +++ b/nym-browser-extension/storage/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "extension-storage" -version = "1.2.0-rc.2" +version = "1.2.0-rc.9" edition = "2021" license = "Apache-2.0" repository = "https://github.com/nymtech/nym" diff --git a/nym-browser-extension/storage/src/storage.rs b/nym-browser-extension/storage/src/storage.rs index 4a0874f47e..41389c8602 100644 --- a/nym-browser-extension/storage/src/storage.rs +++ b/nym-browser-extension/storage/src/storage.rs @@ -1,6 +1,12 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +// I'm not convinced by the lint (on Arc). +// Sure. wasm is currently single threaded and does not require `Send` or `Sync` +// but this data is moved across futures, so imo we should leave the Arc as it is, +// because it might cause us headache in the future +#![allow(clippy::arc_with_non_send_sync)] + use crate::ExtensionStorageError; use js_sys::Promise; use std::sync::Arc; diff --git a/nym-connect/desktop/Cargo.lock b/nym-connect/desktop/Cargo.lock index 9e3096872a..409a1ee9e2 100644 --- a/nym-connect/desktop/Cargo.lock +++ b/nym-connect/desktop/Cargo.lock @@ -1513,9 +1513,9 @@ dependencies = [ [[package]] name = "dashmap" -version = "5.5.0" +version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6943ae99c34386c84a470c499d3414f66502a41340aa895406e0d2e4a207b91d" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", "hashbrown 0.14.0", @@ -4026,7 +4026,7 @@ dependencies = [ [[package]] name = "nym-connect" -version = "1.1.20" +version = "1.1.21" dependencies = [ "anyhow", "bip39", @@ -4384,6 +4384,7 @@ dependencies = [ name = "nym-socks5-client-core" version = "0.1.0" dependencies = [ + "anyhow", "dirs 4.0.0", "futures", "log", @@ -4594,6 +4595,7 @@ dependencies = [ "tokio", "wasm-bindgen", "wasm-bindgen-futures", + "wasmtimer", ] [[package]] @@ -4604,6 +4606,7 @@ dependencies = [ "bs58 0.4.0", "log", "nym-bin-common", + "nym-config", "nym-crypto", "nym-mixnet-contract-common", "nym-sphinx-addressing", @@ -4611,6 +4614,8 @@ dependencies = [ "nym-sphinx-types", "rand 0.7.3", "semver 0.11.0", + "serde", + "serde_json", "thiserror", ] diff --git a/nym-connect/desktop/src-tauri/src/config/mod.rs b/nym-connect/desktop/src-tauri/src/config/mod.rs index 267c970069..0b8d9b0789 100644 --- a/nym-connect/desktop/src-tauri/src/config/mod.rs +++ b/nym-connect/desktop/src-tauri/src/config/mod.rs @@ -9,7 +9,8 @@ use nym_client_core::client::base_client::storage::gateway_details::OnDiskGatewa use nym_client_core::client::key_manager::persistence::OnDiskKeys; use nym_client_core::config::GatewayEndpointConfig; use nym_client_core::error::ClientCoreError; -use nym_client_core::init::GatewaySetup; +use nym_client_core::init::helpers::current_gateways; +use nym_client_core::init::types::{GatewaySelectionSpecification, GatewaySetup}; use nym_config::{ must_get_home, read_config_from_toml_file, save_formatted_config_to_file, NymConfigTemplate, DEFAULT_CONFIG_DIR, DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR, @@ -70,7 +71,7 @@ pub struct Config { } impl NymConfigTemplate for Config { - fn template() -> &'static str { + fn template(&self) -> &'static str { CONFIG_TEMPLATE } } @@ -203,7 +204,16 @@ pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: Str } let gateway_setup = if register_gateway { - GatewaySetup::new_fresh(Some(chosen_gateway_id), None) + let selection_spec = + GatewaySelectionSpecification::new(Some(chosen_gateway_id), None, false); + let mut rng = rand_07::thread_rng(); + let available_gateways = + current_gateways(&mut rng, &config.core.base.client.nym_api_urls).await?; + GatewaySetup::New { + specification: selection_spec, + available_gateways, + overwrite_data: register_gateway, + } } else { GatewaySetup::MustLoad }; @@ -212,21 +222,18 @@ pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: Str let key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone()); let details_store = OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details); - let init_details = nym_client_core::init::setup_gateway( - gateway_setup, - &key_store, - &details_store, - register_gateway, - Some(&config.core.base.client.nym_api_urls), - ) - .await? - .details; + let init_details = + nym_client_core::init::setup_gateway(gateway_setup, &key_store, &details_store).await?; + let gateway_endpoint = init_details + .gateway_details + .try_get_configured_endpoint() + .unwrap(); config.save_to_default_location().tap_err(|_| { log::error!("Failed to save the config file"); })?; - print_saved_config(&config, &init_details.gateway_details); + print_saved_config(&config, gateway_endpoint); let address = init_details.client_address()?; log::info!("The address of this client is: {address}"); diff --git a/nym-connect/desktop/src-tauri/src/config/persistence.rs b/nym-connect/desktop/src-tauri/src/config/persistence.rs index b5a67d1f54..69b311d474 100644 --- a/nym-connect/desktop/src-tauri/src/config/persistence.rs +++ b/nym-connect/desktop/src-tauri/src/config/persistence.rs @@ -14,7 +14,7 @@ pub struct NymConnectPaths { impl NymConnectPaths { pub fn new_default>(base_data_directory: P) -> Self { NymConnectPaths { - common_paths: CommonClientPaths::new_default(base_data_directory), + common_paths: CommonClientPaths::new_base(base_data_directory), } } } diff --git a/nym-connect/desktop/src-tauri/src/config/upgrade.rs b/nym-connect/desktop/src-tauri/src/config/upgrade.rs index 2f41a964f4..bdaf138a00 100644 --- a/nym-connect/desktop/src-tauri/src/config/upgrade.rs +++ b/nym-connect/desktop/src-tauri/src/config/upgrade.rs @@ -29,7 +29,7 @@ fn persist_gateway_details(config: &Config, details: GatewayEndpointConfig) -> R }, } })?; - let persisted_details = PersistedGatewayDetails::new(details, &shared_keys); + let persisted_details = PersistedGatewayDetails::new(details.into(), Some(&shared_keys))?; details_store .store_to_disk(&persisted_details) .map_err(|source| BackendError::ClientCoreError { diff --git a/nym-connect/desktop/src-tauri/src/state.rs b/nym-connect/desktop/src-tauri/src/state.rs index f9abbe2b8f..20471e6171 100644 --- a/nym-connect/desktop/src-tauri/src/state.rs +++ b/nym-connect/desktop/src-tauri/src/state.rs @@ -257,7 +257,13 @@ impl State { let (control_tx, msg_rx, exit_status_rx, used_gateway) = tasks::start_nym_socks5_client(&id, &privacy_level).await?; self.socks5_client_sender = Some(control_tx); - self.gateway = Some(used_gateway.gateway_id); + self.gateway = Some( + used_gateway + .try_get_configured_endpoint() + .unwrap() + .gateway_id + .clone(), + ); Ok((msg_rx, exit_status_rx)) } diff --git a/nym-connect/desktop/src-tauri/src/tasks.rs b/nym-connect/desktop/src-tauri/src/tasks.rs index b18cb8277d..d4264f2274 100644 --- a/nym-connect/desktop/src-tauri/src/tasks.rs +++ b/nym-connect/desktop/src-tauri/src/tasks.rs @@ -1,9 +1,10 @@ use futures::{channel::mpsc, StreamExt}; +use nym_client_core::init::types::GatewayDetails; use nym_client_core::{ client::base_client::storage::{ gateway_details::GatewayDetailsStore, MixnetClientStorage, OnDiskPersistent, }, - config::{GatewayEndpointConfig, GroupBy, TopologyStructure}, + config::{GroupBy, TopologyStructure}, error::ClientCoreStatusMessage, }; use nym_socks5_client_core::{NymClient as Socks5NymClient, Socks5ControlMessageSender}; @@ -73,7 +74,7 @@ pub async fn start_nym_socks5_client( Socks5ControlMessageSender, nym_task::StatusReceiver, ExitStatusReceiver, - GatewayEndpointConfig, + GatewayDetails, )> { log::info!("Loading config from file: {id}"); let mut config = Config::read_from_default_path(id) @@ -113,7 +114,7 @@ pub async fn start_nym_socks5_client( let result = tokio::runtime::Runtime::new() .expect("Failed to create runtime for SOCKS5 client") .block_on(async move { - let socks5_client = Socks5NymClient::new(config.core, storage); + let socks5_client = Socks5NymClient::new(config.core, storage, None); socks5_client .run_and_listen(socks5_ctrl_rx, socks5_status_tx) diff --git a/nym-connect/desktop/src/growth.tsx b/nym-connect/desktop/src/growth.tsx index d90a8bb462..683b49c2e1 100644 --- a/nym-connect/desktop/src/growth.tsx +++ b/nym-connect/desktop/src/growth.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; import { ErrorBoundary } from 'react-error-boundary'; import { ClientContextProvider } from './context/main'; import { ErrorFallback } from './components/Error'; @@ -7,17 +7,19 @@ import { NymShipyardTheme } from './theme'; import { TestAndEarnPopup } from './components/Growth/TestAndEarnPopup'; import { TestAndEarnContextProvider } from './components/Growth/context/TestAndEarnContext'; -const root = document.getElementById('root-growth'); +const elem = document.getElementById('root-growth'); -ReactDOM.render( - - - - - - - - - , - root, -); +if (elem) { + const root = createRoot(elem); + root.render( + + + + + + + + + , + ); +} diff --git a/nym-connect/desktop/src/index.tsx b/nym-connect/desktop/src/index.tsx index 4399c91cf2..996825445d 100644 --- a/nym-connect/desktop/src/index.tsx +++ b/nym-connect/desktop/src/index.tsx @@ -7,7 +7,6 @@ import { ClientContextProvider } from './context/main'; import { ErrorFallback } from './components/Error'; import { NymMixnetTheme } from './theme'; import { AppWindowFrame } from './components/AppWindowFrame'; -import { TestAndEarnContextProvider } from './components/Growth/context/TestAndEarnContext'; import { AppRoutes } from './routes'; const elem = document.getElementById('root'); @@ -18,14 +17,12 @@ if (elem) { - - - - - - - - + + + + + + , diff --git a/nym-connect/desktop/src/log.tsx b/nym-connect/desktop/src/log.tsx index cd17271368..ffce19c1d9 100644 --- a/nym-connect/desktop/src/log.tsx +++ b/nym-connect/desktop/src/log.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; import { ErrorBoundary } from 'react-error-boundary'; import { LogViewer } from './components/LogViewer'; import { ErrorFallback } from './components/ErrorFallback'; @@ -13,6 +13,9 @@ const Log = () => ( ); -const root = document.getElementById('root-log'); +const elem = document.getElementById('root-log'); -ReactDOM.render(, root); +if (elem) { + const root = createRoot(elem); + root.render(); +} diff --git a/nym-connect/desktop/webpack.common.js b/nym-connect/desktop/webpack.common.js index 38423b5e6b..dfd23f7c96 100644 --- a/nym-connect/desktop/webpack.common.js +++ b/nym-connect/desktop/webpack.common.js @@ -4,7 +4,6 @@ const { webpackCommon } = require('@nymproject/webpack'); const entry = { app: path.resolve(__dirname, 'src/index.tsx'), - growth: path.resolve(__dirname, 'src/growth.tsx'), log: path.resolve(__dirname, 'src/log.tsx'), }; @@ -19,7 +18,6 @@ module.exports = mergeWithRules({ webpackCommon(__dirname, [ { filename: 'index.html', chunks: ['app'], template: path.resolve(__dirname, 'public/index.html') }, { filename: 'log.html', chunks: ['log'], template: path.resolve(__dirname, 'public/log.html') }, - { filename: 'growth.html', chunks: ['growth'], template: path.resolve(__dirname, 'public/growth.html') }, ]), { module: { diff --git a/nym-connect/desktop/webpack.prod.js b/nym-connect/desktop/webpack.prod.js index 0e9061e25a..cb3789f7a6 100644 --- a/nym-connect/desktop/webpack.prod.js +++ b/nym-connect/desktop/webpack.prod.js @@ -4,7 +4,6 @@ const common = require('./webpack.common'); const entry = { app: path.resolve(__dirname, 'src/index.tsx'), - growth: path.resolve(__dirname, 'src/growth.tsx'), log: path.resolve(__dirname, 'src/log.tsx'), }; diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index 3cb32da98f..b00fed546d 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -3512,7 +3512,7 @@ dependencies = [ [[package]] name = "nym_wallet" -version = "1.2.7" +version = "1.2.8" dependencies = [ "async-trait", "base64 0.13.1", diff --git a/nym-wallet/package.json b/nym-wallet/package.json index 308bd4f63a..f3b4ae62d6 100644 --- a/nym-wallet/package.json +++ b/nym-wallet/package.json @@ -31,7 +31,7 @@ "@nymproject/mui-theme": "^1.0.0", "@nymproject/react": "^1.0.0", "@nymproject/types": "^1.0.0", - "@nymproject/node-tester": ">=1.2.0-rc.1 || ^1", + "@nymproject/node-tester": ">=1.2.0-rc.5", "@storybook/react": "^6.5.15", "@tauri-apps/api": "^1.2.0", "@tauri-apps/tauri-forage": "^1.0.0-beta.2", diff --git a/nym-wallet/src/components/Accounts/modals/MultiAccountHowTo.tsx b/nym-wallet/src/components/Accounts/modals/MultiAccountHowTo.tsx index 46dc3b0b27..04b50f3785 100644 --- a/nym-wallet/src/components/Accounts/modals/MultiAccountHowTo.tsx +++ b/nym-wallet/src/components/Accounts/modals/MultiAccountHowTo.tsx @@ -19,7 +19,6 @@ export const MultiAccountHowTo = ({ show, handleClose }: { show: boolean; handle In order to import or create account(s) you need to log in with password } - bgColor="#fff" /> If you don’t have a password set for your account, go to the Settings, under Security tab create a password diff --git a/nym-wallet/src/components/Bonding/modals/RedeemRewardsModal.tsx b/nym-wallet/src/components/Bonding/modals/RedeemRewardsModal.tsx index ba802967d8..11279278f6 100644 --- a/nym-wallet/src/components/Bonding/modals/RedeemRewardsModal.tsx +++ b/nym-wallet/src/components/Bonding/modals/RedeemRewardsModal.tsx @@ -37,9 +37,9 @@ export const RedeemRewardsModal = ({ return ( - + @@ -89,9 +89,9 @@ export const DelegationsActionsMenu: FCWithChildren<{ /> } onClick={() => handleActionSelect('undelegate')} /> R} + Icon={C} onClick={() => handleActionSelect('redeem')} disabled={disableRedeemingRewards} /> diff --git a/nym-wallet/src/components/Delegation/DelegationList.tsx b/nym-wallet/src/components/Delegation/DelegationList.tsx index 415843bde9..c5e0a896dd 100644 --- a/nym-wallet/src/components/Delegation/DelegationList.tsx +++ b/nym-wallet/src/components/Delegation/DelegationList.tsx @@ -22,7 +22,7 @@ interface EnhancedTableProps { interface HeadCell { id: string; - label: string; + label: string | React.ReactNode; sortable: boolean; disablePadding?: boolean; align: 'left' | 'center' | 'right'; @@ -34,7 +34,12 @@ const headCells: HeadCell[] = [ { id: 'profit_margin_percent', label: 'Profit margin', sortable: true, align: 'left' }, { id: 'operating_cost', label: 'Operating Cost', sortable: true, align: 'left' }, { id: 'stake_saturation', label: 'Stake saturation', sortable: true, align: 'left' }, - { id: 'delegated_on_iso_datetime', label: 'Delegated on', sortable: true, align: 'left' }, + { + id: 'delegated_on_iso_datetime', + label: 'Delegated on', + sortable: true, + align: 'left', + }, { id: 'amount', label: 'Delegation', sortable: true, align: 'left' }, { id: 'unclaimed_rewards', label: 'Reward', sortable: true, align: 'left' }, { id: 'uses_locked_tokens', label: '', sortable: false, align: 'left' }, diff --git a/nym-wallet/src/components/Rewards/RedeemModal.stories.tsx b/nym-wallet/src/components/Rewards/RedeemModal.stories.tsx index 0cf6e56567..9d24f95733 100644 --- a/nym-wallet/src/components/Rewards/RedeemModal.stories.tsx +++ b/nym-wallet/src/components/Rewards/RedeemModal.stories.tsx @@ -82,7 +82,7 @@ export const RedeemRewardForMixnode = () => { open={open} onClose={() => setOpen(false)} onOk={async () => setOpen(false)} - message="Redeem rewards" + message="Claim rewards" denom="nym" mixId={1234} identityKey="D88RfeY8DttMD3CQKoayV6mss5a5FC3RoH75Kmcujaaa" @@ -128,7 +128,7 @@ export const FeeIsMoreThanMixnodeReward = () => { onOk={async () => setOpen(false)} mixId={1234} identityKey="D88RfeY8DttMD3CQKoayV6mss5a5FC3RoH75Kmcujaaa" - message="Redeem rewards" + message="Claim rewards" denom="nym" amount={0.001} {...storybookStyles(theme)} diff --git a/nym-wallet/src/components/Rewards/RedeemModal.tsx b/nym-wallet/src/components/Rewards/RedeemModal.tsx index b9c774cb2e..3a513a7bee 100644 --- a/nym-wallet/src/components/Rewards/RedeemModal.tsx +++ b/nym-wallet/src/components/Rewards/RedeemModal.tsx @@ -47,7 +47,7 @@ export const RedeemModal: FCWithChildren<{ onOk={handleOk} header={message} subHeader="Rewards from delegations" - okLabel="Redeem rewards" + okLabel="Claim rewards" sx={sx} backdropProps={backdropProps} > diff --git a/nym-wallet/src/components/Rewards/RewardsSummary.tsx b/nym-wallet/src/components/Rewards/RewardsSummary.tsx index aa25ce8af9..c6e48b395c 100644 --- a/nym-wallet/src/components/Rewards/RewardsSummary.tsx +++ b/nym-wallet/src/components/Rewards/RewardsSummary.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { CircularProgress, Stack, Typography } from '@mui/material'; import { useTheme } from '@mui/material/styles'; +import { useDelegationContext } from 'src/context/delegations'; import { InfoTooltip } from '../InfoToolTip'; export const RewardsSummary: FCWithChildren<{ @@ -9,19 +10,28 @@ export const RewardsSummary: FCWithChildren<{ totalRewards?: string; }> = ({ isLoading, totalDelegation, totalRewards }) => { const theme = useTheme(); + + const { totalDelegationsAndRewards } = useDelegationContext(); return ( - - + + - + Total delegations: + + {isLoading ? : totalDelegationsAndRewards || '-'} + + + + + Original delegations: {isLoading ? : totalDelegation || '-'} - - New rewards: + + Total rewards: {isLoading ? : totalRewards || '-'} diff --git a/nym-wallet/src/context/delegations.tsx b/nym-wallet/src/context/delegations.tsx index 63ead2aa51..5f235e0703 100644 --- a/nym-wallet/src/context/delegations.tsx +++ b/nym-wallet/src/context/delegations.tsx @@ -25,6 +25,7 @@ export type TDelegationContext = { pendingDelegations?: WrappedDelegationEvent[]; totalDelegations?: string; totalRewards?: string; + totalDelegationsAndRewards?: string; refresh: () => Promise; addDelegation: ( data: { mix_id: number; amount: DecCoin }, @@ -71,6 +72,7 @@ export const DelegationContextProvider: FC<{ const [delegations, setDelegations] = useState(); const [totalDelegations, setTotalDelegations] = useState(); const [totalRewards, setTotalRewards] = useState(); + const [totalDelegationsAndRewards, setTotalDelegationsAndRewards] = useState(); const [pendingDelegations, setPendingDelegations] = useState(); const addDelegation = async (data: { mix_id: number; amount: DecCoin }, tokenPool: TPoolOption, fee?: FeeDetails) => { @@ -109,10 +111,13 @@ export const DelegationContextProvider: FC<{ }, })); + const delegationsAndRewards = (+data.total_delegations.amount + +data.total_rewards.amount).toFixed(6); + setPendingDelegations(pending); setDelegations([...items, ...pendingOnNewNodes]); setTotalDelegations(`${data.total_delegations.amount} ${data.total_delegations.denom}`); setTotalRewards(`${data.total_rewards.amount} ${data.total_rewards.denom}`); + setTotalDelegationsAndRewards(`${delegationsAndRewards} ${data.total_delegations.denom}`); } catch (e) { Console.error(e); } @@ -130,12 +135,13 @@ export const DelegationContextProvider: FC<{ pendingDelegations, totalDelegations, totalRewards, + totalDelegationsAndRewards, refresh, addDelegation, undelegate: undelegateFromMixnode, undelegateVesting: vestingUndelegateFromMixnode, }), - [isLoading, delegations, pendingDelegations, totalDelegations], + [isLoading, delegations, pendingDelegations, totalDelegations, totalRewards, totalDelegationsAndRewards], ); return {children}; diff --git a/nym-wallet/src/log.tsx b/nym-wallet/src/log.tsx index 5b4055d5be..8fc9f166c1 100644 --- a/nym-wallet/src/log.tsx +++ b/nym-wallet/src/log.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; import { ErrorBoundary } from 'react-error-boundary'; import { LogViewer } from './components/LogViewer'; import { ErrorFallback } from './components'; @@ -13,6 +13,9 @@ const Log = () => ( ); -const root = document.getElementById('root-log'); +const elem = document.getElementById('root-log'); -ReactDOM.render(, root); +if (elem) { + const root = createRoot(elem); + root.render(); +} diff --git a/nym-wallet/src/pages/delegation/index.tsx b/nym-wallet/src/pages/delegation/index.tsx index 77f0db7091..7bcd6cda06 100644 --- a/nym-wallet/src/pages/delegation/index.tsx +++ b/nym-wallet/src/pages/delegation/index.tsx @@ -354,16 +354,18 @@ export const Delegation: FC<{ isStorybook?: boolean }> = ({ isStorybook }) => { Delegations {!!delegations?.length && ( - + + Select nodes to delegate to using the + + )} {!!delegations?.length && ( @@ -445,7 +447,7 @@ export const Delegation: FC<{ isStorybook?: boolean }> = ({ isStorybook }) => { open={showRedeemRewardsModal} onClose={() => setShowRedeemRewardsModal(false)} onOk={(mixId, identity, fee) => handleRedeem(mixId, identity, fee)} - message="Redeem rewards" + message="Claim rewards" denom={clientDetails?.display_mix_denom || 'nym'} mixId={currentDelegationListActionItem.mix_id} identityKey={currentDelegationListActionItem?.node_identity} diff --git a/package.json b/package.json index 1fbdb8bf82..de7428d0d5 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "license": "Apache 2.0", "workspaces": [ "dist/wasm/**", + "dist/node/**", "sdk/typescript/packages/**", "ts-packages/*", "nym-wallet", @@ -31,9 +32,8 @@ "build:playground": "lerna run --scope @nymproject/react storybook:build --stream", "build:ci": "yarn build && run-p build:react-example build:playground && yarn build:ci:collect-artifacts", "build:ci:collect-artifacts": "mkdir -p ts-packages/dist && mv ts-packages/react-components/storybook-static ts-packages/dist/storybook && mv ts-packages/react-webpack-with-theme-example/dist ts-packages/dist/example", - "docs:prod:build": "run-p docs:prod:build:ws docs:prod:build:ts:sdk", + "docs:prod:build": "run-s docs:prod:build:ws", "docs:prod:build:ws": "lerna run docs:prod:build --stream", - "docs:prod:build:ts:sdk": "cd sdk/typescript/docs && npm i && npm run docs:prod:build", "sdk:build": "./sdk/typescript/scripts/build-prod-sdk.sh", "sdk:publish": "./sdk/typescript/scripts/publish.sh", "lint": "lerna run lint --stream", @@ -43,9 +43,9 @@ "audit:fix": "npm_config_yes=true npx yarn-audit-fix -- --dry-run" }, "devDependencies": { - "lerna": "^6.6.2", + "lerna": "^7.3.0", "npm-run-all": "^4.1.5", "@npmcli/node-gyp": "^3.0.0", "node-gyp": "^9.3.1" } -} \ No newline at end of file +} diff --git a/sdk/lib/socks5-listener/Cargo.toml b/sdk/lib/socks5-listener/Cargo.toml index fe2ff08134..462ce33b20 100644 --- a/sdk/lib/socks5-listener/Cargo.toml +++ b/sdk/lib/socks5-listener/Cargo.toml @@ -12,10 +12,6 @@ required-features = ["headers"] [lib] crate-type = ["cdylib", "staticlib", "rlib"] -[profile.release] -strip = true -codegen-units = 1 - [dependencies] anyhow = { workspace = true } futures = { workspace = true } diff --git a/sdk/lib/socks5-listener/src/config/mod.rs b/sdk/lib/socks5-listener/src/config/mod.rs index c6a7060954..5ace48c88f 100644 --- a/sdk/lib/socks5-listener/src/config/mod.rs +++ b/sdk/lib/socks5-listener/src/config/mod.rs @@ -55,7 +55,7 @@ pub struct Config { } impl NymConfigTemplate for Config { - fn template() -> &'static str { + fn template(&self) -> &'static str { CONFIG_TEMPLATE } } diff --git a/sdk/lib/socks5-listener/src/config/persistence.rs b/sdk/lib/socks5-listener/src/config/persistence.rs index cdd46aad87..525ea7066f 100644 --- a/sdk/lib/socks5-listener/src/config/persistence.rs +++ b/sdk/lib/socks5-listener/src/config/persistence.rs @@ -15,12 +15,12 @@ pub struct MobileSocksClientPaths { impl MobileSocksClientPaths { pub fn new_default>(base_data_directory: P) -> Self { MobileSocksClientPaths { - common_paths: CommonClientPaths::new_default(base_data_directory), + common_paths: CommonClientPaths::new_base(base_data_directory), } } pub fn change_root, R: AsRef>(&mut self, new_root: P, id: R) { let new_data_dir = data_directory_from_root(new_root, id); - self.common_paths = CommonClientPaths::new_default(new_data_dir) + self.common_paths = CommonClientPaths::new_base(new_data_dir) } } diff --git a/sdk/lib/socks5-listener/src/lib.rs b/sdk/lib/socks5-listener/src/lib.rs index 7c199d5f09..0c9e2f7771 100644 --- a/sdk/lib/socks5-listener/src/lib.rs +++ b/sdk/lib/socks5-listener/src/lib.rs @@ -8,9 +8,11 @@ use anyhow::{anyhow, Result}; use lazy_static::lazy_static; use log::{debug, info, warn}; use nym_bin_common::logging::setup_logging; -use nym_client_core::init::GatewaySetup; +use nym_client_core::init::helpers::current_gateways; +use nym_client_core::init::types::{GatewaySelectionSpecification, GatewaySetup}; use nym_config_common::defaults::setup_env; use nym_socks5_client_core::NymClient as Socks5NymClient; +use rand::rngs::OsRng; use safer_ffi::char_p::char_p_boxed; use std::marker::Send; use std::path::PathBuf; @@ -258,17 +260,27 @@ where F: FnMut(String), S: FnMut(), { + let mut rng = OsRng; + set_default_env(); let stop_handle = Arc::new(Notify::new()); set_shutdown_handle(stop_handle.clone()).await; let config = load_or_generate_base_config(storage_dir, client_id, service_provider).await?; + let nym_apis = config.core.base.client.nym_api_urls.clone(); + let storage = MobileClientStorage::new(&config); - let socks5_client = Socks5NymClient::new(config.core, storage) - .with_gateway_setup(GatewaySetup::New { by_latency: false }); + let socks5_client = + Socks5NymClient::new(config.core, storage, None).with_gateway_setup(GatewaySetup::New { + specification: GatewaySelectionSpecification::UniformRemote { + must_use_tls: false, + }, + available_gateways: current_gateways(&mut rng, &nym_apis).await?, + overwrite_data: false, + }); eprintln!("starting the socks5 client"); - let mut started_client = socks5_client.start().await?; + let started_client = socks5_client.start().await?; eprintln!("the client has started!"); // invoke the callback since we've started! @@ -278,8 +290,12 @@ where stop_handle.notified().await; // and then do graceful shutdown of all tasks - started_client.shutdown_handle.signal_shutdown().ok(); - started_client.shutdown_handle.wait_for_shutdown().await; + let mut task_manager = started_client + .shutdown_handle + .try_into_task_manager() + .unwrap(); + task_manager.signal_shutdown().ok(); + task_manager.wait_for_shutdown().await; // and the corresponding one for shutdown! on_shutdown_callback(); diff --git a/sdk/rust/nym-sdk/Cargo.toml b/sdk/rust/nym-sdk/Cargo.toml index 9d8cdbe621..fb5cbf4ac8 100644 --- a/sdk/rust/nym-sdk/Cargo.toml +++ b/sdk/rust/nym-sdk/Cargo.toml @@ -54,4 +54,4 @@ parking_lot = "0.12" hex = "0.4" [features] -libp2p-vanilla = [] \ No newline at end of file +libp2p-vanilla = [] diff --git a/sdk/rust/nym-sdk/examples/bandwidth.rs b/sdk/rust/nym-sdk/examples/bandwidth.rs index 377dd48527..96a064cf1d 100644 --- a/sdk/rust/nym-sdk/examples/bandwidth.rs +++ b/sdk/rust/nym-sdk/examples/bandwidth.rs @@ -16,8 +16,7 @@ async fn main() -> anyhow::Result<()> { let mixnet_client = mixnet::MixnetClientBuilder::new_ephemeral() .network_details(sandbox_network) .enable_credentials_mode() - .build() - .await?; + .build()?; let bandwidth_client = mixnet_client.create_bandwidth_client(mnemonic)?; diff --git a/sdk/rust/nym-sdk/examples/builder.rs b/sdk/rust/nym-sdk/examples/builder.rs index 6ab50bc92c..c06fc55913 100644 --- a/sdk/rust/nym-sdk/examples/builder.rs +++ b/sdk/rust/nym-sdk/examples/builder.rs @@ -9,7 +9,6 @@ async fn main() { // where you don't want to connect just yet. let client = mixnet::MixnetClientBuilder::new_ephemeral() .build() - .await .unwrap(); // Now we connect to the mixnet, using ephemeral keys already created diff --git a/sdk/rust/nym-sdk/examples/builder_with_storage.rs b/sdk/rust/nym-sdk/examples/builder_with_storage.rs index 900b2d323f..b733239f5f 100644 --- a/sdk/rust/nym-sdk/examples/builder_with_storage.rs +++ b/sdk/rust/nym-sdk/examples/builder_with_storage.rs @@ -16,7 +16,6 @@ async fn main() { .await .unwrap() .build() - .await .unwrap(); // Now we connect to the mixnet, using keys now stored in the paths provided. diff --git a/sdk/rust/nym-sdk/examples/custom_topology_provider.rs b/sdk/rust/nym-sdk/examples/custom_topology_provider.rs index 7232f5ac58..d21916e6c9 100644 --- a/sdk/rust/nym-sdk/examples/custom_topology_provider.rs +++ b/sdk/rust/nym-sdk/examples/custom_topology_provider.rs @@ -60,7 +60,6 @@ async fn main() { let mut client = mixnet::MixnetClientBuilder::new_ephemeral() .custom_topology_provider(Box::new(my_topology_provider)) .build() - .await .unwrap() .connect_to_mixnet() .await diff --git a/sdk/rust/nym-sdk/examples/manually_handle_storage.rs b/sdk/rust/nym-sdk/examples/manually_handle_storage.rs index 6130af5a25..dd650b1e2a 100644 --- a/sdk/rust/nym-sdk/examples/manually_handle_storage.rs +++ b/sdk/rust/nym-sdk/examples/manually_handle_storage.rs @@ -16,7 +16,6 @@ async fn main() { let mock_storage = MockClientStorage::empty(); let mut client = mixnet::MixnetClientBuilder::new_with_storage(mock_storage) .build() - .await .unwrap() .connect_to_mixnet() .await diff --git a/sdk/rust/nym-sdk/examples/socks5.rs b/sdk/rust/nym-sdk/examples/socks5.rs index bf028a7e76..05732db53b 100644 --- a/sdk/rust/nym-sdk/examples/socks5.rs +++ b/sdk/rust/nym-sdk/examples/socks5.rs @@ -11,11 +11,10 @@ async fn main() { let sending_client = mixnet::MixnetClientBuilder::new_ephemeral() .socks5_config(socks5_config) .build() - .await .unwrap(); println!("Connecting sender"); - let mut sending_client = sending_client.connect_to_mixnet_via_socks5().await.unwrap(); + let sending_client = sending_client.connect_to_mixnet_via_socks5().await.unwrap(); let proxy = reqwest::Proxy::all(sending_client.socks5_url()).unwrap(); let reqwest_client = reqwest::Client::builder().proxy(proxy).build().unwrap(); diff --git a/sdk/rust/nym-sdk/examples/surb-reply.rs b/sdk/rust/nym-sdk/examples/surb-reply.rs index abe955b2b9..926cac0314 100644 --- a/sdk/rust/nym-sdk/examples/surb-reply.rs +++ b/sdk/rust/nym-sdk/examples/surb-reply.rs @@ -18,7 +18,6 @@ async fn main() { .await .unwrap() .build() - .await .unwrap(); // Now we connect to the mixnet, using keys now stored in the paths provided. diff --git a/sdk/rust/nym-sdk/src/bandwidth.rs b/sdk/rust/nym-sdk/src/bandwidth.rs index e9cfb0f8fb..b1548dcb96 100644 --- a/sdk/rust/nym-sdk/src/bandwidth.rs +++ b/sdk/rust/nym-sdk/src/bandwidth.rs @@ -13,7 +13,6 @@ //! let mixnet_client = mixnet::MixnetClientBuilder::new_ephemeral() //! .enable_credentials_mode() //! .build() -//! .await //! .unwrap(); //! //! let bandwidth_client = mixnet_client.create_bandwidth_client(String::from("my super secret mnemonic")).unwrap(); diff --git a/sdk/rust/nym-sdk/src/error.rs b/sdk/rust/nym-sdk/src/error.rs index e88368b19a..e47b8b784f 100644 --- a/sdk/rust/nym-sdk/src/error.rs +++ b/sdk/rust/nym-sdk/src/error.rs @@ -93,6 +93,17 @@ pub enum Error { #[error("failed to send the provided message")] MessageSendingFailure, + + #[error("this operation is currently unsupported: {details}")] + Unsupported { details: String }, +} + +impl Error { + pub fn new_unsupported>(details: S) -> Self { + Error::Unsupported { + details: details.into(), + } + } } pub type Result = std::result::Result; diff --git a/sdk/rust/nym-sdk/src/lib.rs b/sdk/rust/nym-sdk/src/lib.rs index fee4a2f323..7834aca487 100644 --- a/sdk/rust/nym-sdk/src/lib.rs +++ b/sdk/rust/nym-sdk/src/lib.rs @@ -8,3 +8,11 @@ pub mod bandwidth; pub mod mixnet; pub use error::{Error, Result}; +pub use nym_client_core::client::mix_traffic::transceiver::*; +pub use nym_network_defaults::{ + ChainDetails, DenomDetails, DenomDetailsOwned, NymContracts, NymNetworkDetails, + ValidatorDetails, +}; +// we have to re-expose TaskClient since we're allowing custom shutdown in public API +// (which is quite a shame if you ask me...) +pub use nym_task::TaskClient; diff --git a/sdk/rust/nym-sdk/src/mixnet/client.rs b/sdk/rust/nym-sdk/src/mixnet/client.rs index 215305f408..81f6ddd730 100644 --- a/sdk/rust/nym-sdk/src/mixnet/client.rs +++ b/sdk/rust/nym-sdk/src/mixnet/client.rs @@ -5,9 +5,12 @@ use super::{connection_state::BuilderState, Config, StoragePaths}; use crate::bandwidth::BandwidthAcquireClient; use crate::mixnet::socks5_client::Socks5MixnetClient; use crate::mixnet::{CredentialStorage, MixnetClient, Recipient}; +use crate::GatewayTransceiver; +use crate::NymNetworkDetails; use crate::{Error, Result}; use futures::channel::mpsc; use futures::StreamExt; +use log::warn; use nym_client_core::client::base_client::storage::gateway_details::GatewayDetailsStore; use nym_client_core::client::base_client::storage::{ Ephemeral, MixnetClientStorage, OnDiskPersistent, @@ -15,16 +18,18 @@ use nym_client_core::client::base_client::storage::{ use nym_client_core::client::base_client::BaseClient; use nym_client_core::client::key_manager::persistence::KeyStore; use nym_client_core::config::DebugConfig; -use nym_client_core::init::GatewaySetup; +use nym_client_core::init::helpers::current_gateways; +use nym_client_core::init::types::{GatewaySelectionSpecification, GatewaySetup}; use nym_client_core::{ client::{base_client::BaseClientBuilder, replies::reply_storage::ReplyStorageBackend}, config::GatewayEndpointConfig, }; -use nym_network_defaults::NymNetworkDetails; use nym_socks5_client_core::config::Socks5; use nym_task::manager::TaskStatus; +use nym_task::{TaskClient, TaskHandle}; use nym_topology::provider_trait::TopologyProvider; use nym_validator_client::{nyxd, QueryHttpRpcNyxdClient}; +use rand::rngs::OsRng; use std::path::Path; use std::path::PathBuf; use url::Url; @@ -38,7 +43,11 @@ pub struct MixnetClientBuilder { storage_paths: Option, gateway_config: Option, socks5_config: Option, + + wait_for_gateway: bool, custom_topology_provider: Option>, + custom_gateway_transceiver: Option>, + custom_shutdown: Option, // TODO: incorporate it properly into `MixnetClientStorage` (I will need it in wasm anyway) gateway_endpoint_config_path: Option, @@ -69,11 +78,14 @@ impl MixnetClientBuilder { storage_paths: None, gateway_config: None, socks5_config: None, + wait_for_gateway: false, custom_topology_provider: None, storage: storage_paths .initialise_default_persistent_storage() .await?, gateway_endpoint_config_path: None, + custom_shutdown: None, + custom_gateway_transceiver: None, }) } } @@ -95,7 +107,10 @@ where storage_paths: None, gateway_config: None, socks5_config: None, + wait_for_gateway: false, custom_topology_provider: None, + custom_gateway_transceiver: None, + custom_shutdown: None, gateway_endpoint_config_path: None, storage, } @@ -109,7 +124,10 @@ where storage_paths: self.storage_paths, gateway_config: self.gateway_config, socks5_config: self.socks5_config, + wait_for_gateway: self.wait_for_gateway, custom_topology_provider: self.custom_topology_provider, + custom_gateway_transceiver: self.custom_gateway_transceiver, + custom_shutdown: self.custom_shutdown, gateway_endpoint_config_path: self.gateway_endpoint_config_path, storage, } @@ -169,6 +187,31 @@ where self } + /// Use an externally managed shutdown mechanism. + #[must_use] + pub fn custom_shutdown(mut self, shutdown: TaskClient) -> Self { + self.custom_shutdown = Some(shutdown); + self + } + + /// Attempt to wait for the selected gateway (if applicable) to come online if its currently not bonded. + #[must_use] + pub fn with_wait_for_gateway(mut self, wait_for_gateway: bool) -> Self { + self.wait_for_gateway = wait_for_gateway; + self + } + + /// Use custom mixnet sender that might not be the default websocket gateway connection. + /// only for advanced use + #[must_use] + pub fn custom_gateway_transceiver( + mut self, + gateway_transceiver: Box, + ) -> Self { + self.custom_gateway_transceiver = Some(gateway_transceiver); + self + } + /// Use specified file for storing gateway configuration. pub fn gateway_endpoint_config_path>(mut self, path: P) -> Self { self.gateway_endpoint_config_path = Some(path.as_ref().to_owned()); @@ -176,14 +219,12 @@ where } /// Construct a [`DisconnectedMixnetClient`] from the setup specified. - pub async fn build(self) -> Result> { - let client = DisconnectedMixnetClient::new( - self.config, - self.socks5_config, - self.storage, - self.custom_topology_provider, - ) - .await?; + pub fn build(self) -> Result> { + let client = DisconnectedMixnetClient::new(self.config, self.socks5_config, self.storage)? + .custom_gateway_transceiver(self.custom_gateway_transceiver) + .custom_topology_provider(self.custom_topology_provider) + .custom_shutdown(self.custom_shutdown) + .wait_for_gateway(self.wait_for_gateway); Ok(client) } @@ -217,6 +258,15 @@ where /// Alternative provider of network topology used for constructing sphinx packets. custom_topology_provider: Option>, + + /// advanced usage of custom gateways + custom_gateway_transceiver: Option>, + + /// Attempt to wait for the selected gateway (if applicable) to come online if its currently not bonded. + wait_for_gateway: bool, + + /// Allows passing an externally controlled shutdown handle. + custom_shutdown: Option, } impl DisconnectedMixnetClient @@ -235,11 +285,10 @@ where /// Callers have the option of supplying further parameters to: /// - store persistent identities at a location on-disk, if desired; /// - use SOCKS5 mode - async fn new( + fn new( config: Config, socks5_config: Option, storage: S, - custom_topology_provider: Option>, ) -> Result> { // don't create dkg client for the bandwidth controller if credentials are disabled let dkg_query_client = if config.enabled_credentials_mode { @@ -260,10 +309,43 @@ where state: BuilderState::New, dkg_query_client, storage, - custom_topology_provider, + custom_topology_provider: None, + custom_gateway_transceiver: None, + wait_for_gateway: false, + custom_shutdown: None, }) } + #[must_use] + pub fn custom_shutdown(mut self, shutdown: Option) -> Self { + self.custom_shutdown = shutdown; + self + } + + #[must_use] + pub fn custom_topology_provider( + mut self, + provider: Option>, + ) -> Self { + self.custom_topology_provider = provider; + self + } + + #[must_use] + pub fn custom_gateway_transceiver( + mut self, + gateway_transceiver: Option>, + ) -> Self { + self.custom_gateway_transceiver = gateway_transceiver; + self + } + + #[must_use] + pub fn wait_for_gateway(mut self, wait_for_gateway: bool) -> Self { + self.wait_for_gateway = wait_for_gateway; + self + } + fn get_api_endpoints(&self) -> Vec { self.config .network_details @@ -288,16 +370,34 @@ where /// key, however, is created during the gateway registration handshake so it might not /// necessarily be available. /// Furthermore, it has to be coupled with particular gateway's config. - async fn has_gateway_info(&self) -> bool { - let has_keys = self.storage.key_store().load_keys().await.is_ok(); - let has_gateway_details = self + async fn has_valid_gateway_info(&self) -> bool { + let keys = match self.storage.key_store().load_keys().await { + Ok(keys) => keys, + Err(err) => { + warn!("failed to load stored keys: {err}"); + return false; + } + }; + + let gateway_details = match self .storage .gateway_details_store() .load_gateway_details() .await - .is_ok(); + { + Ok(details) => details, + Err(err) => { + warn!("failed to load stored gateway details: {err}"); + return false; + } + }; + + if let Err(err) = gateway_details.validate(keys.gateway_shared_key().as_deref()) { + warn!("stored key verification failure: {err}"); + return false; + } - has_keys && has_gateway_details + true } /// Register with a gateway. If a gateway is provided in the config then that will try to be @@ -316,10 +416,22 @@ where let api_endpoints = self.get_api_endpoints(); - let gateway_setup = if self.has_gateway_info().await { + let gateway_setup = if self.has_valid_gateway_info().await { GatewaySetup::MustLoad } else { - GatewaySetup::new_fresh(self.config.user_chosen_gateway.clone(), None) + let selection_spec = GatewaySelectionSpecification::new( + self.config.user_chosen_gateway.clone(), + None, + false, + ); + + let mut rng = OsRng; + + GatewaySetup::New { + specification: selection_spec, + available_gateways: current_gateways(&mut rng, &api_endpoints).await?, + overwrite_data: !self.config.key_mode.is_keep(), + } }; // this will perform necessary key and details load and optional store @@ -327,8 +439,6 @@ where gateway_setup, self.storage.key_store(), self.storage.gateway_details_store(), - !self.config.key_mode.is_keep(), - Some(&api_endpoints), ) .await?; @@ -367,24 +477,40 @@ where // a temporary workaround let base_config = self .config - .as_base_client_config(nyxd_endpoints, nym_api_endpoints); + .as_base_client_config(nyxd_endpoints, nym_api_endpoints.clone()); - let known_gateway = self.has_gateway_info().await; + let known_gateway = self.has_valid_gateway_info().await; let mut base_builder: BaseClientBuilder<_, _> = - BaseClientBuilder::new(&base_config, self.storage, self.dkg_query_client); + BaseClientBuilder::new(&base_config, self.storage, self.dkg_query_client) + .with_wait_for_gateway(self.wait_for_gateway); if !known_gateway { - base_builder = base_builder.with_gateway_setup(GatewaySetup::new_fresh( - self.config.user_chosen_gateway, - None, - )) + let selection_spec = + GatewaySelectionSpecification::new(self.config.user_chosen_gateway, None, false); + + let mut rng = OsRng; + let setup = GatewaySetup::New { + specification: selection_spec, + available_gateways: current_gateways(&mut rng, &nym_api_endpoints).await?, + overwrite_data: !self.config.key_mode.is_keep(), + }; + + base_builder = base_builder.with_gateway_setup(setup) } if let Some(topology_provider) = self.custom_topology_provider { base_builder = base_builder.with_topology_provider(topology_provider); } + if let Some(custom_shutdown) = self.custom_shutdown { + base_builder = base_builder.with_shutdown(custom_shutdown) + } + + if let Some(gateway_transceiver) = self.custom_gateway_transceiver { + base_builder = base_builder.with_gateway_transceiver(gateway_transceiver); + } + let started_client = base_builder.start_base().await?; self.state = BuilderState::Registered {}; let nym_address = started_client.address; @@ -412,7 +538,6 @@ where /// let client = mixnet::MixnetClientBuilder::new_ephemeral() /// .socks5_config(socks5_config) /// .build() - /// .await /// .unwrap(); /// let client = client.connect_to_mixnet_via_socks5().await.unwrap(); /// } @@ -438,29 +563,34 @@ where client_output, client_state.clone(), nym_address, - started_client.task_manager.subscribe(), + started_client.task_handle.get_handle(), packet_type, ); - started_client - .task_manager - .start_status_listener(socks5_status_tx) - .await; - match socks5_status_rx - .next() - .await - .ok_or(Error::Socks5NotStarted)? - .downcast_ref::() - .ok_or(Error::Socks5NotStarted)? - { - TaskStatus::Ready => { - log::debug!("Socks5 connected"); + + // TODO: more graceful handling here, surely both variants should work... I think? + if let TaskHandle::Internal(task_manager) = &mut started_client.task_handle { + task_manager.start_status_listener(socks5_status_tx).await; + match socks5_status_rx + .next() + .await + .ok_or(Error::Socks5NotStarted)? + .downcast_ref::() + .ok_or(Error::Socks5NotStarted)? + { + TaskStatus::Ready => { + log::debug!("Socks5 connected"); + } } + } else { + return Err(Error::new_unsupported( + "connecting with socks5 is currently unsupported with custom shutdown", + )); } Ok(Socks5MixnetClient { nym_address, client_state, - task_manager: started_client.task_manager, + task_handle: started_client.task_handle, socks5_config, }) } @@ -481,7 +611,6 @@ where /// async fn main() { /// let client = mixnet::MixnetClientBuilder::new_ephemeral() /// .build() - /// .await /// .unwrap(); /// let client = client.connect_to_mixnet().await.unwrap(); /// } @@ -503,7 +632,7 @@ where client_output, client_state, reconstructed_receiver, - started_client.task_manager, + started_client.task_handle, None, )) } diff --git a/sdk/rust/nym-sdk/src/mixnet/native_client.rs b/sdk/rust/nym-sdk/src/mixnet/native_client.rs index 3266b37506..519961d6fd 100644 --- a/sdk/rust/nym-sdk/src/mixnet/native_client.rs +++ b/sdk/rust/nym-sdk/src/mixnet/native_client.rs @@ -13,7 +13,7 @@ use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::{params::PacketType, receiver::ReconstructedMessage}; use nym_task::{ connections::{ConnectionCommandSender, LaneQueueLengths}, - TaskManager, + TaskHandle, }; use nym_topology::NymTopology; use std::pin::Pin; @@ -24,7 +24,7 @@ pub struct MixnetClient { /// The nym address of this connected client. pub(crate) nym_address: Recipient, - /// Input to the client from the users perspective. This can be either data to send or controll + /// Input to the client from the users perspective. This can be either data to send or control /// messages. pub(crate) client_input: ClientInput, @@ -40,8 +40,8 @@ pub struct MixnetClient { /// A channel for messages arriving from the mixnet after they have been reconstructed. pub(crate) reconstructed_receiver: ReconstructedMessagesReceiver, - /// The task manager that controlls all the spawned tasks that the clients uses to do it's job. - pub(crate) task_manager: TaskManager, + /// The task manager that controls all the spawned tasks that the clients uses to do it's job. + pub(crate) task_handle: TaskHandle, pub(crate) packet_type: Option, // internal state used for the `Stream` implementation @@ -55,7 +55,7 @@ impl MixnetClient { client_output: ClientOutput, client_state: ClientState, reconstructed_receiver: ReconstructedMessagesReceiver, - task_manager: TaskManager, + task_handle: TaskHandle, packet_type: Option, ) -> Self { Self { @@ -64,7 +64,7 @@ impl MixnetClient { client_output, client_state, reconstructed_receiver, - task_manager, + task_handle, packet_type, _buffered: Vec::new(), } @@ -86,8 +86,7 @@ impl MixnetClient { /// ``` pub async fn connect_new() -> Result { MixnetClientBuilder::new_ephemeral() - .build() - .await? + .build()? .connect_to_mixnet() .await } @@ -158,9 +157,14 @@ impl MixnetClient { /// Disconnect from the mixnet. Currently it is not supported to reconnect a disconnected /// client. - pub async fn disconnect(&mut self) { - self.task_manager.signal_shutdown().ok(); - self.task_manager.wait_for_shutdown().await; + pub async fn disconnect(mut self) { + if let TaskHandle::Internal(task_manager) = &mut self.task_handle { + task_manager.signal_shutdown().ok(); + task_manager.wait_for_shutdown().await; + } + + // note: it's important to take ownership of the struct as if the shutdown is `TaskHandle::External`, + // it must be dropped to finalize the shutdown } } diff --git a/sdk/rust/nym-sdk/src/mixnet/socks5_client.rs b/sdk/rust/nym-sdk/src/mixnet/socks5_client.rs index add4294f4e..776fd8b9b3 100644 --- a/sdk/rust/nym-sdk/src/mixnet/socks5_client.rs +++ b/sdk/rust/nym-sdk/src/mixnet/socks5_client.rs @@ -1,7 +1,7 @@ use nym_client_core::client::base_client::ClientState; use nym_socks5_client_core::config::Socks5; use nym_sphinx::addressing::clients::Recipient; -use nym_task::{connections::LaneQueueLengths, TaskManager}; +use nym_task::{connections::LaneQueueLengths, TaskHandle}; use nym_topology::NymTopology; @@ -17,8 +17,8 @@ pub struct Socks5MixnetClient { /// current message send queue length. pub(crate) client_state: ClientState, - /// The task manager that controlls all the spawned tasks that the clients uses to do it's job. - pub(crate) task_manager: TaskManager, + /// The task manager that controls all the spawned tasks that the clients uses to do it's job. + pub(crate) task_handle: TaskHandle, /// SOCKS5 configuration parameters. pub(crate) socks5_config: Socks5, @@ -43,8 +43,7 @@ impl Socks5MixnetClient { pub async fn connect_new>(provider_mix_address: S) -> Result { MixnetClientBuilder::new_ephemeral() .socks5_config(Socks5::new(provider_mix_address)) - .build() - .await? + .build()? .connect_to_mixnet_via_socks5() .await } @@ -87,8 +86,13 @@ impl Socks5MixnetClient { /// Disconnect from the mixnet. Currently it is not supported to reconnect a disconnected /// client. - pub async fn disconnect(&mut self) { - self.task_manager.signal_shutdown().ok(); - self.task_manager.wait_for_shutdown().await; + pub async fn disconnect(mut self) { + if let TaskHandle::Internal(task_manager) = &mut self.task_handle { + task_manager.signal_shutdown().ok(); + task_manager.wait_for_shutdown().await; + } + + // note: it's important to take ownership of the struct as if the shutdown is `TaskHandle::External`, + // it must be dropped to finalize the shutdown } } diff --git a/sdk/typescript/codegen/contract-clients/README.md b/sdk/typescript/codegen/contract-clients/README.md index c311b7e9c7..b2f52cbd8d 100644 --- a/sdk/typescript/codegen/contract-clients/README.md +++ b/sdk/typescript/codegen/contract-clients/README.md @@ -23,7 +23,7 @@ async function main() { const accounts = await signer.getAccounts(); // make a signing client for the Nym Mixnet contract on mainnet - const cosmWasmSigningClient = await SigningCosmWasmClient.connectWithSigner("rpc.nymtech.net:443", signer); + const cosmWasmSigningClient = await SigningCosmWasmClient.connectWithSigner("https://rpc.nymtech.net:443", signer); const client = new contracts.Mixnet.MixnetClient(cosmWasmSigningClient, accounts[0].address, 'n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr'); // delegate 1 NYM to mixnode with id 100 diff --git a/sdk/typescript/codegen/contract-clients/package.json b/sdk/typescript/codegen/contract-clients/package.json index 7f70204918..e898a2201f 100644 --- a/sdk/typescript/codegen/contract-clients/package.json +++ b/sdk/typescript/codegen/contract-clients/package.json @@ -1,13 +1,15 @@ { "name": "@nymproject/contract-clients", - "version": "1.2.0-rc.1", + "version": "1.2.0-rc.9", "description": "A client for all Nym smart contracts", + "license": "Apache-2.0", + "author": "Nym Technologies SA", "main": "dist/index.js", "browser": "dist/index.js", - "types": "./dist/index.d.ts", "scripts": { - "build": "tsc", + "build": "./scripts/build-prod.sh", "build:autogen": "node build.mjs", + "build:tsc": "tsc", "docs:dev": "run-p docs:watch docs:serve ", "docs:generate": "typedoc", "docs:generate:prod": "typedoc --basePath ./docs/tsdoc/nymproject/contract-clients/", @@ -20,10 +22,9 @@ "nodemon": "3.0.1", "npm-run-all": "^4.1.5", "reload": "^3.2.1", - "typescript": "^4.6.2", - "typedoc": "^0.24.8" + "typedoc": "^0.24.8", + "typescript": "^4.6.2" }, - "keywords": [], - "author": "", - "license": "Apache-2.0" -} + "private": false, + "types": "./dist/index.d.ts" +} \ No newline at end of file diff --git a/sdk/typescript/codegen/contract-clients/scripts/build-prod-docs-collect.sh b/sdk/typescript/codegen/contract-clients/scripts/build-prod-docs-collect.sh new file mode 100755 index 0000000000..17382f7fec --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/scripts/build-prod-docs-collect.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +rm -rf ../../../../dist/ts/docs/tsdoc/nymproject/contract-clients || true + +# run the build +yarn docs:generate:prod + +# move the output outside of the yarn/npm workspaces +mkdir -p ../../../../dist/ts/docs/tsdoc/nymproject +mv docs ../../../../dist/ts/docs/tsdoc/nymproject/contract-clients + +echo "Output can be found in:" +realpath ../../../../dist/ts/docs/tsdoc/nymproject/contract-clients diff --git a/sdk/typescript/codegen/contract-clients/scripts/build-prod.sh b/sdk/typescript/codegen/contract-clients/scripts/build-prod.sh new file mode 100755 index 0000000000..5eff4de112 --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/scripts/build-prod.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +rm -rf dist || true +rm -rf ../../../../dist/ts/sdk/contract-clients || true + +# run the build +npm run build:tsc +node scripts/buildPackageJson.mjs +cp README.md dist + +# move the output outside of the yarn/npm workspaces +mkdir -p ../../../../dist/ts/sdk +mv dist ../../../../dist/ts/sdk +mv ../../../../dist/ts/sdk/dist ../../../../dist/ts/sdk/contract-clients + +echo "Output can be found in:" +realpath ../../../../dist/ts/sdk/contract-clients diff --git a/sdk/typescript/codegen/contract-clients/scripts/buildPackageJson.mjs b/sdk/typescript/codegen/contract-clients/scripts/buildPackageJson.mjs new file mode 100644 index 0000000000..ff91d755ca --- /dev/null +++ b/sdk/typescript/codegen/contract-clients/scripts/buildPackageJson.mjs @@ -0,0 +1,22 @@ +import * as fs from 'fs'; + +// parse the package.json from the SDK, so we can keep fields like the name and version +const json = JSON.parse(fs.readFileSync('package.json').toString()); + +// defaults (NB: these are in the output file locations) +const browser = 'index.js'; +const main = 'index.js'; +const types = 'index.d.ts'; + +const getPackageJson = (type) => ({ + name: json.name, + version: json.version, + license: json.license, + author: json.author, + type, + browser, + main, + types, +}); + +fs.writeFileSync('dist/package.json', JSON.stringify(getPackageJson('module'), null, 2)); diff --git a/sdk/typescript/docs/.gitignore b/sdk/typescript/docs/.gitignore index 1fcb1529f8..46f9bd0984 100644 --- a/sdk/typescript/docs/.gitignore +++ b/sdk/typescript/docs/.gitignore @@ -1 +1,6 @@ +.next +node_modules out + +# the lock file will break Vercel because it may get committed from a machine with a different build architecture +package-lock.json diff --git a/sdk/typescript/docs/code-examples/cosmoskit-example-code.mdx b/sdk/typescript/docs/code-examples/cosmoskit-example-code.mdx new file mode 100644 index 0000000000..dd04d7c466 --- /dev/null +++ b/sdk/typescript/docs/code-examples/cosmoskit-example-code.mdx @@ -0,0 +1,190 @@ +```ts copy filename="CosmosKitExample.tsx" +import React, { FC } from 'react'; +import { ChainProvider, useChain } from '@cosmos-kit/react'; +import { assets, chains } from 'chain-registry'; +import { wallets as keplr } from '@cosmos-kit/keplr'; +import { wallets as ledger } from '@cosmos-kit/ledger'; +import Button from '@mui/material/Button'; +import CircularProgress from '@mui/material/CircularProgress'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import { Alert, AlertTitle } from '@mui/material'; +import { Wallet } from '@cosmos-kit/core'; +import { CosmosKitLedger } from './ledger'; +import { CosmosKitSign } from './sign'; + +const CosmosKitSetup: FC<{ children: React.ReactNode }> = ({ children }) => { + const assetsFixedUp = React.useMemo(() => { + const nyx = assets.find((a) => a.chain_name === 'nyx'); + if (nyx) { + const nyxCoin = nyx.assets.find((a) => a.name === 'nyx'); + if (nyxCoin) { + nyxCoin.coingecko_id = 'nyx'; + } + nyx.assets = nyx.assets.reverse(); + } + return assets; + }, [assets]); + + const chainsFixedUp = React.useMemo(() => { + const nyx = chains.find((c) => c.chain_id === 'nyx'); + if (nyx) { + if (!nyx.staking) { + nyx.staking = { + staking_tokens: [{ denom: 'unyx' }], + lock_duration: { + blocks: 10000, + }, + }; + } + } + return chains; + }, [chains]); + + return ( + 'amino', + }} + > + {children} + + ); +}; + +function walletRejectMessageOrError(wallet?: Wallet, error?: React.ReactNode) { + if (!wallet) { + if (!error) { + return undefined; + } + return error; + } + if (typeof wallet.rejectMessage === 'string') { + return wallet.rejectMessage; + } + return wallet.rejectMessage.source; +} +const Wrapper: FC<{ + children?: React.ReactNode; + wallet?: Wallet; + header?: React.ReactNode; + error?: React.ReactNode; + disconnect: () => Promise; +}> = ({ wallet, disconnect, error, header, children }) => { + if (error) { + return ( + + + {wallet && Failed to connect to {wallet.prettyName}} + {wallet && walletRejectMessageOrError(wallet)} + + + + + + ); + } + return ( + + + {header && header} + + + {children} + + ); +}; + +const CosmosKitInner = () => { + const { + wallet, + address, + connect, + disconnect, + isWalletConnecting, + isWalletDisconnected, + isWalletError, + isWalletNotExist, + isWalletRejected, + } = useChain('nyx'); + + if (isWalletError) { + return ; + } + + if (isWalletNotExist) { + return ; + } + + if (isWalletRejected) { + return ( + + ); + } + + if (isWalletDisconnected) { + return ( + + ); + } + + if (isWalletConnecting) { + return ; + } + + // Ledger Hardware Wallet + if (wallet.mode === 'ledger') { + return ( + + Connected to {wallet.prettyName} + + Address: {address}{' '} + + + } + disconnect={disconnect} + > + + + ); + } + + // Extension or Wallet Connect + return ( + + Connected to {wallet.prettyName} + + Address: {address}{' '} + + + } + disconnect={disconnect} + > + + + ); +}; + +export const CosmosKit = () => ( + + + +); +``` diff --git a/sdk/typescript/docs/code-examples/mixfetch-example-code.mdx b/sdk/typescript/docs/code-examples/mixfetch-example-code.mdx new file mode 100644 index 0000000000..70ba77f9d1 --- /dev/null +++ b/sdk/typescript/docs/code-examples/mixfetch-example-code.mdx @@ -0,0 +1,80 @@ +```ts copy filename="mixFetchExample.tsx" +import React, { useState } from 'react'; +import CircularProgress from '@mui/material/CircularProgress'; +import Button from '@mui/material/Button'; +import TextField from '@mui/material/TextField'; +import Typography from '@mui/material/Typography'; +import Box from '@mui/material/Box'; +import { mixFetch } from '@nymproject/mix-fetch-full-fat'; +import Stack from '@mui/material/Stack'; +import Paper from '@mui/material/Paper'; + +const defaultUrl = 'https://nymtech.net/favicon.svg'; +const args = { mode: 'unsafe-ignore-cors' }; +const mixFetchOptions = { + preferredGateway: 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM', + preferredNetworkRequester: + 'GiRjFWrMxt58pEMuusm4yT3RxoMD1MMPrR9M2N4VWRJP.3CNZBPq4vg7v7qozjGjdPMXcvDmkbWPCgbGCjQVw9n6Z@2xU4CBE6QiiYt6EyBXSALwxkNvM7gqJfjHXaMkjiFmYW', + mixFetchOverride: { + requestTimeoutMs: 60_000, + }, +}; + +export const MixFetch = () => { + const [url, setUrl] = useState(defaultUrl); + const [html, setHtml] = useState(); + const [busy, setBusy] = useState(false); + + const handleFetch = async () => { + try { + setBusy(true); + setHtml(undefined); + const response = await mixFetch(url, args, mixFetchOptions); + console.log(response); + const resHtml = await response.text(); + setHtml(resHtml); + } catch (err) { + console.log(err); + } finally { + setBusy(false); + } + }; + + return ( +

+ + setUrl(e.target.value)} + /> + + + + {busy && ( + + + + )} + {html && ( + <> + + Response + + + + {html} + + + + )} +
+ ); +}; +``` diff --git a/sdk/typescript/docs/code-examples/mixnodes-example-code.mdx b/sdk/typescript/docs/code-examples/mixnodes-example-code.mdx new file mode 100644 index 0000000000..e0624287bd --- /dev/null +++ b/sdk/typescript/docs/code-examples/mixnodes-example-code.mdx @@ -0,0 +1,54 @@ +```ts copy filename="MixnodeContractQueryExample.ts" +import { useEffect, useState } from "react"; +import { contracts } from "@nymproject/contract-clients"; +import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate"; +import { settings } from "./client"; +import Box from "@mui/material/Box"; +import CircularProgress from "@mui/material/CircularProgress"; + +const getClient = async () => { + const cosmWasmClient = await SigningCosmWasmClient.connect(settings.url); + + const client = new contracts.Mixnet.MixnetQueryClient( + cosmWasmClient, + settings.mixnetContractAddress + ); + return client; +}; + +export const Mixnodes = () => { + const [mixnodes, setMixnodes] = useState(); + + const getMixnodes = async () => { + const client = await getClient(); + const { nodes } = await client.getMixNodesDetailed({}); + setMixnodes(nodes); + }; + + useEffect(() => { + getMixnodes(); + }, []); + + if (!mixnodes) { + return ( + + + + ); + } + + return ( +
+ {mixnodes?.length && + mixnodes.map((mixnode: any) => ( + + {`id: ${mixnode.bond_information.mix_id}`} + {`owner: ${mixnode.bond_information.owner}`} + + ))} +
+ ); +}; +``` diff --git a/sdk/typescript/docs/code-examples/traffic-example-code.mdx b/sdk/typescript/docs/code-examples/traffic-example-code.mdx new file mode 100644 index 0000000000..d64b300479 --- /dev/null +++ b/sdk/typescript/docs/code-examples/traffic-example-code.mdx @@ -0,0 +1,102 @@ +```ts copy filename="MixnetWASMClientExample.tsx" +import React, { useEffect, useState } from 'react'; +import { createNymMixnetClient, NymMixnetClient, Payload } from '@nymproject/sdk-full-fat'; +import Box from '@mui/material/Box'; +import CircularProgress from '@mui/material/CircularProgress'; +import Paper from '@mui/material/Paper'; +import Typography from '@mui/material/Typography'; +import Stack from '@mui/material/Stack'; +import TextField from '@mui/material/TextField'; +import Button from '@mui/material/Button'; + +const nymApiUrl = 'https://validator.nymtech.net/api'; + +export const Traffic = () => { + const [nym, setNym] = useState(); + const [selfAddress, setSelfAddress] = useState(); + const [recipient, setRecipient] = useState(); + const [payload, setPayload] = useState(); + const [receivedMessage, setReceivedMessage] = useState(); + + const init = async () => { + const client = await createNymMixnetClient(); + setNym(client); + + await client?.client.start({ + clientId: crypto.randomUUID(), + nymApiUrl, + }); + + client?.events.subscribeToConnected((e) => { + const { address } = e.args; + setSelfAddress(address); + }); + + client?.events.subscribeToLoaded((e) => { + console.log('Client ready: ', e.args); + }); + + + client?.events.subscribeToTextMessageReceivedEvent((e) => { + console.log(e.args.payload); + setReceivedMessage(e.args.payload); + }); + }; + + const stop = async () => { + await nym?.client.stop(); + }; + + const send = () => nym.client.send({ payload, recipient }); + + useEffect(() => { + init(); + return () => { + stop(); + }; + }, []); + + if (!nym || !selfAddress) { + return ( + + + + ); + } + + return ( + + + + My self address is: + {selfAddress || 'loading'} + Communication through the Mixnet + setRecipient(e.target.value)} + size="small" + /> + setPayload({ message: e.target.value, mimeType: 'text/plain' })} + size="small" + /> + + + {receivedMessage && ( + + Message Received! + {receivedMessage} + + )} + + + ); +}; +``` diff --git a/sdk/typescript/docs/code-examples/wallet-example-code.mdx b/sdk/typescript/docs/code-examples/wallet-example-code.mdx new file mode 100644 index 0000000000..c131b74282 --- /dev/null +++ b/sdk/typescript/docs/code-examples/wallet-example-code.mdx @@ -0,0 +1,384 @@ +```ts copy filename="WalletSigningClientExample.tsx" +import React, { useCallback, useEffect, useState } from 'react'; +import { contracts } from '@nymproject/contract-clients'; +import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'; +import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing'; +import { Coin, GasPrice } from '@cosmjs/stargate'; +import Button from '@mui/material/Button'; +import Input from '@mui/material/Input'; +import Paper from '@mui/material/Paper'; +import Box from '@mui/material/Box'; +import { TableBody, TableCell, TableHead, TableRow, TextField, Typography } from '@mui/material'; +import Divider from '@mui/material/Divider'; +import Table from '@mui/material/Table'; +import LoadingButton from '@mui/lab/LoadingButton'; +import SaveIcon from '@mui/icons-material/Save'; +import { settings } from './client'; + +const signerAccount = async (mnemonic) => { + const signer = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { + prefix: 'n', + }); + + return signer; +}; + +const fetchSignerCosmosWasmClient = async (mnemonic) => { + const signer = await signerAccount(mnemonic); + + const cosmWasmClient = await SigningCosmWasmClient.connectWithSigner(settings.url, signer, { + gasPrice: GasPrice.fromString('0.025unym'), + }); + + return cosmWasmClient; +}; + +const fetchSignerClient = async (mnemonic) => { + const signer = await signerAccount(mnemonic); + + const cosmWasmClient = await SigningCosmWasmClient.connectWithSigner(settings.url, signer, { + gasPrice: GasPrice.fromString('0.025unym'), + }); + + /** create a mixnet contract client + * @param cosmWasmClient the client to use for signing and querying + * @param settings.address the bech32 address prefix (human readable part) + * @param settings.mixnetContractAddress the bech32 address prefix (human readable part) + * @returns the client in MixnetClient form + */ + + const mixnetClient = new contracts.Mixnet.MixnetClient( + cosmWasmClient, + settings.address, // sender (that account of the signer) + settings.mixnetContractAddress, // contract address (different on mainnet, QA, etc) + ); + + return mixnetClient; +}; + +export const Wallet = () => { + const [mnemonic, setMnemonic] = useState(); + const [signerCosmosWasmClient, setSignerCosmosWasmClient] = useState(); + const [signerClient, setSignerClient] = useState(); + const [account, setAccount] = useState(); + const [accountLoading, setAccountLoading] = useState(false); + const [clientLoading, setClientLoading] = useState(false); + const [balance, setBalance] = useState(); + const [balanceLoading, setBalanceLoading] = useState(false); + const [log, setLog] = useState([]); + const [tokensToSend, setTokensToSend] = useState(); + const [sendingTokensLoader, setSendingTokensLoader] = useState(false); + const [delegations, setDelegations] = useState(); + const [recipientAddress, setRecipientAddress] = useState(''); + const [delegationNodeId, setDelegationNodeId] = useState(); + const [amountToBeDelegated, setAmountToBeDelegated] = useState(); + const [delegationLoader, setDelegationLoader] = useState(false); + const [undeledationLoader, setUndeledationLoader] = useState(false); + const [withdrawLoading, setWithdrawLoading] = useState(false); + + const getBalance = useCallback(async () => { + setBalanceLoading(true); + try { + const newBalance = await signerCosmosWasmClient?.getBalance(account, 'unym'); + setBalance(newBalance); + } catch (error) { + console.error(error); + } + setBalanceLoading(false); + }, [account, signerCosmosWasmClient]); + + const getSignerAccount = async () => { + setAccountLoading(true); + try { + const signer = await signerAccount(mnemonic); + const accounts = await signer.getAccounts(); + if (accounts[0]) { + setAccount(accounts[0].address); + } + } catch (error) { + console.error(error); + } + setAccountLoading(false); + }; + + const getClients = async () => { + setClientLoading(true); + try { + setSignerCosmosWasmClient(await fetchSignerCosmosWasmClient(mnemonic)); + setSignerClient(await fetchSignerClient(mnemonic)); + } catch (error) { + console.error(error); + } + setClientLoading(false); + }; + + const getDelegations = useCallback(async () => { + const newDelegations = await signerClient.getDelegatorDelegations({ + delegator: settings.address, + }); + setDelegations(newDelegations); + }, [signerClient]); + + const connect = () => { + getSignerAccount(); + getClients(); + }; + + const doUndelegateAll = async () => { + if (!signerClient) { + return; + } + setUndeledationLoader(true); + try { + // eslint-disable-next-line no-restricted-syntax + for (const delegation of delegations.delegations) { + // eslint-disable-next-line no-await-in-loop + await signerClient.undelegateFromMixnode({ mixId: delegation.mix_id }, 'auto'); + } + } catch (error) { + console.error(error); + } + setUndeledationLoader(false); + }; + + const doDelegate = async ({ mixId, amount }: { mixId: number; amount: number }) => { + if (!signerClient) { + return; + } + setDelegationLoader(true); + try { + const res = await signerClient.delegateToMixnode({ mixId }, 'auto', undefined, [ + { amount: `${amount}`, denom: 'unym' }, + ]); + console.log('res', res); + setLog((prev) => [ + ...prev, +
+ {new Date().toLocaleTimeString()} +
{JSON.stringify(res, null, 2)}
+
, + ]); + } catch (error) { + console.error(error); + } + setDelegationLoader(false); + }; + // End delegate + + // Sending tokens + const doSendTokens = async () => { + const memo = 'test sending tokens'; + setSendingTokensLoader(true); + try { + const res = await signerCosmosWasmClient.sendTokens( + account, + recipientAddress, + [{ amount: tokensToSend, denom: 'unym' }], + 'auto', + memo, + ); + setLog((prev) => [ + ...prev, +
+ {new Date().toLocaleTimeString()} +
{JSON.stringify(res, null, 2)}
+
, + ]); + } catch (error) { + console.error(error); + } + setSendingTokensLoader(false); + }; + // End send tokens + + // Withdraw Rewards + const doWithdrawRewards = async () => { + const delegatorAddress = ''; + const validatorAdress = ''; + const memo = 'test sending tokens'; + setWithdrawLoading(true); + try { + const res = await signerCosmosWasmClient.withdrawRewards(delegatorAddress, validatorAdress, 'auto', memo); + setLog((prev) => [ + ...prev, +
+ {new Date().toLocaleTimeString()} +
{JSON.stringify(res, null, 2)}
+
, + ]); + } catch (error) { + console.error(error); + } + setWithdrawLoading(false); + }; + + useEffect(() => { + if (account && signerCosmosWasmClient) { + if (!balance) { + setBalanceLoading(true); + getBalance(); + setBalanceLoading(false); + } + } + }, [account, signerCosmosWasmClient, balance, getBalance]); + + useEffect(() => { + if (signerClient && !delegations) { + console.log('getDelegations'); + getDelegations(); + } + }, [signerClient, getDelegations, delegations]); + + return ( + + + + Basic Wallet + + + Your account + + + Enter the mnemonic + + setMnemonic(e.target.value)} + fullWidth + multiline + maxRows={4} + sx={{ marginBottom: 3 }} + /> + + + {account && balance ? ( + + Address: {account} + + Balance: {balance?.amount} {balance?.denom} + + + ) : ( + + Please, enter your nemonic to receive your account info + + )} + + + + Send Tokens + + setRecipientAddress(e.target.value)} + size="small" + /> + + setTokensToSend(e.target.value)} + size="small" + /> + + + + + + + Delegations + + + + Make a delegation + + setDelegationNodeId(e.target.value)} + size="small" + /> + + setAmountToBeDelegated(e.target.value)} + size="small" + /> + + + + + + Your delegations + + {!delegations?.delegations?.length ? ( + You do not have delegations + ) : ( + + + + + MixId + Owner + Amount + Cumulative Reward Ratio + + + + {delegations?.delegations.map((delegation: any) => ( + + {delegation.mix_id} + {delegation.owner} + {delegation.amount.amount} + {delegation.cumulative_reward_ratio} + + ))} + +
+
+ )} +
+ {delegations && ( + + + + )} + + + +
+
+
+ + + Transaction Logs: + {log} + +
+ ); +}; + +``` diff --git a/sdk/typescript/docs/components/client/index.ts b/sdk/typescript/docs/components/client/index.ts new file mode 100644 index 0000000000..afaf1253e8 --- /dev/null +++ b/sdk/typescript/docs/components/client/index.ts @@ -0,0 +1,15 @@ +export const mainnetSettings = { + url: 'wss://rpc.nymtech.net:443', + mixnetContractAddress: 'n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr', + mnemonic: process.env.MAINNET_MNEMONIC, + address: 'n1c7y676pe3av76r5usala759xgj0yplmvngu8u8', +}; + +export const qaSettings = { + url: 'wss://sandbox-validator1.nymtech.net/', + mixnetContractAddress: 'n1xr3rq8yvd7qplsw5yx90ftsr2zdhg4e9z60h5duusgxpv72hud3sjkxkav', + mnemonic: process.env.QA_MNEMONIC, + address: 'n13uryxldwdllpakevsmt6n0uyfn3kgr2wvj5dnf', +}; + +export const settings = qaSettings; diff --git a/sdk/typescript/docs/components/cosmos-kit/data.ts b/sdk/typescript/docs/components/cosmos-kit/data.ts new file mode 100644 index 0000000000..d25456c980 --- /dev/null +++ b/sdk/typescript/docs/components/cosmos-kit/data.ts @@ -0,0 +1,28 @@ +import { AminoMsg, makeSignDoc, serializeSignDoc } from '@cosmjs/amino'; +import { MsgSend } from 'cosmjs-types/cosmos/bank/v1beta1/tx'; + +export const getDoc = (address: string) => { + const chainId = 'nyx'; + + const msg: AminoMsg = { + type: '/cosmos.bank.v1beta1.MsgSend', + value: MsgSend.fromPartial({ + fromAddress: address, + toAddress: 'n1nn8tghp94n8utsgyg3kfttlxm0exgjrsqkuwu9', + amount: [{ amount: '1000', denom: 'unym' }], + }), + }; + const fee = { + amount: [{ amount: '2000', denom: 'ucosm' }], + gas: '180000', // 180k + }; + const memo = 'Use your power wisely'; + const accountNumber = 15; + const sequence = 16; + + return makeSignDoc([msg], fee, chainId, memo, accountNumber, sequence); +}; +export const aminoDoc = (address: string) => { + const signDoc = getDoc(address); + return serializeSignDoc(signDoc); +}; diff --git a/sdk/typescript/docs/components/cosmos-kit/index.tsx b/sdk/typescript/docs/components/cosmos-kit/index.tsx new file mode 100644 index 0000000000..c7d5abbf56 --- /dev/null +++ b/sdk/typescript/docs/components/cosmos-kit/index.tsx @@ -0,0 +1,188 @@ +import React, { FC } from 'react'; +import { ChainProvider, useChain } from '@cosmos-kit/react'; +import { assets, chains } from 'chain-registry'; +import { wallets as keplr } from '@cosmos-kit/keplr'; +import { wallets as ledger } from '@cosmos-kit/ledger'; +import Button from '@mui/material/Button'; +import CircularProgress from '@mui/material/CircularProgress'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import { Alert, AlertTitle } from '@mui/material'; +import { Wallet } from '@cosmos-kit/core'; +import { CosmosKitLedger } from './ledger'; +import { CosmosKitSign } from './sign'; + +const CosmosKitSetup: FC<{ children: React.ReactNode }> = ({ children }) => { + const assetsFixedUp = React.useMemo(() => { + const nyx = assets.find((a) => a.chain_name === 'nyx'); + if (nyx) { + const nyxCoin = nyx.assets.find((a) => a.name === 'nyx'); + if (nyxCoin) { + nyxCoin.coingecko_id = 'nyx'; + } + nyx.assets = nyx.assets.reverse(); + } + return assets; + }, [assets]); + + const chainsFixedUp = React.useMemo(() => { + const nyx = chains.find((c) => c.chain_id === 'nyx'); + if (nyx) { + if (!nyx.staking) { + nyx.staking = { + staking_tokens: [{ denom: 'unyx' }], + lock_duration: { + blocks: 10000, + }, + }; + } + } + return chains; + }, [chains]); + + return ( + 'amino', + }} + > + {children} + + ); +}; + +function walletRejectMessageOrError(wallet?: Wallet, error?: React.ReactNode) { + if (!wallet) { + if (!error) { + return undefined; + } + return error; + } + if (typeof wallet.rejectMessage === 'string') { + return wallet.rejectMessage; + } + return wallet.rejectMessage.source; +} +const Wrapper: FC<{ + children?: React.ReactNode; + wallet?: Wallet; + header?: React.ReactNode; + error?: React.ReactNode; + disconnect: () => Promise; +}> = ({ wallet, disconnect, error, header, children }) => { + if (error) { + return ( + + + {wallet && Failed to connect to {wallet.prettyName}} + {wallet && walletRejectMessageOrError(wallet)} + + + + + + ); + } + return ( + + + {header && header} + + + {children} + + ); +}; + +const CosmosKitInner = () => { + const { + wallet, + address, + connect, + disconnect, + isWalletConnecting, + isWalletDisconnected, + isWalletError, + isWalletNotExist, + isWalletRejected, + } = useChain('nyx'); + + if (isWalletError) { + return ; + } + + if (isWalletNotExist) { + return ; + } + + if (isWalletRejected) { + return ( + + ); + } + + if (isWalletDisconnected) { + return ( + + ); + } + + if (isWalletConnecting) { + return ; + } + + // Ledger Hardware Wallet + if (wallet.mode === 'ledger') { + return ( + + Connected to {wallet.prettyName} + + Address: {address}{' '} + + + } + disconnect={disconnect} + > + + + ); + } + + // Extension or Wallet Connect + return ( + + Connected to {wallet.prettyName} + + Address: {address}{' '} + + + } + disconnect={disconnect} + > + + + ); +}; + +export const CosmosKit = () => ( + + + +); diff --git a/sdk/typescript/docs/components/cosmos-kit/ledger.tsx b/sdk/typescript/docs/components/cosmos-kit/ledger.tsx new file mode 100644 index 0000000000..a983c30e6d --- /dev/null +++ b/sdk/typescript/docs/components/cosmos-kit/ledger.tsx @@ -0,0 +1,74 @@ +import React from 'react'; +import { useChain, useWalletClient } from '@cosmos-kit/react'; +import Button from '@mui/material/Button'; +import Box from '@mui/material/Box'; +import { pubkeyType } from '@cosmjs/amino'; +import { toBase64 } from '@cosmjs/encoding'; +import { Alert, AlertTitle, LinearProgress } from '@mui/material'; +import { aminoDoc } from './data'; + +export const CosmosKitLedger = () => { + const { wallet, address } = useChain('nyx'); + const { client } = useWalletClient(wallet?.name); + const [signResponse, setSignResponse] = React.useState(); + const [busy, setBusy] = React.useState(); + + const sign = async () => { + setBusy(true); + + const serialized = aminoDoc(address); + const account = await client.getAccount('nyx'); + + console.log('Accounts: ', account); + console.log('Info', await (client as any).client.getAppConfiguration()); + const sigAmino = await (client as any).client.sign(account.username, serialized); + const sig = { + signature: toBase64(sigAmino.signature), + pub_key: { + type: pubkeyType.secp256k1, + value: toBase64(account.pubkey), + }, + }; + console.log('Sig', { sigAmino, sig }); + setBusy(false); + + return { signature: sig }; + }; + + const handleSign = async () => { + setSignResponse(await sign()); + }; + + if (busy) { + return ( + + + + Please approve on the Ledger + Follow the instructions on the Ledger to review the message + + + ); + } + + return ( + <> + {!signResponse && ( + + Click the button below to sign a fake request with your Ledger + + + )} + {signResponse && ( + + Signature: + +
{JSON.stringify(signResponse?.signature, null, 2)}
+
+
+ )} + + ); +}; diff --git a/sdk/typescript/docs/components/cosmos-kit/sign.tsx b/sdk/typescript/docs/components/cosmos-kit/sign.tsx new file mode 100644 index 0000000000..0cff71808e --- /dev/null +++ b/sdk/typescript/docs/components/cosmos-kit/sign.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { useChain } from '@cosmos-kit/react'; +import Button from '@mui/material/Button'; +import Box from '@mui/material/Box'; +import { Alert, AlertTitle, LinearProgress } from '@mui/material'; +import { getDoc } from './data'; + +export const CosmosKitSign = () => { + const { address, getOfflineSignerAmino } = useChain('nyx'); + const [signResponse, setSignResponse] = React.useState(); + const [busy, setBusy] = React.useState(); + + const sign = async () => { + setBusy(true); + const doc = getDoc(address); + const tx = await getOfflineSignerAmino().signAmino(address, doc); + setBusy(false); + return tx; + }; + + const handleSign = async () => { + setSignResponse(await sign()); + }; + + if (busy) { + return ( + + + + Please approve in your wallet + Review the message to sign + + + ); + } + + return ( + <> + {!signResponse && ( + + Click the button below to sign a fake request with your wallet + + + )} + {signResponse && ( + + Signature: + +
{JSON.stringify(signResponse?.signature, null, 2)}
+
+
+ )} + + ); +}; diff --git a/sdk/typescript/docs/components/footer.tsx b/sdk/typescript/docs/components/footer.tsx new file mode 100644 index 0000000000..2f3ee6c976 --- /dev/null +++ b/sdk/typescript/docs/components/footer.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import Stack from '@mui/material/Stack'; + +const links = [ + ['Twitter', 'https://twitter.com/nymproject'], + ['Telegram', 'https://t.me/nymchan'], + ['Discord', 'https://discord.com/invite/nym'], + ['GitHub', 'https://github.com/nymtech/nym'], + ['Nym Wallet', 'https://nymtech.net/download/wallet'], + ['Nym Explorer', 'https://explorer.nymtech.net/'], + ['Nym Blog', 'https://nymtech.medium.com/'], + ['Nym Shipyard', 'https://shipyard.nymtech.net/'], +]; +export const Footer = () => ( + + {links.map((link) => ( + + {link[0]} + + ))} + +); diff --git a/sdk/typescript/docs/components/mixfetch.tsx b/sdk/typescript/docs/components/mixfetch.tsx new file mode 100644 index 0000000000..564de818e4 --- /dev/null +++ b/sdk/typescript/docs/components/mixfetch.tsx @@ -0,0 +1,94 @@ +import React, { useState } from 'react'; +import CircularProgress from '@mui/material/CircularProgress'; +import Button from '@mui/material/Button'; +import TextField from '@mui/material/TextField'; +import Typography from '@mui/material/Typography'; +import Box from '@mui/material/Box'; +import { mixFetch } from '@nymproject/mix-fetch-full-fat'; +import Stack from '@mui/material/Stack'; +import Paper from '@mui/material/Paper'; +import type { SetupMixFetchOps } from '@nymproject/mix-fetch'; + +const defaultUrl = 'https://nymtech.net/favicon.svg'; +const args = { mode: 'unsafe-ignore-cors' }; + +const extra = { + hiddenGateways: [ + { + owner: 'n1kymvkx6vsq7pvn6hfurkpg06h3j4gxj4em7tlg', + host: 'gateway1.nymtech.net', + explicitIp: '213.219.38.119', + identityKey: 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM', + sphinxKey: 'CYcrjoJ8GT7Dp54zViUyyRUfegeRCyPifWQZHRgMZrfX', + }, + ], +}; + +const mixFetchOptions: SetupMixFetchOps = { + preferredGateway: 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM', // with WSS + preferredNetworkRequester: + 'GiRjFWrMxt58pEMuusm4yT3RxoMD1MMPrR9M2N4VWRJP.3CNZBPq4vg7v7qozjGjdPMXcvDmkbWPCgbGCjQVw9n6Z@2xU4CBE6QiiYt6EyBXSALwxkNvM7gqJfjHXaMkjiFmYW', + mixFetchOverride: { + requestTimeoutMs: 60_000, + }, + forceTls: true, // force WSS + extra, // manually set the gateway details for WSS so certificates will work for hostname +}; + +export const MixFetch = () => { + const [url, setUrl] = useState(defaultUrl); + const [html, setHtml] = useState(); + const [busy, setBusy] = useState(false); + + const handleFetch = async () => { + try { + setBusy(true); + setHtml(undefined); + const response = await mixFetch(url, args, mixFetchOptions); + console.log(response); + const resHtml = await response.text(); + setHtml(resHtml); + } catch (err) { + console.log(err); + } finally { + setBusy(false); + } + }; + + return ( +
+ + setUrl(e.target.value)} + /> + + + + {busy && ( + + + + )} + {html && ( + <> + + Response + + + + {html} + + + + )} +
+ ); +}; diff --git a/sdk/typescript/docs/components/mixnodes.tsx b/sdk/typescript/docs/components/mixnodes.tsx new file mode 100644 index 0000000000..616c950a95 --- /dev/null +++ b/sdk/typescript/docs/components/mixnodes.tsx @@ -0,0 +1,79 @@ +import React, { useState } from 'react'; +import { contracts } from '@nymproject/contract-clients'; +import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'; +import Box from '@mui/material/Box'; +import CircularProgress from '@mui/material/CircularProgress'; +import Button from '@mui/material/Button'; +import Typography from '@mui/material/Typography'; +import Stack from '@mui/material/Stack'; +import Table from '@mui/material/Table'; +import { TableBody, TableCell, TableHead, TableRow } from '@mui/material'; +import { settings } from './client'; + +const getClient = async () => { + const cosmWasmClient = await SigningCosmWasmClient.connect(settings.url); + + const client = new contracts.Mixnet.MixnetQueryClient(cosmWasmClient, settings.mixnetContractAddress); + return client; +}; + +export const Mixnodes = () => { + const [mixnodes, setMixnodes] = useState(); + const [busy, setBusy] = useState(false); + + const getMixnodes = async () => { + setBusy(true); + const client = await getClient(); + const { nodes } = await client.getMixNodesDetailed({}); + setMixnodes(nodes); + setBusy(false); + }; + + if (busy) { + return ( + + + + Loading... + + + ); + } + + if (!mixnodes) { + return ( + + + + ); + } + + return ( + + {mixnodes?.length && ( + + + + MixId + Owner Account + Layer + Bonded at Block Height + + + + {mixnodes.map((mixnode: any) => ( + + {mixnode.bond_information.mix_id} + {mixnode.bond_information.owner} + {mixnode.bond_information.layer} + {mixnode.bond_information.bonding_height} + + ))} + +
+ )} +
+ ); +}; diff --git a/sdk/typescript/docs/components/npm.tsx b/sdk/typescript/docs/components/npm.tsx new file mode 100644 index 0000000000..1836e18b38 --- /dev/null +++ b/sdk/typescript/docs/components/npm.tsx @@ -0,0 +1,17 @@ +import React, { FC } from 'react'; +import { Chip, Link } from '@mui/material'; + +export const NPMLink: FC<{ packageName: string; kind: 'esm' | 'cjs'; preBundled?: boolean }> = ({ + packageName, + kind, + preBundled, +}) => ( + + {packageName} {' '} + {preBundled && } + +); diff --git a/sdk/typescript/docs/components/traffic.tsx b/sdk/typescript/docs/components/traffic.tsx new file mode 100644 index 0000000000..e6ff0cd605 --- /dev/null +++ b/sdk/typescript/docs/components/traffic.tsx @@ -0,0 +1,112 @@ +import React, { useEffect, useState } from 'react'; +import { createNymMixnetClient, NymMixnetClient, Payload } from '@nymproject/sdk-full-fat'; +import Box from '@mui/material/Box'; +import CircularProgress from '@mui/material/CircularProgress'; +import Paper from '@mui/material/Paper'; +import Typography from '@mui/material/Typography'; +import Stack from '@mui/material/Stack'; +import TextField from '@mui/material/TextField'; +import Button from '@mui/material/Button'; + +const nymApiUrl = 'https://validator.nymtech.net/api'; + +export const Traffic = () => { + const [nym, setNym] = useState(); + const [selfAddress, setSelfAddress] = useState(); + const [recipient, setRecipient] = useState(); + const [payload, setPayload] = useState(); + const [receivedMessage, setReceivedMessage] = useState(); + const [buttonEnabled, setButtonEnabled] = useState(false); + + const init = async () => { + const client = await createNymMixnetClient(); + setNym(client); + + // start the client and connect to a gateway + await client?.client.start({ + clientId: crypto.randomUUID(), + nymApiUrl, + }); + + // check when is connected and set the self address + client?.events.subscribeToConnected((e) => { + const { address } = e.args; + setSelfAddress(address); + }); + + // show whether the client is ready or not + client?.events.subscribeToLoaded((e) => { + console.log('Client ready: ', e.args); + }); + + // show message payload content when received + client?.events.subscribeToTextMessageReceivedEvent((e) => { + console.log(e.args.payload); + setReceivedMessage(e.args.payload); + }); + }; + + const stop = async () => { + await nym?.client.stop(); + }; + + const send = () => nym.client.send({ payload, recipient }); + + useEffect(() => { + init(); + return () => { + stop(); + }; + }, []); + + useEffect(() => { + if (recipient && payload) { + setButtonEnabled(true); + } else { + setButtonEnabled(false); + } + }, [recipient, payload]); + + if (!nym || !selfAddress) { + return ( + + + + ); + } + + return ( + + + + My self address is: + {selfAddress || 'loading'} + Communication through the Mixnet + setRecipient(e.target.value)} + size="small" + /> + setPayload({ message: e.target.value, mimeType: 'text/plain' })} + size="small" + /> + + + {receivedMessage && ( + + Message Received! + {receivedMessage} + + )} + + + ); +}; diff --git a/sdk/typescript/docs/components/wallet.tsx b/sdk/typescript/docs/components/wallet.tsx index 666b7a3173..538a55de03 100644 --- a/sdk/typescript/docs/components/wallet.tsx +++ b/sdk/typescript/docs/components/wallet.tsx @@ -1,27 +1,392 @@ -import React, { FC } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; +import { contracts } from '@nymproject/contract-clients'; +import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'; +import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing'; +import { Coin, GasPrice } from '@cosmjs/stargate'; +import Button from '@mui/material/Button'; +import Paper from '@mui/material/Paper'; +import Box from '@mui/material/Box'; +import { TableBody, TableCell, TableHead, TableRow, TextField, Typography } from '@mui/material'; +import Divider from '@mui/material/Divider'; +import Table from '@mui/material/Table'; +import { settings } from './client'; -import { ChainProvider, useChainWallet } from '@cosmos-kit/react'; -import { chains, assets } from 'chain-registry'; -import { wallets } from '@cosmos-kit/keplr'; +const signerAccount = async (mnemonic) => { + // create a wallet to sign transactions with the mnemonic + const signer = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { + prefix: 'n', + }); -// Import this in your top-level route/layout -import '@interchain-ui/react/styles'; + return signer; +}; + +const fetchSignerCosmosWasmClient = async (mnemonic: string) => { + const signer = await signerAccount(mnemonic); + + // create a signing client we don't need to set the gas price conversion for queries + const cosmWasmClient = await SigningCosmWasmClient.connectWithSigner(settings.url, signer, { + gasPrice: GasPrice.fromString('0.025unym'), + }); + + return cosmWasmClient; +}; + +const fetchSignerClient = async (mnemonic) => { + const signer = await signerAccount(mnemonic); -const WalletInner: FC = () => { - const chainContext = useChainWallet('nyx', 'keplr'); + // create a signing client we don't need to set the gas price conversion for queries + // if you want to connect without signer you'd write ".connect" and "url" as param + const cosmWasmClient = await SigningCosmWasmClient.connectWithSigner(settings.url, signer, { + gasPrice: GasPrice.fromString('0.025unym'), + }); - return
{JSON.stringify(chainContext, null, 2)}
; + /** create a mixnet contract client + * @param cosmWasmClient the client to use for signing and querying + * @param settings.address the bech32 address prefix (human readable part) + * @param settings.mixnetContractAddress the bech32 address prefix (human readable part) + * @returns the client in MixnetClient form + */ + + const mixnetClient = new contracts.Mixnet.MixnetClient( + cosmWasmClient, + settings.address, // sender (that account of the signer) + settings.mixnetContractAddress, // contract address (different on mainnet, QA, etc) + ); + + return mixnetClient; }; -export const Wallet: FC = () => ( - // TODO - - -
This is a wallet
- -
-); +export const Wallet = () => { + const [mnemonic, setMnemonic] = useState(); + const [signerCosmosWasmClient, setSignerCosmosWasmClient] = useState(); + const [signerClient, setSignerClient] = useState(); + const [account, setAccount] = useState(); + const [accountLoading, setAccountLoading] = useState(false); + const [clientLoading, setClientLoading] = useState(false); + const [balance, setBalance] = useState(); + const [balanceLoading, setBalanceLoading] = useState(false); + const [log, setLog] = useState([]); + const [tokensToSend, setTokensToSend] = useState(); + const [sendingTokensLoader, setSendingTokensLoader] = useState(false); + const [delegations, setDelegations] = useState(); + const [recipientAddress, setRecipientAddress] = useState(''); + const [delegationNodeId, setDelegationNodeId] = useState(); + const [amountToBeDelegated, setAmountToBeDelegated] = useState(); + const [delegationLoader, setDelegationLoader] = useState(false); + const [undeledationLoader, setUndeledationLoader] = useState(false); + const [withdrawLoading, setWithdrawLoading] = useState(false); + const [connectButtonText, setConnectButtonText] = useState('Connect'); + + const getBalance = useCallback(async () => { + setBalanceLoading(true); + try { + const newBalance = await signerCosmosWasmClient?.getBalance(account, 'unym'); + setBalance(newBalance); + } catch (error) { + console.error(error); + } + setBalanceLoading(false); + }, [account, signerCosmosWasmClient]); + + const getSignerAccount = async () => { + setAccountLoading(true); + try { + const signer = await signerAccount(mnemonic); + const accounts = await signer.getAccounts(); + if (accounts[0]) { + setAccount(accounts[0].address); + } + } catch (error) { + console.error(error); + } + setAccountLoading(false); + }; + + const getClients = async () => { + setClientLoading(true); + try { + setSignerCosmosWasmClient(await fetchSignerCosmosWasmClient(mnemonic)); + setSignerClient(await fetchSignerClient(mnemonic)); + } catch (error) { + console.error(error); + } + setClientLoading(false); + }; + + const getDelegations = useCallback(async () => { + const newDelegations = await signerClient.getDelegatorDelegations({ + delegator: settings.address, + }); + setDelegations(newDelegations); + }, [signerClient]); + + const connect = () => { + getSignerAccount(); + getClients(); + }; + + const doUndelegateAll = async () => { + if (!signerClient) { + return; + } + setUndeledationLoader(true); + try { + // eslint-disable-next-line no-restricted-syntax + for (const delegation of delegations.delegations) { + // eslint-disable-next-line no-await-in-loop + await signerClient.undelegateFromMixnode({ mixId: delegation.mix_id }, 'auto'); + } + } catch (error) { + console.error(error); + } + setUndeledationLoader(false); + }; + + const doDelegate = async ({ mixId, amount }: { mixId: number; amount: number }) => { + if (!signerClient) { + return; + } + setDelegationLoader(true); + try { + const res = await signerClient.delegateToMixnode({ mixId }, 'auto', undefined, [ + { amount: `${amount}`, denom: 'unym' }, + ]); + console.log('res', res); + setLog((prev) => [ + ...prev, +
+ {new Date().toLocaleTimeString()} +
{JSON.stringify(res, null, 2)}
+
, + ]); + } catch (error) { + console.error(error); + } + setDelegationLoader(false); + }; + // End delegate + + // Sending tokens + const doSendTokens = async () => { + const memo = 'test sending tokens'; + setSendingTokensLoader(true); + try { + const res = await signerCosmosWasmClient.sendTokens( + account, + recipientAddress, + [{ amount: tokensToSend, denom: 'unym' }], + 'auto', + memo, + ); + setLog((prev) => [ + ...prev, +
+ {new Date().toLocaleTimeString()} +
{JSON.stringify(res, null, 2)}
+
, + ]); + } catch (error) { + console.error(error); + } + setSendingTokensLoader(false); + }; + // End send tokens + + // Withdraw Rewards + const doWithdrawRewards = async () => { + const delegatorAddress = ''; + const validatorAdress = ''; + const memo = 'test sending tokens'; + setWithdrawLoading(true); + try { + const res = await signerCosmosWasmClient.withdrawRewards(delegatorAddress, validatorAdress, 'auto', memo); + setLog((prev) => [ + ...prev, +
+ {new Date().toLocaleTimeString()} +
{JSON.stringify(res, null, 2)}
+
, + ]); + } catch (error) { + console.error(error); + } + setWithdrawLoading(false); + }; + + useEffect(() => { + if (account && signerCosmosWasmClient) { + if (!balance) { + setBalanceLoading(true); + getBalance(); + setBalanceLoading(false); + } + } + }, [account, signerCosmosWasmClient, balance, getBalance]); + + useEffect(() => { + if (signerClient && !delegations) { + console.log('getDelegations'); + getDelegations(); + } + }, [signerClient, getDelegations, delegations]); + + useEffect(() => { + if (accountLoading || clientLoading || balanceLoading) { + setConnectButtonText('Loading...'); + } else if (balance) { + setConnectButtonText('Connected'); + } + setConnectButtonText('Connect'); + }, [accountLoading, clientLoading, balanceLoading]); + + return ( + + + + Basic Wallet + + + Your account + + + Enter the mnemonic + + setMnemonic(e.target.value)} + fullWidth + multiline + maxRows={4} + sx={{ marginBottom: 3 }} + /> + + + {account && balance ? ( + + Address: {account} + + Balance: {balance?.amount} {balance?.denom} + + + ) : ( + + Please, enter your nemonic to receive your account info + + )} + + + + Send Tokens + + setRecipientAddress(e.target.value)} + size="small" + /> + + setTokensToSend(e.target.value)} + size="small" + /> + + + + + + + Delegations + + + + Make a delegation + + setDelegationNodeId(e.target.value)} + size="small" + /> + + setAmountToBeDelegated(e.target.value)} + size="small" + /> + + + + + + Your delegations + + {!delegations?.delegations?.length ? ( + You do not have delegations + ) : ( + + + + + MixId + Owner + Amount + Cumulative Reward Ratio + + + + {delegations?.delegations.map((delegation: any) => ( + + {delegation.mix_id} + {delegation.owner} + {delegation.amount.amount} + {delegation.cumulative_reward_ratio} + + ))} + +
+
+ )} +
+ {delegations && ( + + + + )} + + + +
+
+
+ + + Transaction Logs: + {log} + +
+ ); +}; diff --git a/sdk/typescript/docs/next.config.js b/sdk/typescript/docs/next.config.js index f4e7f0aac9..cbb3bc7364 100644 --- a/sdk/typescript/docs/next.config.js +++ b/sdk/typescript/docs/next.config.js @@ -1,21 +1,50 @@ +// const path = require('path'); +// const CopyPlugin = require('copy-webpack-plugin'); + const withNextra = require('nextra')({ theme: 'nextra-theme-docs', themeConfig: './theme.config.tsx', }); -console.dir(withNextra(), { depth: 30 }); -console.dir(withNextra().rewrites, { depth: 30 }); +const nextra = withNextra(); +nextra.webpack = (config, options) => { + // generate Nextra's webpack config + const newConfig = withNextra().webpack(config, options); + + newConfig.module.rules.push({ + test: /\.txt$/i, + use: 'raw-loader', + }); + + // TODO: figure out how to properly bundle WASM and workers with Nextra + // newConfig.plugins.push( + // new CopyPlugin({ + // patterns: [ + // { + // from: path.resolve(path.dirname(require.resolve('@nymproject/mix-fetch/package.json')), '*.wasm'), + // to: '[name][ext]', + // context: path.resolve(__dirname, 'out'), + // }, + // { + // from: path.resolve(path.dirname(require.resolve('@nymproject/mix-fetch/package.json')), '*worker*.js'), + // to: '[name][ext]', + // context: path.resolve(__dirname, 'out'), + // }, + // ], + // }), + // ); + + return newConfig; +}; const config = { - ...withNextra(), - output: 'export', - rewrites: undefined, + ...nextra, + // output: 'export', // static HTML files, has problems with Vercel + // rewrites: undefined, images: { unoptimized: true, }, - basePath: process.env.NODE_ENV === 'development' ? undefined : '/docs/sdk/typescript', // this makes the SDK docs appear at https://nymtech.net/docs/sdk/typescript + transpilePackages: ['@nymproject/contract-clients'], }; -// config.images.unoptimized = true; - module.exports = config; diff --git a/sdk/typescript/docs/package-lock.json b/sdk/typescript/docs/package-lock.json deleted file mode 100644 index fc1d744b25..0000000000 --- a/sdk/typescript/docs/package-lock.json +++ /dev/null @@ -1,7113 +0,0 @@ -{ - "name": "nym-sdk-docs", - "version": "0.0.1", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "nym-sdk-docs", - "version": "0.0.1", - "dependencies": { - "@cosmjs/amino": "^0.31.0", - "@cosmjs/cosmwasm-stargate": "^0.31.0", - "@cosmos-kit/keplr": "^2.1.0", - "@cosmos-kit/react": "^2.1.1", - "@interchain-ui/react": "^1.3.3", - "chain-registry": "^1.18.0", - "next": "^13.0.6", - "nextra": "latest", - "nextra-theme-docs": "latest", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@types/node": "18.11.10", - "typescript": "^4.9.3" - } - }, - "node_modules/@babel/runtime": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz", - "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==", - "dependencies": { - "regenerator-runtime": "^0.13.11" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@braintree/sanitize-url": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.2.tgz", - "integrity": "sha512-Tbsj02wXCbqGmzdnXNk0SOF19ChhRU70BsroIi4Pm6Ehp56in6vch94mfbdQ17DozxkL3BAVjbZ4Qc1a0HFRAg==" - }, - "node_modules/@chain-registry/keplr": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@chain-registry/keplr/-/keplr-1.8.0.tgz", - "integrity": "sha512-P1IyZihR/rZUBgFZm5DGs4LAVpMSJ7QfQ5YV1ofpMNeB0iXEEGC4BuuT8NonwgAyWGOw9/c8Z/cNN8f9m5nFkQ==", - "dependencies": { - "@babel/runtime": "^7.19.4", - "@chain-registry/types": "^0.13.1", - "@keplr-wallet/cosmos": "0.11.16", - "@keplr-wallet/crypto": "0.11.16", - "semver": "^7.3.8" - } - }, - "node_modules/@chain-registry/keplr/node_modules/@keplr-wallet/common": { - "version": "0.11.16", - "resolved": "https://registry.npmjs.org/@keplr-wallet/common/-/common-0.11.16.tgz", - "integrity": "sha512-RTbfe8LkPzQQqYntx53dZTuDUgx+W6KRY4g3fIv1c59DS/bp9ZqjYfUDmj3yH0GQk822zqJJwCtjk+qsgvyebg==", - "dependencies": { - "@keplr-wallet/crypto": "0.11.16", - "buffer": "^6.0.3", - "delay": "^4.4.0" - } - }, - "node_modules/@chain-registry/keplr/node_modules/@keplr-wallet/cosmos": { - "version": "0.11.16", - "resolved": "https://registry.npmjs.org/@keplr-wallet/cosmos/-/cosmos-0.11.16.tgz", - "integrity": "sha512-Rgch9zw+GKQ2wAKw6I5+J8AAlKHs4MhnkGFfTuqy0e453Ig0+KCHvs+IgMURM9j6E7K0OPQVc4vCvWnQLs6Zbw==", - "dependencies": { - "@ethersproject/address": "^5.6.0", - "@keplr-wallet/common": "0.11.16", - "@keplr-wallet/crypto": "0.11.16", - "@keplr-wallet/proto-types": "0.11.16", - "@keplr-wallet/types": "0.11.16", - "@keplr-wallet/unit": "0.11.16", - "axios": "^0.27.2", - "bech32": "^1.1.4", - "buffer": "^6.0.3", - "long": "^4.0.0", - "protobufjs": "^6.11.2" - } - }, - "node_modules/@chain-registry/keplr/node_modules/@keplr-wallet/crypto": { - "version": "0.11.16", - "resolved": "https://registry.npmjs.org/@keplr-wallet/crypto/-/crypto-0.11.16.tgz", - "integrity": "sha512-th3t05Aq+uQLbhhiqIHbevY3pA4dBKr+vKcUpfdshcc78fI1eGpmzGcQKxlvbectBn4UwamTEANssyplXOGQqg==", - "dependencies": { - "@ethersproject/keccak256": "^5.5.0", - "bip32": "^2.0.6", - "bip39": "^3.0.3", - "bs58check": "^2.1.2", - "buffer": "^6.0.3", - "crypto-js": "^4.0.0", - "elliptic": "^6.5.3", - "sha.js": "^2.4.11" - } - }, - "node_modules/@chain-registry/keplr/node_modules/@keplr-wallet/proto-types": { - "version": "0.11.16", - "resolved": "https://registry.npmjs.org/@keplr-wallet/proto-types/-/proto-types-0.11.16.tgz", - "integrity": "sha512-0tX7AN1bmlZdpUwqgjQU6MI+p+qBBaWUxHvOrNYtvX0FShw9RihasWdrV6biciQewVd54fChVIGmYKhCLtwPsg==", - "dependencies": { - "long": "^4.0.0", - "protobufjs": "^6.11.2" - } - }, - "node_modules/@chain-registry/keplr/node_modules/@keplr-wallet/types": { - "version": "0.11.16", - "resolved": "https://registry.npmjs.org/@keplr-wallet/types/-/types-0.11.16.tgz", - "integrity": "sha512-jkBWj6bcw6BZqPavLms3EcaK6YG4suoTPA9PuO6+eFjj7TomUrzzYdhXyc7Mm0K/KVEz5CjPxjmx7LsPuWYKgg==", - "dependencies": { - "axios": "^0.27.2", - "long": "^4.0.0", - "secretjs": "0.17.7" - } - }, - "node_modules/@chain-registry/keplr/node_modules/@keplr-wallet/unit": { - "version": "0.11.16", - "resolved": "https://registry.npmjs.org/@keplr-wallet/unit/-/unit-0.11.16.tgz", - "integrity": "sha512-RRVE3oLZq84P4CQONHXDRX+jdqsP9Zar0V9ROAkG4qzitG2glNY/KCVd9SeSOatbGOb/4X88/4pH273TkjtlRA==", - "dependencies": { - "@keplr-wallet/types": "0.11.16", - "big-integer": "^1.6.48", - "utility-types": "^3.10.0" - } - }, - "node_modules/@chain-registry/keplr/node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", - "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" - } - }, - "node_modules/@chain-registry/types": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/@chain-registry/types/-/types-0.13.1.tgz", - "integrity": "sha512-NF4x7pqkQJ/zSQLoT28sYlBdzWUyCTFvWgVE9hJ2jkirX+It9VUHP5j1wtTq+vxQ74SZk2V8vRBo2uuoEYBB1A==", - "dependencies": { - "@babel/runtime": "^7.19.4" - } - }, - "node_modules/@confio/ics23": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@confio/ics23/-/ics23-0.6.8.tgz", - "integrity": "sha512-wB6uo+3A50m0sW/EWcU64xpV/8wShZ6bMTa7pF8eYsTrSkQA7oLUIJcs/wb8g4y2Oyq701BaGiO6n/ak5WXO1w==", - "dependencies": { - "@noble/hashes": "^1.0.0", - "protobufjs": "^6.8.8" - } - }, - "node_modules/@cosmjs/amino": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.31.0.tgz", - "integrity": "sha512-xJ5CCEK7H79FTpOuEmlpSzVI+ZeYESTVvO3wHDgbnceIyAne3C68SvyaKqLUR4uJB0Z4q4+DZHbqW6itUiv4lA==", - "dependencies": { - "@cosmjs/crypto": "^0.31.0", - "@cosmjs/encoding": "^0.31.0", - "@cosmjs/math": "^0.31.0", - "@cosmjs/utils": "^0.31.0" - } - }, - "node_modules/@cosmjs/cosmwasm-stargate": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@cosmjs/cosmwasm-stargate/-/cosmwasm-stargate-0.31.0.tgz", - "integrity": "sha512-l6aX++3LhaAGZO46qIgrrNF40lYhOrdPfl35Z32ks6Wf3mwgbQEZwaxnoGzwUePY7/yaIiEFJ1JO6MlVPZVuag==", - "dependencies": { - "@cosmjs/amino": "^0.31.0", - "@cosmjs/crypto": "^0.31.0", - "@cosmjs/encoding": "^0.31.0", - "@cosmjs/math": "^0.31.0", - "@cosmjs/proto-signing": "^0.31.0", - "@cosmjs/stargate": "^0.31.0", - "@cosmjs/tendermint-rpc": "^0.31.0", - "@cosmjs/utils": "^0.31.0", - "cosmjs-types": "^0.8.0", - "long": "^4.0.0", - "pako": "^2.0.2" - } - }, - "node_modules/@cosmjs/crypto": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.31.0.tgz", - "integrity": "sha512-UaqCe6Tgh0pe1QlZ66E13t6FlIF86QrnBXXq+EN7Xe1Rouza3fJ1ojGlPleJZkBoq3tAyYVIOOqdZIxtVj/sIQ==", - "dependencies": { - "@cosmjs/encoding": "^0.31.0", - "@cosmjs/math": "^0.31.0", - "@cosmjs/utils": "^0.31.0", - "@noble/hashes": "^1", - "bn.js": "^5.2.0", - "elliptic": "^6.5.4", - "libsodium-wrappers-sumo": "^0.7.11" - } - }, - "node_modules/@cosmjs/encoding": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.31.0.tgz", - "integrity": "sha512-NYGQDRxT7MIRSlcbAezwxK0FqnaSPKCH7O32cmfpHNWorFxhy9lwmBoCvoe59Kd0HmArI4h+NGzLEfX3OLnA4Q==", - "dependencies": { - "base64-js": "^1.3.0", - "bech32": "^1.1.4", - "readonly-date": "^1.0.0" - } - }, - "node_modules/@cosmjs/json-rpc": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@cosmjs/json-rpc/-/json-rpc-0.31.0.tgz", - "integrity": "sha512-Ix2Cil2qysiLNrX+E0w3vtwCrqxGVq8jklpLA7B2vtMrw7tru/rS65fdFSy8ep0wUNLL6Ud32VXa5K0YObDOMA==", - "dependencies": { - "@cosmjs/stream": "^0.31.0", - "xstream": "^11.14.0" - } - }, - "node_modules/@cosmjs/math": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.31.0.tgz", - "integrity": "sha512-Sb/8Ry/+gKJaYiV6X8q45kxXC9FoV98XCY1WXtu0JQwOi61VCG2VXsURQnVvZ/EhR/CuT/swOlNKrqEs3da0fw==", - "dependencies": { - "bn.js": "^5.2.0" - } - }, - "node_modules/@cosmjs/proto-signing": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.31.0.tgz", - "integrity": "sha512-JNlyOJRkn8EKB9mCthkjr6lVX6eyVQ09PFdmB4/DR874E62dFTvQ+YvyKMAgN7K7Dcjj26dVlAD3f6Xs7YOGDg==", - "dependencies": { - "@cosmjs/amino": "^0.31.0", - "@cosmjs/crypto": "^0.31.0", - "@cosmjs/encoding": "^0.31.0", - "@cosmjs/math": "^0.31.0", - "@cosmjs/utils": "^0.31.0", - "cosmjs-types": "^0.8.0", - "long": "^4.0.0" - } - }, - "node_modules/@cosmjs/socket": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@cosmjs/socket/-/socket-0.31.0.tgz", - "integrity": "sha512-WDh9gTyiP3OCXvSAJJn33+Ef3XqMWag+bpR1TdMBxTmlTxuvU+kPy4cf6P2OF+jkkUBEA5Se2EAju0eFbJMT+w==", - "dependencies": { - "@cosmjs/stream": "^0.31.0", - "isomorphic-ws": "^4.0.1", - "ws": "^7", - "xstream": "^11.14.0" - } - }, - "node_modules/@cosmjs/stargate": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.31.0.tgz", - "integrity": "sha512-GYhk9lzZPj/QmYHC0VV/4AMoRzVcOP+EnB1YZCoWlBdLuVmpBYKRagJqWIrIwdk1E0gF2ZoESd2TYfdh1fqIpg==", - "dependencies": { - "@confio/ics23": "^0.6.8", - "@cosmjs/amino": "^0.31.0", - "@cosmjs/encoding": "^0.31.0", - "@cosmjs/math": "^0.31.0", - "@cosmjs/proto-signing": "^0.31.0", - "@cosmjs/stream": "^0.31.0", - "@cosmjs/tendermint-rpc": "^0.31.0", - "@cosmjs/utils": "^0.31.0", - "cosmjs-types": "^0.8.0", - "long": "^4.0.0", - "protobufjs": "~6.11.3", - "xstream": "^11.14.0" - } - }, - "node_modules/@cosmjs/stream": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.31.0.tgz", - "integrity": "sha512-Y+aSHwhHkLGIaQOdqRob+yga2zr9ifl9gZDKD+B7+R5pdWN5f2TTDhYWxA6YZcZ6xRmfr7u8a7tDh7iYLC/zKA==", - "dependencies": { - "xstream": "^11.14.0" - } - }, - "node_modules/@cosmjs/tendermint-rpc": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.31.0.tgz", - "integrity": "sha512-yo9xbeuI6UoEKIhFZ9g0dvUKLqnBzwdpEc/uldQygQc51j38gQVwFko+6sjmhieJqRYYvrYumcbJMiV6GFM9aA==", - "dependencies": { - "@cosmjs/crypto": "^0.31.0", - "@cosmjs/encoding": "^0.31.0", - "@cosmjs/json-rpc": "^0.31.0", - "@cosmjs/math": "^0.31.0", - "@cosmjs/socket": "^0.31.0", - "@cosmjs/stream": "^0.31.0", - "@cosmjs/utils": "^0.31.0", - "axios": "^0.21.2", - "readonly-date": "^1.0.0", - "xstream": "^11.14.0" - } - }, - "node_modules/@cosmjs/utils": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.31.0.tgz", - "integrity": "sha512-nNcycZWUYLNJlrIXgpcgVRqdl6BXjF4YlXdxobQWpW9Tikk61bEGeAFhDYtC0PwHlokCNw0KxWiHGJL4nL7Q5A==" - }, - "node_modules/@cosmos-kit/core": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@cosmos-kit/core/-/core-2.1.0.tgz", - "integrity": "sha512-QFtVtzd2VXDQ55WfelPtMRdgnd3nalonEdcKnWe54GTCmyOa9zkADQFW7N48w6yoFDXZFPAnbIFoa5CEJo99CA==", - "dependencies": { - "@chain-registry/types": "0.13.0", - "@walletconnect/types": "2.7.2", - "bowser": "2.11.0", - "events": "3.3.0" - }, - "peerDependencies": { - "@cosmjs/amino": ">= 0.28", - "@cosmjs/cosmwasm-stargate": ">= 0.28", - "@cosmjs/proto-signing": ">= 0.28", - "@cosmjs/stargate": ">= 0.28", - "cosmjs-types": ">= 0.5" - } - }, - "node_modules/@cosmos-kit/core/node_modules/@chain-registry/types": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@chain-registry/types/-/types-0.13.0.tgz", - "integrity": "sha512-2xgKaRK6T3qkkzWkj2n5nHzGNl+0RuDDB8nS+oyssBe4tCq835yMkxrVAOivFfEm5YGl92FcaVDLrzmfPUO0MA==", - "dependencies": { - "@babel/runtime": "^7.19.4", - "@keplr-wallet/cosmos": "^0.11.12", - "@keplr-wallet/crypto": "^0.11.12" - } - }, - "node_modules/@cosmos-kit/keplr": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@cosmos-kit/keplr/-/keplr-2.1.0.tgz", - "integrity": "sha512-Y7Rz5QUlXvkPLAp3RgiiHTeRk16+O+5peosYGzbTE563j5Au8hl9y/mHuxk7z0Rtc++GjAnAzEar31FqCaeYhQ==", - "dependencies": { - "@cosmos-kit/keplr-extension": "^2.1.0", - "@cosmos-kit/keplr-mobile": "^2.1.0" - } - }, - "node_modules/@cosmos-kit/keplr-extension": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@cosmos-kit/keplr-extension/-/keplr-extension-2.1.0.tgz", - "integrity": "sha512-2heJlcKwcFCizhneqJKKYefDb8qvk0WzSv6Sgnqh4jnnXEU+Hh3+6jOCktjNY540naXIucEeICwa3kvTkqDp2w==", - "dependencies": { - "@chain-registry/keplr": "1.8.0", - "@cosmos-kit/core": "^2.1.0" - }, - "peerDependencies": { - "@cosmjs/amino": ">= 0.28", - "@cosmjs/proto-signing": ">= 0.28" - } - }, - "node_modules/@cosmos-kit/keplr-mobile": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@cosmos-kit/keplr-mobile/-/keplr-mobile-2.1.0.tgz", - "integrity": "sha512-i8SwDsaSGqo0b9y2Pk3mrsAQzl0Omt10LVaUryPKVYYzRqulcSbICV6bwsG5ZfYuLM7Su4qDuma+tupfKz3ijQ==", - "dependencies": { - "@chain-registry/keplr": "1.8.0", - "@cosmos-kit/core": "^2.1.0", - "@cosmos-kit/walletconnect": "^2.1.0" - }, - "peerDependencies": { - "@cosmjs/amino": ">= 0.28", - "@cosmjs/proto-signing": ">= 0.28" - } - }, - "node_modules/@cosmos-kit/react": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@cosmos-kit/react/-/react-2.1.1.tgz", - "integrity": "sha512-ZSpwVoEZDkJPJG+Ru4iR87v3WbRSOPgyf4wRq1zbp5kmNoezbjumoFuWRx2MpSvl0yYRfLlzpEqB3HGq5TTWYA==", - "dependencies": { - "@chain-registry/types": "0.13.1", - "@cosmos-kit/core": "^2.1.0", - "@cosmos-kit/react-lite": "^2.1.1", - "@interchain-ui/react": "1.3.0", - "@react-icons/all-files": "^4.1.0" - }, - "peerDependencies": { - "react": "^18.2.0", - "react-dom": "^18.2.0" - } - }, - "node_modules/@cosmos-kit/react-lite": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@cosmos-kit/react-lite/-/react-lite-2.1.1.tgz", - "integrity": "sha512-2wDkZYYGA45alR6xfd7nDizh8P3Sqmc0FlWLHS+Y6Gx66CRnsEoWejQz2kkakEai1PcNMefvkAJt9l5fCloUyg==", - "dependencies": { - "@chain-registry/types": "0.13.1", - "@cosmos-kit/core": "^2.1.0" - }, - "peerDependencies": { - "react": "^18.2.0", - "react-dom": "^18.2.0" - } - }, - "node_modules/@cosmos-kit/react/node_modules/@interchain-ui/react": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@interchain-ui/react/-/react-1.3.0.tgz", - "integrity": "sha512-17Forqigz0o0vUsg9b+oJoYiYTr5FLwCcj5VNivOBH4+Icg/IzAl7nR5UeCkcpXbd6QHdFPBZtijLKLmfj1O1Q==", - "dependencies": { - "@fastify/deepmerge": "^1.3.0", - "@formkit/auto-animate": "1.0.0-beta.6", - "@types/react-transition-group": "4.4.5", - "@vanilla-extract/css": "^1.12.0", - "@vanilla-extract/css-utils": "^0.1.3", - "@vanilla-extract/dynamic": "^2.0.3", - "@vanilla-extract/recipes": "^0.4.0", - "@zag-js/dialog": "^0.9.2", - "@zag-js/react": "^0.9.2", - "animejs": "^3.2.1", - "bignumber.js": "^9.1.1", - "clsx": "^1.2.1", - "copy-to-clipboard": "^3.3.3", - "immer": "^9.0.19", - "lodash": "^4.17.21", - "motion": "^10.16.2", - "polished": "^4.2.2", - "rainbow-sprinkles": "^0.17.0", - "zustand": "^4.3.8" - }, - "peerDependencies": { - "react": "^18.x", - "react-dom": "^18.x" - } - }, - "node_modules/@cosmos-kit/walletconnect": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@cosmos-kit/walletconnect/-/walletconnect-2.1.0.tgz", - "integrity": "sha512-/y+JBjGOi11uYJZsBvJZkC30EH6KBeo0bxPfbe8yLusdhItHavwjZlnv0BOVI0BA7mIIb38hAM1c3yQmS9g/pQ==", - "dependencies": { - "@babel/runtime": "7.11.2", - "@cosmos-kit/core": "^2.1.0", - "@walletconnect/sign-client": "^2.9.0", - "@walletconnect/types": "^2.9.0", - "@walletconnect/utils": "^2.9.0", - "events": "3.3.0" - }, - "peerDependencies": { - "@cosmjs/amino": ">= 0.28", - "@cosmjs/proto-signing": ">= 0.28" - } - }, - "node_modules/@cosmos-kit/walletconnect/node_modules/@babel/runtime": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", - "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", - "dependencies": { - "regenerator-runtime": "^0.13.4" - } - }, - "node_modules/@cosmos-kit/walletconnect/node_modules/@walletconnect/types": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.9.1.tgz", - "integrity": "sha512-xbGgTPuD6xsb7YMvCESBIH55cjB86QAnnVL50a/ED42YkQzDsOdJ0VGTbrm0tG5cxUOF933rpxZQjxGdP+ovww==", - "dependencies": { - "@walletconnect/events": "^1.0.1", - "@walletconnect/heartbeat": "1.2.1", - "@walletconnect/jsonrpc-types": "1.0.3", - "@walletconnect/keyvaluestorage": "^1.0.2", - "@walletconnect/logger": "^2.0.1", - "events": "^3.3.0" - } - }, - "node_modules/@emotion/hash": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", - "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" - }, - "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/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/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/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/@fastify/deepmerge": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-1.3.0.tgz", - "integrity": "sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A==" - }, - "node_modules/@formkit/auto-animate": { - "version": "1.0.0-beta.6", - "resolved": "https://registry.npmjs.org/@formkit/auto-animate/-/auto-animate-1.0.0-beta.6.tgz", - "integrity": "sha512-PVDhLAlr+B4Xb7e+1wozBUWmXa6BFU8xUPR/W/E+TsQhPS1qkAdAsJ25keEnFrcePSnXHrOsh3tiFbEToOzV9w==" - }, - "node_modules/@headlessui/react": { - "version": "1.7.15", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.15.tgz", - "integrity": "sha512-OTO0XtoRQ6JPB1cKNFYBZv2Q0JMqMGNhYP1CjPvcJvjz8YGokz8oAj89HIYZGN0gZzn/4kk9iUpmMF4Q21Gsqw==", - "dependencies": { - "client-only": "^0.0.1" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "react": "^16 || ^17 || ^18", - "react-dom": "^16 || ^17 || ^18" - } - }, - "node_modules/@interchain-ui/react": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@interchain-ui/react/-/react-1.3.3.tgz", - "integrity": "sha512-YMgbsa935yCM+vsK2SnZe220TRcDr8+Pm1xBwaQVwthUd2OWFMjB2ktJ+zrtT8pii6XlOZ5EMbE5M1BPQVGbAQ==", - "dependencies": { - "@fastify/deepmerge": "^1.3.0", - "@formkit/auto-animate": "1.0.0-beta.6", - "@vanilla-extract/css": "^1.12.0", - "@vanilla-extract/css-utils": "^0.1.3", - "@vanilla-extract/dynamic": "^2.0.3", - "@vanilla-extract/recipes": "^0.4.0", - "@zag-js/dialog": "^0.9.2", - "@zag-js/react": "^0.9.2", - "animejs": "^3.2.1", - "bignumber.js": "^9.1.1", - "clsx": "^1.2.1", - "copy-to-clipboard": "^3.3.3", - "immer": "^9.0.19", - "motion": "^10.16.2", - "rainbow-sprinkles": "^0.17.0", - "zustand": "^4.3.8" - }, - "peerDependencies": { - "react": "^18.x", - "react-dom": "^18.x" - } - }, - "node_modules/@iov/crypto": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@iov/crypto/-/crypto-2.1.0.tgz", - "integrity": "sha512-jnb4XuK50admolm7fBxOcxfAW2TO+wYrZlhDWiMETItY/Y5gNNa1zaDSO2wNIjjfGng+8nQ1yqnNhqy7busV2Q==", - "dependencies": { - "@iov/encoding": "^2.1.0", - "bip39": "^3.0.2", - "bn.js": "^4.11.8", - "elliptic": "^6.4.0", - "js-sha3": "^0.8.0", - "libsodium-wrappers": "^0.7.6", - "pbkdf2": "^3.0.16", - "ripemd160": "^2.0.2", - "sha.js": "^2.4.11", - "type-tagger": "^1.0.0", - "unorm": "^1.5.0" - } - }, - "node_modules/@iov/crypto/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/@iov/encoding": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@iov/encoding/-/encoding-2.1.0.tgz", - "integrity": "sha512-5IOdLO7Xg/uRykuiCqeMYghQ3IjWDtGxv7NTWXkgpHuna0aewx43mRpT2NPCpOZd1tpuorDtQ7/zbDNRaIIF/w==", - "dependencies": { - "base64-js": "^1.3.0", - "bech32": "^1.1.3", - "bn.js": "^4.11.8", - "readonly-date": "^1.0.0" - } - }, - "node_modules/@iov/encoding/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/@iov/utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@iov/utils/-/utils-2.0.2.tgz", - "integrity": "sha512-4D8MEvTcFc/DVy5q25vHxRItmgJyeX85dixMH+MxdKr+yy71h3sYk+sVBEIn70uqGP7VqAJkGOPNFs08/XYELw==" - }, - "node_modules/@keplr-wallet/common": { - "version": "0.11.64", - "resolved": "https://registry.npmjs.org/@keplr-wallet/common/-/common-0.11.64.tgz", - "integrity": "sha512-kEnv6K+TxH+BBwwqUgiTcIXuRLBn6PaZMO4jwJbE1O8C8Qh/2j1QtkMLAMgl3Nj9qQkHgJ/dvA5oIqOIdLVMwg==", - "dependencies": { - "@keplr-wallet/crypto": "0.11.64", - "buffer": "^6.0.3", - "delay": "^4.4.0" - } - }, - "node_modules/@keplr-wallet/cosmos": { - "version": "0.11.64", - "resolved": "https://registry.npmjs.org/@keplr-wallet/cosmos/-/cosmos-0.11.64.tgz", - "integrity": "sha512-S6pLRaDKOyOFPfry7Km+Bgwr087gwHI4n3fp8NLGHtL75mLnOdeGvSEVW5LXJEWc5EyYgngM2CeS7xNHz+vjHg==", - "dependencies": { - "@ethersproject/address": "^5.6.0", - "@keplr-wallet/common": "0.11.64", - "@keplr-wallet/crypto": "0.11.64", - "@keplr-wallet/proto-types": "0.11.64", - "@keplr-wallet/types": "0.11.64", - "@keplr-wallet/unit": "0.11.64", - "axios": "^0.27.2", - "bech32": "^1.1.4", - "buffer": "^6.0.3", - "long": "^4.0.0", - "protobufjs": "^6.11.2" - } - }, - "node_modules/@keplr-wallet/cosmos/node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", - "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" - } - }, - "node_modules/@keplr-wallet/crypto": { - "version": "0.11.64", - "resolved": "https://registry.npmjs.org/@keplr-wallet/crypto/-/crypto-0.11.64.tgz", - "integrity": "sha512-DMeGhs+UUBpvefYa/0pF8h8D0lVS1T/eTGNKrn7SIO5CBMp1qfght+k1Se0pHGLr4CAtxFSXTDvYm3mr+ovKhg==", - "dependencies": { - "@ethersproject/keccak256": "^5.5.0", - "bip32": "^2.0.6", - "bip39": "^3.0.3", - "bs58check": "^2.1.2", - "buffer": "^6.0.3", - "crypto-js": "^4.0.0", - "elliptic": "^6.5.3", - "sha.js": "^2.4.11" - } - }, - "node_modules/@keplr-wallet/proto-types": { - "version": "0.11.64", - "resolved": "https://registry.npmjs.org/@keplr-wallet/proto-types/-/proto-types-0.11.64.tgz", - "integrity": "sha512-3oxfD1+zHPPuyKz41wt5A/gVhf2FQbA/L2u/4TxnmnITkY3IENirvMDrZUDJF0pWyGgZuXjhoVVFN2hMWI++PQ==", - "dependencies": { - "long": "^4.0.0", - "protobufjs": "^6.11.2" - } - }, - "node_modules/@keplr-wallet/types": { - "version": "0.11.64", - "resolved": "https://registry.npmjs.org/@keplr-wallet/types/-/types-0.11.64.tgz", - "integrity": "sha512-GgzeLDHHfZFyne3O7UIfFHj/uYqVbxAZI31RbBwt460OBbvwQzjrlZwvJW3vieWRAgxKSITjzEDBl2WneFTQdQ==", - "dependencies": { - "axios": "^0.27.2", - "long": "^4.0.0" - } - }, - "node_modules/@keplr-wallet/types/node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", - "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" - } - }, - "node_modules/@keplr-wallet/unit": { - "version": "0.11.64", - "resolved": "https://registry.npmjs.org/@keplr-wallet/unit/-/unit-0.11.64.tgz", - "integrity": "sha512-BKTaDYI17QgEcBBCP5ZqsHsfNH29P6VMRxjR4nOXcJfhsuwvdJxa/p88VwQYbpVBw0oXcDOwudNiu7Bgf8w6QQ==", - "dependencies": { - "@keplr-wallet/types": "0.11.64", - "big-integer": "^1.6.48", - "utility-types": "^3.10.0" - } - }, - "node_modules/@mdx-js/mdx": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-2.3.0.tgz", - "integrity": "sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/mdx": "^2.0.0", - "estree-util-build-jsx": "^2.0.0", - "estree-util-is-identifier-name": "^2.0.0", - "estree-util-to-js": "^1.1.0", - "estree-walker": "^3.0.0", - "hast-util-to-estree": "^2.0.0", - "markdown-extensions": "^1.0.0", - "periscopic": "^3.0.0", - "remark-mdx": "^2.0.0", - "remark-parse": "^10.0.0", - "remark-rehype": "^10.0.0", - "unified": "^10.0.0", - "unist-util-position-from-estree": "^1.0.0", - "unist-util-stringify-position": "^3.0.0", - "unist-util-visit": "^4.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/@mdx-js/react": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-2.3.0.tgz", - "integrity": "sha512-zQH//gdOmuu7nt2oJR29vFhDv88oGPmVw6BggmrHeMI+xgEkp1B2dX9/bMBSYtK0dyLX/aOmesKS09g222K1/g==", - "dependencies": { - "@types/mdx": "^2.0.0", - "@types/react": ">=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "react": ">=16" - } - }, - "node_modules/@motionone/animation": { - "version": "10.15.1", - "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.15.1.tgz", - "integrity": "sha512-mZcJxLjHor+bhcPuIFErMDNyrdb2vJur8lSfMCsuCB4UyV8ILZLvK+t+pg56erv8ud9xQGK/1OGPt10agPrCyQ==", - "dependencies": { - "@motionone/easing": "^10.15.1", - "@motionone/types": "^10.15.1", - "@motionone/utils": "^10.15.1", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/dom": { - "version": "10.16.2", - "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.16.2.tgz", - "integrity": "sha512-bnuHdNbge1FutZXv+k7xub9oPWcF0hsu8y1HTH/qg6av58YI0VufZ3ngfC7p2xhMJMnoh0LXFma2EGTgPeCkeg==", - "dependencies": { - "@motionone/animation": "^10.15.1", - "@motionone/generators": "^10.15.1", - "@motionone/types": "^10.15.1", - "@motionone/utils": "^10.15.1", - "hey-listen": "^1.0.8", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/easing": { - "version": "10.15.1", - "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.15.1.tgz", - "integrity": "sha512-6hIHBSV+ZVehf9dcKZLT7p5PEKHGhDwky2k8RKkmOvUoYP3S+dXsKupyZpqx5apjd9f+php4vXk4LuS+ADsrWw==", - "dependencies": { - "@motionone/utils": "^10.15.1", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/generators": { - "version": "10.15.1", - "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.15.1.tgz", - "integrity": "sha512-67HLsvHJbw6cIbLA/o+gsm7h+6D4Sn7AUrB/GPxvujse1cGZ38F5H7DzoH7PhX+sjvtDnt2IhFYF2Zp1QTMKWQ==", - "dependencies": { - "@motionone/types": "^10.15.1", - "@motionone/utils": "^10.15.1", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/svelte": { - "version": "10.16.2", - "resolved": "https://registry.npmjs.org/@motionone/svelte/-/svelte-10.16.2.tgz", - "integrity": "sha512-38xsroKrfK+aHYhuQlE6eFcGy0EwrB43Q7RGjF73j/kRUTcLNu/LAaKiLLsN5lyqVzCgTBVt4TMT/ShWbTbc5Q==", - "dependencies": { - "@motionone/dom": "^10.16.2", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/types": { - "version": "10.15.1", - "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.15.1.tgz", - "integrity": "sha512-iIUd/EgUsRZGrvW0jqdst8st7zKTzS9EsKkP+6c6n4MPZoQHwiHuVtTQLD6Kp0bsBLhNzKIBlHXponn/SDT4hA==" - }, - "node_modules/@motionone/utils": { - "version": "10.15.1", - "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.15.1.tgz", - "integrity": "sha512-p0YncgU+iklvYr/Dq4NobTRdAPv9PveRDUXabPEeOjBLSO/1FNB2phNTZxOxpi1/GZwYpAoECEa0Wam+nsmhSw==", - "dependencies": { - "@motionone/types": "^10.15.1", - "hey-listen": "^1.0.8", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/vue": { - "version": "10.16.2", - "resolved": "https://registry.npmjs.org/@motionone/vue/-/vue-10.16.2.tgz", - "integrity": "sha512-7/dEK/nWQXOkJ70bqb2KyNfSWbNvWqKKq1C8juj+0Mg/AorgD8O5wE3naddK0G+aXuNMqRuc4jlsYHHWHtIzVw==", - "dependencies": { - "@motionone/dom": "^10.16.2", - "tslib": "^2.3.1" - } - }, - "node_modules/@napi-rs/simple-git": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git/-/simple-git-0.1.8.tgz", - "integrity": "sha512-BvOMdkkofTz6lEE35itJ/laUokPhr/5ToMGlOH25YnhLD2yN1KpRAT4blW9tT8281/1aZjW3xyi73bs//IrDKA==", - "engines": { - "node": ">= 10" - }, - "optionalDependencies": { - "@napi-rs/simple-git-android-arm-eabi": "0.1.8", - "@napi-rs/simple-git-android-arm64": "0.1.8", - "@napi-rs/simple-git-darwin-arm64": "0.1.8", - "@napi-rs/simple-git-darwin-x64": "0.1.8", - "@napi-rs/simple-git-linux-arm-gnueabihf": "0.1.8", - "@napi-rs/simple-git-linux-arm64-gnu": "0.1.8", - "@napi-rs/simple-git-linux-arm64-musl": "0.1.8", - "@napi-rs/simple-git-linux-x64-gnu": "0.1.8", - "@napi-rs/simple-git-linux-x64-musl": "0.1.8", - "@napi-rs/simple-git-win32-arm64-msvc": "0.1.8", - "@napi-rs/simple-git-win32-x64-msvc": "0.1.8" - } - }, - "node_modules/@napi-rs/simple-git-android-arm-eabi": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-android-arm-eabi/-/simple-git-android-arm-eabi-0.1.8.tgz", - "integrity": "sha512-JJCejHBB1G6O8nxjQLT4quWCcvLpC3oRdJJ9G3MFYSCoYS8i1bWCWeU+K7Br+xT+D6s1t9q8kNJAwJv9Ygpi0g==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/simple-git-android-arm64": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-android-arm64/-/simple-git-android-arm64-0.1.8.tgz", - "integrity": "sha512-mraHzwWBw3tdRetNOS5KnFSjvdAbNBnjFLA8I4PwTCPJj3Q4txrigcPp2d59cJ0TC51xpnPXnZjYdNwwSI9g6g==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/simple-git-darwin-arm64": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-darwin-arm64/-/simple-git-darwin-arm64-0.1.8.tgz", - "integrity": "sha512-ufy/36eI/j4UskEuvqSH7uXtp3oXeLDmjQCfKJz3u5Vx98KmOMKrqAm2H81AB2WOtCo5mqS6PbBeUXR8BJX8lQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/simple-git-darwin-x64": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-darwin-x64/-/simple-git-darwin-x64-0.1.8.tgz", - "integrity": "sha512-Vb21U+v3tPJNl+8JtIHHT8HGe6WZ8o1Tq3f6p+Jx9Cz71zEbcIiB9FCEMY1knS/jwQEOuhhlI9Qk7d4HY+rprA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/simple-git-linux-arm-gnueabihf": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-arm-gnueabihf/-/simple-git-linux-arm-gnueabihf-0.1.8.tgz", - "integrity": "sha512-6BPTJ7CzpSm2t54mRLVaUr3S7ORJfVJoCk2rQ8v8oDg0XAMKvmQQxOsAgqKBo9gYNHJnqrOx3AEuEgvB586BuQ==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/simple-git-linux-arm64-gnu": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-arm64-gnu/-/simple-git-linux-arm64-gnu-0.1.8.tgz", - "integrity": "sha512-qfESqUCAA/XoQpRXHptSQ8gIFnETCQt1zY9VOkplx6tgYk9PCeaX4B1Xuzrh3eZamSCMJFn+1YB9Ut8NwyGgAA==", - "cpu": [ - "arm64" - ], - "hasInstallScript": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/simple-git-linux-arm64-musl": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-arm64-musl/-/simple-git-linux-arm64-musl-0.1.8.tgz", - "integrity": "sha512-G80BQPpaRmQpn8dJGHp4I2/YVhWDUNJwcCrJAtAdbKFDCMyCHJBln2ERL/+IEUlIAT05zK/c1Z5WEprvXEdXow==", - "cpu": [ - "arm64" - ], - "hasInstallScript": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/simple-git-linux-x64-gnu": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-x64-gnu/-/simple-git-linux-x64-gnu-0.1.8.tgz", - "integrity": "sha512-NI6o1sZYEf6vPtNWJAm9w8BxJt+LlSFW0liSjYe3lc3e4dhMfV240f0ALeqlwdIldRPaDFwZSJX5/QbS7nMzhw==", - "cpu": [ - "x64" - ], - "hasInstallScript": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/simple-git-linux-x64-musl": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-x64-musl/-/simple-git-linux-x64-musl-0.1.8.tgz", - "integrity": "sha512-wljGAEOW41er45VTiU8kXJmO480pQKzsgRCvPlJJSCaEVBbmo6XXbFIXnZy1a2J3Zyy2IOsRB4PVkUZaNuPkZQ==", - "cpu": [ - "x64" - ], - "hasInstallScript": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/simple-git-win32-arm64-msvc": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-win32-arm64-msvc/-/simple-git-win32-arm64-msvc-0.1.8.tgz", - "integrity": "sha512-QuV4QILyKPfbWHoQKrhXqjiCClx0SxbCTVogkR89BwivekqJMd9UlMxZdoCmwLWutRx4z9KmzQqokvYI5QeepA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/simple-git-win32-x64-msvc": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-win32-x64-msvc/-/simple-git-win32-x64-msvc-0.1.8.tgz", - "integrity": "sha512-UzNS4JtjhZhZ5hRLq7BIUq+4JOwt1ThIKv11CsF1ag2l99f0123XvfEpjczKTaa94nHtjXYc2Mv9TjccBqYOew==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/env": { - "version": "13.4.8", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.8.tgz", - "integrity": "sha512-twuSf1klb3k9wXI7IZhbZGtFCWvGD4wXTY2rmvzIgVhXhs7ISThrbNyutBx3jWIL8Y/Hk9+woytFz5QsgtcRKQ==" - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "13.4.8", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.8.tgz", - "integrity": "sha512-MSFplVM4dTWOuKAUv0XR9gY7AWtMSBu9os9f+kp+s5rWhM1I2CdR3obFttd6366nS/W/VZxbPM5oEIdlIa46zA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "13.4.8", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.8.tgz", - "integrity": "sha512-Reox+UXgonon9P0WNDE6w85DGtyBqGitl/ryznOvn6TvfxEaZIpTgeu3ZrJLU9dHSMhiK7YAM793mE/Zii2/Qw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.4.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.8.tgz", - "integrity": "sha512-kdyzYvAYtqQVgzIKNN7e1rLU8aZv86FDSRqPlOkKZlvqudvTO0iohuTPmnEEDlECeBM6qRPShNffotDcU/R2KA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.4.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.8.tgz", - "integrity": "sha512-oWxx4yRkUGcR81XwbI+T0zhZ3bDF6V1aVLpG+C7hSG50ULpV8gC39UxVO22/bv93ZlcfMY4zl8xkz9Klct6dpQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.4.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.8.tgz", - "integrity": "sha512-anhtvuO6eE9YRhYnaEGTfbpH3L5gT/9qPFcNoi6xS432r/4DAtpJY8kNktqkTVevVIC/pVumqO8tV59PR3zbNg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "13.4.8", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.8.tgz", - "integrity": "sha512-aR+J4wWfNgH1DwCCBNjan7Iumx0lLtn+2/rEYuhIrYLY4vnxqSVGz9u3fXcgUwo6Q9LT8NFkaqK1vPprdq+BXg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.4.8", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.8.tgz", - "integrity": "sha512-OWBKIrJwQBTqrat0xhxEB/jcsjJR3+diD9nc/Y8F1mRdQzsn4bPsomgJyuqPVZs6Lz3K18qdIkvywmfSq75SsQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.4.8", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.8.tgz", - "integrity": "sha512-agiPWGjUndXGTOn4ChbKipQXRA6/UPkywAWIkx7BhgGv48TiJfHTK6MGfBoL9tS6B4mtW39++uy0wFPnfD0JWg==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.4.8", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.8.tgz", - "integrity": "sha512-UIRKoByVKbuR6SnFG4JM8EMFlJrfEGuUQ1ihxzEleWcNwRMMiVaCj1KyqfTOW8VTQhJ0u8P1Ngg6q1RwnIBTtw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@noble/hashes": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", - "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@popperjs/core": { - "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, - "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/@react-icons/all-files": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@react-icons/all-files/-/all-files-4.1.0.tgz", - "integrity": "sha512-hxBI2UOuVaI3O/BhQfhtb4kcGn9ft12RWAFVMUeNjqqhLsHvFtzIkFaptBJpFDANTKoDfdVoHTKZDlwKCACbMQ==", - "peerDependencies": { - "react": "*" - } - }, - "node_modules/@stablelib/aead": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/aead/-/aead-1.0.1.tgz", - "integrity": "sha512-q39ik6sxGHewqtO0nP4BuSe3db5G1fEJE8ukvngS2gLkBXyy6E7pLubhbYgnkDFv6V8cWaxcE4Xn0t6LWcJkyg==" - }, - "node_modules/@stablelib/binary": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/binary/-/binary-1.0.1.tgz", - "integrity": "sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q==", - "dependencies": { - "@stablelib/int": "^1.0.1" - } - }, - "node_modules/@stablelib/bytes": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/bytes/-/bytes-1.0.1.tgz", - "integrity": "sha512-Kre4Y4kdwuqL8BR2E9hV/R5sOrUj6NanZaZis0V6lX5yzqC3hBuVSDXUIBqQv/sCpmuWRiHLwqiT1pqqjuBXoQ==" - }, - "node_modules/@stablelib/chacha": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/chacha/-/chacha-1.0.1.tgz", - "integrity": "sha512-Pmlrswzr0pBzDofdFuVe1q7KdsHKhhU24e8gkEwnTGOmlC7PADzLVxGdn2PoNVBBabdg0l/IfLKg6sHAbTQugg==", - "dependencies": { - "@stablelib/binary": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/chacha20poly1305": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/chacha20poly1305/-/chacha20poly1305-1.0.1.tgz", - "integrity": "sha512-MmViqnqHd1ymwjOQfghRKw2R/jMIGT3wySN7cthjXCBdO+qErNPUBnRzqNpnvIwg7JBCg3LdeCZZO4de/yEhVA==", - "dependencies": { - "@stablelib/aead": "^1.0.1", - "@stablelib/binary": "^1.0.1", - "@stablelib/chacha": "^1.0.1", - "@stablelib/constant-time": "^1.0.1", - "@stablelib/poly1305": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/constant-time/-/constant-time-1.0.1.tgz", - "integrity": "sha512-tNOs3uD0vSJcK6z1fvef4Y+buN7DXhzHDPqRLSXUel1UfqMB1PWNsnnAezrKfEwTLpN0cGH2p9NNjs6IqeD0eg==" - }, - "node_modules/@stablelib/ed25519": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@stablelib/ed25519/-/ed25519-1.0.3.tgz", - "integrity": "sha512-puIMWaX9QlRsbhxfDc5i+mNPMY+0TmQEskunY1rZEBPi1acBCVQAhnsk/1Hk50DGPtVsZtAWQg4NHGlVaO9Hqg==", - "dependencies": { - "@stablelib/random": "^1.0.2", - "@stablelib/sha512": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/hash": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/hash/-/hash-1.0.1.tgz", - "integrity": "sha512-eTPJc/stDkdtOcrNMZ6mcMK1e6yBbqRBaNW55XA1jU8w/7QdnCF0CmMmOD1m7VSkBR44PWrMHU2l6r8YEQHMgg==" - }, - "node_modules/@stablelib/hkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/hkdf/-/hkdf-1.0.1.tgz", - "integrity": "sha512-SBEHYE16ZXlHuaW5RcGk533YlBj4grMeg5TooN80W3NpcHRtLZLLXvKyX0qcRFxf+BGDobJLnwkvgEwHIDBR6g==", - "dependencies": { - "@stablelib/hash": "^1.0.1", - "@stablelib/hmac": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/hmac": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/hmac/-/hmac-1.0.1.tgz", - "integrity": "sha512-V2APD9NSnhVpV/QMYgCVMIYKiYG6LSqw1S65wxVoirhU/51ACio6D4yDVSwMzuTJXWZoVHbDdINioBwKy5kVmA==", - "dependencies": { - "@stablelib/constant-time": "^1.0.1", - "@stablelib/hash": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/int": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/int/-/int-1.0.1.tgz", - "integrity": "sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w==" - }, - "node_modules/@stablelib/keyagreement": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/keyagreement/-/keyagreement-1.0.1.tgz", - "integrity": "sha512-VKL6xBwgJnI6l1jKrBAfn265cspaWBPAPEc62VBQrWHLqVgNRE09gQ/AnOEyKUWrrqfD+xSQ3u42gJjLDdMDQg==", - "dependencies": { - "@stablelib/bytes": "^1.0.1" - } - }, - "node_modules/@stablelib/poly1305": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/poly1305/-/poly1305-1.0.1.tgz", - "integrity": "sha512-1HlG3oTSuQDOhSnLwJRKeTRSAdFNVB/1djy2ZbS35rBSJ/PFqx9cf9qatinWghC2UbfOYD8AcrtbUQl8WoxabA==", - "dependencies": { - "@stablelib/constant-time": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/random": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@stablelib/random/-/random-1.0.2.tgz", - "integrity": "sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w==", - "dependencies": { - "@stablelib/binary": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/sha256": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/sha256/-/sha256-1.0.1.tgz", - "integrity": "sha512-GIIH3e6KH+91FqGV42Kcj71Uefd/QEe7Dy42sBTeqppXV95ggCcxLTk39bEr+lZfJmp+ghsR07J++ORkRELsBQ==", - "dependencies": { - "@stablelib/binary": "^1.0.1", - "@stablelib/hash": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/sha512": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/sha512/-/sha512-1.0.1.tgz", - "integrity": "sha512-13gl/iawHV9zvDKciLo1fQ8Bgn2Pvf7OV6amaRVKiq3pjQ3UmEpXxWiAfV8tYjUpeZroBxtyrwtdooQT/i3hzw==", - "dependencies": { - "@stablelib/binary": "^1.0.1", - "@stablelib/hash": "^1.0.1", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@stablelib/wipe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/wipe/-/wipe-1.0.1.tgz", - "integrity": "sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==" - }, - "node_modules/@stablelib/x25519": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@stablelib/x25519/-/x25519-1.0.3.tgz", - "integrity": "sha512-KnTbKmUhPhHavzobclVJQG5kuivH+qDLpe84iRqX3CLrKp881cF160JvXJ+hjn1aMyCwYOKeIZefIH/P5cJoRw==", - "dependencies": { - "@stablelib/keyagreement": "^1.0.1", - "@stablelib/random": "^1.0.2", - "@stablelib/wipe": "^1.0.1" - } - }, - "node_modules/@swc/helpers": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.1.tgz", - "integrity": "sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==", - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@theguild/remark-mermaid": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@theguild/remark-mermaid/-/remark-mermaid-0.0.3.tgz", - "integrity": "sha512-fccVR6o4UPUztrBjdUhM4ahwx+X7YHhoxsUoXv2vI07vz4dq+I03Ot0SjuZzDA/H7engxcb8ZxzCUEkZgGr/2g==", - "dependencies": { - "mermaid": "^10.2.2", - "unist-util-visit": "^4.1.2" - }, - "peerDependencies": { - "react": "^18.2.0" - } - }, - "node_modules/@types/acorn": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", - "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==", - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/@types/debug": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", - "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" - }, - "node_modules/@types/estree-jsx": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.0.tgz", - "integrity": "sha512-3qvGd0z8F2ENTGr/GG1yViqfiKmRfrXVx5sJyHGFu3z7m5g5utCQtGp/g29JnjflhtQJBv1WDQukHiT58xPcYQ==", - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/@types/hast": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz", - "integrity": "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/js-yaml": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.5.tgz", - "integrity": "sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==" - }, - "node_modules/@types/katex": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.14.0.tgz", - "integrity": "sha512-+2FW2CcT0K3P+JMR8YG846bmDwplKUTsWgT2ENwdQ1UdVfRk3GQrh6Mi4sTopy30gI8Uau5CEqHTDZ6YvWIUPA==" - }, - "node_modules/@types/long": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", - "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" - }, - "node_modules/@types/mdast": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.11.tgz", - "integrity": "sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw==", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/mdx": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.5.tgz", - "integrity": "sha512-76CqzuD6Q7LC+AtbPqrvD9AqsN0k8bsYo2bM2J8pmNldP1aIPAbzUQ7QbobyXL4eLr1wK5x8FZFe8eF/ubRuBg==" - }, - "node_modules/@types/ms": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" - }, - "node_modules/@types/node": { - "version": "18.11.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.10.tgz", - "integrity": "sha512-juG3RWMBOqcOuXC643OAdSA525V44cVgGV6dUDuiFtss+8Fk5x1hI93Rsld43VeJVIeqlP9I7Fn9/qaVqoEAuQ==" - }, - "node_modules/@types/prop-types": { - "version": "15.7.5", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", - "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" - }, - "node_modules/@types/react": { - "version": "18.2.14", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.14.tgz", - "integrity": "sha512-A0zjq+QN/O0Kpe30hA1GidzyFjatVvrpIvWLxD+xv67Vt91TWWgco9IvrJBkeyHm1trGaFS/FSGqPlhyeZRm0g==", - "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-transition-group": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==", - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/scheduler": { - "version": "0.16.3", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", - "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" - }, - "node_modules/@types/unist": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", - "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" - }, - "node_modules/@vanilla-extract/css": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@vanilla-extract/css/-/css-1.12.0.tgz", - "integrity": "sha512-TEttZfnqTRtwgVYiBWQSGGUiVaYWReHp59DsavITEvh4TpJNifZFGhBznHx4wQFEsyio6xA513jps4tmqR6zmw==", - "dependencies": { - "@emotion/hash": "^0.9.0", - "@vanilla-extract/private": "^1.0.3", - "ahocorasick": "1.0.2", - "chalk": "^4.1.1", - "css-what": "^6.1.0", - "cssesc": "^3.0.0", - "csstype": "^3.0.7", - "deep-object-diff": "^1.1.9", - "deepmerge": "^4.2.2", - "media-query-parser": "^2.0.2", - "outdent": "^0.8.0" - } - }, - "node_modules/@vanilla-extract/css-utils": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@vanilla-extract/css-utils/-/css-utils-0.1.3.tgz", - "integrity": "sha512-PZAcHROlgtCUGI2y0JntdNwvPwCNyeVnkQu6KTYKdmxBbK3w72XJUmLFYapfaFfgami4I9CTLnrJTPdtmS3gpw==" - }, - "node_modules/@vanilla-extract/css/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/@vanilla-extract/css/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/@vanilla-extract/css/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/@vanilla-extract/css/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/@vanilla-extract/css/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/@vanilla-extract/css/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/@vanilla-extract/dynamic": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@vanilla-extract/dynamic/-/dynamic-2.0.3.tgz", - "integrity": "sha512-Rglfw2gXAYiBzAQ4jgUG7rBgE2c88e/zcG27ZVoIqMHVq56wf2C1katGMm1yFMNBgzqM7oBNYzz4YOMzznydkg==", - "dependencies": { - "@vanilla-extract/private": "^1.0.3" - } - }, - "node_modules/@vanilla-extract/private": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@vanilla-extract/private/-/private-1.0.3.tgz", - "integrity": "sha512-17kVyLq3ePTKOkveHxXuIJZtGYs+cSoev7BlP+Lf4916qfDhk/HBjvlYDe8egrea7LNPHKwSZJK/bzZC+Q6AwQ==" - }, - "node_modules/@vanilla-extract/recipes": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@vanilla-extract/recipes/-/recipes-0.4.0.tgz", - "integrity": "sha512-gFgB7BofUYbtbxINHK6DhMv1JDFDXp/YI/Xm+cqKar+1I/2dfxPepeDxSexL6YB4ftfeaDw8Kn5zydMvHcGOEQ==", - "peerDependencies": { - "@vanilla-extract/css": "^1.0.0" - } - }, - "node_modules/@walletconnect/core": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.9.1.tgz", - "integrity": "sha512-xyWeP0eLhEEDQAVJSmqs4n/AClKUM+8os2ZFe7BTuw1tFYjeLNVDtKCHziVOSTh8wEChMsKSGKA4zerQoH8mAQ==", - "dependencies": { - "@walletconnect/heartbeat": "1.2.1", - "@walletconnect/jsonrpc-provider": "1.0.13", - "@walletconnect/jsonrpc-types": "1.0.3", - "@walletconnect/jsonrpc-utils": "1.0.8", - "@walletconnect/jsonrpc-ws-connection": "1.0.13", - "@walletconnect/keyvaluestorage": "^1.0.2", - "@walletconnect/logger": "^2.0.1", - "@walletconnect/relay-api": "^1.0.9", - "@walletconnect/relay-auth": "^1.0.4", - "@walletconnect/safe-json": "^1.0.2", - "@walletconnect/time": "^1.0.2", - "@walletconnect/types": "2.9.1", - "@walletconnect/utils": "2.9.1", - "events": "^3.3.0", - "lodash.isequal": "4.5.0", - "uint8arrays": "^3.1.0" - } - }, - "node_modules/@walletconnect/core/node_modules/@walletconnect/types": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.9.1.tgz", - "integrity": "sha512-xbGgTPuD6xsb7YMvCESBIH55cjB86QAnnVL50a/ED42YkQzDsOdJ0VGTbrm0tG5cxUOF933rpxZQjxGdP+ovww==", - "dependencies": { - "@walletconnect/events": "^1.0.1", - "@walletconnect/heartbeat": "1.2.1", - "@walletconnect/jsonrpc-types": "1.0.3", - "@walletconnect/keyvaluestorage": "^1.0.2", - "@walletconnect/logger": "^2.0.1", - "events": "^3.3.0" - } - }, - "node_modules/@walletconnect/environment": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@walletconnect/environment/-/environment-1.0.1.tgz", - "integrity": "sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg==", - "dependencies": { - "tslib": "1.14.1" - } - }, - "node_modules/@walletconnect/environment/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/@walletconnect/events": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@walletconnect/events/-/events-1.0.1.tgz", - "integrity": "sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ==", - "dependencies": { - "keyvaluestorage-interface": "^1.0.0", - "tslib": "1.14.1" - } - }, - "node_modules/@walletconnect/events/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/@walletconnect/heartbeat": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@walletconnect/heartbeat/-/heartbeat-1.2.1.tgz", - "integrity": "sha512-yVzws616xsDLJxuG/28FqtZ5rzrTA4gUjdEMTbWB5Y8V1XHRmqq4efAxCw5ie7WjbXFSUyBHaWlMR+2/CpQC5Q==", - "dependencies": { - "@walletconnect/events": "^1.0.1", - "@walletconnect/time": "^1.0.2", - "tslib": "1.14.1" - } - }, - "node_modules/@walletconnect/heartbeat/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/@walletconnect/jsonrpc-provider": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.13.tgz", - "integrity": "sha512-K73EpThqHnSR26gOyNEL+acEex3P7VWZe6KE12ZwKzAt2H4e5gldZHbjsu2QR9cLeJ8AXuO7kEMOIcRv1QEc7g==", - "dependencies": { - "@walletconnect/jsonrpc-utils": "^1.0.8", - "@walletconnect/safe-json": "^1.0.2", - "tslib": "1.14.1" - } - }, - "node_modules/@walletconnect/jsonrpc-provider/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/@walletconnect/jsonrpc-types": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.3.tgz", - "integrity": "sha512-iIQ8hboBl3o5ufmJ8cuduGad0CQm3ZlsHtujv9Eu16xq89q+BG7Nh5VLxxUgmtpnrePgFkTwXirCTkwJH1v+Yw==", - "dependencies": { - "keyvaluestorage-interface": "^1.0.0", - "tslib": "1.14.1" - } - }, - "node_modules/@walletconnect/jsonrpc-types/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/@walletconnect/jsonrpc-utils": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz", - "integrity": "sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw==", - "dependencies": { - "@walletconnect/environment": "^1.0.1", - "@walletconnect/jsonrpc-types": "^1.0.3", - "tslib": "1.14.1" - } - }, - "node_modules/@walletconnect/jsonrpc-utils/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/@walletconnect/jsonrpc-ws-connection": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.13.tgz", - "integrity": "sha512-mfOM7uFH4lGtQxG+XklYuFBj6dwVvseTt5/ahOkkmpcAEgz2umuzu7fTR+h5EmjQBdrmYyEBOWADbeaFNxdySg==", - "dependencies": { - "@walletconnect/jsonrpc-utils": "^1.0.6", - "@walletconnect/safe-json": "^1.0.2", - "events": "^3.3.0", - "tslib": "1.14.1", - "ws": "^7.5.1" - } - }, - "node_modules/@walletconnect/jsonrpc-ws-connection/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/@walletconnect/keyvaluestorage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.0.2.tgz", - "integrity": "sha512-U/nNG+VLWoPFdwwKx0oliT4ziKQCEoQ27L5Hhw8YOFGA2Po9A9pULUYNWhDgHkrb0gYDNt//X7wABcEWWBd3FQ==", - "dependencies": { - "safe-json-utils": "^1.1.1", - "tslib": "1.14.1" - }, - "peerDependencies": { - "@react-native-async-storage/async-storage": "1.x", - "lokijs": "1.x" - }, - "peerDependenciesMeta": { - "@react-native-async-storage/async-storage": { - "optional": true - }, - "lokijs": { - "optional": true - } - } - }, - "node_modules/@walletconnect/keyvaluestorage/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/@walletconnect/logger": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@walletconnect/logger/-/logger-2.0.1.tgz", - "integrity": "sha512-SsTKdsgWm+oDTBeNE/zHxxr5eJfZmE9/5yp/Ku+zJtcTAjELb3DXueWkDXmE9h8uHIbJzIb5wj5lPdzyrjT6hQ==", - "dependencies": { - "pino": "7.11.0", - "tslib": "1.14.1" - } - }, - "node_modules/@walletconnect/logger/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/@walletconnect/relay-api": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@walletconnect/relay-api/-/relay-api-1.0.9.tgz", - "integrity": "sha512-Q3+rylJOqRkO1D9Su0DPE3mmznbAalYapJ9qmzDgK28mYF9alcP3UwG/og5V7l7CFOqzCLi7B8BvcBUrpDj0Rg==", - "dependencies": { - "@walletconnect/jsonrpc-types": "^1.0.2", - "tslib": "1.14.1" - } - }, - "node_modules/@walletconnect/relay-api/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/@walletconnect/relay-auth": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@walletconnect/relay-auth/-/relay-auth-1.0.4.tgz", - "integrity": "sha512-kKJcS6+WxYq5kshpPaxGHdwf5y98ZwbfuS4EE/NkQzqrDFm5Cj+dP8LofzWvjrrLkZq7Afy7WrQMXdLy8Sx7HQ==", - "dependencies": { - "@stablelib/ed25519": "^1.0.2", - "@stablelib/random": "^1.0.1", - "@walletconnect/safe-json": "^1.0.1", - "@walletconnect/time": "^1.0.2", - "tslib": "1.14.1", - "uint8arrays": "^3.0.0" - } - }, - "node_modules/@walletconnect/relay-auth/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/@walletconnect/safe-json": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@walletconnect/safe-json/-/safe-json-1.0.2.tgz", - "integrity": "sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA==", - "dependencies": { - "tslib": "1.14.1" - } - }, - "node_modules/@walletconnect/safe-json/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/@walletconnect/sign-client": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.9.1.tgz", - "integrity": "sha512-Z7tFRrJ9btA1vU427vsjUS6cPlHQVcTWdKH90khEc2lv3dB6mU8FNO0VJsw+I2D7CW7WaMWF3nnj6Z1FfotbDg==", - "dependencies": { - "@walletconnect/core": "2.9.1", - "@walletconnect/events": "^1.0.1", - "@walletconnect/heartbeat": "1.2.1", - "@walletconnect/jsonrpc-utils": "1.0.8", - "@walletconnect/logger": "^2.0.1", - "@walletconnect/time": "^1.0.2", - "@walletconnect/types": "2.9.1", - "@walletconnect/utils": "2.9.1", - "events": "^3.3.0" - } - }, - "node_modules/@walletconnect/sign-client/node_modules/@walletconnect/types": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.9.1.tgz", - "integrity": "sha512-xbGgTPuD6xsb7YMvCESBIH55cjB86QAnnVL50a/ED42YkQzDsOdJ0VGTbrm0tG5cxUOF933rpxZQjxGdP+ovww==", - "dependencies": { - "@walletconnect/events": "^1.0.1", - "@walletconnect/heartbeat": "1.2.1", - "@walletconnect/jsonrpc-types": "1.0.3", - "@walletconnect/keyvaluestorage": "^1.0.2", - "@walletconnect/logger": "^2.0.1", - "events": "^3.3.0" - } - }, - "node_modules/@walletconnect/time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@walletconnect/time/-/time-1.0.2.tgz", - "integrity": "sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==", - "dependencies": { - "tslib": "1.14.1" - } - }, - "node_modules/@walletconnect/time/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/@walletconnect/types": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.7.2.tgz", - "integrity": "sha512-1O2UefakZpT0ErRfEAXY7Ls3qdUrKDky/DsK088xR6klyfkQOx+aSVH0fJYLhmnqPTuvp3lrqNbsDc0s6/6nvg==", - "dependencies": { - "@walletconnect/events": "^1.0.1", - "@walletconnect/heartbeat": "1.2.1", - "@walletconnect/jsonrpc-types": "^1.0.2", - "@walletconnect/keyvaluestorage": "^1.0.2", - "@walletconnect/logger": "^2.0.1", - "events": "^3.3.0" - } - }, - "node_modules/@walletconnect/utils": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.9.1.tgz", - "integrity": "sha512-tXeQVebF5oPBvhdmuUyVSkSIBYx/egIi4czav1QrnUpwrUS1LsrFhyWBxSbhN7TXY287ULWkEf6aFpWOHdp5EA==", - "dependencies": { - "@stablelib/chacha20poly1305": "1.0.1", - "@stablelib/hkdf": "1.0.1", - "@stablelib/random": "^1.0.2", - "@stablelib/sha256": "1.0.1", - "@stablelib/x25519": "^1.0.3", - "@walletconnect/relay-api": "^1.0.9", - "@walletconnect/safe-json": "^1.0.2", - "@walletconnect/time": "^1.0.2", - "@walletconnect/types": "2.9.1", - "@walletconnect/window-getters": "^1.0.1", - "@walletconnect/window-metadata": "^1.0.1", - "detect-browser": "5.3.0", - "query-string": "7.1.3", - "uint8arrays": "^3.1.0" - } - }, - "node_modules/@walletconnect/utils/node_modules/@walletconnect/types": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.9.1.tgz", - "integrity": "sha512-xbGgTPuD6xsb7YMvCESBIH55cjB86QAnnVL50a/ED42YkQzDsOdJ0VGTbrm0tG5cxUOF933rpxZQjxGdP+ovww==", - "dependencies": { - "@walletconnect/events": "^1.0.1", - "@walletconnect/heartbeat": "1.2.1", - "@walletconnect/jsonrpc-types": "1.0.3", - "@walletconnect/keyvaluestorage": "^1.0.2", - "@walletconnect/logger": "^2.0.1", - "events": "^3.3.0" - } - }, - "node_modules/@walletconnect/window-getters": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@walletconnect/window-getters/-/window-getters-1.0.1.tgz", - "integrity": "sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q==", - "dependencies": { - "tslib": "1.14.1" - } - }, - "node_modules/@walletconnect/window-getters/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/@walletconnect/window-metadata": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@walletconnect/window-metadata/-/window-metadata-1.0.1.tgz", - "integrity": "sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA==", - "dependencies": { - "@walletconnect/window-getters": "^1.0.1", - "tslib": "1.14.1" - } - }, - "node_modules/@walletconnect/window-metadata/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/@zag-js/anatomy": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@zag-js/anatomy/-/anatomy-0.9.2.tgz", - "integrity": "sha512-DgzZf4oo1/tdnSzUDu75pdxYep8WmgvxZi3h1Qa0hlu0erGvWPV0L7aAkdrau+Z3z4phc0FndieIDZN1oN1bEg==" - }, - "node_modules/@zag-js/aria-hidden": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@zag-js/aria-hidden/-/aria-hidden-0.9.2.tgz", - "integrity": "sha512-Md+RCv8yOQ7uALjE8GRV0al3sb007aobFn1g6Vz0OSUD6Owsl4k1hwV1ZBWkSq6+OHhty35HROydqsKANDGc1g==", - "dependencies": { - "@zag-js/dom-query": "0.9.2" - } - }, - "node_modules/@zag-js/core": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@zag-js/core/-/core-0.9.2.tgz", - "integrity": "sha512-L8MwOCuKnOdWqjSRlgb8HQYuD29yRmi0PrTip+T42YK4+SiBiROeGcExYH2txIpVCk3Gww8TU5TzOHDvKCACyA==", - "dependencies": { - "@zag-js/store": "0.9.2", - "klona": "2.0.6" - } - }, - "node_modules/@zag-js/dialog": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@zag-js/dialog/-/dialog-0.9.2.tgz", - "integrity": "sha512-F7LrX2W5lSXukzRNnEL9z8E4zoHmqagrfP/o55jlM8+U/CVoLrRzTmPfl9b3ARguidkFIKj1ZgxZkphM9B0xoQ==", - "dependencies": { - "@zag-js/anatomy": "0.9.2", - "@zag-js/aria-hidden": "0.9.2", - "@zag-js/core": "0.9.2", - "@zag-js/dismissable": "0.9.2", - "@zag-js/dom-query": "0.9.2", - "@zag-js/remove-scroll": "0.9.2", - "@zag-js/types": "0.9.2", - "@zag-js/utils": "0.9.2", - "focus-trap": "7.4.1" - } - }, - "node_modules/@zag-js/dismissable": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@zag-js/dismissable/-/dismissable-0.9.2.tgz", - "integrity": "sha512-e654TDrIMedzFawTF6o/o4Pdf5k78asE5nSBKri3FZqbHWmpCacLc+vil5d27nc7Y3BXRuM7AyAaFoyBnZ/IOw==", - "dependencies": { - "@zag-js/dom-event": "0.9.2", - "@zag-js/dom-query": "0.9.2", - "@zag-js/interact-outside": "0.9.2", - "@zag-js/utils": "0.9.2" - } - }, - "node_modules/@zag-js/dom-event": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@zag-js/dom-event/-/dom-event-0.9.2.tgz", - "integrity": "sha512-2HUoIZw7Ig5bzm3S1f5i7S50LlyakhAD1seHBw6w+VwM7I6AFpbpJZjYAESeeKE+SAIA5q3CpdpL+KfdO5jpRg==", - "dependencies": { - "@zag-js/text-selection": "0.9.2", - "@zag-js/types": "0.9.2" - } - }, - "node_modules/@zag-js/dom-query": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-0.9.2.tgz", - "integrity": "sha512-N4K9sl3Dup+Jb0kaXrrwClwUdXgpgBb4xKYRDfG9HPO8ixX11Px8j4iTU3MdvhEt81sE7SkECdJNoyXaNxFqZA==" - }, - "node_modules/@zag-js/interact-outside": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@zag-js/interact-outside/-/interact-outside-0.9.2.tgz", - "integrity": "sha512-UYaim/6dgqo5lUyfag5SeWqyGwGHyBgh7MC92eymI86Kb3BYOUhIfXEUaoaacFBxRuJbhmFEsxFF8bN/tWNTJw==", - "dependencies": { - "@zag-js/dom-event": "0.9.2", - "@zag-js/dom-query": "0.9.2", - "@zag-js/tabbable": "0.9.2", - "@zag-js/utils": "0.9.2" - } - }, - "node_modules/@zag-js/react": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@zag-js/react/-/react-0.9.2.tgz", - "integrity": "sha512-7HBRfXQnPghWQwH/SY4MjUfRg8F6JaX/AosUA1mgUAi6WAIMEr8bIwb3iRVdRdjMoya/w3uynESpuimvo/7GFA==", - "dependencies": { - "@zag-js/core": "0.9.2", - "@zag-js/store": "0.9.2", - "@zag-js/types": "0.9.2", - "proxy-compare": "2.5.1" - }, - "peerDependencies": { - "react": ">=18.0.0", - "react-dom": ">=18.0.0" - } - }, - "node_modules/@zag-js/remove-scroll": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@zag-js/remove-scroll/-/remove-scroll-0.9.2.tgz", - "integrity": "sha512-SJti7IWmsXQU58vlMOz6BxzfSVKjLWMf7TJB2S6B/vuxLqrDpVal4+K5kgYqwa2rmbf/NkR+4ocdLyF63YupUg==", - "dependencies": { - "@zag-js/dom-query": "0.9.2" - } - }, - "node_modules/@zag-js/store": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@zag-js/store/-/store-0.9.2.tgz", - "integrity": "sha512-FO6BUK6ri0pZCEWqT8veiaZoTQwnCMqQ+C1pvf+ZtMnGMCjMXe/QvNUx/dcHSrscGckWJDBTJRbLhmDedyDPUA==", - "dependencies": { - "proxy-compare": "2.5.1" - } - }, - "node_modules/@zag-js/tabbable": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@zag-js/tabbable/-/tabbable-0.9.2.tgz", - "integrity": "sha512-CekXUcJ7HqK+MIFXazBD7KIrntOIJZc8lscf3aXEkpbYfTmilad1ZORAR5tnsIkYIoDHcLdxhT69CKR87NMNFA==", - "dependencies": { - "@zag-js/dom-query": "0.9.2" - } - }, - "node_modules/@zag-js/text-selection": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@zag-js/text-selection/-/text-selection-0.9.2.tgz", - "integrity": "sha512-xaXeLb9U7wZ5kEZ/L/if5INcX2YWi+Yzr8KIH2cNUaRE79cJFf0z1JG4D8VmO40EnCE396DVyNeLFdQXOAsu4Q==", - "dependencies": { - "@zag-js/dom-query": "0.9.2" - } - }, - "node_modules/@zag-js/types": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@zag-js/types/-/types-0.9.2.tgz", - "integrity": "sha512-MM8KPTW5nX438fDb57K0DM+nxcLA9+WoFyE9A/fEaCH2kGsaVltmsY1ejolU4duYNOEQVon9T39QlGfgc81f/w==", - "dependencies": { - "csstype": "3.1.2" - } - }, - "node_modules/@zag-js/utils": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@zag-js/utils/-/utils-0.9.2.tgz", - "integrity": "sha512-PQZRIhgaowNrON7UF4u1JTABUhlWhMiu4uwN7S7SXcpyq1z8JXb4j5YEHNkH4F7lLMQAwmMdpJXHfjH5bYXR1Q==" - }, - "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", - "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==", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ahocorasick": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ahocorasick/-/ahocorasick-1.0.2.tgz", - "integrity": "sha512-hCOfMzbFx5IDutmWLAt6MZwOUjIfSM9G9FyVxytmE4Rs/5YDPWQrD/+IR1w+FweD9H2oOZEnv36TmkjhNURBVA==" - }, - "node_modules/animejs": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/animejs/-/animejs-3.2.1.tgz", - "integrity": "sha512-sWno3ugFryK5nhiDm/2BKeFCpZv7vzerWUcUPyAZLDhMek3+S/p418ldZJbJXo5ZUOpfm2kP2XRO4NJcULMy9A==" - }, - "node_modules/ansi-sequence-parser": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.0.tgz", - "integrity": "sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==" - }, - "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==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "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/arg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/arg/-/arg-1.0.0.tgz", - "integrity": "sha512-Wk7TEzl1KqvTGs/uyhmHO/3XLd3t1UeU4IstvPXVzGPM522cTjqjNZ99esCkcL52sjqjo8e8CTBcWhkxvGzoAw==" - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/astring": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.6.tgz", - "integrity": "sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==", - "bin": { - "astring": "bin/astring" - } - }, - "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/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dependencies": { - "follow-redirects": "^1.14.0" - } - }, - "node_modules/bail": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", - "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "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/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" - }, - "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/bignumber.js": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz", - "integrity": "sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==", - "engines": { - "node": "*" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bip32": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz", - "integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==", - "dependencies": { - "@types/node": "10.12.18", - "bs58check": "^2.1.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "tiny-secp256k1": "^1.1.3", - "typeforce": "^1.11.5", - "wif": "^2.0.6" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/bip32/node_modules/@types/node": { - "version": "10.12.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", - "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" - }, - "node_modules/bip39": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", - "integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==", - "dependencies": { - "@noble/hashes": "^1.2.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/bowser": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", - "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" - }, - "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/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "dependencies": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "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/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001512", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001512.tgz", - "integrity": "sha512-2S9nK0G/mE+jasCUsMPlARhRCts1ebcp2Ji8Y8PWi4NDE1iRdLCnEPHkEfeBrGC45L4isBx5ur3IQ6yTE2mRZw==", - "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/ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chain-registry": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/chain-registry/-/chain-registry-1.18.0.tgz", - "integrity": "sha512-m80cUS7DM235FVxw82Vxf/9/j3qp8GXCQa7wtC55AaHdyajX/C0hWw513FVBKnMyCLPwLfMzC58eiFudBk888w==", - "dependencies": { - "@babel/runtime": "^7.21.0", - "@chain-registry/types": "^0.16.0" - } - }, - "node_modules/chain-registry/node_modules/@chain-registry/types": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@chain-registry/types/-/types-0.16.0.tgz", - "integrity": "sha512-4j6vq2Vqn/nF+UBjvRPUVs6eM3+5rJ+dPmEWpd/OoNH3wTy1k6aoilcSTZRR//vGcI5EOVGsxhhJxUzo2qqweA==", - "dependencies": { - "@babel/runtime": "^7.21.0" - } - }, - "node_modules/chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dependencies": { - "ansi-styles": "^3.1.0", - "escape-string-regexp": "^1.0.5", - "supports-color": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk/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==", - "engines": { - "node": ">=0.8.0" - } - }, - "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==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-html4": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", - "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-reference-invalid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", - "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", - "engines": { - "node": "*" - } - }, - "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" - }, - "node_modules/clipboardy": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-1.2.2.tgz", - "integrity": "sha512-16KrBOV7bHmHdxcQiCvfUFYVFyEah4FI8vYT1Fr7CGSA4G+xBWMEfUEQJS1hxeHGtI9ju1Bzs9uXSbj5HZKArw==", - "dependencies": { - "arch": "^2.1.0", - "execa": "^0.8.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/clsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", - "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", - "engines": { - "node": ">=6" - } - }, - "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-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/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==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "engines": { - "node": ">= 12" - } - }, - "node_modules/compute-scroll-into-view": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.0.3.tgz", - "integrity": "sha512-nadqwNxghAGTamwIqQSG433W6OADZx2vCo3UXHNrzTRHK/htu+7+L0zhjEoaeaQVNAi3YgqWDv8+tzf0hRfR+A==" - }, - "node_modules/copy-to-clipboard": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", - "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", - "dependencies": { - "toggle-selection": "^1.0.6" - } - }, - "node_modules/cose-base": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", - "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", - "dependencies": { - "layout-base": "^1.0.0" - } - }, - "node_modules/cosmjs-types": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.8.0.tgz", - "integrity": "sha512-Q2Mj95Fl0PYMWEhA2LuGEIhipF7mQwd9gTQ85DdP9jjjopeoGaDxvmPa5nakNzsq7FnO1DMTatXTAx6bxMH7Lg==", - "dependencies": { - "long": "^4.0.0", - "protobufjs": "~6.11.2" - } - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "node_modules/cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", - "dependencies": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "node_modules/crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", - "engines": { - "node": "*" - } - }, - "node_modules/crypto-js": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", - "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" - }, - "node_modules/curve25519-js": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/curve25519-js/-/curve25519-js-0.0.4.tgz", - "integrity": "sha512-axn2UMEnkhyDUPWOwVKBMVIzSQy2ejH2xRGy1wq81dqRwApXfIzfbE3hIX0ZRFBIihf/KDqK158DLwESu4AK1w==" - }, - "node_modules/cytoscape": { - "version": "3.25.0", - "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.25.0.tgz", - "integrity": "sha512-7MW3Iz57mCUo6JQCho6CmPBCbTlJr7LzyEtIkutG255HLVd4XuBg2I9BkTZLI/e4HoaOB/BiAzXuQybQ95+r9Q==", - "dependencies": { - "heap": "^0.2.6", - "lodash": "^4.17.21" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/cytoscape-cose-bilkent": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", - "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", - "dependencies": { - "cose-base": "^1.0.0" - }, - "peerDependencies": { - "cytoscape": "^3.2.0" - } - }, - "node_modules/cytoscape-fcose": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", - "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", - "dependencies": { - "cose-base": "^2.2.0" - }, - "peerDependencies": { - "cytoscape": "^3.2.0" - } - }, - "node_modules/cytoscape-fcose/node_modules/cose-base": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", - "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", - "dependencies": { - "layout-base": "^2.0.0" - } - }, - "node_modules/cytoscape-fcose/node_modules/layout-base": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", - "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==" - }, - "node_modules/d3": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.5.tgz", - "integrity": "sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==", - "dependencies": { - "d3-array": "3", - "d3-axis": "3", - "d3-brush": "3", - "d3-chord": "3", - "d3-color": "3", - "d3-contour": "4", - "d3-delaunay": "6", - "d3-dispatch": "3", - "d3-drag": "3", - "d3-dsv": "3", - "d3-ease": "3", - "d3-fetch": "3", - "d3-force": "3", - "d3-format": "3", - "d3-geo": "3", - "d3-hierarchy": "3", - "d3-interpolate": "3", - "d3-path": "3", - "d3-polygon": "3", - "d3-quadtree": "3", - "d3-random": "3", - "d3-scale": "4", - "d3-scale-chromatic": "3", - "d3-selection": "3", - "d3-shape": "3", - "d3-time": "3", - "d3-time-format": "4", - "d3-timer": "3", - "d3-transition": "3", - "d3-zoom": "3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-array": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", - "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", - "dependencies": { - "internmap": "1 - 2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-axis": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", - "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-brush": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", - "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "3", - "d3-transition": "3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-chord": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", - "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", - "dependencies": { - "d3-path": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-contour": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", - "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", - "dependencies": { - "d3-array": "^3.2.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-delaunay": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", - "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", - "dependencies": { - "delaunator": "5" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-dispatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", - "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-drag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", - "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-selection": "3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-dsv": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", - "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", - "dependencies": { - "commander": "7", - "iconv-lite": "0.6", - "rw": "1" - }, - "bin": { - "csv2json": "bin/dsv2json.js", - "csv2tsv": "bin/dsv2dsv.js", - "dsv2dsv": "bin/dsv2dsv.js", - "dsv2json": "bin/dsv2json.js", - "json2csv": "bin/json2dsv.js", - "json2dsv": "bin/json2dsv.js", - "json2tsv": "bin/json2dsv.js", - "tsv2csv": "bin/dsv2dsv.js", - "tsv2json": "bin/dsv2json.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-dsv/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/d3-ease": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-fetch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", - "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", - "dependencies": { - "d3-dsv": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-force": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", - "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-quadtree": "1 - 3", - "d3-timer": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-format": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", - "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-geo": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz", - "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==", - "dependencies": { - "d3-array": "2.5.0 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-hierarchy": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", - "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", - "dependencies": { - "d3-color": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", - "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-polygon": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", - "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-quadtree": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", - "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-random": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", - "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-scale": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", - "dependencies": { - "d3-array": "2.10.0 - 3", - "d3-format": "1 - 3", - "d3-interpolate": "1.2.0 - 3", - "d3-time": "2.1.1 - 3", - "d3-time-format": "2 - 4" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-scale-chromatic": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", - "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==", - "dependencies": { - "d3-color": "1 - 3", - "d3-interpolate": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-shape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", - "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", - "dependencies": { - "d3-path": "^3.1.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", - "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", - "dependencies": { - "d3-array": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time-format": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", - "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", - "dependencies": { - "d3-time": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-timer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-transition": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", - "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", - "dependencies": { - "d3-color": "1 - 3", - "d3-dispatch": "1 - 3", - "d3-ease": "1 - 3", - "d3-interpolate": "1 - 3", - "d3-timer": "1 - 3" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "d3-selection": "2 - 3" - } - }, - "node_modules/d3-zoom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", - "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "2 - 3", - "d3-transition": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/dagre-d3-es": { - "version": "7.0.10", - "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.10.tgz", - "integrity": "sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==", - "dependencies": { - "d3": "^7.8.2", - "lodash-es": "^4.17.21" - } - }, - "node_modules/dayjs": { - "version": "1.11.9", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz", - "integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==" - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": 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==", - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/deep-object-diff": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/deep-object-diff/-/deep-object-diff-1.1.9.tgz", - "integrity": "sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA==" - }, - "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==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delaunator": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", - "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==", - "dependencies": { - "robust-predicates": "^3.0.0" - } - }, - "node_modules/delay": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/delay/-/delay-4.4.1.tgz", - "integrity": "sha512-aL3AhqtfhOlT/3ai6sWXeqwnw63ATNpnUiN4HL7x9q+My5QtHlO3OIkasmug9LKzpheLdmUKGRKnYXYAS7FQkQ==", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "engines": { - "node": ">=6" - } - }, - "node_modules/detect-browser": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-5.3.0.tgz", - "integrity": "sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==" - }, - "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==", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dompurify": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.3.tgz", - "integrity": "sha512-axQ9zieHLnAnHh0sfAamKYiqXMJAVwu+LM/alQ7WDagoWessyWvMSFyW65CqF3owufNu8HBcE4cM2Vflu7YWcQ==" - }, - "node_modules/duplexify": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", - "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", - "dependencies": { - "end-of-stream": "^1.4.1", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1", - "stream-shift": "^1.0.0" - } - }, - "node_modules/elkjs": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.8.2.tgz", - "integrity": "sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==" - }, - "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/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/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "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/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/estree-util-attach-comments": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-2.1.1.tgz", - "integrity": "sha512-+5Ba/xGGS6mnwFbXIuQiDPTbuTxuMCooq3arVv7gPZtYpjp+VXH/NkHAP35OOefPhNG/UGqU3vt/LTABwcHX0w==", - "dependencies": { - "@types/estree": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-util-build-jsx": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-2.2.2.tgz", - "integrity": "sha512-m56vOXcOBuaF+Igpb9OPAy7f9w9OIkb5yhjsZuaPm7HoGi4oTOQi0h2+yZ+AtKklYFZ+rPC4n0wYCJCEU1ONqg==", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "estree-util-is-identifier-name": "^2.0.0", - "estree-walker": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-util-is-identifier-name": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-2.1.0.tgz", - "integrity": "sha512-bEN9VHRyXAUOjkKVQVvArFym08BTWB0aJPppZZr0UNyAqWsLaVfAqP7hbaTJjzHifmB5ebnR8Wm7r7yGN/HonQ==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-util-to-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-1.2.0.tgz", - "integrity": "sha512-IzU74r1PK5IMMGZXUVZbmiu4A1uhiPgW5hm1GjcOfr4ZzHaMPpLNJjR7HjXiIOzi25nZDrgFTobHTkV5Q6ITjA==", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "astring": "^1.8.0", - "source-map": "^0.7.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-util-value-to-estree": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-1.3.0.tgz", - "integrity": "sha512-Y+ughcF9jSUJvncXwqRageavjrNPAI+1M/L3BI3PyLp1nmgYTGUXU6t5z1Y7OWuThoDdhPME07bQU+d5LxdJqw==", - "dependencies": { - "is-plain-obj": "^3.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/estree-util-visit": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-1.2.1.tgz", - "integrity": "sha512-xbgqcrkIVbIG+lI/gzbvd9SGTJL4zqJKBFttUl5pP27KhAjtMKbX/mQXJ7qgyXpMgVy/zvpm0xoQQaGL8OloOw==", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "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": "0.8.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", - "integrity": "sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA==", - "dependencies": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "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/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" - }, - "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/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, - "node_modules/filter-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", - "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/flexsearch": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/flexsearch/-/flexsearch-0.7.31.tgz", - "integrity": "sha512-XGozTsMPYkm+6b5QL3Z9wQcJjNYxp0CYn3U1gO7dwD6PAqU1SVWZxI9CCg3z+ml3YfqdPnrBehaBrnH2AGKbNA==" - }, - "node_modules/focus-trap": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.4.1.tgz", - "integrity": "sha512-rnXP5ERIjlo1gEZp7hQb4ekYqUxRuSDQeyWvxhahH3/GkWtd8h8g1C8Eu/KGpuvbUWNVeogK0kuzzrM4u2Z9jA==", - "dependencies": { - "tabbable": "^6.1.2" - } - }, - "node_modules/focus-visible": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/focus-visible/-/focus-visible-5.2.0.tgz", - "integrity": "sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ==" - }, - "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "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/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/git-up": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz", - "integrity": "sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==", - "dependencies": { - "is-ssh": "^1.4.0", - "parse-url": "^8.1.0" - } - }, - "node_modules/git-url-parse": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-13.1.0.tgz", - "integrity": "sha512-5FvPJP/70WkIprlUZ33bm4UAaFdjcLkJLpWft1BeZKqwR0uhhNGoKwlUaPtVb4LxCSQ++erHapRak9kWGj+FCA==", - "dependencies": { - "git-up": "^7.0.0" - } - }, - "node_modules/github-slugger": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", - "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==" - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" - }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==" - }, - "node_modules/gray-matter": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", - "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", - "dependencies": { - "js-yaml": "^3.13.1", - "kind-of": "^6.0.2", - "section-matter": "^1.0.0", - "strip-bom-string": "^1.0.0" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "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/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash-obj": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/hash-obj/-/hash-obj-4.0.0.tgz", - "integrity": "sha512-FwO1BUVWkyHasWDW4S8o0ssQXjvyghLV2rfVhnN36b2bbcj45eGiuzdn9XOvOpjV3TKQD7Gm2BWNXdE9V4KKYg==", - "dependencies": { - "is-obj": "^3.0.0", - "sort-keys": "^5.0.0", - "type-fest": "^1.0.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/hast-util-from-dom": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-4.2.0.tgz", - "integrity": "sha512-t1RJW/OpJbCAJQeKi3Qrj1cAOLA0+av/iPFori112+0X7R3wng+jxLA+kXec8K4szqPRGI8vPxbbpEYvvpwaeQ==", - "dependencies": { - "hastscript": "^7.0.0", - "web-namespaces": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-html": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-1.0.2.tgz", - "integrity": "sha512-LhrTA2gfCbLOGJq2u/asp4kwuG0y6NhWTXiPKP+n0qNukKy7hc10whqqCFfyvIA1Q5U5d0sp9HhNim9gglEH4A==", - "dependencies": { - "@types/hast": "^2.0.0", - "hast-util-from-parse5": "^7.0.0", - "parse5": "^7.0.0", - "vfile": "^5.0.0", - "vfile-message": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-html-isomorphic": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-1.0.0.tgz", - "integrity": "sha512-Yu480AKeOEN/+l5LA674a+7BmIvtDj24GvOt7MtQWuhzUwlaaRWdEPXAh3Qm5vhuthpAipFb2vTetKXWOjmTvw==", - "dependencies": { - "@types/hast": "^2.0.0", - "hast-util-from-dom": "^4.0.0", - "hast-util-from-html": "^1.0.0", - "unist-util-remove-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz", - "integrity": "sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==", - "dependencies": { - "@types/hast": "^2.0.0", - "@types/unist": "^2.0.0", - "hastscript": "^7.0.0", - "property-information": "^6.0.0", - "vfile": "^5.0.0", - "vfile-location": "^4.0.0", - "web-namespaces": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-is-element": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-2.1.3.tgz", - "integrity": "sha512-O1bKah6mhgEq2WtVMk+Ta5K7pPMqsBBlmzysLdcwKVrqzZQ0CHqUPiIVspNhAG1rvxpvJjtGee17XfauZYKqVA==", - "dependencies": { - "@types/hast": "^2.0.0", - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-parse-selector": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", - "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", - "dependencies": { - "@types/hast": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-estree": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-2.3.3.tgz", - "integrity": "sha512-ihhPIUPxN0v0w6M5+IiAZZrn0LH2uZomeWwhn7uP7avZC6TE7lIiEh2yBMPr5+zi1aUCXq6VoYRgs2Bw9xmycQ==", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^2.0.0", - "@types/unist": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "estree-util-attach-comments": "^2.0.0", - "estree-util-is-identifier-name": "^2.0.0", - "hast-util-whitespace": "^2.0.0", - "mdast-util-mdx-expression": "^1.0.0", - "mdast-util-mdxjs-esm": "^1.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "style-to-object": "^0.4.1", - "unist-util-position": "^4.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-text": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-3.1.2.tgz", - "integrity": "sha512-tcllLfp23dJJ+ju5wCCZHVpzsQQ43+moJbqVX3jNWPB7z/KFC4FyZD6R7y94cHL6MQ33YtMZL8Z0aIXXI4XFTw==", - "dependencies": { - "@types/hast": "^2.0.0", - "@types/unist": "^2.0.0", - "hast-util-is-element": "^2.0.0", - "unist-util-find-after": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-whitespace": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", - "integrity": "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hastscript": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", - "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", - "dependencies": { - "@types/hast": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-parse-selector": "^3.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/heap": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", - "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==" - }, - "node_modules/hey-listen": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", - "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==" - }, - "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/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "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/immer": { - "version": "9.0.21", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", - "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/immer" - } - }, - "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/inline-style-parser": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", - "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" - }, - "node_modules/internmap": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", - "engines": { - "node": ">=12" - } - }, - "node_modules/intersection-observer": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.12.2.tgz", - "integrity": "sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==" - }, - "node_modules/is-alphabetical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", - "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-alphanumerical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", - "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", - "dependencies": { - "is-alphabetical": "^2.0.0", - "is-decimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "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==", - "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-decimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", - "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-hexadecimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", - "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-3.0.0.tgz", - "integrity": "sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-reference": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.1.tgz", - "integrity": "sha512-baJJdQLiYaJdvFbJqXrcGv3WU3QCzBlUcI5QhbesIm6/xPsvmO+2CDoi/GMOFBQEQm+PXkwOPrp9KK5ozZsp2w==", - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/is-ssh": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.0.tgz", - "integrity": "sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==", - "dependencies": { - "protocols": "^2.0.1" - } - }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/isomorphic-ws": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", - "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", - "peerDependencies": { - "ws": "*" - } - }, - "node_modules/js-crypto-env": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/js-crypto-env/-/js-crypto-env-0.3.2.tgz", - "integrity": "sha512-F1uHiCkSOo36qBuuZABA4sBf+xeFBzhJZ0Sd7af8FAruszIhm1Xxv+Zr5Ne90Zlh7/fnxCsrdkj0N8f0a3lVlQ==" - }, - "node_modules/js-crypto-hash": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/js-crypto-hash/-/js-crypto-hash-0.6.3.tgz", - "integrity": "sha512-SG8c9tM8y3sUb4k7WvpVfu5vU7zfPvX+eaYR5578TvehkehdaQbqAc+y+1FwxnqQ3WZ0gsYoOKp/mW+mqtNoWA==", - "dependencies": { - "buffer": "~5.4.3", - "hash.js": "~1.1.7", - "js-crypto-env": "^0.3.2", - "md5": "~2.2.1", - "sha3": "~2.1.0" - } - }, - "node_modules/js-crypto-hash/node_modules/buffer": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz", - "integrity": "sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==", - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "node_modules/js-crypto-hkdf": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/js-crypto-hkdf/-/js-crypto-hkdf-0.7.3.tgz", - "integrity": "sha512-eAaVArAjS2GCacWGXY4hjBiexrLQYlI0PMOcbwtrSEj84XU3kUfMYZm9bpTyaTXgdHC/eQoXe/Of6biG+RSEaQ==", - "dependencies": { - "js-crypto-env": "^0.3.2", - "js-crypto-hmac": "^0.6.3", - "js-crypto-random": "^0.4.3", - "js-encoding-utils": "0.5.6" - } - }, - "node_modules/js-crypto-hmac": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/js-crypto-hmac/-/js-crypto-hmac-0.6.3.tgz", - "integrity": "sha512-T0pKOaHACOSG6Xs6/06G8RDDeZouQwIQNBq9L/zoUGsd4F67gAjpT3q2lGigAGpUd1hiyy7vnhvLpz7VDt6DbA==", - "dependencies": { - "js-crypto-env": "^0.3.2", - "js-crypto-hash": "^0.6.3" - } - }, - "node_modules/js-crypto-random": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/js-crypto-random/-/js-crypto-random-0.4.3.tgz", - "integrity": "sha512-C3gzphPPfw9jfQ9Q/LjhJMZxQNp3AaoVRDvyZkiB+zYltfs8tKQPsskWkXACpg1Nzh01PtSRUvVijjptd2qGHQ==", - "dependencies": { - "js-crypto-env": "^0.3.2" - } - }, - "node_modules/js-encoding-utils": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/js-encoding-utils/-/js-encoding-utils-0.5.6.tgz", - "integrity": "sha512-qnAGsUIWrmzh5n+3AXqbxX1KsB9hkQmJZf3aA9DLAS7GpL/NEHCBreFFbW+imramoU+Q0TDyvkwhRbBRH1TVkg==" - }, - "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==" - }, - "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==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==" - }, - "node_modules/katex": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.8.tgz", - "integrity": "sha512-ftuDnJbcbOckGY11OO+zg3OofESlbR5DRl2cmN8HeWeeFIV7wTXvAOx8kEjZjobhA+9wh2fbKeO6cdcA9Mnovg==", - "funding": [ - "https://opencollective.com/katex", - "https://github.com/sponsors/katex" - ], - "dependencies": { - "commander": "^8.3.0" - }, - "bin": { - "katex": "cli.js" - } - }, - "node_modules/keyvaluestorage-interface": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz", - "integrity": "sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==" - }, - "node_modules/khroma": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.0.0.tgz", - "integrity": "sha512-2J8rDNlQWbtiNYThZRvmMv5yt44ZakX+Tz5ZIp/mN1pt4snn+m030Va5Z4v8xA0cQFDXBwO/8i42xL4QPsVk3g==" - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "engines": { - "node": ">=6" - } - }, - "node_modules/klona": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", - "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/layout-base": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", - "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==" - }, - "node_modules/libsodium": { - "version": "0.7.11", - "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.11.tgz", - "integrity": "sha512-WPfJ7sS53I2s4iM58QxY3Inb83/6mjlYgcmZs7DJsvDlnmVUwNinBCi5vBT43P6bHRy01O4zsMU2CoVR6xJ40A==" - }, - "node_modules/libsodium-sumo": { - "version": "0.7.11", - "resolved": "https://registry.npmjs.org/libsodium-sumo/-/libsodium-sumo-0.7.11.tgz", - "integrity": "sha512-bY+7ph7xpk51Ez2GbE10lXAQ5sJma6NghcIDaSPbM/G9elfrjLa0COHl/7P6Wb/JizQzl5UQontOOP1z0VwbLA==" - }, - "node_modules/libsodium-wrappers": { - "version": "0.7.11", - "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.11.tgz", - "integrity": "sha512-SrcLtXj7BM19vUKtQuyQKiQCRJPgbpauzl3s0rSwD+60wtHqSUuqcoawlMDheCJga85nKOQwxNYQxf/CKAvs6Q==", - "dependencies": { - "libsodium": "^0.7.11" - } - }, - "node_modules/libsodium-wrappers-sumo": { - "version": "0.7.11", - "resolved": "https://registry.npmjs.org/libsodium-wrappers-sumo/-/libsodium-wrappers-sumo-0.7.11.tgz", - "integrity": "sha512-DGypHOmJbB1nZn89KIfGOAkDgfv5N6SBGC3Qvmy/On0P0WD1JQvNRS/e3UL3aFF+xC0m+MYz5M+MnRnK2HMrKQ==", - "dependencies": { - "libsodium-sumo": "^0.7.11" - } - }, - "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-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" - }, - "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==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/markdown-extensions": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-1.1.1.tgz", - "integrity": "sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/markdown-table": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", - "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/match-sorter": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.1.tgz", - "integrity": "sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==", - "dependencies": { - "@babel/runtime": "^7.12.5", - "remove-accents": "0.4.2" - } - }, - "node_modules/md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha512-PlGG4z5mBANDGCKsYQe0CaUYHdZYZt8ZPZLmEt+Urf0W4GlpTX4HescwHU+dc9+Z/G/vZKYZYFrwgm9VxK6QOQ==", - "dependencies": { - "charenc": "~0.0.1", - "crypt": "~0.0.1", - "is-buffer": "~1.1.1" - } - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/md5/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "node_modules/mdast-util-definitions": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz", - "integrity": "sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==", - "dependencies": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-find-and-replace": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-2.2.2.tgz", - "integrity": "sha512-MTtdFRz/eMDHXzeK6W3dO7mXUlF82Gom4y0oOgvHhh/HXZAGvIQDUvQ0SuUx+j2tv44b8xTHOm8K/9OoRFnXKw==", - "dependencies": { - "@types/mdast": "^3.0.0", - "escape-string-regexp": "^5.0.0", - "unist-util-is": "^5.0.0", - "unist-util-visit-parents": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "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==", - "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-gfm": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-2.0.2.tgz", - "integrity": "sha512-qvZ608nBppZ4icQlhQQIAdc6S3Ffj9RGmzwUKUWuEICFnd1LVkN3EktF7ZHAgfcEdvZB5owU9tQgt99e2TlLjg==", - "dependencies": { - "mdast-util-from-markdown": "^1.0.0", - "mdast-util-gfm-autolink-literal": "^1.0.0", - "mdast-util-gfm-footnote": "^1.0.0", - "mdast-util-gfm-strikethrough": "^1.0.0", - "mdast-util-gfm-table": "^1.0.0", - "mdast-util-gfm-task-list-item": "^1.0.0", - "mdast-util-to-markdown": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-autolink-literal": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-1.0.3.tgz", - "integrity": "sha512-My8KJ57FYEy2W2LyNom4n3E7hKTuQk/0SES0u16tjA9Z3oFkF4RrC/hPAPgjlSpezsOvI8ObcXcElo92wn5IGA==", - "dependencies": { - "@types/mdast": "^3.0.0", - "ccount": "^2.0.0", - "mdast-util-find-and-replace": "^2.0.0", - "micromark-util-character": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-footnote": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-1.0.2.tgz", - "integrity": "sha512-56D19KOGbE00uKVj3sgIykpwKL179QsVFwx/DCW0u/0+URsryacI4MAdNJl0dh+u2PSsD9FtxPFbHCzJ78qJFQ==", - "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-to-markdown": "^1.3.0", - "micromark-util-normalize-identifier": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-strikethrough": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-1.0.3.tgz", - "integrity": "sha512-DAPhYzTYrRcXdMjUtUjKvW9z/FNAMTdU0ORyMcbmkwYNbKocDpdk+PX1L1dQgOID/+vVs1uBQ7ElrBQfZ0cuiQ==", - "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-to-markdown": "^1.3.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-table": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-1.0.7.tgz", - "integrity": "sha512-jjcpmNnQvrmN5Vx7y7lEc2iIOEytYv7rTvu+MeyAsSHTASGCCRA79Igg2uKssgOs1i1po8s3plW0sTu1wkkLGg==", - "dependencies": { - "@types/mdast": "^3.0.0", - "markdown-table": "^3.0.0", - "mdast-util-from-markdown": "^1.0.0", - "mdast-util-to-markdown": "^1.3.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-task-list-item": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-1.0.2.tgz", - "integrity": "sha512-PFTA1gzfp1B1UaiJVyhJZA1rm0+Tzn690frc/L8vNX1Jop4STZgOE6bxUhnzdVSB+vm2GU1tIsuQcA9bxTQpMQ==", - "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-to-markdown": "^1.3.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-math": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-2.0.2.tgz", - "integrity": "sha512-8gmkKVp9v6+Tgjtq6SYx9kGPpTf6FVYRa53/DLh479aldR9AyP48qeVOgNZ5X7QUK7nOy4yw7vg6mbiGcs9jWQ==", - "dependencies": { - "@types/mdast": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-to-markdown": "^1.3.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-2.0.1.tgz", - "integrity": "sha512-38w5y+r8nyKlGvNjSEqWrhG0w5PmnRA+wnBvm+ulYCct7nsGYhFVb0lljS9bQav4psDAS1eGkP2LMVcZBi/aqw==", - "dependencies": { - "mdast-util-from-markdown": "^1.0.0", - "mdast-util-mdx-expression": "^1.0.0", - "mdast-util-mdx-jsx": "^2.0.0", - "mdast-util-mdxjs-esm": "^1.0.0", - "mdast-util-to-markdown": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "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==", - "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-jsx": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-2.1.4.tgz", - "integrity": "sha512-DtMn9CmVhVzZx3f+optVDF8yFgQVt7FghCRNdlIaS3X5Bnym3hZwPbg/XW86vdpKjlc1PVj26SpnLGeJBXD3JA==", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^2.0.0", - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "ccount": "^2.0.0", - "mdast-util-from-markdown": "^1.1.0", - "mdast-util-to-markdown": "^1.3.0", - "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-remove-position": "^4.0.0", - "unist-util-stringify-position": "^3.0.0", - "vfile-message": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdxjs-esm": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-1.3.1.tgz", - "integrity": "sha512-SXqglS0HrEvSdUEfoXFtcg7DRl7S2cwOXc7jkuusG472Mmjag34DUDeOJUZtl+BVnyeO1frIgVpHlNRWc2gk/w==", - "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-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==", - "dependencies": { - "@types/mdast": "^3.0.0", - "unist-util-is": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz", - "integrity": "sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==", - "dependencies": { - "@types/hast": "^2.0.0", - "@types/mdast": "^3.0.0", - "mdast-util-definitions": "^5.0.0", - "micromark-util-sanitize-uri": "^1.1.0", - "trim-lines": "^3.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/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==", - "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-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==", - "dependencies": { - "@types/mdast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/media-query-parser": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/media-query-parser/-/media-query-parser-2.0.2.tgz", - "integrity": "sha512-1N4qp+jE0pL5Xv4uEcwVUhIkwdUO3S/9gML90nqKA7v7FcOS5vUtatfzok9S9U1EJU8dHWlcv95WLnKmmxZI9w==", - "dependencies": { - "@babel/runtime": "^7.12.5" - } - }, - "node_modules/mermaid": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.2.4.tgz", - "integrity": "sha512-zHGjEI7lBvWZX+PQYmlhSA2p40OzW6QbGodTCSzDeVpqaTnyAC+2sRGqrpXO+uQk3CnoeClHQPraQUMStdqy2g==", - "dependencies": { - "@braintree/sanitize-url": "^6.0.2", - "cytoscape": "^3.23.0", - "cytoscape-cose-bilkent": "^4.1.0", - "cytoscape-fcose": "^2.1.0", - "d3": "^7.4.0", - "dagre-d3-es": "7.0.10", - "dayjs": "^1.11.7", - "dompurify": "3.0.3", - "elkjs": "^0.8.2", - "khroma": "^2.0.0", - "lodash-es": "^4.17.21", - "mdast-util-from-markdown": "^1.3.0", - "non-layered-tidy-tree-layout": "^2.0.2", - "stylis": "^4.1.3", - "ts-dedent": "^2.2.0", - "uuid": "^9.0.0", - "web-worker": "^1.2.0" - } - }, - "node_modules/micromark": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz", - "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==", - "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/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==", - "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/micromark-extension-gfm": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-2.0.3.tgz", - "integrity": "sha512-vb9OoHqrhCmbRidQv/2+Bc6pkP0FrtlhurxZofvOEy5o8RtuuvTq+RQ1Vw5ZDNrVraQZu3HixESqbG+0iKk/MQ==", - "dependencies": { - "micromark-extension-gfm-autolink-literal": "^1.0.0", - "micromark-extension-gfm-footnote": "^1.0.0", - "micromark-extension-gfm-strikethrough": "^1.0.0", - "micromark-extension-gfm-table": "^1.0.0", - "micromark-extension-gfm-tagfilter": "^1.0.0", - "micromark-extension-gfm-task-list-item": "^1.0.0", - "micromark-util-combine-extensions": "^1.0.0", - "micromark-util-types": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.5.tgz", - "integrity": "sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg==", - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-footnote": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.1.2.tgz", - "integrity": "sha512-Yxn7z7SxgyGWRNa4wzf8AhYYWNrwl5q1Z8ii+CSTTIqVkmGZF1CElX2JI8g5yGoM3GAman9/PVCUFUSJ0kB/8Q==", - "dependencies": { - "micromark-core-commonmark": "^1.0.0", - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-strikethrough": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.7.tgz", - "integrity": "sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw==", - "dependencies": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-classify-character": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-table": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.7.tgz", - "integrity": "sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw==", - "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", - "uvu": "^0.5.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-tagfilter": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-1.0.2.tgz", - "integrity": "sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g==", - "dependencies": { - "micromark-util-types": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-task-list-item": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.5.tgz", - "integrity": "sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ==", - "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", - "uvu": "^0.5.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-math": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-2.1.2.tgz", - "integrity": "sha512-es0CcOV89VNS9wFmyn+wyFTKweXGW4CEvdaAca6SWRWPyYCbBisnjaHLjWO4Nszuiud84jCpkHsqAJoa768Pvg==", - "dependencies": { - "@types/katex": "^0.16.0", - "katex": "^0.16.0", - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-math/node_modules/@types/katex": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.0.tgz", - "integrity": "sha512-hz+S3nV6Mym5xPbT9fnO8dDhBFQguMYpY0Ipxv06JMi1ORgnEM4M1ymWDUhUNer3ElLmT583opRo4RzxKmh9jw==" - }, - "node_modules/micromark-extension-mdx-expression": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-1.0.8.tgz", - "integrity": "sha512-zZpeQtc5wfWKdzDsHRBY003H2Smg+PUi2REhqgIhdzAa5xonhP03FcXxqFSerFiNUr5AWmHpaNPQTBVOS4lrXw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "@types/estree": "^1.0.0", - "micromark-factory-mdx-expression": "^1.0.0", - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-events-to-acorn": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - } - }, - "node_modules/micromark-extension-mdx-jsx": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-1.0.5.tgz", - "integrity": "sha512-gPH+9ZdmDflbu19Xkb8+gheqEDqkSpdCEubQyxuz/Hn8DOXiXvrXeikOoBA71+e8Pfi0/UYmU3wW3H58kr7akA==", - "dependencies": { - "@types/acorn": "^4.0.0", - "@types/estree": "^1.0.0", - "estree-util-is-identifier-name": "^2.0.0", - "micromark-factory-mdx-expression": "^1.0.0", - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0", - "vfile-message": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-mdx-md": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-1.0.1.tgz", - "integrity": "sha512-7MSuj2S7xjOQXAjjkbjBsHkMtb+mDGVW6uI2dBL9snOBCbZmoNgDAeZ0nSn9j3T42UE/g2xVNMn18PJxZvkBEA==", - "dependencies": { - "micromark-util-types": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-mdxjs": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-1.0.1.tgz", - "integrity": "sha512-7YA7hF6i5eKOfFUzZ+0z6avRG52GpWR8DL+kN47y3f2KhxbBZMhmxe7auOeaTBrW2DenbbZTf1ea9tA2hDpC2Q==", - "dependencies": { - "acorn": "^8.0.0", - "acorn-jsx": "^5.0.0", - "micromark-extension-mdx-expression": "^1.0.0", - "micromark-extension-mdx-jsx": "^1.0.0", - "micromark-extension-mdx-md": "^1.0.0", - "micromark-extension-mdxjs-esm": "^1.0.0", - "micromark-util-combine-extensions": "^1.0.0", - "micromark-util-types": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-mdxjs-esm": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-1.0.5.tgz", - "integrity": "sha512-xNRBw4aoURcyz/S69B19WnZAkWJMxHMT5hE36GtDAyhoyn/8TuAeqjFJQlwk+MKQsUD7b3l7kFX+vlfVWgcX1w==", - "dependencies": { - "@types/estree": "^1.0.0", - "micromark-core-commonmark": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-events-to-acorn": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "unist-util-position-from-estree": "^1.1.0", - "uvu": "^0.5.0", - "vfile-message": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "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==", - "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/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==", - "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/micromark-factory-mdx-expression": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-1.0.9.tgz", - "integrity": "sha512-jGIWzSmNfdnkJq05c7b0+Wv0Kfz3NJ3N4cBjnbO4zjXIlxJr+f8lk+5ZmwFvqdAbUy2q6B5rCY//g0QAAaXDWA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "@types/estree": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-events-to-acorn": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "unist-util-position-from-estree": "^1.0.0", - "uvu": "^0.5.0", - "vfile-message": "^3.0.0" - } - }, - "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==", - "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/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==", - "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/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==", - "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/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==", - "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/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==", - "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/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==", - "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/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==", - "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/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==", - "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/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==", - "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/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==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-events-to-acorn": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-1.2.3.tgz", - "integrity": "sha512-ij4X7Wuc4fED6UoLWkmo0xJQhsktfNh1J0m8g4PbIMPlx+ek/4YdW5mvbye8z/aZvAPUoxgXHrwVlXAPKMRp1w==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "@types/acorn": "^4.0.0", - "@types/estree": "^1.0.0", - "@types/unist": "^2.0.0", - "estree-util-visit": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0", - "vfile-message": "^3.0.0" - } - }, - "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==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "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==", - "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/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==", - "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/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==", - "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/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==", - "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/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==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "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==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "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/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/miscreant": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/miscreant/-/miscreant-0.3.2.tgz", - "integrity": "sha512-fL9KxsQz9BJB2KGPMHFrReioywkiomBiuaLk6EuChijK0BsJsIKJXdVomR+/bPj5mvbFD6wM0CM3bZio9g7OHA==" - }, - "node_modules/motion": { - "version": "10.16.2", - "resolved": "https://registry.npmjs.org/motion/-/motion-10.16.2.tgz", - "integrity": "sha512-p+PurYqfUdcJZvtnmAqu5fJgV2kR0uLFQuBKtLeFVTrYEVllI99tiOTSefVNYuip9ELTEkepIIDftNdze76NAQ==", - "dependencies": { - "@motionone/animation": "^10.15.1", - "@motionone/dom": "^10.16.2", - "@motionone/svelte": "^10.16.2", - "@motionone/types": "^10.15.1", - "@motionone/utils": "^10.15.1", - "@motionone/vue": "^10.16.2" - } - }, - "node_modules/mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", - "engines": { - "node": ">=4" - } - }, - "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==" - }, - "node_modules/multiformats": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", - "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==" - }, - "node_modules/nan": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==" - }, - "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/next": { - "version": "13.4.8", - "resolved": "https://registry.npmjs.org/next/-/next-13.4.8.tgz", - "integrity": "sha512-lxUjndYKjZHGK3CWeN2RI+/6ni6EUvjiqGWXAYPxUfGIdFGQ5XoisrqAJ/dF74aP27buAfs8MKIbIMMdxjqSBg==", - "dependencies": { - "@next/env": "13.4.8", - "@swc/helpers": "0.5.1", - "busboy": "1.6.0", - "caniuse-lite": "^1.0.30001406", - "postcss": "8.4.14", - "styled-jsx": "5.1.1", - "watchpack": "2.4.0", - "zod": "3.21.4" - }, - "bin": { - "next": "dist/bin/next" - }, - "engines": { - "node": ">=16.8.0" - }, - "optionalDependencies": { - "@next/swc-darwin-arm64": "13.4.8", - "@next/swc-darwin-x64": "13.4.8", - "@next/swc-linux-arm64-gnu": "13.4.8", - "@next/swc-linux-arm64-musl": "13.4.8", - "@next/swc-linux-x64-gnu": "13.4.8", - "@next/swc-linux-x64-musl": "13.4.8", - "@next/swc-win32-arm64-msvc": "13.4.8", - "@next/swc-win32-ia32-msvc": "13.4.8", - "@next/swc-win32-x64-msvc": "13.4.8" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.1.0", - "fibers": ">= 3.1.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "sass": "^1.3.0" - }, - "peerDependenciesMeta": { - "@opentelemetry/api": { - "optional": true - }, - "fibers": { - "optional": true - }, - "sass": { - "optional": true - } - } - }, - "node_modules/next-mdx-remote": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-4.4.1.tgz", - "integrity": "sha512-1BvyXaIou6xy3XoNF4yaMZUCb6vD2GTAa5ciOa6WoO+gAUTYsb1K4rI/HSC2ogAWLrb/7VSV52skz07vOzmqIQ==", - "dependencies": { - "@mdx-js/mdx": "^2.2.1", - "@mdx-js/react": "^2.2.1", - "vfile": "^5.3.0", - "vfile-matter": "^3.0.1" - }, - "engines": { - "node": ">=14", - "npm": ">=7" - }, - "peerDependencies": { - "react": ">=16.x <=18.x", - "react-dom": ">=16.x <=18.x" - } - }, - "node_modules/next-seo": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/next-seo/-/next-seo-6.1.0.tgz", - "integrity": "sha512-iMBpFoJsR5zWhguHJvsoBDxDSmdYTHtnVPB1ij+CD0NReQCP78ZxxbdL9qkKIf4oEuZEqZkrjAQLB0bkII7RYA==", - "peerDependencies": { - "next": "^8.1.1-canary.54 || >=9.0.0", - "react": ">=16.0.0", - "react-dom": ">=16.0.0" - } - }, - "node_modules/next-themes": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.2.1.tgz", - "integrity": "sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==", - "peerDependencies": { - "next": "*", - "react": "*", - "react-dom": "*" - } - }, - "node_modules/nextra": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/nextra/-/nextra-2.8.0.tgz", - "integrity": "sha512-WyRNzw1IM/eF3M1H3LSsbZH97QsYYgj8upjx0f8hY6GspmPyPRAvBBscmXRt+7vye2oIYjfVwSiD1rj9amqq9Q==", - "dependencies": { - "@mdx-js/mdx": "^2.3.0", - "@mdx-js/react": "^2.3.0", - "@napi-rs/simple-git": "^0.1.8", - "@theguild/remark-mermaid": "^0.0.3", - "clsx": "^1.2.1", - "github-slugger": "^2.0.0", - "graceful-fs": "^4.2.11", - "gray-matter": "^4.0.3", - "katex": "^0.16.7", - "lodash.get": "^4.4.2", - "next-mdx-remote": "^4.2.1", - "p-limit": "^3.1.0", - "rehype-katex": "^6.0.3", - "rehype-pretty-code": "0.9.9", - "remark-gfm": "^3.0.1", - "remark-math": "^5.1.1", - "remark-reading-time": "^2.0.1", - "shiki": "^0.14.2", - "slash": "^3.0.0", - "title": "^3.5.3", - "unist-util-remove": "^3.1.1", - "unist-util-visit": "^4.1.1", - "zod": "^3.20.2" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "next": ">=9.5.3", - "react": ">=16.13.1", - "react-dom": ">=16.13.1" - } - }, - "node_modules/nextra-theme-docs": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/nextra-theme-docs/-/nextra-theme-docs-2.8.0.tgz", - "integrity": "sha512-JoSAILDVp0GxeVWWZBFGoRijE2RcjZcXrMa47Fssi254T5wF+gm0HvEOSwrTaKaPaUL+IfshAiKglvXNKGzbNw==", - "dependencies": { - "@headlessui/react": "^1.7.10", - "@popperjs/core": "^2.11.6", - "clsx": "^1.2.1", - "flexsearch": "^0.7.21", - "focus-visible": "^5.2.0", - "git-url-parse": "^13.1.0", - "intersection-observer": "^0.12.2", - "match-sorter": "^6.3.1", - "next-seo": "^6.0.0", - "next-themes": "^0.2.1", - "scroll-into-view-if-needed": "^3.0.0", - "zod": "^3.20.2" - }, - "peerDependencies": { - "next": ">=9.5.3", - "nextra": "2.8.0", - "react": ">=16.13.1", - "react-dom": ">=16.13.1" - } - }, - "node_modules/non-layered-tidy-tree-layout": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz", - "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==" - }, - "node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "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==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/on-exit-leak-free": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz", - "integrity": "sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==" - }, - "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/outdent": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.8.0.tgz", - "integrity": "sha512-KiOAIsdpUTcAXuykya5fnVVT+/5uS0Q1mrkRHcF89tpieSmY33O/tmc54CqwA+bfhbtEfZUNLHaPUiB9X3jt1A==" - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", - "engines": { - "node": ">=4" - } - }, - "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==", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pako": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", - "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" - }, - "node_modules/parse-entities": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", - "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", - "dependencies": { - "@types/unist": "^2.0.0", - "character-entities": "^2.0.0", - "character-entities-legacy": "^3.0.0", - "character-reference-invalid": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "is-alphanumerical": "^2.0.0", - "is-decimal": "^2.0.0", - "is-hexadecimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/parse-numeric-range": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", - "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" - }, - "node_modules/parse-path": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz", - "integrity": "sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==", - "dependencies": { - "protocols": "^2.0.0" - } - }, - "node_modules/parse-url": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz", - "integrity": "sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==", - "dependencies": { - "parse-path": "^7.0.0" - } - }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/periscopic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", - "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^3.0.0", - "is-reference": "^3.0.0" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "node_modules/pino": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-7.11.0.tgz", - "integrity": "sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg==", - "dependencies": { - "atomic-sleep": "^1.0.0", - "fast-redact": "^3.0.0", - "on-exit-leak-free": "^0.2.0", - "pino-abstract-transport": "v0.5.0", - "pino-std-serializers": "^4.0.0", - "process-warning": "^1.0.0", - "quick-format-unescaped": "^4.0.3", - "real-require": "^0.1.0", - "safe-stable-stringify": "^2.1.0", - "sonic-boom": "^2.2.1", - "thread-stream": "^0.15.1" - }, - "bin": { - "pino": "bin.js" - } - }, - "node_modules/pino-abstract-transport": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz", - "integrity": "sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ==", - "dependencies": { - "duplexify": "^4.1.2", - "split2": "^4.0.0" - } - }, - "node_modules/pino-std-serializers": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz", - "integrity": "sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==" - }, - "node_modules/polished": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/polished/-/polished-4.2.2.tgz", - "integrity": "sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==", - "dependencies": { - "@babel/runtime": "^7.17.8" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/postcss": { - "version": "8.4.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", - "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], - "dependencies": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/process-warning": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", - "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==" - }, - "node_modules/property-information": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.2.0.tgz", - "integrity": "sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/protobufjs": { - "version": "6.11.3", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", - "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", - "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/long": "^4.0.1", - "@types/node": ">=13.7.0", - "long": "^4.0.0" - }, - "bin": { - "pbjs": "bin/pbjs", - "pbts": "bin/pbts" - } - }, - "node_modules/protocols": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", - "integrity": "sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==" - }, - "node_modules/proxy-compare": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.5.1.tgz", - "integrity": "sha512-oyfc0Tx87Cpwva5ZXezSp5V9vht1c7dZBhvuV/y3ctkgMVUmiAGDVeeB0dKhGSyT0v1ZTEQYpe/RXlBVBNuCLA==" - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" - }, - "node_modules/query-string": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", - "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", - "dependencies": { - "decode-uri-component": "^0.2.2", - "filter-obj": "^1.1.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/rainbow-sprinkles": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/rainbow-sprinkles/-/rainbow-sprinkles-0.17.0.tgz", - "integrity": "sha512-ok3NrylQ0szvJtuBYaB/w09L9zOvvqcSQrvycT2A5XJxQNvwvkeADvTqQWGOQ3b6MkO8UmYccBPt8g8vVvxM9A==", - "peerDependencies": { - "@vanilla-extract/css": "^1", - "@vanilla-extract/dynamic": "^2" - } - }, - "node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" - }, - "peerDependencies": { - "react": "^18.2.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/reading-time": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", - "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==" - }, - "node_modules/readonly-date": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/readonly-date/-/readonly-date-1.0.0.tgz", - "integrity": "sha512-tMKIV7hlk0h4mO3JTmmVuIlJVXjKk3Sep9Bf5OH0O+758ruuVkUy2J9SttDLm91IEX/WHlXPSpxMGjPj4beMIQ==" - }, - "node_modules/real-require": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.1.0.tgz", - "integrity": "sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==", - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, - "node_modules/rehype-katex": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-6.0.3.tgz", - "integrity": "sha512-ByZlRwRUcWegNbF70CVRm2h/7xy7jQ3R9LaY4VVSvjnoVWwWVhNL60DiZsBpC5tSzYQOCvDbzncIpIjPZWodZA==", - "dependencies": { - "@types/hast": "^2.0.0", - "@types/katex": "^0.14.0", - "hast-util-from-html-isomorphic": "^1.0.0", - "hast-util-to-text": "^3.1.0", - "katex": "^0.16.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-pretty-code": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/rehype-pretty-code/-/rehype-pretty-code-0.9.9.tgz", - "integrity": "sha512-mlU2Qgupn9MMK31CTmWk0Ie5Vp0od+jh2vCkGDBMlPAMeAvYASn6Ois6xRmosutMT4yH/COc3R4r/PELpuUoWg==", - "dependencies": { - "@types/hast": "^2.0.0", - "hash-obj": "^4.0.0", - "parse-numeric-range": "^1.3.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "shiki": "*" - } - }, - "node_modules/remark-gfm": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz", - "integrity": "sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==", - "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-gfm": "^2.0.0", - "micromark-extension-gfm": "^2.0.0", - "unified": "^10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-math": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-5.1.1.tgz", - "integrity": "sha512-cE5T2R/xLVtfFI4cCePtiRn+e6jKMtFDR3P8V3qpv8wpKjwvHoBA4eJzvX+nVrnlNy0911bdGmuspCSwetfYHw==", - "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-math": "^2.0.0", - "micromark-extension-math": "^2.0.0", - "unified": "^10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-mdx": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-2.3.0.tgz", - "integrity": "sha512-g53hMkpM0I98MU266IzDFMrTD980gNF3BJnkyFcmN+dD873mQeD5rdMO3Y2X+x8umQfbSE0PcoEDl7ledSA+2g==", - "dependencies": { - "mdast-util-mdx": "^2.0.0", - "micromark-extension-mdxjs": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-parse": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.2.tgz", - "integrity": "sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==", - "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-from-markdown": "^1.0.0", - "unified": "^10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-reading-time": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/remark-reading-time/-/remark-reading-time-2.0.1.tgz", - "integrity": "sha512-fy4BKy9SRhtYbEHvp6AItbRTnrhiDGbqLQTSYVbQPGuRCncU1ubSsh9p/W5QZSxtYcUXv8KGL0xBgPLyNJA1xw==", - "dependencies": { - "estree-util-is-identifier-name": "^2.0.0", - "estree-util-value-to-estree": "^1.3.0", - "reading-time": "^1.3.0", - "unist-util-visit": "^3.1.0" - } - }, - "node_modules/remark-reading-time/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==", - "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/remark-reading-time/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==", - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-rehype": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-10.1.0.tgz", - "integrity": "sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==", - "dependencies": { - "@types/hast": "^2.0.0", - "@types/mdast": "^3.0.0", - "mdast-util-to-hast": "^12.1.0", - "unified": "^10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remove-accents": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", - "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==" - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/robust-predicates": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", - "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" - }, - "node_modules/rw": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" - }, - "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==", - "dependencies": { - "mri": "^1.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "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-json-utils": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/safe-json-utils/-/safe-json-utils-1.1.1.tgz", - "integrity": "sha512-SAJWGKDs50tAbiDXLf89PDwt9XYkWyANFWVzn4dTXl5QyI8t2o/bW5/OJl3lvc2WVU4MEpTo9Yz5NVFNsp+OJQ==" - }, - "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/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/scroll-into-view-if-needed": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.0.10.tgz", - "integrity": "sha512-t44QCeDKAPf1mtQH3fYpWz8IM/DyvHLjs8wUvvwMYxk5moOqCzrMSxK6HQVD0QVmVjXFavoFIPRVrMuJPKAvtg==", - "dependencies": { - "compute-scroll-into-view": "^3.0.2" - } - }, - "node_modules/secretjs": { - "version": "0.17.7", - "resolved": "https://registry.npmjs.org/secretjs/-/secretjs-0.17.7.tgz", - "integrity": "sha512-j39l9+vR2A8067QBqDDejS7LmRLgdkG4uRw2Ar6HMfzDGo26eTh7cIXVlVu/yHBumxtQzKun20epOXwuYHXjQg==", - "deprecated": "deprecated", - "dependencies": { - "@iov/crypto": "2.1.0", - "@iov/encoding": "2.1.0", - "@iov/utils": "2.0.2", - "axios": "0.21.1", - "curve25519-js": "0.0.4", - "fast-deep-equal": "3.1.1", - "js-crypto-hkdf": "0.7.3", - "miscreant": "0.3.2", - "pako": "1.0.11", - "protobufjs": "6.11.3", - "secure-random": "1.1.2" - } - }, - "node_modules/secretjs/node_modules/axios": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", - "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", - "dependencies": { - "follow-redirects": "^1.10.0" - } - }, - "node_modules/secretjs/node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" - }, - "node_modules/section-matter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", - "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", - "dependencies": { - "extend-shallow": "^2.0.1", - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/secure-random": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/secure-random/-/secure-random-1.1.2.tgz", - "integrity": "sha512-H2bdSKERKdBV1SwoqYm6C0y+9EA94v6SUBOWO8kDndc4NoUih7Dv6Tsgma7zO1lv27wIvjlD0ZpMQk7um5dheQ==" - }, - "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==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "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==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/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/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/sha3": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/sha3/-/sha3-2.1.4.tgz", - "integrity": "sha512-S8cNxbyb0UGUM2VhRD4Poe5N58gJnJsLJ5vC7FYWGUmGhcsj4++WaIOBFVDxlG0W3To6xBuiRh+i0Qp2oNCOtg==", - "dependencies": { - "buffer": "6.0.3" - } - }, - "node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shiki": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.3.tgz", - "integrity": "sha512-U3S/a+b0KS+UkTyMjoNojvTgrBHjgp7L6ovhFVZsXmBGnVdQ4K4U9oK0z63w538S91ATngv1vXigHCSWOwnr+g==", - "dependencies": { - "ansi-sequence-parser": "^1.1.0", - "jsonc-parser": "^3.2.0", - "vscode-oniguruma": "^1.7.0", - "vscode-textmate": "^8.0.0" - } - }, - "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/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/sonic-boom": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.8.0.tgz", - "integrity": "sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "node_modules/sort-keys": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-5.0.0.tgz", - "integrity": "sha512-Pdz01AvCAottHTPQGzndktFNdbRA75BgOfeT1hH+AMnJFv8lynkPi42rfeEhpx1saTEI3YNMWxfqu0sFD1G8pw==", - "dependencies": { - "is-plain-obj": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/sort-keys/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==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", - "engines": { - "node": ">=6" - } - }, - "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==" - }, - "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" - }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", - "engines": { - "node": ">=4" - } - }, - "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/stringify-entities": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.3.tgz", - "integrity": "sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==", - "dependencies": { - "character-entities-html4": "^2.0.0", - "character-entities-legacy": "^3.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/style-to-object": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.1.tgz", - "integrity": "sha512-HFpbb5gr2ypci7Qw+IOhnP2zOU7e77b+rzM+wTzXzfi1PrtBCX0E7Pk4wL4iTLnhzZ+JgEGAhX81ebTg/aYjQw==", - "dependencies": { - "inline-style-parser": "0.1.1" - } - }, - "node_modules/styled-jsx": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", - "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", - "dependencies": { - "client-only": "0.0.1" - }, - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/stylis": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.0.tgz", - "integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==" - }, - "node_modules/supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha512-ycQR/UbvI9xIlEdQT1TQqwoXtEldExbCEAJgRo5YXlmSKjv6ThHnP9/vwGa1gr19Gfw+LkFd7KqYMhzrRC5JYw==", - "dependencies": { - "has-flag": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/symbol-observable": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-2.0.3.tgz", - "integrity": "sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/tabbable": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", - "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" - }, - "node_modules/thread-stream": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-0.15.2.tgz", - "integrity": "sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA==", - "dependencies": { - "real-require": "^0.1.0" - } - }, - "node_modules/tiny-secp256k1": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz", - "integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==", - "hasInstallScript": true, - "dependencies": { - "bindings": "^1.3.0", - "bn.js": "^4.11.8", - "create-hmac": "^1.1.7", - "elliptic": "^6.4.0", - "nan": "^2.13.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/tiny-secp256k1/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/title": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/title/-/title-3.5.3.tgz", - "integrity": "sha512-20JyowYglSEeCvZv3EZ0nZ046vLarO37prvV0mbtQV7C8DJPGgN967r8SJkqd3XK3K3lD3/Iyfp3avjfil8Q2Q==", - "dependencies": { - "arg": "1.0.0", - "chalk": "2.3.0", - "clipboardy": "1.2.2", - "titleize": "1.0.0" - }, - "bin": { - "title": "bin/title.js" - } - }, - "node_modules/titleize": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/titleize/-/titleize-1.0.0.tgz", - "integrity": "sha512-TARUb7z1pGvlLxgPk++7wJ6aycXF3GJ0sNSBTAsTuJrQG5QuZlkUQP+zl+nbjAh4gMX9yDw9ZYklMd7vAfJKEw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/toggle-selection": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", - "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" - }, - "node_modules/trim-lines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", - "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/trough": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz", - "integrity": "sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/ts-dedent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", - "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", - "engines": { - "node": ">=6.10" - } - }, - "node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" - }, - "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/type-tagger": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/type-tagger/-/type-tagger-1.0.0.tgz", - "integrity": "sha512-FIPqqpmDgdaulCnRoKv1/d3U4xVBUrYn42QXWNP3XYmgfPUDuBUsgFOb9ntT0aIe0UsUP+lknpQ5d9Kn36RssA==" - }, - "node_modules/typeforce": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", - "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" - }, - "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/uint8arrays": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.1.1.tgz", - "integrity": "sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==", - "dependencies": { - "multiformats": "^9.4.2" - } - }, - "node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "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/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==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/unist-util-find-after": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-4.0.1.tgz", - "integrity": "sha512-QO/PuPMm2ERxC6vFXEPtmAutOopy5PknD+Oq64gGwxKtk4xwo9Z97t9Av1obPmGU0IyTa6EKYUfTrK2QJS3Ozw==", - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^5.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==", - "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==", - "dependencies": { - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "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==", - "dependencies": { - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-position-from-estree": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-1.1.2.tgz", - "integrity": "sha512-poZa0eXpS+/XpoQwGwl79UUdea4ol2ZuCYguVaJS4qzIOMDzbqz8a3erUCOmubSZkaOuGamb3tX790iwOIROww==", - "dependencies": { - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-remove": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-3.1.1.tgz", - "integrity": "sha512-kfCqZK5YVY5yEa89tvpl7KnBBHu2c6CzMkqHUrlOqaRgGOMp0sMvwWOVrbAtj03KhovQB7i96Gda72v/EFE0vw==", - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^5.0.0", - "unist-util-visit-parents": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-remove-position": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-4.0.2.tgz", - "integrity": "sha512-TkBb0HABNmxzAcfLf4qsIbFbaPDvMO6wa3b3j4VcEzFVaw1LBKwnW4/sRJ/atSLSzoIg41JWEdnE7N6DIhGDGQ==", - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "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==", - "dependencies": { - "@types/unist": "^2.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==", - "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==", - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unorm": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz", - "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/use-sync-external-store": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "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/utility-types": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", - "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", - "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==", - "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/vfile": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz", - "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==", - "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==", - "dependencies": { - "@types/unist": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-matter": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/vfile-matter/-/vfile-matter-3.0.1.tgz", - "integrity": "sha512-CAAIDwnh6ZdtrqAuxdElUqQRQDQgbbIrYtDYI8gCjXS1qQ+1XdLoK8FIZWxJwn0/I+BkSSZpar3SOgjemQz4fg==", - "dependencies": { - "@types/js-yaml": "^4.0.0", - "is-buffer": "^2.0.0", - "js-yaml": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-matter/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/vfile-matter/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/vfile-message": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz", - "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==", - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-stringify-position": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vscode-oniguruma": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==" - }, - "node_modules/vscode-textmate": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", - "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==" - }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/web-namespaces": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", - "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/web-worker": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz", - "integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==" - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/wif": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", - "integrity": "sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==", - "dependencies": { - "bs58check": "<3.0.0" - } - }, - "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/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xstream": { - "version": "11.14.0", - "resolved": "https://registry.npmjs.org/xstream/-/xstream-11.14.0.tgz", - "integrity": "sha512-1bLb+kKKtKPbgTK6i/BaoAn03g47PpFstlbe1BA+y3pNS/LfvcaghS5BFf9+EE1J+KwSQsEpfJvFN5GqFtiNmw==", - "dependencies": { - "globalthis": "^1.0.1", - "symbol-observable": "^2.0.3" - } - }, - "node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" - }, - "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==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zod": { - "version": "3.21.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", - "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zustand": { - "version": "4.3.9", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.3.9.tgz", - "integrity": "sha512-Tat5r8jOMG1Vcsj8uldMyqYKC5IZvQif8zetmLHs9WoZlntTHmIoNM8TpLRY31ExncuUvUOXehd0kvahkuHjDw==", - "dependencies": { - "use-sync-external-store": "1.2.0" - }, - "engines": { - "node": ">=12.7.0" - }, - "peerDependencies": { - "immer": ">=9.0", - "react": ">=16.8" - }, - "peerDependenciesMeta": { - "immer": { - "optional": true - }, - "react": { - "optional": true - } - } - }, - "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==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - } - } -} diff --git a/sdk/typescript/docs/package.json b/sdk/typescript/docs/package.json index a33f6f33d0..fd56bf8024 100644 --- a/sdk/typescript/docs/package.json +++ b/sdk/typescript/docs/package.json @@ -1,29 +1,54 @@ { - "name": "nym-sdk-docs", - "version": "0.0.1", + "name": "@nymproject/ts-sdk-docs", + "version": "1.2.0-rc.9", + "description": "Nym Typescript SDK Docs", + "license": "Apache-2.0", + "author": "Nym Technologies SA", "scripts": { - "dev": "next dev", "build": "next build", - "start": "next start", + "dev": "next dev", "lint": "next lint", "lint:fix": "next lint --fix", - "docs:prod:build": "./scripts/build-prod-docs.sh" + "start": "next start" }, "dependencies": { - "@cosmjs/amino": "^0.31.0", - "@cosmjs/cosmwasm-stargate": "^0.31.0", - "@cosmos-kit/keplr": "^2.1.0", - "@cosmos-kit/react": "^2.1.1", - "@interchain-ui/react": "^1.3.3", - "chain-registry": "^1.18.0", - "next": "^13.0.6", + "@cosmjs/amino": "^0.31.1", + "@cosmjs/cosmwasm-launchpad": "^0.25.6", + "@cosmjs/cosmwasm-stargate": "^0.31.1", + "@cosmjs/encoding": "^0.31.1", + "@cosmjs/proto-signing": "^0.31.1", + "@cosmjs/stargate": "^0.31.0", + "@cosmos-kit/core": "^2.6.2", + "@cosmos-kit/keplr": "^2.3.9", + "@cosmos-kit/ledger": "^2.4.3", + "@cosmos-kit/react": "^2.8.0", + "@emotion/react": "^11.11.1", + "@emotion/styled": "^11.11.0", + "@interchain-ui/react": "^1.8.0", + "@mui/icons-material": "^5.14.9", + "@mui/lab": "^5.0.0-alpha.145", + "@mui/material": "^5.14.8", + "@nymproject/contract-clients": "^1.2.0-rc.9", + "@nymproject/mix-fetch": "^1.2.0-rc.9", + "@nymproject/mix-fetch-full-fat": "^1.2.0-rc.9", + "@nymproject/sdk-full-fat": "^1.2.0-rc.9", + "chain-registry": "^1.19.0", + "cosmjs-types": "^0.8.0", + "next": "^13.4.19", "nextra": "latest", "nextra-theme-docs": "latest", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "save": "^2.9.0", + "uuid": "^9.0.0" }, "devDependencies": { "@types/node": "18.11.10", + "copy-webpack-plugin": "^11.0.0", + "eslint": "8.46.0", + "eslint-config-next": "13.4.13", + "raw-loader": "^4.0.2", "typescript": "^4.9.3" - } + }, + "private": false } diff --git a/sdk/typescript/docs/pages/_app.tsx b/sdk/typescript/docs/pages/_app.tsx new file mode 100644 index 0000000000..b3fbeaf252 --- /dev/null +++ b/sdk/typescript/docs/pages/_app.tsx @@ -0,0 +1,27 @@ +import React, { useMemo } from 'react'; +import type { AppProps } from 'next/app'; +import './styles.css'; +import { ThemeProvider, createTheme } from '@mui/material/styles'; + +const MyApp: React.FC = ({ Component, pageProps }) => { + const muiTheme = useMemo( + () => + createTheme({ + palette: { + mode: 'dark', + primary: { + main: '#e67300', + }, + }, + }), + [], + ); + const AnyComponent = Component as any; + return ( + + + + ); +}; + +export default MyApp; diff --git a/sdk/typescript/docs/pages/_meta.json b/sdk/typescript/docs/pages/_meta.json index 3d07d952be..d0a3f5cdfc 100644 --- a/sdk/typescript/docs/pages/_meta.json +++ b/sdk/typescript/docs/pages/_meta.json @@ -1,6 +1,16 @@ { "index": "Introduction", - "sdk": "Typescript SDK", - "examples": "Example usage and apps", - "blockchain": "Nym Cosmos chain" + "overview": "SDK overview", + "installation": "Installation", + "start": "Getting started", + "guides": "Examples", + "playground": "Live Playground", + + + "contact": { + "title": "Contact ↗", + "type": "page", + "href": "https://nymtech.net/", + "newWindow": true + } } diff --git a/sdk/typescript/docs/pages/blockchain/_meta.json b/sdk/typescript/docs/pages/blockchain/_meta.json deleted file mode 100644 index 4f8abbb472..0000000000 --- a/sdk/typescript/docs/pages/blockchain/_meta.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "wallet": "Wallet support" -} diff --git a/sdk/typescript/docs/pages/blockchain/wallet.mdx b/sdk/typescript/docs/pages/blockchain/wallet.mdx deleted file mode 100644 index 5e7bbe91a8..0000000000 --- a/sdk/typescript/docs/pages/blockchain/wallet.mdx +++ /dev/null @@ -1,13 +0,0 @@ - -You can try out interacting with the Nyx chain that runs the Nym smart contracts by connecting your wallet: - -```tsx -// TODO - move this out of fencing and fix up compile errors - -import { Wallet } from '../components/wallet'; - - -``` - -Nulla reprehenderit nostrud culpa consectetur culpa occaecat tempor culpa tempor eiusmod. Ullamco amet labore culpa ipsum ullamco veniam ex sunt et. Pariatur qui consectetur commodo irure non laboris officia in ex dolor eu. Quis est quis eiusmod non cillum ea aliqua amet excepteur deserunt. Esse commodo anim Lorem enim nostrud veniam ex cillum commodo proident laboris ad dolore. Lorem ea veniam ex cillum adipisicing ut sunt minim voluptate cupidatat labore voluptate eiusmod irure. Laborum ipsum ullamco fugiat elit ullamco officia laborum nulla aute ea et tempor labore id. - diff --git a/sdk/typescript/docs/pages/bundling.mdx b/sdk/typescript/docs/pages/bundling.mdx new file mode 100644 index 0000000000..7d69a1d9df --- /dev/null +++ b/sdk/typescript/docs/pages/bundling.mdx @@ -0,0 +1,55 @@ +# Troubleshooting Bundling + +You might need some help bundling packages from the Nym Typescript SDK into your package. + +Here are some things that could go wrong: + +## WebAssembly (WASM) and web worker not included in output bundle + +### Webpack + +You might need to use the CopyPlugin by adding this to your Webpack config: + +```js +const CopyPlugin = require('copy-webpack-plugin'); + +... + +module.exports = { + ... + plugins: [ + ... + new CopyPlugin({ + patterns: [ + { + from: path.resolve(path.dirname(require.resolve('@nymproject/mix-fetch/package.json')), '*.wasm'), + to: '[name][ext]', + }, + { + from: path.resolve(path.dirname(require.resolve('@nymproject/mix-fetch/package.json')), '*worker*.js'), + to: '[name][ext]', + }, + ], + }), + ], +} +``` + +How does this work? The statement `require.resolve('@nymproject/mix-fetch/package.json')` finds the disk location of +the Nym SDK package, and resolve the directory name is `path.dirname`, the add the `*.wasm` glob to the search pattern +list. Use `[name][ext]` to preserve the output filename, because the package expects the filename to stay the same. + +## ESM not supported + +If your bundler does not support ECMAScript Modules (ESM) we provide CommonJS packages for most parts of the SDK. + +For those that don't have ESM versions, you will need to use a tool like [Babel](https://babeljs.io/) to convert +ESM to CommonJS. + +## CSP prevents loading + +If you are using a `*-full-fat` package, or if you inline WASM or web workers, you may not be able to load them if the +[CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) prevents WASM from being instantiated from a string. + +You'll have to experiment with either adjusting the CSP or use another variant that is unbundled. + diff --git a/sdk/typescript/docs/pages/examples/_meta.json b/sdk/typescript/docs/pages/examples/_meta.json deleted file mode 100644 index 1a0898b0b9..0000000000 --- a/sdk/typescript/docs/pages/examples/_meta.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "index": "List of live examples", - "community": "Apps made by the Nym community", - "playground": "Interactive playground" -} diff --git a/sdk/typescript/docs/pages/examples/community.mdx b/sdk/typescript/docs/pages/examples/community.mdx deleted file mode 100644 index e5e5f3fb87..0000000000 --- a/sdk/typescript/docs/pages/examples/community.mdx +++ /dev/null @@ -1,8 +0,0 @@ -# Community Typescript and Javascript apps - -Here is a list of apps built by our awesome community using the Nym Typescript SDK: - -- project 1 -- project 2 -- project 3 - diff --git a/sdk/typescript/docs/pages/examples/index.mdx b/sdk/typescript/docs/pages/examples/index.mdx deleted file mode 100644 index 05e56d947c..0000000000 --- a/sdk/typescript/docs/pages/examples/index.mdx +++ /dev/null @@ -1,12 +0,0 @@ -# Examples - -Here are some live examples of what you can do with the Typescript SDK: - -- Chat app -- Node tester -- mixFetch demo - -And some examples of usage: - -- Firefox browser extension -- Chrome browser extension diff --git a/sdk/typescript/docs/pages/examples/playground.mdx b/sdk/typescript/docs/pages/examples/playground.mdx deleted file mode 100644 index 3200695a3b..0000000000 --- a/sdk/typescript/docs/pages/examples/playground.mdx +++ /dev/null @@ -1,7 +0,0 @@ -# Try out the Typescript SDK live in your browser - -Commodo magna ullamco voluptate aute adipisicing culpa duis reprehenderit. Laboris fugiat in duis mollit dolor voluptate ex anim. Cupidatat enim nostrud laboris incididunt minim do do et adipisicing. Adipisicing pariatur dolor elit nisi elit. Cillum nisi irure officia ipsum. Pariatur ex esse dolor sit esse consectetur dolore dolor. Nostrud dolor proident ullamco sint commodo laboris culpa. - -Occaecat commodo deserunt ut laborum pariatur exercitation ea cillum officia non. Cupidatat amet aute ex exercitation magna quis fugiat consequat minim exercitation fugiat deserunt Lorem deserunt. Commodo irure incididunt officia et aute. - -Ut voluptate deserunt sunt voluptate elit. Incididunt enim nulla amet occaecat incididunt officia sunt eu fugiat dolore id anim. Aliqua duis voluptate consectetur ex voluptate nisi sit quis esse nulla irure aliquip. diff --git a/sdk/typescript/docs/pages/guides/_meta.json b/sdk/typescript/docs/pages/guides/_meta.json new file mode 100644 index 0000000000..630b32b2cf --- /dev/null +++ b/sdk/typescript/docs/pages/guides/_meta.json @@ -0,0 +1,6 @@ +{ + "nym-smart-contracts": "1. Nym Smart Contracts", + "mixnet": "2. Mixnet Client", + "mix-fetch": "3. mixFetch", + "cosmos-kit": "4. Cosmos Kit" +} diff --git a/sdk/typescript/docs/pages/guides/cosmos-kit.mdx b/sdk/typescript/docs/pages/guides/cosmos-kit.mdx new file mode 100644 index 0000000000..7d5fc11291 --- /dev/null +++ b/sdk/typescript/docs/pages/guides/cosmos-kit.mdx @@ -0,0 +1,41 @@ +# Cosmos Kit + +The wonderful people of Cosmology have made some [fantastic components](https://cosmoskit.com/) that can be used with +Nym, these include: + +- using the wallets such as Keplr, Cosmostation and others from your React application +- using the [Ledger hardware wallet](https://docs.cosmoskit.com/integrating-wallets/ledger) from the browser +- any wallet that supports [Wallet Connect v2.0](https://docs.cosmoskit.com/integrating-wallets/adding-new-wallets) + +```ts +import React from 'react'; +import { useChain } from '@cosmos-kit/react'; +import { assets, chains } from 'chain-registry'; +import { wallets } from '@cosmos-kit/keplr'; + +export const MyComponent = () => { + const { wallet, address, connect, getOfflineSignerDirect } = + useChain('nyx'); + + React.useEffect(() => { + connect(); + }, []); + + const sign = async () => { + const doc = { ... }; + return getOfflineSignerDirect().signDirect(address, doc); + }; + + return ( +
+
+ Connected to {wallet.prettyName} +
+
+ Address: {address} +
+
+ ); +} +``` + diff --git a/sdk/typescript/docs/pages/guides/mix-fetch.mdx b/sdk/typescript/docs/pages/guides/mix-fetch.mdx new file mode 100644 index 0000000000..6cdeaae7c0 --- /dev/null +++ b/sdk/typescript/docs/pages/guides/mix-fetch.mdx @@ -0,0 +1,78 @@ +# `mixFetch` + +An easy way to secure parts or all of your web app is to replace calls to [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) with `mixFetch`: + +``` +npm install @nymproject/mix-fetch +``` + +And then: + +```ts +import { mixFetch } from '@nymproject/mix-fetch'; + +... + +// HTTP GET +const response = await mixFetch('https://nymtech.net'); +const html = await response.text(); + +... + +// HTTP POST +const apiResponse = await mixFetch('https://api.example.com', { + method: 'POST', + body: JSON.stringify({ foo: 'bar' }), + headers: { [`Content-Type`]: 'application/json', Authorization: `Bearer ${AUTH_TOKEN}` } +}); +``` + +Sounds great, are there any catches? Well, there are a few (for now): + +1. Currently, the operators of Network Requesters that make the final request at the egress part of the Nym Mixnet to +the internet use a [standard allow list](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) +in combination with their own configuration. If you are trying to access something that is not on the allow list, you +have two choices: +- run your own Network Requester and locally configure it to allow the hosts you need to connect to +- get in touch with us and give us more information about the sites you want included in the standard allow list + +2. We periodically update the CA certificates in `mixFetch` so if you get a certificate error, we may not have the +root CA certificate you need in our list. [Send us a PR](https://github.com/nymtech/nym/pulls) if you need changes. + +3. If you are using `mixFetch` in a web app with HTTPS you will need to use a gateway that has Secure Websockets to +avoid getting a [mixed content](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content) error. + +4. Workaround for Mixed Content Errors because you might be using `mixFetch` from web app served from HTTPS while +connecting a gateway that only listens on a plain websocket, without HTTPS/TLS. + +We are currently working on a feature that adds a Secure Websocket (WSS) listener with HTTPS (automatically generated with LetsEncrypt) to Nym's +gateways. + +While we are adding this feature, you can use a gateway that has Caddy providing HTTPS/WSS by adding this to the options when settings up `mixFetch`: + +```ts +import type { SetupMixFetchOps } from '@nymproject/mix-fetch'; + +const extra = { + hiddenGateways: [ + { + owner: 'n1kymvkx6vsq7pvn6hfurkpg06h3j4gxj4em7tlg', + host: 'gateway1.nymtech.net', + explicitIp: '213.219.38.119', + identityKey: 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM', + sphinxKey: 'CYcrjoJ8GT7Dp54zViUyyRUfegeRCyPifWQZHRgMZrfX', + }, + ], +}; + +const mixFetchOptions: SetupMixFetchOps = { + preferredGateway: 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM', // with WSS + preferredNetworkRequester: + 'GiRjFWrMxt58pEMuusm4yT3RxoMD1MMPrR9M2N4VWRJP.3CNZBPq4vg7v7qozjGjdPMXcvDmkbWPCgbGCjQVw9n6Z@2xU4CBE6QiiYt6EyBXSALwxkNvM7gqJfjHXaMkjiFmYW', + mixFetchOverride: { + requestTimeoutMs: 60_000, + }, + forceTls: true, // force WSS + extra, // manually set the gateway details for WSS so certificates will work for hostname +}; +``` diff --git a/sdk/typescript/docs/pages/guides/mixnet.mdx b/sdk/typescript/docs/pages/guides/mixnet.mdx new file mode 100644 index 0000000000..4e3f6025ad --- /dev/null +++ b/sdk/typescript/docs/pages/guides/mixnet.mdx @@ -0,0 +1,106 @@ +import { Callout } from 'nextra/components' + +# Mixnet Client + +As you know by now, in order to send or receive messages over the mixnet, you'll need to use the [`SDK Client`](https://www.npmjs.com/package/@nymproject/sdk), which will allow you to create apps that can use the Nym Mixnet and Coconut credentials. + +This client is message based - it can only send a one-way message to another client's address. + +Replying can be done in two ways: +- reveal the sender's address to the recipient (as part of the payload) +- use a SURB (single use reply block) that allows the recipient to reply to the sender without compromising the identity of either party + +##### Imports +Import the SDK's Mixnet Client as well as the payload in your app: +````js +import { createNymMixnetClient, NymMixnetClient, Payload } from "@nymproject/sdk-full-fat"; +```` + +##### Example: using the SDK's Mixnet Client to send and receive messages over the Nym Mixnet + + For this example, we will be using the `full-fat` version of the ESM SDK. If you'd like to use the unbundled ESM one, make sure your [bundler configuration](../../bundling) copies the WebAssembly (WASM) and web worker files to the output bundle. + + + +```ts +import { useEffect, useState } from "react"; +import { + createNymMixnetClient, + NymMixnetClient, + Payload, +} from "@nymproject/sdk-full-fat"; + +const nymApiUrl = "https://validator.nymtech.net/api"; + +export const Traffic = () => { + const [nym, setNym] = useState(); + const [selfAddress, setSelfAddress] = useState(); + const [recipient, setRecipient] = useState(); + const [payload, setPayload] = useState(); + const [receivedMessage, setReceivedMessage] = useState(); + + const init = async () => { + const nym = await createNymMixnetClient(); + setNym(nym); + + // start the client and connect to a gateway + await nym?.client.start({ + clientId: crypto.randomUUID(), + nymApiUrl, + }); + + // check when is connected and set the self address + nym?.events.subscribeToConnected((e) => { + const { address } = e.args; + setSelfAddress(address); + }); + + // show whether the client is ready or not + nym?.events.subscribeToLoaded((e) => { + console.log("Client ready: ", e.args); + }); + + // show message payload content when received + nym?.events.subscribeToTextMessageReceivedEvent((e) => { + console.log(e.args.payload); + setReceivedMessage(e.args.payload); + }); + }; + + const send = () => nym.client.send({ payload, recipient }); + + useEffect(() => { + init(); + }, []); + + if (!nym) return
waiting for the mixnet client...
; + + if (!selfAddress) return
connecting...
; + + return ( +
+

Send messages through the Mixnet

+

+ My self address is: {selfAddress ? selfAddress : "loading"} +

+
+ + setRecipient(e.target.value)} + > + + setPayload({ message: e.target.value, mimeType: "text/plain" }) + } + > + +
+

Received message: {receivedMessage}

+
+ ); +}; + + +``` diff --git a/sdk/typescript/docs/pages/guides/nym-smart-contracts.mdx b/sdk/typescript/docs/pages/guides/nym-smart-contracts.mdx new file mode 100644 index 0000000000..b0fcbc472f --- /dev/null +++ b/sdk/typescript/docs/pages/guides/nym-smart-contracts.mdx @@ -0,0 +1,342 @@ +import { Callout } from 'nextra/components' + +# Nym Smart Contract Clients + +As previously mentioned, to query or execute on any of the Nym contracts, you'll need to use one of the [`Contract Clients`](https://www.npmjs.com/package/@nymproject/contract-clients), which contains read-only query and signing clients for all of Nym's smart contracts. + +##### Contract Clients list +Lists of the diffent available clients and methods from the `Contract Clients` can be found in the `.client.ts` files: +| Client name | Functionality| Methods list | +| :-------------: | :----------: | :----------: | +| Coconut Bandwidth Client| Manages the depositing and release of funds. Tracks double spending. | [Coconut Bandwidth](https://github.com/nymtech/nym/blob/develop/sdk/typescript/codegen/contract-clients/src/CoconutBandwidth.client.ts) | +| Coconut DKG Client | Allows signers partcipating in issuing Coconut credentials to derive keys to be used. | [Coconut DKG](https://github.com/nymtech/nym/blob/develop/sdk/typescript/codegen/contract-clients/src/CoconutDkg.client.ts) | +| Cw3FlexMultisig Client | Used by the Coconut APIs to issue credentials. [This](https://github.com/CosmWasm/cw-plus/tree/main/contracts/cw3-flex-multisig) is a multisig contract that is backed by the cw4 (group) contract, which independently maintains the voter set. | [Cw3Flex Multisig](https://github.com/nymtech/nym/blob/develop/sdk/typescript/codegen/contract-clients/src/Cw3FlexMultisig.client.ts) | +| Cw4Group Client | Used by the Coconut APIs to issue credentials. [Cw4 Group](https://github.com/CosmWasm/cw-plus/tree/main/contracts/cw4-group) stores a set of members along with an admin, and allows the admin to update the state. | [Cw4Group](https://github.com/nymtech/nym/blob/develop/sdk/typescript/codegen/contract-clients/src/Cw4Group.client.ts) | +| Mixnet Client | Manages the network topology of the mixnet, tracking delegations and rewarding | [Mixnet](https://github.com/nymtech/nym/blob/develop/sdk/typescript/codegen/contract-clients/src/Mixnet.client.ts) | +| Name Service Client | Operates as a directory of user-defined aliases, analogous to a Domain Name System (DNS). | [Name service](https://github.com/nymtech/nym/blob/develop/sdk/typescript/codegen/contract-clients/src/NameService.client.ts) | +| Service provider Directory Client| Allows users to register their service provider in a public directory. | [Service Provider](https://github.com/nymtech/nym/blob/develop/sdk/typescript/codegen/contract-clients/src/ServiceProviderDirectory.client.ts) | +| Vesting Client | Manages NYM token vesting functionality. | [Vesting](https://github.com/nymtech/nym/blob/develop/sdk/typescript/codegen/contract-clients/src/Vesting.client.ts) | + + +Depending on your app or project's architecture, this could be any of the ESM or CJS versions of the `Contract Clients`. + +##### Set-up your environment +Create your directory and set-up your app environment: +``` +npx create-react-app my-app +``` + +##### Installation +Install the package and its dependencies from Cosmos Stargate: +``` +npm install @nymproject/contract-clients @cosmjs/cosmwasm-stargate @cosmjs/proto-signing +``` +## Query clients + +##### Imports +Import the contracts' client in your app: +````js +import { contracts } from '@nymproject/contract-clients'; +import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate"; +```` + +##### Polyfills + +You will need to install: + +`npm install --save url fs assert crypto-browserify stream-http https-browserify os-browserify buffer stream-browserify process react-app-rewired` + +and create a `config-overrides.js`file: +```js +const webpack = require('webpack'); +module.exports = function override(config, env) { + config.resolve.fallback = { + url: require.resolve('url'), + fs: require.resolve('fs'), + assert: require.resolve('assert'), + crypto: require.resolve('crypto-browserify'), + http: require.resolve('stream-http'), + https: require.resolve('https-browserify'), + os: require.resolve('os-browserify/browser'), + buffer: require.resolve('buffer'), + stream: require.resolve('stream-browserify'), + }; + config.plugins.push( + new webpack.ProvidePlugin({ + process: 'process/browser', + Buffer: ['buffer', 'Buffer'], + }), + ); + + return config; +} +``` +Update your `package.json` file: +```json +"scripts": { + "start": "react-app-rewired start", + "build": "react-app-rewired build", + "test": "react-app-rewired test", + "eject": "react-scripts eject" // don't change the eject + }, + ``` + + + + + + + +##### Example: using the Mixnet smart contract client to query +In this example, we will use the `MixnetQueryClient`from the `Contract Clients` to simply query the contract and return a list of Mixnodes. + +```js +import "./App.css"; +import { contracts } from "@nymproject/contract-clients"; +import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate"; +import { useEffect, useState } from "react"; + +export default function Mixnodes() { + + const [mixnodes, setMixnodes] = useState(null); + + async function fetchMixnodes(){ + // Set-up the CosmWasm Client + const cosmWasmClient = await SigningCosmWasmClient.connect("wss://rpc.nymtech.net:443"); + + const client = new contracts.Mixnet.MixnetQueryClient( + cosmWasmClient, + "n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr" // the contract address (which is different on mainnet, QA, etc) + ); + console.log("client:", client) + const result = await client.getMixNodesDetailed({}); + console.log(result) + setMixnodes(result.nodes) + + } + + useEffect(() => { + fetchMixnodes(); + }, []) + + return( + <> + + + {mixnodes?.map((value, index) => { + return( + + + + ) + }) + } + +
{value?.bond_information?.mix_node?.identity_key}
+ + ) + } + ``` + + + +## Execute clients + +##### Imports +Import the contracts' execute clients in your app: +````js +import { contracts } from '@nymproject/contract-clients'; +import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate"; +import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"; +```` + +##### Example: using the Mixnet smart contract client to execute methods +In this example, we will use the `MixnetClient`and the `signer` from the [`Contract Clients`](https://www.npmjs.com/package/@nymproject/contract-clients) to execute methods. + +Note that for the `settings.ts` file, we have used the following structure: +```json + +export const mySettings = { + url: "wss://rpc.nymtech.net:443", + mixnetContractAddress: , + mnemonic: ', + address: +}; + +export const settings = mySettings; +``` + + +```js + +import "./App.css"; +import { contracts } from "@nymproject/contract-clients"; +import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate"; +import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"; +import { GasPrice } from "@cosmjs/stargate"; +import { settings } from "./settings.ts"; + +export default function Exec() { + let signer = null; + let address = null; + let signerMixnetClient = null; + let cosmWasmSigningClient = null; + let mixId = null; + let amountToDelegate = null; + let balance = null; + let nodeAddress = null; + let amountToSend = null; + let delegations = null; + + async function ExecuteOnNyx() { + // Signer + try { + // Generate a signer from a mnemonic + signer = await DirectSecp256k1HdWallet.fromMnemonic(settings.mnemonic, { + prefix: "n", + }); + const accounts = await signer.getAccounts(); + address = accounts[0].address; + } catch (error) { + console.error("Problem getting the signer: ", error); + } + + try { + const cosmWasmClient = await SigningCosmWasmClient.connectWithSigner( + settings.url, + signer, + { + gasPrice: GasPrice.fromString("0.025unym"), + } + ); + cosmWasmSigningClient = cosmWasmClient; + try { + balance = await cosmWasmSigningClient?.getBalance(address, "unym"); + console.log("balance", balance); + } catch (error) { + console.error("problem geting the balance: ", error); + } + + const mixnetClient = new contracts.Mixnet.MixnetClient( + cosmWasmSigningClient, + settings.address, // sender (that account of the signer) + settings.mixnetContractAddress // contract address (different on mainnet, QA, etc) + ); + signerMixnetClient = mixnetClient; + } catch (error) { + console.error("Problem getting the cosmWasmSigningClient: ", error); + } + } + + // Get delegations + const getDelegations = async () => { + if (!signerMixnetClient) { + return; + } + const delegationsObject = await signerMixnetClient.getDelegatorDelegations({ + delegator: settings.address, + }); + delegations = delegationsObject; + }; + + // Make delegation + const doDelegation = async () => { + if (!signerMixnetClient) { + return; + } + try { + const res = await signerMixnetClient.delegateToMixnode( + { mixId }, + "auto", + undefined, + [{ amount: `${amountToDelegate}`, denom: "unym" }] + ); + console.log("delegations: ", res); + } catch (error) { + console.error(error); + } + }; + + // Undelegate all + const doUndelegateAll = async () => { + if (!signerMixnetClient) { + return; + } + console.log("delegations", delegations); + try { + for (const delegation of delegations.delegations) { + await signerMixnetClient.undelegateFromMixnode( + { mixId: delegation.mix_id }, + "auto" + ); + } + } catch (error) { + console.error(error); + } + }; + + // Sending tokens + const doSendTokens = async () => { + const memo = "test sending tokens"; + + try { + const res = await cosmWasmSigningClient.sendTokens( + settings.address, + nodeAddress, + [{ amount: amountToSend, denom: "unym" }], + "auto", + memo + ); + console.log("res", res); + } catch (error) { + console.error(error); + } + }; + + ExecuteOnNyx(); + setTimeout(() => getDelegations(), 1000); + + return ( +
+

Exec

+
+

Send Tokens

+ (nodeAddress = e.target.value)} + /> + (amountToSend = e.target.value)} + /> +
+ +
+
+
+

Delegate

+ (mixId = e.target.value)} + /> + (amountToDelegate = e.target.value)} + /> +
+ +
+
+ +
+
+
+ ); +} + +``` + diff --git a/sdk/typescript/docs/pages/index.mdx b/sdk/typescript/docs/pages/index.mdx index a36b03cc62..1b14188e7c 100644 --- a/sdk/typescript/docs/pages/index.mdx +++ b/sdk/typescript/docs/pages/index.mdx @@ -1,3 +1,36 @@ # Introduction -Welcome to the documentation for the Nym Typescript SDK. +Welcome to the documentation for Nym's TypeScript SDK!
+ +This guide contains valuable information about the various TypeScript SDK modules that facilitate interaction with different components of the Nym stack, including the mixnet, Nyx chain, and Coconut credentials. + + +### Our other developer guides + +If you're new to the Nym ecosystem and aiming to understand the mixnet concept, explore kickstart options and demos, learn network integration, or follow developer tutorials, the [Developer Portal](https://nymtech.net/developers/) is your go-to resource. + +For a more in-depth exploration of Nym's architecture, clients, nodes, and SDK examples, we recommend referring to the [Technical Documentation](https://nymtech.net/docs/) section. + +If you're looking for information and setup guides for the various pieces of Nym mixnet infrastructure (mix nodes, gateways, network requesters) and Nyx blockchain validators, then have a look at our [Operators Guide](https://nymtech.net/operators/introduction.html). + + +### What is Nym? +Nym is a **privacy infrastructure that secures user data and protects against surveillance at the network level**. +The platform does so by leveraging different technological components: + - **A Mixnet**, a type of overlay network that makes both content and metadata of transactions private through network-level obfuscation and incentivisation (using [Sphinx](https://blog.nymtech.net/sphinx-tl-dr-the-data-packet-that-can-anonymize-bitcoin-and-the-internet-18d152c6e4dc)); +- **A blockchain, [Nyx](https://blog.nymtech.net/nym-is-not-a-blockchain-but-it-is-powered-by-one-4bb16ef16587)**, our Cosmos SDK blockchain, to allow for us to use payment tokens in the form of NYM, as well as smart contracts, in order to create a robust, decentralized, and secure environment incentives for the mixnet; +- **Coconut, a signature scheme** that creates an application-level private access control layer to power [Zk-Nyms](https://blog.nymtech.net/zk-nyms-are-here-a-major-milestone-towards-a-market-ready-mixnet-a3470c9ab10a); +- **A utility token, [NYM](https://blog.nymtech.net/nym-tokens-where-do-they-live-and-how-are-they-distributed-cross-chain-8d134bf9c41f)**, to pay for usage, measure reputation and serve as rewards for the privacy infrastructure. + +Simply put, the Nym network ("Nym") is a decentralized and incentivized infrastructure to provision privacy to a broad range of message-based applications and services. + + + +### Read our protocol + +[The Nym network ("Nym")](https://www.feat-nym-update-nym-web.websites.dev.nymte.ch/nym-whitepaper.pdf) is a privacy infrastructure that, simply put, can be seen as a ["Layer 0" privacy infrastructure](https://blog.nymtech.net/nym-layer-0-privacy-infrastructure-for-the-whole-internet-e53238f9b8e7) for the entire internet. +Read more to understand the differences in between Nym, TOR (and other mixnets) and VPNs. + + + + diff --git a/sdk/typescript/docs/pages/installation.mdx b/sdk/typescript/docs/pages/installation.mdx new file mode 100644 index 0000000000..37b2a8883a --- /dev/null +++ b/sdk/typescript/docs/pages/installation.mdx @@ -0,0 +1,65 @@ +import { Callout } from 'nextra/components' + +# Overview + +The Typescript SDK's different modules allow developers to start building browser-based applications quickly, by simply importing the SDK module of their choice - depending on the component from the Nym architecture they want to use - into their code via NPM as they would any other Typescript library. + + + SDK modules come in four different flavours (ESM, CJS and full-fat for ESM and CJS). + This documentation only shows instructions and examples for the unbundled ESM variant. + + +#### Install all + +``` +npm install @nymproject/contract-clients @cosmjs/cosmwasm-stargate @cosmjs/proto-signing @nymproject/sdk @nymproject/mix-fetch --save +``` + +## Nym Smart Contracts +#### Overview +The Nyx blockchain is a general-purpose CosmWasm-enabled smart contract platform, and the home of the smart contracts which keep track of the mixnet, amongst others. +Information about the chain can be found on the [Nyx blockchain explorer](https://nym.explorers.guru/). + +Using the [Nym Mixnet smart contract clients](https://nymtech.net/docs/nyx/smart-contracts.html), you will be able to query contract states or execute methods when providing a signing key. + +*You can learn about our different methods to interact with the chain [here](https://nymtech.net/docs/nyx/interacting-with-chain.html)*. + +#### Installation: Contract Clients +In order to query or execute on any of the Nym smart contracts, you'll need to use the [`Contract Clients`](https://www.npmjs.com/package/@nymproject/contract-clients), which contains read-only query and signing clients for all Nyx's smart contracts. + +First install the package and its dependencies from Cosmos Stargate: + +``` +npm install @nymproject/contract-clients @cosmjs/cosmwasm-stargate @cosmjs/proto-signing --save +``` + +## Mixnet +#### Overview +The [Nym mixnet](https://nymtech.net/docs/architecture/network-overview.html) provides very strong security guarantees against network-level surveillance. It wraps into packets and mixes together IP traffic from many users inside the mixnet. It encrypts and mixes [Sphinx packet](https://cypherpunks.ca/~iang/pubs/Sphinx_Oakland09.pdf) traffic so that it cannot be determined who is communicating with whom. Our mixnet is based on a modified version of the Loopix design. + +*You can explore our mixnet using our [mixnet explorer](https://nymtech.net/docs/explorers/mixnet-explorer.html) here.* + + +#### Installation: Mixnet Client +In order to send or receive traffic over the mixnet, you'll need to use the [`Mixnet Client`](https://www.npmjs.com/package/@nymproject/sdk). + +First install the package and its dependencies: + +``` +npm install @nymproject/sdk --save +``` + +## MixFetch +#### Overview +MixFetch is a drop-in replacement for [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) that sends HTTP requests through the Mixnet. It does this by grabbing the same arguments as traditional fetch and constructing a SOCKS5 request that will be made to the destination host on the Internet via a [SOCKS5](https://nymtech.net/developers/quickstart/socks-proxy.html) [Network Requester](https://nymtech.net/docs/nodes/network-requester.html). + +#### Installation: MixFetch package +In order to fetch data through mixFetch you'll need to use the [`MixFetch package`](https://www.npmjs.com/package/@nymproject/mix-fetch). + +First install the package and its dependencies: + +``` +npm install @nymproject/mix-fetch --save +``` + + diff --git a/sdk/typescript/docs/pages/overview.mdx b/sdk/typescript/docs/pages/overview.mdx new file mode 100644 index 0000000000..0b456b7fa9 --- /dev/null +++ b/sdk/typescript/docs/pages/overview.mdx @@ -0,0 +1,72 @@ +import { Callout } from 'nextra/components' +import { TableContainer, Table, TableBody, TableCell, TableRow, Paper } from '@mui/material' +import { NPMLink } from '../components/npm'; + +## SDK overview +The Typescript SDK allows developers to start building browser-based mixnet applications quickly, by simply importing the SDK modules into their code via NPM as they would any other Typescript library. + +Currently developers can use different packages from the Typescript SDK to do the following entirely in the browser: + + + + + + + **Nym Smart Contracts** + + + Create a simple query or query and execute methods on the smart contracts that run the Nym Mixnet + + + + + + + + **Mixnet Client** + + + Send & receive text and binary traffic over the Nym Mixnet + + +
+
+
+ +
+
+ + + **mixFetch** + + + A drop-in replacement for [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) + that sends HTTP requests over the Nym Mixnet + + +
+
+
+ +
+
+
+
+
+ +## Which package should I use? + +All packages come in four different variations: +- **ESM**: For new projects with current tooling. These packages use the ECMAScript Modules (ESM) system. You may need to [configure your bundler](bundling) to handle the packages WASM and Web Worker components; +- **ESM full-fat**: These ESM packages are pre-bundled and include inline WebAssembly and web worker code; +- **CommonJS**: For older projects that still use CommonJS. All WebAssembly (WASM) and Web Workers in the package need to be [bundled](bundling) to work correctly; +- **CommonJS full-fat**: These packages are already pre-bundled and should work in your project as is; + + + All `*-full-fat` variants have large bundle sizes because they include all WASM and web-workers as inline Base64 strings. If you care about your app's bundle size, then use the ESM variant. + + + + As the Typescript SDK and associated modules are still a work in progress, note that the inline WASM and web worker versions are likely to have issues if the web site / app / extension has a strict [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP). + + diff --git a/sdk/typescript/docs/pages/playground/_meta.json b/sdk/typescript/docs/pages/playground/_meta.json new file mode 100644 index 0000000000..76d1fa39df --- /dev/null +++ b/sdk/typescript/docs/pages/playground/_meta.json @@ -0,0 +1,7 @@ +{ + "mixnodes": "1. Query mixnet contract for a list of mix nodes", + "wallet": "1.2. Basic wallet operations", + "traffic": "2. Send traffic over the mixnet", + "mixfetch": "3. Use mixFetch", + "cosmos-kit": "4. Cosmos Kit" +} diff --git a/sdk/typescript/docs/pages/playground/cosmos-kit.mdx b/sdk/typescript/docs/pages/playground/cosmos-kit.mdx new file mode 100644 index 0000000000..d99600a25e --- /dev/null +++ b/sdk/typescript/docs/pages/playground/cosmos-kit.mdx @@ -0,0 +1,28 @@ +import "@interchain-ui/react/styles" +import { CosmosKit } from "../../components/cosmos-kit"; +import { Callout } from 'nextra/components' +import FormattedCosmoskitExampleCode from '../../code-examples/cosmoskit-example-code.mdx'; + +# Cosmos Kit + +Below is an example that uses [CosmosKit](https://cosmoskit.com/) to connect your [Keplr wallet](https://www.keplr.app/) or +[Ledger hardware wallet](https://www.ledger.com/) to this page: + + + +Once you connect either Keplr or your hardware Ledger, you can request a fake transaction to be signed. The hash +of the message will be displayed. + + + No transactions will be broadcast. You will only be signing a transaction. + + +If you are using the Ledger hardware wallet, please make sure: + +- you have the `cosmoshub` app installed on the Ledger +- it is connected to your computer +- it is unlocked +- the Cosmos Hub app is open +- grant permissions to your browser when you click the button above to connect to the Ledger (if you do not see a prompt, try another browser) + + diff --git a/sdk/typescript/docs/pages/playground/mixfetch.mdx b/sdk/typescript/docs/pages/playground/mixfetch.mdx new file mode 100644 index 0000000000..6b8b9c24f7 --- /dev/null +++ b/sdk/typescript/docs/pages/playground/mixfetch.mdx @@ -0,0 +1,11 @@ +# mixFetch + +import { MixFetch } from '../../components/mixfetch' +import Box from '@mui/material/Box'; +import FormattedMixFetchExampleCode from '../../code-examples/mixfetch-example-code.mdx'; + +Look in the [standard allowed list](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) and +use the playground below to do a HTTP GET request to any host in the allowed list: + + + diff --git a/sdk/typescript/docs/pages/playground/mixnodes.mdx b/sdk/typescript/docs/pages/playground/mixnodes.mdx new file mode 100644 index 0000000000..3ecc33c628 --- /dev/null +++ b/sdk/typescript/docs/pages/playground/mixnodes.mdx @@ -0,0 +1,13 @@ +# Query for Mixnodes + +import { Mixnodes } from '../../components/mixnodes'; +import Box from '@mui/material/Box'; +import FormattedExampleCode from '../../code-examples/mixnodes-example-code.mdx'; + +The Nym Mixnet contract keeps a directory of all mixnodes that can be used to mix traffic. + +Here is a live example of querying the Mixnet Contract for a paged list of mixnodes: + + + + diff --git a/sdk/typescript/docs/pages/playground/traffic.mdx b/sdk/typescript/docs/pages/playground/traffic.mdx new file mode 100644 index 0000000000..76a85ab9fb --- /dev/null +++ b/sdk/typescript/docs/pages/playground/traffic.mdx @@ -0,0 +1,10 @@ +# Traffic + +import { Traffic } from '../../components/traffic'; +import Box from '@mui/material/Box'; +import FormattedTrafficExampleCode from '../../code-examples/traffic-example-code.mdx'; + +Use this tool to experiment with the Mixnet: send and receive messages! + + + \ No newline at end of file diff --git a/sdk/typescript/docs/pages/playground/wallet.mdx b/sdk/typescript/docs/pages/playground/wallet.mdx new file mode 100644 index 0000000000..1e6a2b8905 --- /dev/null +++ b/sdk/typescript/docs/pages/playground/wallet.mdx @@ -0,0 +1,11 @@ +# Wallet + +import { Wallet } from '../../components/wallet' +import Box from '@mui/material/Box'; +import FormattedWalletExampleCode from '../../code-examples/wallet-example-code.mdx'; + +Here's a small wallet example for you to test some of the methods of our clients. +You can use the testnet address provided as recipient address, and to delegate just go to the Mixnodes list and paste in the Mix ID number of the Mixnode you'd like to delegate to. + + + \ No newline at end of file diff --git a/sdk/typescript/docs/pages/sdk/_meta.json b/sdk/typescript/docs/pages/sdk/_meta.json deleted file mode 100644 index fc58278791..0000000000 --- a/sdk/typescript/docs/pages/sdk/_meta.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "index": "Introduction", - "mix-fetch": "mixFetch", - "react": "React" -} diff --git a/sdk/typescript/docs/pages/sdk/index.mdx b/sdk/typescript/docs/pages/sdk/index.mdx deleted file mode 100644 index f55fd65cca..0000000000 --- a/sdk/typescript/docs/pages/sdk/index.mdx +++ /dev/null @@ -1,9 +0,0 @@ -# Nym Typescript SDK - -Commodo magna ullamco voluptate aute adipisicing culpa duis reprehenderit. Laboris fugiat in duis mollit dolor voluptate ex anim. Cupidatat enim nostrud laboris incididunt minim do do et adipisicing. Adipisicing pariatur dolor elit nisi elit. Cillum nisi irure officia ipsum. Pariatur ex esse dolor sit esse consectetur dolore dolor. Nostrud dolor proident ullamco sint commodo laboris culpa. - -Occaecat commodo deserunt ut laborum pariatur exercitation ea cillum officia non. Cupidatat amet aute ex exercitation magna quis fugiat consequat minim exercitation fugiat deserunt Lorem deserunt. Commodo irure incididunt officia et aute. - -Ut voluptate deserunt sunt voluptate elit. Incididunt enim nulla amet occaecat incididunt officia sunt eu fugiat dolore id anim. Aliqua duis voluptate consectetur ex voluptate nisi sit quis esse nulla irure aliquip. - -Culpa proident aliqua eu in. Id Lorem eu nostrud cupidatat sint adipisicing ex esse tempor commodo. Enim labore commodo aute quis aliqua enim. Veniam minim sunt commodo cillum quis officia ea tempor adipisicing pariatur. Nisi ea in reprehenderit in nostrud. Mollit non proident cupidatat aliqua ut ea quis id exercitation labore excepteur nulla ex. diff --git a/sdk/typescript/docs/pages/sdk/mix-fetch.mdx b/sdk/typescript/docs/pages/sdk/mix-fetch.mdx deleted file mode 100644 index 8ca721850d..0000000000 --- a/sdk/typescript/docs/pages/sdk/mix-fetch.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -description: Send your HTTP requests over the Nym mixnet securely with a drop-in replacement for fetch ---- - -# mixFetch - -Anim occaecat exercitation officia aliquip sit culpa incididunt labore sit aute sint incididunt consequat. Ex enim ullamco dolore laboris incididunt aliqua duis consectetur non voluptate. Dolore ut sunt ad commodo. Veniam enim culpa tempor consectetur excepteur pariatur adipisicing. Commodo adipisicing magna irure deserunt cupidatat excepteur cupidatat consectetur fugiat irure aliqua laboris qui. Officia incididunt adipisicing elit eu fugiat cupidatat non irure id dolor. - diff --git a/sdk/typescript/docs/pages/sdk/node-tester.mdx b/sdk/typescript/docs/pages/sdk/node-tester.mdx deleted file mode 100644 index 374a0dae0e..0000000000 --- a/sdk/typescript/docs/pages/sdk/node-tester.mdx +++ /dev/null @@ -1,3 +0,0 @@ -# Node Tester - -Deserunt commodo tempor magna culpa qui consectetur reprehenderit. Pariatur ipsum nostrud mollit ex elit est reprehenderit enim deserunt. Et voluptate veniam proident sunt ea in. Aute aliquip do commodo aliqua duis Lorem. Ut sunt officia exercitation magna nisi ea commodo do nostrud ullamco cupidatat tempor est. Magna minim magna minim occaecat. Tempor nisi occaecat amet duis duis qui deserunt culpa ex. diff --git a/sdk/typescript/docs/pages/sdk/react/_meta.json b/sdk/typescript/docs/pages/sdk/react/_meta.json deleted file mode 100644 index d3673f13ea..0000000000 --- a/sdk/typescript/docs/pages/sdk/react/_meta.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "index": "Introduction" -} diff --git a/sdk/typescript/docs/pages/sdk/react/components.mdx b/sdk/typescript/docs/pages/sdk/react/components.mdx deleted file mode 100644 index cb09ef1200..0000000000 --- a/sdk/typescript/docs/pages/sdk/react/components.mdx +++ /dev/null @@ -1,9 +0,0 @@ -# Nym React Components - -Voluptate laborum sit deserunt mollit labore ex labore sunt. Aliquip culpa est veniam culpa dolore irure do veniam aliquip ullamco reprehenderit pariatur. Elit proident sit ullamco dolore deserunt aute minim. Irure consectetur minim elit et incididunt non fugiat ad deserunt consectetur ad. Veniam enim non ipsum duis anim duis duis cillum consectetur anim eiusmod sint veniam. Amet commodo dolor esse amet dolor quis labore elit. Tempor commodo ipsum enim consectetur sit culpa consequat nisi. - -UI to show: -- address display -- address form text input (with validation) -- currency display -- currency form text input (with validation) diff --git a/sdk/typescript/docs/pages/sdk/react/hooks.mdx b/sdk/typescript/docs/pages/sdk/react/hooks.mdx deleted file mode 100644 index 53c6ceab8a..0000000000 --- a/sdk/typescript/docs/pages/sdk/react/hooks.mdx +++ /dev/null @@ -1,3 +0,0 @@ -# React Hooks for the SDK - -Voluptate laborum sit deserunt mollit labore ex labore sunt. Aliquip culpa est veniam culpa dolore irure do veniam aliquip ullamco reprehenderit pariatur. Elit proident sit ullamco dolore deserunt aute minim. Irure consectetur minim elit et incididunt non fugiat ad deserunt consectetur ad. Veniam enim non ipsum duis anim duis duis cillum consectetur anim eiusmod sint veniam. Amet commodo dolor esse amet dolor quis labore elit. Tempor commodo ipsum enim consectetur sit culpa consequat nisi. diff --git a/sdk/typescript/docs/pages/sdk/react/index.mdx b/sdk/typescript/docs/pages/sdk/react/index.mdx deleted file mode 100644 index 9d94d539ac..0000000000 --- a/sdk/typescript/docs/pages/sdk/react/index.mdx +++ /dev/null @@ -1,9 +0,0 @@ -# React support - -Nym provides several React libraries: - - -We also suggest you look at [CosmosKit](https://docs.cosmoskit.com/) if you want to: -- use a wallet (Keplr, Cosmostation) in your app -- sign transactions with a Ledger hardware wallet -- query and execute methods on Nym's smart contracts diff --git a/sdk/typescript/docs/pages/sdk/tsdoc/_meta.json b/sdk/typescript/docs/pages/sdk/tsdoc/_meta.json deleted file mode 100644 index 2a80340c0e..0000000000 --- a/sdk/typescript/docs/pages/sdk/tsdoc/_meta.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "index": "List of packages", - "@nymproject/sdk": { - "title": "@nymproject/sdk", - "type": "page", - "href": "/docs/tsdoc/nymproject/sdk/", - "newWindow": true - }, - "nymproject/mix-fetch": { - "title": "@nymproject/mix-fetch", - "type": "page", - "href": "/docs/tsdoc/nymproject/mix-fetch/", - "newWindow": true - }, - "nymproject/node-tester": { - "title": "@nymproject/node-tester", - "type": "page", - "href": "/docs/tsdoc/nymproject/node-tester/", - "newWindow": true - } -} diff --git a/sdk/typescript/docs/pages/sdk/tsdoc/index.mdx b/sdk/typescript/docs/pages/sdk/tsdoc/index.mdx deleted file mode 100644 index 632c593e86..0000000000 --- a/sdk/typescript/docs/pages/sdk/tsdoc/index.mdx +++ /dev/null @@ -1,4 +0,0 @@ -# `tsdoc` for all classes and interfaces - -Nostrud sint occaecat dolore qui mollit deserunt aliquip est elit. Fugiat id minim minim ut incididunt enim ipsum eiusmod tempor pariatur laborum proident. Exercitation adipisicing laborum culpa ipsum irure. Lorem amet anim pariatur exercitation dolore velit. Voluptate tempor proident laboris qui aliqua reprehenderit deserunt. In tempor eu nostrud ex consectetur incididunt in. - diff --git a/sdk/typescript/docs/pages/start.mdx b/sdk/typescript/docs/pages/start.mdx new file mode 100644 index 0000000000..01151ea232 --- /dev/null +++ b/sdk/typescript/docs/pages/start.mdx @@ -0,0 +1,86 @@ +import { Callout } from 'nextra/components' + +## Nym Smart Contracts + +After having installed your client from the [`Contract Clients`](https://www.npmjs.com/package/@nymproject/contract-clients) to query any of the Nym smart contracts, you can import the packages and execute some methods, signing them with a mnemonic: +````js +import { contracts } from '@nymproject/contract-clients'; +import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate"; +import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"; + +async function main() { + // Generate a signer from a mnemonic + const signer = await DirectSecp256k1HdWallet.fromMnemonic("..."); + const accounts = await signer.getAccounts(); + + // Make a signing client for the Nym Mixnet contract on mainnet + const cosmWasmSigningClient = await SigningCosmWasmClient.connectWithSigner("https://rpc.nymtech.net:443", signer); + const client = new contracts.Mixnet.MixnetClient(cosmWasmSigningClient, accounts[0].address, 'n17srjznxl9dvzdkpwpw24gg668wc73val88a6m5ajg6ankwvz9wtst0cznr'); + + // Delegate 1 NYM to mixnode with id 100 + const result = await client.delegateToMixnode({ mixId: 100 }, 'auto', undefined, [{ amount: `${1_000_000}`, denom: 'unym' }]); + + console.log(`Tx Hash = ${result.transactionHash}`); +}; +```` + +## Mixnet Client +After instantiating the [`Mixnet Client`](https://www.npmjs.com/package/@nymproject/sdk), you can use it and send messages to yourself and output them in the console by following these steps: +````js +import { createNymMixnetClient } from '@nymproject/sdk'; + +const main = async () => { + const nym = await createNymMixnetClient(); + + const nymApiUrl = 'https://validator.nymtech.net/api'; + + // Show message payload content when received + nym.events.subscribeToTextMessageReceivedEvent((e) => { + console.log('Got a message: ', e.args.payload); + }); + + // Start the client and connect to a gateway + await nym.client.start({ + clientId: 'My awesome client', + nymApiUrl, + }); + + // Stop the client connection + const stop = async () => { + await nym?.client.stop(); + }; + + // Send a message to yourself + const payload = 'Hello mixnet'; + const recipient = nym.client.selfAddress(); + nym.client.send({ payload, recipient }); + +}; +```` + +## MixFetch + +Use the [`mixFetch`](https://www.npmjs.com/package/@nymproject/mix-fetch) package as a drop-in replacement for `fetch`to send HTTP requests over the Nym Mixnet: + +```ts +import { mixFetch } from '@nymproject/mix-fetch'; + +// HTTP GET +const response = await mixFetch('https://nymtech.net'); +const html = await response.text(); + +// HTTP POST +const apiResponse = await mixFetch('https://api.example.com', { + method: 'POST', + body: JSON.stringify({ foo: 'bar' }), + headers: { [`Content-Type`]: 'application/json', Authorization: `Bearer ${AUTH_TOKEN}` } +}); +``` + +Check the [standard allowed list](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt) to see +if the host you want to `mixFetch` from is allowed. + + + + + diff --git a/sdk/typescript/docs/pages/styles.css b/sdk/typescript/docs/pages/styles.css new file mode 100644 index 0000000000..205f4add44 --- /dev/null +++ b/sdk/typescript/docs/pages/styles.css @@ -0,0 +1,105 @@ +body { +--colorPrimary: #fb6e4e; +--textPrimary: #121726; +} + +div.nextra-code-block > div { + background:var(--colorPrimary)!important; +} + +.nextra-code-block > pre { + max-height: 350px; + scroll-y: auto; +} + +/* Code blocks*/ +.nx-absolute.nx-top-0 { + background: var(--colorPrimary) !important; + color: var(--textPrimary) !important; +} + + +:is(html[class~=dark] .dark\:nx-bg-primary-300\/10) { + background-color: hsl(var(black)100% 77%/.1); +} + + +/* Sidebar buttons */ +:is(html .dark\:nx-bg-primary-400\/10){ + background: var(--colorPrimary) !important; + color: var(--textPrimary) !important; +} + +/* aside ul > li > a:hover{ + background: #fb6e4ea9 !important; +} */ + +/* aside ul > li > a:active{ + background: #fb6e4e !important; +} */ + + +/* Links*/ +.nx-text-primary-600.nx-underline.nx-decoration-from-font { + color: var(--colorPrimary)!important; +} + +.MuiTypography-root.MuiTypography-inherit.MuiLink-root.MuiLink-underlineAlways.css-1xr3c94-MuiTypography-root-MuiLink-root { + color: var(--colorPrimary) !important; +} + +/* Callouts */ +.nextra-callout { + background-color: #fb6e4e21 !important; +} + +.nx-mt-6 .nx-leading-7 > p { + color: var(--colorPrimary)!important; +} + +/* Callout Secondary */ +:is(html .dark\:nx-border-yellow-200\/30) { + border-color: transparent !important; +} + +/* Callout Primary */ +:is(html .dark\:nx-border-blue-200\/30) { + border-color: var(--colorPrimary)!important; +} + +/* Chips*/ +.css-sv2u65-MuiChip-root { + background-color: var(--colorPrimary); +} + +/* Buttons */ +.MuiButton-root { + color: var(--colorPrimary); + border-color: var(--colorPrimary); +} + +.MuiButton-root:hover { + color: white; + background-color: var(--colorPrimary); +} + +.MuiCircularProgress-root { + color: var(--colorPrimary); +} + +.nextra-scrollbar.nx-sticky{ + color: var(--colorPrimary) !important; +} + +.nx-text-primary-600 { + color: var(--colorPrimary) !important; +} + +input:focus-visible { + --tw-ring-shadow: var(--colorPrimary) !important; +} + +.Mui-focused > fieldset { +border-color: var(--colorPrimary) !important; +} + diff --git a/sdk/typescript/docs/pnpm-lock.yaml b/sdk/typescript/docs/pnpm-lock.yaml deleted file mode 100644 index afa36b4e63..0000000000 --- a/sdk/typescript/docs/pnpm-lock.yaml +++ /dev/null @@ -1,2172 +0,0 @@ -lockfileVersion: 5.3 - -specifiers: - '@types/node': 18.11.10 - next: ^13.0.6 - nextra: latest - nextra-theme-docs: latest - react: ^18.2.0 - react-dom: ^18.2.0 - typescript: ^4.9.3 - -dependencies: - next: 13.0.6_react-dom@18.2.0+react@18.2.0 - nextra: 2.2.14_f26ff3bd08f1cd28b0f73422c76f5ffd - nextra-theme-docs: 2.2.14_d8d66b9d2170cddb63c39dddec8541b9 - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - -devDependencies: - '@types/node': 18.11.10 - typescript: 4.9.3 - -packages: - - /@babel/runtime/7.20.6: - resolution: {integrity: sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.13.11 - dev: false - - /@headlessui/react/1.7.10_react-dom@18.2.0+react@18.2.0: - resolution: {integrity: sha512-1m66h/5eayTEZVT2PI13/2PG3EVC7a9XalmUtVSC8X76pcyKYMuyX1XAL2RUtCr8WhoMa/KrDEyoeU5v+kSQOw==} - engines: {node: '>=10'} - peerDependencies: - react: ^16 || ^17 || ^18 - react-dom: ^16 || ^17 || ^18 - dependencies: - client-only: 0.0.1 - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - dev: false - - /@mdx-js/mdx/2.2.1: - resolution: {integrity: sha512-hZ3ex7exYLJn6FfReq8yTvA6TE53uW9UHJQM9IlSauOuS55J9y8RtA7W+dzp6Yrzr00/U1sd7q+Wf61q6SfiTQ==} - dependencies: - '@types/estree-jsx': 1.0.0 - '@types/mdx': 2.0.3 - estree-util-build-jsx: 2.2.0 - estree-util-is-identifier-name: 2.0.1 - estree-util-to-js: 1.1.0 - estree-walker: 3.0.1 - hast-util-to-estree: 2.1.0 - markdown-extensions: 1.1.1 - periscopic: 3.0.4 - remark-mdx: 2.1.5 - remark-parse: 10.0.1 - remark-rehype: 10.1.0 - unified: 10.1.2 - unist-util-position-from-estree: 1.1.1 - unist-util-stringify-position: 3.0.2 - unist-util-visit: 4.1.1 - vfile: 5.3.6 - transitivePeerDependencies: - - supports-color - dev: false - - /@mdx-js/react/2.2.1_react@18.2.0: - resolution: {integrity: sha512-YdXcMcEnqZhzql98RNrqYo9cEhTTesBiCclEtoiQUbJwx87q9453GTapYU6kJ8ZZ2ek1Vp25SiAXEFy5O/eAPw==} - peerDependencies: - react: '>=16' - dependencies: - '@types/mdx': 2.0.3 - '@types/react': 18.0.25 - react: 18.2.0 - dev: false - - /@napi-rs/simple-git-android-arm-eabi/0.1.8: - resolution: {integrity: sha512-JJCejHBB1G6O8nxjQLT4quWCcvLpC3oRdJJ9G3MFYSCoYS8i1bWCWeU+K7Br+xT+D6s1t9q8kNJAwJv9Ygpi0g==} - engines: {node: '>= 10'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: false - optional: true - - /@napi-rs/simple-git-android-arm64/0.1.8: - resolution: {integrity: sha512-mraHzwWBw3tdRetNOS5KnFSjvdAbNBnjFLA8I4PwTCPJj3Q4txrigcPp2d59cJ0TC51xpnPXnZjYdNwwSI9g6g==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: false - optional: true - - /@napi-rs/simple-git-darwin-arm64/0.1.8: - resolution: {integrity: sha512-ufy/36eI/j4UskEuvqSH7uXtp3oXeLDmjQCfKJz3u5Vx98KmOMKrqAm2H81AB2WOtCo5mqS6PbBeUXR8BJX8lQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@napi-rs/simple-git-darwin-x64/0.1.8: - resolution: {integrity: sha512-Vb21U+v3tPJNl+8JtIHHT8HGe6WZ8o1Tq3f6p+Jx9Cz71zEbcIiB9FCEMY1knS/jwQEOuhhlI9Qk7d4HY+rprA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@napi-rs/simple-git-linux-arm-gnueabihf/0.1.8: - resolution: {integrity: sha512-6BPTJ7CzpSm2t54mRLVaUr3S7ORJfVJoCk2rQ8v8oDg0XAMKvmQQxOsAgqKBo9gYNHJnqrOx3AEuEgvB586BuQ==} - engines: {node: '>= 10'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@napi-rs/simple-git-linux-arm64-gnu/0.1.8: - resolution: {integrity: sha512-qfESqUCAA/XoQpRXHptSQ8gIFnETCQt1zY9VOkplx6tgYk9PCeaX4B1Xuzrh3eZamSCMJFn+1YB9Ut8NwyGgAA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@napi-rs/simple-git-linux-arm64-musl/0.1.8: - resolution: {integrity: sha512-G80BQPpaRmQpn8dJGHp4I2/YVhWDUNJwcCrJAtAdbKFDCMyCHJBln2ERL/+IEUlIAT05zK/c1Z5WEprvXEdXow==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@napi-rs/simple-git-linux-x64-gnu/0.1.8: - resolution: {integrity: sha512-NI6o1sZYEf6vPtNWJAm9w8BxJt+LlSFW0liSjYe3lc3e4dhMfV240f0ALeqlwdIldRPaDFwZSJX5/QbS7nMzhw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@napi-rs/simple-git-linux-x64-musl/0.1.8: - resolution: {integrity: sha512-wljGAEOW41er45VTiU8kXJmO480pQKzsgRCvPlJJSCaEVBbmo6XXbFIXnZy1a2J3Zyy2IOsRB4PVkUZaNuPkZQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@napi-rs/simple-git-win32-arm64-msvc/0.1.8: - resolution: {integrity: sha512-QuV4QILyKPfbWHoQKrhXqjiCClx0SxbCTVogkR89BwivekqJMd9UlMxZdoCmwLWutRx4z9KmzQqokvYI5QeepA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@napi-rs/simple-git-win32-x64-msvc/0.1.8: - resolution: {integrity: sha512-UzNS4JtjhZhZ5hRLq7BIUq+4JOwt1ThIKv11CsF1ag2l99f0123XvfEpjczKTaa94nHtjXYc2Mv9TjccBqYOew==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@napi-rs/simple-git/0.1.8: - resolution: {integrity: sha512-BvOMdkkofTz6lEE35itJ/laUokPhr/5ToMGlOH25YnhLD2yN1KpRAT4blW9tT8281/1aZjW3xyi73bs//IrDKA==} - engines: {node: '>= 10'} - optionalDependencies: - '@napi-rs/simple-git-android-arm-eabi': 0.1.8 - '@napi-rs/simple-git-android-arm64': 0.1.8 - '@napi-rs/simple-git-darwin-arm64': 0.1.8 - '@napi-rs/simple-git-darwin-x64': 0.1.8 - '@napi-rs/simple-git-linux-arm-gnueabihf': 0.1.8 - '@napi-rs/simple-git-linux-arm64-gnu': 0.1.8 - '@napi-rs/simple-git-linux-arm64-musl': 0.1.8 - '@napi-rs/simple-git-linux-x64-gnu': 0.1.8 - '@napi-rs/simple-git-linux-x64-musl': 0.1.8 - '@napi-rs/simple-git-win32-arm64-msvc': 0.1.8 - '@napi-rs/simple-git-win32-x64-msvc': 0.1.8 - dev: false - - /@next/env/13.0.6: - resolution: {integrity: sha512-yceT6DCHKqPRS1cAm8DHvDvK74DLIkDQdm5iV+GnIts8h0QbdHvkUIkdOvQoOODgpr6018skbmSQp12z5OWIQQ==} - dev: false - - /@next/swc-android-arm-eabi/13.0.6: - resolution: {integrity: sha512-FGFSj3v2Bluw8fD/X+1eXIEB0PhoJE0zfutsAauRhmNpjjZshLDgoXMWm1jTRL/04K/o9gwwO2+A8+sPVCH1uw==} - engines: {node: '>= 10'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: false - optional: true - - /@next/swc-android-arm64/13.0.6: - resolution: {integrity: sha512-7MgbtU7kimxuovVsd7jSJWMkIHBDBUsNLmmlkrBRHTvgzx5nDBXogP0hzZm7EImdOPwVMPpUHRQMBP9mbsiJYQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: false - optional: true - - /@next/swc-darwin-arm64/13.0.6: - resolution: {integrity: sha512-AUVEpVTxbP/fxdFsjVI9d5a0CFn6NVV7A/RXOb0Y+pXKIIZ1V5rFjPwpYfIfyOo2lrqgehMNQcyMRoTrhq04xg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@next/swc-darwin-x64/13.0.6: - resolution: {integrity: sha512-SasCDJlshglsPnbzhWaIF6VEGkQy2NECcAOxPwaPr0cwbbt4aUlZ7QmskNzgolr5eAjFS/xTr7CEeKJtZpAAtQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@next/swc-freebsd-x64/13.0.6: - resolution: {integrity: sha512-6Lbxd9gAdXneTkwHyYW/qtX1Tdw7ND9UbiGsGz/SP43ZInNWnW6q0au4hEVPZ9bOWWRKzcVoeTBdoMpQk9Hx9w==} - engines: {node: '>= 10'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-arm-gnueabihf/13.0.6: - resolution: {integrity: sha512-wNdi5A519e1P+ozEuYOhWPzzE6m1y7mkO6NFwn6watUwO0X9nZs7fT9THmnekvmFQpaZ6U+xf2MQ9poQoCh6jQ==} - engines: {node: '>= 10'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-arm64-gnu/13.0.6: - resolution: {integrity: sha512-e8KTRnleQY1KLk5PwGV5hrmvKksCc74QRpHl5ffWnEEAtL2FE0ave5aIkXqErsPdXkiKuA/owp3LjQrP+/AH7Q==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-arm64-musl/13.0.6: - resolution: {integrity: sha512-/7RF03C3mhjYpHN+pqOolgME3guiHU5T3TsejuyteqyEyzdEyLHod+jcYH6ft7UZ71a6TdOewvmbLOtzHW2O8A==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-x64-gnu/13.0.6: - resolution: {integrity: sha512-kxyEXnYHpOEkFnmrlwB1QlzJtjC6sAJytKcceIyFUHbCaD3W/Qb5tnclcnHKTaFccizZRePXvV25Ok/eUSpKTw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-linux-x64-musl/13.0.6: - resolution: {integrity: sha512-N0c6gubS3WW1oYYgo02xzZnNatfVQP/CiJq2ax+DJ55ePV62IACbRCU99TZNXXg+Kos6vNW4k+/qgvkvpGDeyA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-arm64-msvc/13.0.6: - resolution: {integrity: sha512-QjeMB2EBqBFPb/ac0CYr7GytbhUkrG4EwFWbcE0vsRp4H8grt25kYpFQckL4Jak3SUrp7vKfDwZ/SwO7QdO8vw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-ia32-msvc/13.0.6: - resolution: {integrity: sha512-EQzXtdqRTcmhT/tCq81rIwE36Y3fNHPInaCuJzM/kftdXfa0F+64y7FAoMO13npX8EG1+SamXgp/emSusKrCXg==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@next/swc-win32-x64-msvc/13.0.6: - resolution: {integrity: sha512-pSkqZ//UP/f2sS9T7IvHLfEWDPTX0vRyXJnAUNisKvO3eF3e1xdhDX7dix/X3Z3lnN4UjSwOzclAI87JFbOwmQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@popperjs/core/2.11.6: - resolution: {integrity: sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==} - dev: false - - /@swc/helpers/0.4.14: - resolution: {integrity: sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==} - dependencies: - tslib: 2.4.1 - dev: false - - /@types/acorn/4.0.6: - resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} - dependencies: - '@types/estree': 1.0.0 - dev: false - - /@types/debug/4.1.7: - resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==} - dependencies: - '@types/ms': 0.7.31 - dev: false - - /@types/estree-jsx/1.0.0: - resolution: {integrity: sha512-3qvGd0z8F2ENTGr/GG1yViqfiKmRfrXVx5sJyHGFu3z7m5g5utCQtGp/g29JnjflhtQJBv1WDQukHiT58xPcYQ==} - dependencies: - '@types/estree': 1.0.0 - dev: false - - /@types/estree/1.0.0: - resolution: {integrity: sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==} - dev: false - - /@types/hast/2.3.4: - resolution: {integrity: sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==} - dependencies: - '@types/unist': 2.0.6 - dev: false - - /@types/js-yaml/4.0.5: - resolution: {integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==} - dev: false - - /@types/katex/0.11.1: - resolution: {integrity: sha512-DUlIj2nk0YnJdlWgsFuVKcX27MLW0KbKmGVoUHmFr+74FYYNUDAaj9ZqTADvsbE8rfxuVmSFc7KczYn5Y09ozg==} - dev: false - - /@types/mdast/3.0.10: - resolution: {integrity: sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==} - dependencies: - '@types/unist': 2.0.6 - dev: false - - /@types/mdx/2.0.3: - resolution: {integrity: sha512-IgHxcT3RC8LzFLhKwP3gbMPeaK7BM9eBH46OdapPA7yvuIUJ8H6zHZV53J8hGZcTSnt95jANt+rTBNUUc22ACQ==} - dev: false - - /@types/ms/0.7.31: - resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} - dev: false - - /@types/node/18.11.10: - resolution: {integrity: sha512-juG3RWMBOqcOuXC643OAdSA525V44cVgGV6dUDuiFtss+8Fk5x1hI93Rsld43VeJVIeqlP9I7Fn9/qaVqoEAuQ==} - dev: true - - /@types/prop-types/15.7.5: - resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} - dev: false - - /@types/react/18.0.25: - resolution: {integrity: sha512-xD6c0KDT4m7n9uD4ZHi02lzskaiqcBxf4zi+tXZY98a04wvc0hi/TcCPC2FOESZi51Nd7tlUeOJY8RofL799/g==} - dependencies: - '@types/prop-types': 15.7.5 - '@types/scheduler': 0.16.2 - csstype: 3.1.1 - dev: false - - /@types/scheduler/0.16.2: - resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==} - dev: false - - /@types/unist/2.0.6: - resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==} - dev: false - - /acorn-jsx/5.3.2_acorn@8.8.1: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.8.1 - dev: false - - /acorn/8.8.1: - resolution: {integrity: sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: false - - /ansi-styles/3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - dev: false - - /arch/2.2.0: - resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} - dev: false - - /arg/1.0.0: - resolution: {integrity: sha512-Wk7TEzl1KqvTGs/uyhmHO/3XLd3t1UeU4IstvPXVzGPM522cTjqjNZ99esCkcL52sjqjo8e8CTBcWhkxvGzoAw==} - dev: false - - /argparse/1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - dependencies: - sprintf-js: 1.0.3 - dev: false - - /argparse/2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: false - - /astring/1.8.3: - resolution: {integrity: sha512-sRpyiNrx2dEYIMmUXprS8nlpRg2Drs8m9ElX9vVEXaCB4XEAJhKfs7IcX0IwShjuOAjLR6wzIrgoptz1n19i1A==} - hasBin: true - dev: false - - /bail/2.0.2: - resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} - dev: false - - /caniuse-lite/1.0.30001435: - resolution: {integrity: sha512-kdCkUTjR+v4YAJelyiDTqiu82BDr4W4CP5sgTA0ZBmqn30XfS2ZghPLMowik9TPhS+psWJiUNxsqLyurDbmutA==} - dev: false - - /ccount/2.0.1: - resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - dev: false - - /chalk/2.3.0: - resolution: {integrity: sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 4.5.0 - dev: false - - /character-entities-html4/2.1.0: - resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} - dev: false - - /character-entities-legacy/3.0.0: - resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} - dev: false - - /character-entities/2.0.2: - resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} - dev: false - - /character-reference-invalid/2.0.1: - resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} - dev: false - - /client-only/0.0.1: - resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} - dev: false - - /clipboardy/1.2.2: - resolution: {integrity: sha512-16KrBOV7bHmHdxcQiCvfUFYVFyEah4FI8vYT1Fr7CGSA4G+xBWMEfUEQJS1hxeHGtI9ju1Bzs9uXSbj5HZKArw==} - engines: {node: '>=4'} - dependencies: - arch: 2.2.0 - execa: 0.8.0 - dev: false - - /clsx/1.2.1: - resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} - engines: {node: '>=6'} - dev: false - - /color-convert/1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - dev: false - - /color-name/1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: false - - /comma-separated-tokens/2.0.3: - resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} - dev: false - - /commander/8.3.0: - resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} - engines: {node: '>= 12'} - dev: false - - /compute-scroll-into-view/2.0.4: - resolution: {integrity: sha512-y/ZA3BGnxoM/QHHQ2Uy49CLtnWPbt4tTPpEEZiEmmiWBFKjej7nEyH8Ryz54jH0MLXflUYA3Er2zUxPSJu5R+g==} - dev: false - - /cross-spawn/5.1.0: - resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} - dependencies: - lru-cache: 4.1.5 - shebang-command: 1.2.0 - which: 1.3.1 - dev: false - - /csstype/3.1.1: - resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==} - dev: false - - /debug/4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - dev: false - - /decode-named-character-reference/1.0.2: - resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} - dependencies: - character-entities: 2.0.2 - dev: false - - /dequal/2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} - dev: false - - /diff/5.1.0: - resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} - engines: {node: '>=0.3.1'} - dev: false - - /escape-string-regexp/1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: false - - /escape-string-regexp/5.0.0: - resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} - engines: {node: '>=12'} - dev: false - - /esprima/4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - dev: false - - /estree-util-attach-comments/2.1.0: - resolution: {integrity: sha512-rJz6I4L0GaXYtHpoMScgDIwM0/Vwbu5shbMeER596rB2D1EWF6+Gj0e0UKzJPZrpoOc87+Q2kgVFHfjAymIqmw==} - dependencies: - '@types/estree': 1.0.0 - dev: false - - /estree-util-build-jsx/2.2.0: - resolution: {integrity: sha512-apsfRxF9uLrqosApvHVtYZjISPvTJ+lBiIydpC+9wE6cF6ssbhnjyQLqaIjgzGxvC2Hbmec1M7g91PoBayYoQQ==} - dependencies: - '@types/estree-jsx': 1.0.0 - estree-util-is-identifier-name: 2.0.1 - estree-walker: 3.0.1 - dev: false - - /estree-util-is-identifier-name/2.0.1: - resolution: {integrity: sha512-rxZj1GkQhY4x1j/CSnybK9cGuMFQYFPLq0iNyopqf14aOVLFtMv7Esika+ObJWPWiOHuMOAHz3YkWoLYYRnzWQ==} - dev: false - - /estree-util-to-js/1.1.0: - resolution: {integrity: sha512-490lbfCcpLk+ofK6HCgqDfYs4KAfq6QVvDw3+Bm1YoKRgiOjKiKYGAVQE1uwh7zVxBgWhqp4FDtp5SqunpUk1A==} - dependencies: - '@types/estree-jsx': 1.0.0 - astring: 1.8.3 - source-map: 0.7.4 - dev: false - - /estree-util-value-to-estree/1.3.0: - resolution: {integrity: sha512-Y+ughcF9jSUJvncXwqRageavjrNPAI+1M/L3BI3PyLp1nmgYTGUXU6t5z1Y7OWuThoDdhPME07bQU+d5LxdJqw==} - engines: {node: '>=12.0.0'} - dependencies: - is-plain-obj: 3.0.0 - dev: false - - /estree-util-visit/1.2.0: - resolution: {integrity: sha512-wdsoqhWueuJKsh5hqLw3j8lwFqNStm92VcwtAOAny8g/KS/l5Y8RISjR4k5W6skCj3Nirag/WUCMS0Nfy3sgsg==} - dependencies: - '@types/estree-jsx': 1.0.0 - '@types/unist': 2.0.6 - dev: false - - /estree-walker/3.0.1: - resolution: {integrity: sha512-woY0RUD87WzMBUiZLx8NsYr23N5BKsOMZHhu2hoNRVh6NXGfoiT1KOL8G3UHlJAnEDGmfa5ubNA/AacfG+Kb0g==} - dev: false - - /execa/0.8.0: - resolution: {integrity: sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA==} - engines: {node: '>=4'} - dependencies: - cross-spawn: 5.1.0 - get-stream: 3.0.0 - is-stream: 1.1.0 - npm-run-path: 2.0.2 - p-finally: 1.0.0 - signal-exit: 3.0.7 - strip-eof: 1.0.0 - dev: false - - /extend-shallow/2.0.1: - resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} - engines: {node: '>=0.10.0'} - dependencies: - is-extendable: 0.1.1 - dev: false - - /extend/3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - dev: false - - /flexsearch/0.7.31: - resolution: {integrity: sha512-XGozTsMPYkm+6b5QL3Z9wQcJjNYxp0CYn3U1gO7dwD6PAqU1SVWZxI9CCg3z+ml3YfqdPnrBehaBrnH2AGKbNA==} - dev: false - - /focus-visible/5.2.0: - resolution: {integrity: sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ==} - dev: false - - /get-stream/3.0.0: - resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==} - engines: {node: '>=4'} - dev: false - - /git-up/7.0.0: - resolution: {integrity: sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==} - dependencies: - is-ssh: 1.4.0 - parse-url: 8.1.0 - dev: false - - /git-url-parse/13.1.0: - resolution: {integrity: sha512-5FvPJP/70WkIprlUZ33bm4UAaFdjcLkJLpWft1BeZKqwR0uhhNGoKwlUaPtVb4LxCSQ++erHapRak9kWGj+FCA==} - dependencies: - git-up: 7.0.0 - dev: false - - /github-slugger/2.0.0: - resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} - dev: false - - /graceful-fs/4.2.10: - resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} - dev: false - - /gray-matter/4.0.3: - resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} - engines: {node: '>=6.0'} - dependencies: - js-yaml: 3.14.1 - kind-of: 6.0.3 - section-matter: 1.0.0 - strip-bom-string: 1.0.0 - dev: false - - /has-flag/2.0.0: - resolution: {integrity: sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng==} - engines: {node: '>=0.10.0'} - dev: false - - /hash-obj/4.0.0: - resolution: {integrity: sha512-FwO1BUVWkyHasWDW4S8o0ssQXjvyghLV2rfVhnN36b2bbcj45eGiuzdn9XOvOpjV3TKQD7Gm2BWNXdE9V4KKYg==} - engines: {node: '>=12'} - dependencies: - is-obj: 3.0.0 - sort-keys: 5.0.0 - type-fest: 1.4.0 - dev: false - - /hast-util-from-parse5/7.1.1: - resolution: {integrity: sha512-R6PoNcUs89ZxLJmMWsVbwSWuz95/9OriyQZ3e2ybwqGsRXzhA6gv49rgGmQvLbZuSNDv9fCg7vV7gXUsvtUFaA==} - dependencies: - '@types/hast': 2.3.4 - '@types/unist': 2.0.6 - hastscript: 7.2.0 - property-information: 6.2.0 - vfile: 5.3.6 - vfile-location: 4.0.1 - web-namespaces: 2.0.1 - dev: false - - /hast-util-is-element/2.1.3: - resolution: {integrity: sha512-O1bKah6mhgEq2WtVMk+Ta5K7pPMqsBBlmzysLdcwKVrqzZQ0CHqUPiIVspNhAG1rvxpvJjtGee17XfauZYKqVA==} - dependencies: - '@types/hast': 2.3.4 - '@types/unist': 2.0.6 - dev: false - - /hast-util-parse-selector/3.1.1: - resolution: {integrity: sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==} - dependencies: - '@types/hast': 2.3.4 - dev: false - - /hast-util-to-estree/2.1.0: - resolution: {integrity: sha512-Vwch1etMRmm89xGgz+voWXvVHba2iiMdGMKmaMfYt35rbVtFDq8JNwwAIvi8zHMkO6Gvqo9oTMwJTmzVRfXh4g==} - dependencies: - '@types/estree': 1.0.0 - '@types/estree-jsx': 1.0.0 - '@types/hast': 2.3.4 - '@types/unist': 2.0.6 - comma-separated-tokens: 2.0.3 - estree-util-attach-comments: 2.1.0 - estree-util-is-identifier-name: 2.0.1 - hast-util-whitespace: 2.0.0 - mdast-util-mdx-expression: 1.3.1 - mdast-util-mdxjs-esm: 1.3.0 - property-information: 6.2.0 - space-separated-tokens: 2.0.2 - style-to-object: 0.3.0 - unist-util-position: 4.0.3 - zwitch: 2.0.4 - transitivePeerDependencies: - - supports-color - dev: false - - /hast-util-to-text/3.1.2: - resolution: {integrity: sha512-tcllLfp23dJJ+ju5wCCZHVpzsQQ43+moJbqVX3jNWPB7z/KFC4FyZD6R7y94cHL6MQ33YtMZL8Z0aIXXI4XFTw==} - dependencies: - '@types/hast': 2.3.4 - '@types/unist': 2.0.6 - hast-util-is-element: 2.1.3 - unist-util-find-after: 4.0.1 - dev: false - - /hast-util-whitespace/2.0.0: - resolution: {integrity: sha512-Pkw+xBHuV6xFeJprJe2BBEoDV+AvQySaz3pPDRUs5PNZEMQjpXJJueqrpcHIXxnWTcAGi/UOCgVShlkY6kLoqg==} - dev: false - - /hastscript/7.2.0: - resolution: {integrity: sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==} - dependencies: - '@types/hast': 2.3.4 - comma-separated-tokens: 2.0.3 - hast-util-parse-selector: 3.1.1 - property-information: 6.2.0 - space-separated-tokens: 2.0.2 - dev: false - - /inline-style-parser/0.1.1: - resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} - dev: false - - /intersection-observer/0.12.2: - resolution: {integrity: sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==} - dev: false - - /is-alphabetical/2.0.1: - resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} - dev: false - - /is-alphanumerical/2.0.1: - resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} - dependencies: - is-alphabetical: 2.0.1 - is-decimal: 2.0.1 - dev: false - - /is-buffer/2.0.5: - resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} - engines: {node: '>=4'} - dev: false - - /is-decimal/2.0.1: - resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} - dev: false - - /is-extendable/0.1.1: - resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} - engines: {node: '>=0.10.0'} - dev: false - - /is-hexadecimal/2.0.1: - resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} - dev: false - - /is-obj/3.0.0: - resolution: {integrity: sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==} - engines: {node: '>=12'} - dev: false - - /is-plain-obj/3.0.0: - resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} - engines: {node: '>=10'} - dev: false - - /is-plain-obj/4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} - dev: false - - /is-reference/3.0.0: - resolution: {integrity: sha512-Eo1W3wUoHWoCoVM4GVl/a+K0IgiqE5aIo4kJABFyMum1ZORlPkC+UC357sSQUL5w5QCE5kCC9upl75b7+7CY/Q==} - dependencies: - '@types/estree': 1.0.0 - dev: false - - /is-ssh/1.4.0: - resolution: {integrity: sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==} - dependencies: - protocols: 2.0.1 - dev: false - - /is-stream/1.1.0: - resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} - engines: {node: '>=0.10.0'} - dev: false - - /isexe/2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: false - - /js-tokens/4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: false - - /js-yaml/3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - dev: false - - /js-yaml/4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - dependencies: - argparse: 2.0.1 - dev: false - - /jsonc-parser/3.2.0: - resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} - dev: false - - /katex/0.13.24: - resolution: {integrity: sha512-jZxYuKCma3VS5UuxOx/rFV1QyGSl3Uy/i0kTJF3HgQ5xMinCQVF8Zd4bMY/9aI9b9A2pjIBOsjSSm68ykTAr8w==} - hasBin: true - dependencies: - commander: 8.3.0 - dev: false - - /katex/0.15.6: - resolution: {integrity: sha512-UpzJy4yrnqnhXvRPhjEuLA4lcPn6eRngixW7Q3TJErjg3Aw2PuLFBzTkdUb89UtumxjhHTqL3a5GDGETMSwgJA==} - hasBin: true - dependencies: - commander: 8.3.0 - dev: false - - /katex/0.16.4: - resolution: {integrity: sha512-WudRKUj8yyBeVDI4aYMNxhx5Vhh2PjpzQw1GRu/LVGqL4m1AxwD1GcUp0IMbdJaf5zsjtj8ghP0DOQRYhroNkw==} - hasBin: true - dependencies: - commander: 8.3.0 - dev: false - - /kind-of/6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - dev: false - - /kleur/4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} - dev: false - - /lodash.get/4.4.2: - resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} - dev: false - - /longest-streak/3.1.0: - resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} - dev: false - - /loose-envify/1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - dependencies: - js-tokens: 4.0.0 - dev: false - - /lru-cache/4.1.5: - resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} - dependencies: - pseudomap: 1.0.2 - yallist: 2.1.2 - dev: false - - /markdown-extensions/1.1.1: - resolution: {integrity: sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==} - engines: {node: '>=0.10.0'} - dev: false - - /markdown-table/3.0.3: - resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} - dev: false - - /match-sorter/6.3.1: - resolution: {integrity: sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==} - dependencies: - '@babel/runtime': 7.20.6 - remove-accents: 0.4.2 - dev: false - - /mdast-util-definitions/5.1.1: - resolution: {integrity: sha512-rQ+Gv7mHttxHOBx2dkF4HWTg+EE+UR78ptQWDylzPKaQuVGdG4HIoY3SrS/pCp80nZ04greFvXbVFHT+uf0JVQ==} - dependencies: - '@types/mdast': 3.0.10 - '@types/unist': 2.0.6 - unist-util-visit: 4.1.1 - dev: false - - /mdast-util-find-and-replace/2.2.1: - resolution: {integrity: sha512-SobxkQXFAdd4b5WmEakmkVoh18icjQRxGy5OWTCzgsLRm1Fu/KCtwD1HIQSsmq5ZRjVH0Ehwg6/Fn3xIUk+nKw==} - dependencies: - escape-string-regexp: 5.0.0 - unist-util-is: 5.1.1 - unist-util-visit-parents: 5.1.1 - dev: false - - /mdast-util-from-markdown/1.2.0: - resolution: {integrity: sha512-iZJyyvKD1+K7QX1b5jXdE7Sc5dtoTry1vzV28UZZe8Z1xVnB/czKntJ7ZAkG0tANqRnBF6p3p7GpU1y19DTf2Q==} - dependencies: - '@types/mdast': 3.0.10 - '@types/unist': 2.0.6 - decode-named-character-reference: 1.0.2 - mdast-util-to-string: 3.1.0 - micromark: 3.1.0 - micromark-util-decode-numeric-character-reference: 1.0.0 - micromark-util-decode-string: 1.0.2 - micromark-util-normalize-identifier: 1.0.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - unist-util-stringify-position: 3.0.2 - uvu: 0.5.6 - transitivePeerDependencies: - - supports-color - dev: false - - /mdast-util-gfm-autolink-literal/1.0.2: - resolution: {integrity: sha512-FzopkOd4xTTBeGXhXSBU0OCDDh5lUj2rd+HQqG92Ld+jL4lpUfgX2AT2OHAVP9aEeDKp7G92fuooSZcYJA3cRg==} - dependencies: - '@types/mdast': 3.0.10 - ccount: 2.0.1 - mdast-util-find-and-replace: 2.2.1 - micromark-util-character: 1.1.0 - dev: false - - /mdast-util-gfm-footnote/1.0.1: - resolution: {integrity: sha512-p+PrYlkw9DeCRkTVw1duWqPRHX6Ywh2BNKJQcZbCwAuP/59B0Lk9kakuAd7KbQprVO4GzdW8eS5++A9PUSqIyw==} - dependencies: - '@types/mdast': 3.0.10 - mdast-util-to-markdown: 1.3.0 - micromark-util-normalize-identifier: 1.0.0 - dev: false - - /mdast-util-gfm-strikethrough/1.0.2: - resolution: {integrity: sha512-T/4DVHXcujH6jx1yqpcAYYwd+z5lAYMw4Ls6yhTfbMMtCt0PHY4gEfhW9+lKsLBtyhUGKRIzcUA2FATVqnvPDA==} - dependencies: - '@types/mdast': 3.0.10 - mdast-util-to-markdown: 1.3.0 - dev: false - - /mdast-util-gfm-table/1.0.6: - resolution: {integrity: sha512-uHR+fqFq3IvB3Rd4+kzXW8dmpxUhvgCQZep6KdjsLK4O6meK5dYZEayLtIxNus1XO3gfjfcIFe8a7L0HZRGgag==} - dependencies: - '@types/mdast': 3.0.10 - markdown-table: 3.0.3 - mdast-util-from-markdown: 1.2.0 - mdast-util-to-markdown: 1.3.0 - transitivePeerDependencies: - - supports-color - dev: false - - /mdast-util-gfm-task-list-item/1.0.1: - resolution: {integrity: sha512-KZ4KLmPdABXOsfnM6JHUIjxEvcx2ulk656Z/4Balw071/5qgnhz+H1uGtf2zIGnrnvDC8xR4Fj9uKbjAFGNIeA==} - dependencies: - '@types/mdast': 3.0.10 - mdast-util-to-markdown: 1.3.0 - dev: false - - /mdast-util-gfm/2.0.1: - resolution: {integrity: sha512-42yHBbfWIFisaAfV1eixlabbsa6q7vHeSPY+cg+BBjX51M8xhgMacqH9g6TftB/9+YkcI0ooV4ncfrJslzm/RQ==} - dependencies: - mdast-util-from-markdown: 1.2.0 - mdast-util-gfm-autolink-literal: 1.0.2 - mdast-util-gfm-footnote: 1.0.1 - mdast-util-gfm-strikethrough: 1.0.2 - mdast-util-gfm-table: 1.0.6 - mdast-util-gfm-task-list-item: 1.0.1 - mdast-util-to-markdown: 1.3.0 - transitivePeerDependencies: - - supports-color - dev: false - - /mdast-util-math/2.0.2: - resolution: {integrity: sha512-8gmkKVp9v6+Tgjtq6SYx9kGPpTf6FVYRa53/DLh479aldR9AyP48qeVOgNZ5X7QUK7nOy4yw7vg6mbiGcs9jWQ==} - dependencies: - '@types/mdast': 3.0.10 - longest-streak: 3.1.0 - mdast-util-to-markdown: 1.3.0 - dev: false - - /mdast-util-mdx-expression/1.3.1: - resolution: {integrity: sha512-TTb6cKyTA1RD+1su1iStZ5PAv3rFfOUKcoU5EstUpv/IZo63uDX03R8+jXjMEhcobXnNOiG6/ccekvVl4eV1zQ==} - dependencies: - '@types/estree-jsx': 1.0.0 - '@types/hast': 2.3.4 - '@types/mdast': 3.0.10 - mdast-util-from-markdown: 1.2.0 - mdast-util-to-markdown: 1.3.0 - transitivePeerDependencies: - - supports-color - dev: false - - /mdast-util-mdx-jsx/2.1.0: - resolution: {integrity: sha512-KzgzfWMhdteDkrY4mQtyvTU5bc/W4ppxhe9SzelO6QUUiwLAM+Et2Dnjjprik74a336kHdo0zKm7Tp+n6FFeRg==} - dependencies: - '@types/estree-jsx': 1.0.0 - '@types/hast': 2.3.4 - '@types/mdast': 3.0.10 - ccount: 2.0.1 - mdast-util-to-markdown: 1.3.0 - parse-entities: 4.0.0 - stringify-entities: 4.0.3 - unist-util-remove-position: 4.0.1 - unist-util-stringify-position: 3.0.2 - vfile-message: 3.1.3 - dev: false - - /mdast-util-mdx/2.0.0: - resolution: {integrity: sha512-M09lW0CcBT1VrJUaF/PYxemxxHa7SLDHdSn94Q9FhxjCQfuW7nMAWKWimTmA3OyDMSTH981NN1csW1X+HPSluw==} - dependencies: - mdast-util-mdx-expression: 1.3.1 - mdast-util-mdx-jsx: 2.1.0 - mdast-util-mdxjs-esm: 1.3.0 - transitivePeerDependencies: - - supports-color - dev: false - - /mdast-util-mdxjs-esm/1.3.0: - resolution: {integrity: sha512-7N5ihsOkAEGjFotIX9p/YPdl4TqUoMxL4ajNz7PbT89BqsdWJuBC9rvgt6wpbwTZqWWR0jKWqQbwsOWDBUZv4g==} - dependencies: - '@types/estree-jsx': 1.0.0 - '@types/hast': 2.3.4 - '@types/mdast': 3.0.10 - mdast-util-from-markdown: 1.2.0 - mdast-util-to-markdown: 1.3.0 - transitivePeerDependencies: - - supports-color - dev: false - - /mdast-util-to-hast/12.2.4: - resolution: {integrity: sha512-a21xoxSef1l8VhHxS1Dnyioz6grrJkoaCUgGzMD/7dWHvboYX3VW53esRUfB5tgTyz4Yos1n25SPcj35dJqmAg==} - dependencies: - '@types/hast': 2.3.4 - '@types/mdast': 3.0.10 - mdast-util-definitions: 5.1.1 - micromark-util-sanitize-uri: 1.1.0 - trim-lines: 3.0.1 - unist-builder: 3.0.0 - unist-util-generated: 2.0.0 - unist-util-position: 4.0.3 - unist-util-visit: 4.1.1 - dev: false - - /mdast-util-to-markdown/1.3.0: - resolution: {integrity: sha512-6tUSs4r+KK4JGTTiQ7FfHmVOaDrLQJPmpjD6wPMlHGUVXoG9Vjc3jIeP+uyBWRf8clwB2blM+W7+KrlMYQnftA==} - dependencies: - '@types/mdast': 3.0.10 - '@types/unist': 2.0.6 - longest-streak: 3.1.0 - mdast-util-to-string: 3.1.0 - micromark-util-decode-string: 1.0.2 - unist-util-visit: 4.1.1 - zwitch: 2.0.4 - dev: false - - /mdast-util-to-string/3.1.0: - resolution: {integrity: sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA==} - dev: false - - /micromark-core-commonmark/1.0.6: - resolution: {integrity: sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA==} - dependencies: - decode-named-character-reference: 1.0.2 - micromark-factory-destination: 1.0.0 - micromark-factory-label: 1.0.2 - micromark-factory-space: 1.0.0 - micromark-factory-title: 1.0.2 - micromark-factory-whitespace: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-chunked: 1.0.0 - micromark-util-classify-character: 1.0.0 - micromark-util-html-tag-name: 1.1.0 - micromark-util-normalize-identifier: 1.0.0 - micromark-util-resolve-all: 1.0.0 - micromark-util-subtokenize: 1.0.2 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-extension-gfm-autolink-literal/1.0.3: - resolution: {integrity: sha512-i3dmvU0htawfWED8aHMMAzAVp/F0Z+0bPh3YrbTPPL1v4YAlCZpy5rBO5p0LPYiZo0zFVkoYh7vDU7yQSiCMjg==} - dependencies: - micromark-util-character: 1.1.0 - micromark-util-sanitize-uri: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-extension-gfm-footnote/1.0.4: - resolution: {integrity: sha512-E/fmPmDqLiMUP8mLJ8NbJWJ4bTw6tS+FEQS8CcuDtZpILuOb2kjLqPEeAePF1djXROHXChM/wPJw0iS4kHCcIg==} - dependencies: - micromark-core-commonmark: 1.0.6 - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-normalize-identifier: 1.0.0 - micromark-util-sanitize-uri: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-extension-gfm-strikethrough/1.0.4: - resolution: {integrity: sha512-/vjHU/lalmjZCT5xt7CcHVJGq8sYRm80z24qAKXzaHzem/xsDYb2yLL+NNVbYvmpLx3O7SYPuGL5pzusL9CLIQ==} - dependencies: - micromark-util-chunked: 1.0.0 - micromark-util-classify-character: 1.0.0 - micromark-util-resolve-all: 1.0.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-extension-gfm-table/1.0.5: - resolution: {integrity: sha512-xAZ8J1X9W9K3JTJTUL7G6wSKhp2ZYHrFk5qJgY/4B33scJzE2kpfRL6oiw/veJTbt7jiM/1rngLlOKPWr1G+vg==} - dependencies: - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-extension-gfm-tagfilter/1.0.1: - resolution: {integrity: sha512-Ty6psLAcAjboRa/UKUbbUcwjVAv5plxmpUTy2XC/3nJFL37eHej8jrHrRzkqcpipJliuBH30DTs7+3wqNcQUVA==} - dependencies: - micromark-util-types: 1.0.2 - dev: false - - /micromark-extension-gfm-task-list-item/1.0.3: - resolution: {integrity: sha512-PpysK2S1Q/5VXi72IIapbi/jliaiOFzv7THH4amwXeYXLq3l1uo8/2Be0Ac1rEwK20MQEsGH2ltAZLNY2KI/0Q==} - dependencies: - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-extension-gfm/2.0.1: - resolution: {integrity: sha512-p2sGjajLa0iYiGQdT0oelahRYtMWvLjy8J9LOCxzIQsllMCGLbsLW+Nc+N4vi02jcRJvedVJ68cjelKIO6bpDA==} - dependencies: - micromark-extension-gfm-autolink-literal: 1.0.3 - micromark-extension-gfm-footnote: 1.0.4 - micromark-extension-gfm-strikethrough: 1.0.4 - micromark-extension-gfm-table: 1.0.5 - micromark-extension-gfm-tagfilter: 1.0.1 - micromark-extension-gfm-task-list-item: 1.0.3 - micromark-util-combine-extensions: 1.0.0 - micromark-util-types: 1.0.2 - dev: false - - /micromark-extension-math/2.0.2: - resolution: {integrity: sha512-cFv2B/E4pFPBBFuGgLHkkNiFAIQv08iDgPH2HCuR2z3AUgMLecES5Cq7AVtwOtZeRrbA80QgMUk8VVW0Z+D2FA==} - dependencies: - '@types/katex': 0.11.1 - katex: 0.13.24 - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-extension-mdx-expression/1.0.3: - resolution: {integrity: sha512-TjYtjEMszWze51NJCZmhv7MEBcgYRgb3tJeMAJ+HQCAaZHHRBaDCccqQzGizR/H4ODefP44wRTgOn2vE5I6nZA==} - dependencies: - micromark-factory-mdx-expression: 1.0.6 - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-events-to-acorn: 1.2.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-extension-mdx-jsx/1.0.3: - resolution: {integrity: sha512-VfA369RdqUISF0qGgv2FfV7gGjHDfn9+Qfiv5hEwpyr1xscRj/CiVRkU7rywGFCO7JwJ5L0e7CJz60lY52+qOA==} - dependencies: - '@types/acorn': 4.0.6 - estree-util-is-identifier-name: 2.0.1 - micromark-factory-mdx-expression: 1.0.6 - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - vfile-message: 3.1.3 - dev: false - - /micromark-extension-mdx-md/1.0.0: - resolution: {integrity: sha512-xaRAMoSkKdqZXDAoSgp20Azm0aRQKGOl0RrS81yGu8Hr/JhMsBmfs4wR7m9kgVUIO36cMUQjNyiyDKPrsv8gOw==} - dependencies: - micromark-util-types: 1.0.2 - dev: false - - /micromark-extension-mdxjs-esm/1.0.3: - resolution: {integrity: sha512-2N13ol4KMoxb85rdDwTAC6uzs8lMX0zeqpcyx7FhS7PxXomOnLactu8WI8iBNXW8AVyea3KIJd/1CKnUmwrK9A==} - dependencies: - micromark-core-commonmark: 1.0.6 - micromark-util-character: 1.1.0 - micromark-util-events-to-acorn: 1.2.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - unist-util-position-from-estree: 1.1.1 - uvu: 0.5.6 - vfile-message: 3.1.3 - dev: false - - /micromark-extension-mdxjs/1.0.0: - resolution: {integrity: sha512-TZZRZgeHvtgm+IhtgC2+uDMR7h8eTKF0QUX9YsgoL9+bADBpBY6SiLvWqnBlLbCEevITmTqmEuY3FoxMKVs1rQ==} - dependencies: - acorn: 8.8.1 - acorn-jsx: 5.3.2_acorn@8.8.1 - micromark-extension-mdx-expression: 1.0.3 - micromark-extension-mdx-jsx: 1.0.3 - micromark-extension-mdx-md: 1.0.0 - micromark-extension-mdxjs-esm: 1.0.3 - micromark-util-combine-extensions: 1.0.0 - micromark-util-types: 1.0.2 - dev: false - - /micromark-factory-destination/1.0.0: - resolution: {integrity: sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw==} - dependencies: - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - dev: false - - /micromark-factory-label/1.0.2: - resolution: {integrity: sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg==} - dependencies: - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-factory-mdx-expression/1.0.6: - resolution: {integrity: sha512-WRQIc78FV7KrCfjsEf/sETopbYjElh3xAmNpLkd1ODPqxEngP42eVRGbiPEQWpRV27LzqW+XVTvQAMIIRLPnNA==} - dependencies: - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-events-to-acorn: 1.2.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - unist-util-position-from-estree: 1.1.1 - uvu: 0.5.6 - vfile-message: 3.1.3 - dev: false - - /micromark-factory-space/1.0.0: - resolution: {integrity: sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew==} - dependencies: - micromark-util-character: 1.1.0 - micromark-util-types: 1.0.2 - dev: false - - /micromark-factory-title/1.0.2: - resolution: {integrity: sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A==} - dependencies: - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-factory-whitespace/1.0.0: - resolution: {integrity: sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A==} - dependencies: - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - dev: false - - /micromark-util-character/1.1.0: - resolution: {integrity: sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg==} - dependencies: - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - dev: false - - /micromark-util-chunked/1.0.0: - resolution: {integrity: sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g==} - dependencies: - micromark-util-symbol: 1.0.1 - dev: false - - /micromark-util-classify-character/1.0.0: - resolution: {integrity: sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA==} - dependencies: - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - dev: false - - /micromark-util-combine-extensions/1.0.0: - resolution: {integrity: sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA==} - dependencies: - micromark-util-chunked: 1.0.0 - micromark-util-types: 1.0.2 - dev: false - - /micromark-util-decode-numeric-character-reference/1.0.0: - resolution: {integrity: sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w==} - dependencies: - micromark-util-symbol: 1.0.1 - dev: false - - /micromark-util-decode-string/1.0.2: - resolution: {integrity: sha512-DLT5Ho02qr6QWVNYbRZ3RYOSSWWFuH3tJexd3dgN1odEuPNxCngTCXJum7+ViRAd9BbdxCvMToPOD/IvVhzG6Q==} - dependencies: - decode-named-character-reference: 1.0.2 - micromark-util-character: 1.1.0 - micromark-util-decode-numeric-character-reference: 1.0.0 - micromark-util-symbol: 1.0.1 - dev: false - - /micromark-util-encode/1.0.1: - resolution: {integrity: sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA==} - dev: false - - /micromark-util-events-to-acorn/1.2.0: - resolution: {integrity: sha512-WWp3bf7xT9MppNuw3yPjpnOxa8cj5ACivEzXJKu0WwnjBYfzaBvIAT9KfeyI0Qkll+bfQtfftSwdgTH6QhTOKw==} - dependencies: - '@types/acorn': 4.0.6 - '@types/estree': 1.0.0 - estree-util-visit: 1.2.0 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - vfile-location: 4.0.1 - vfile-message: 3.1.3 - dev: false - - /micromark-util-html-tag-name/1.1.0: - resolution: {integrity: sha512-BKlClMmYROy9UiV03SwNmckkjn8QHVaWkqoAqzivabvdGcwNGMMMH/5szAnywmsTBUzDsU57/mFi0sp4BQO6dA==} - dev: false - - /micromark-util-normalize-identifier/1.0.0: - resolution: {integrity: sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg==} - dependencies: - micromark-util-symbol: 1.0.1 - dev: false - - /micromark-util-resolve-all/1.0.0: - resolution: {integrity: sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw==} - dependencies: - micromark-util-types: 1.0.2 - dev: false - - /micromark-util-sanitize-uri/1.1.0: - resolution: {integrity: sha512-RoxtuSCX6sUNtxhbmsEFQfWzs8VN7cTctmBPvYivo98xb/kDEoTCtJQX5wyzIYEmk/lvNFTat4hL8oW0KndFpg==} - dependencies: - micromark-util-character: 1.1.0 - micromark-util-encode: 1.0.1 - micromark-util-symbol: 1.0.1 - dev: false - - /micromark-util-subtokenize/1.0.2: - resolution: {integrity: sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA==} - dependencies: - micromark-util-chunked: 1.0.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-util-symbol/1.0.1: - resolution: {integrity: sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ==} - dev: false - - /micromark-util-types/1.0.2: - resolution: {integrity: sha512-DCfg/T8fcrhrRKTPjRrw/5LLvdGV7BHySf/1LOZx7TzWZdYRjogNtyNq885z3nNallwr3QUKARjqvHqX1/7t+w==} - dev: false - - /micromark/3.1.0: - resolution: {integrity: sha512-6Mj0yHLdUZjHnOPgr5xfWIMqMWS12zDN6iws9SLuSz76W8jTtAv24MN4/CL7gJrl5vtxGInkkqDv/JIoRsQOvA==} - dependencies: - '@types/debug': 4.1.7 - debug: 4.3.4 - decode-named-character-reference: 1.0.2 - micromark-core-commonmark: 1.0.6 - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.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.1 - micromark-util-normalize-identifier: 1.0.0 - micromark-util-resolve-all: 1.0.0 - micromark-util-sanitize-uri: 1.1.0 - micromark-util-subtokenize: 1.0.2 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - transitivePeerDependencies: - - supports-color - dev: false - - /mri/1.2.0: - resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} - engines: {node: '>=4'} - dev: false - - /ms/2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: false - - /nanoid/3.3.4: - resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - dev: false - - /nanoid/4.0.1: - resolution: {integrity: sha512-udKGtCCUafD3nQtJg9wBhRP3KMbPglUsgV5JVsXhvyBs/oefqb4sqMEhKBBgqZncYowu58p1prsZQBYvAj/Gww==} - engines: {node: ^14 || ^16 || >=18} - hasBin: true - dev: false - - /next-mdx-remote/4.3.0_react-dom@18.2.0+react@18.2.0: - resolution: {integrity: sha512-fbxkY03pM2Wx5bDNTVKpYD5Hx3QVZGH+6xDtVIxlxXz4HTifP1yI2DrkDvxXbTz0SYGIbluRMIW81IOOa8pigA==} - engines: {node: '>=14', npm: '>=7'} - peerDependencies: - react: '>=16.x <=18.x' - react-dom: '>=16.x <=18.x' - dependencies: - '@mdx-js/mdx': 2.2.1 - '@mdx-js/react': 2.2.1_react@18.2.0 - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - vfile: 5.3.6 - vfile-matter: 3.0.1 - transitivePeerDependencies: - - supports-color - dev: false - - /next-seo/5.14.1_f26ff3bd08f1cd28b0f73422c76f5ffd: - resolution: {integrity: sha512-NiJeQbxYP3z+EMp52q8k3Q+OfX2+Yv2WehERDj98r2wjXxL+woKpRBdsSVYolTD0Hm8IWs42SzaISE93RoQdOw==} - peerDependencies: - next: ^8.1.1-canary.54 || >=9.0.0 - react: '>=16.0.0' - react-dom: '>=16.0.0' - dependencies: - next: 13.0.6_react-dom@18.2.0+react@18.2.0 - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - dev: false - - /next-themes/0.2.1_f26ff3bd08f1cd28b0f73422c76f5ffd: - resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==} - peerDependencies: - next: '*' - react: '*' - react-dom: '*' - dependencies: - next: 13.0.6_react-dom@18.2.0+react@18.2.0 - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - dev: false - - /next/13.0.6_react-dom@18.2.0+react@18.2.0: - resolution: {integrity: sha512-COvigvms2LRt1rrzfBQcMQ2GZd86Mvk1z+LOLY5pniFtL4VrTmhZ9salrbKfSiXbhsD01TrDdD68ec3ABDyscA==} - engines: {node: '>=14.6.0'} - hasBin: true - peerDependencies: - fibers: '>= 3.1.0' - node-sass: ^6.0.0 || ^7.0.0 - react: ^18.2.0 - react-dom: ^18.2.0 - sass: ^1.3.0 - peerDependenciesMeta: - fibers: - optional: true - node-sass: - optional: true - sass: - optional: true - dependencies: - '@next/env': 13.0.6 - '@swc/helpers': 0.4.14 - caniuse-lite: 1.0.30001435 - postcss: 8.4.14 - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - styled-jsx: 5.1.0_react@18.2.0 - optionalDependencies: - '@next/swc-android-arm-eabi': 13.0.6 - '@next/swc-android-arm64': 13.0.6 - '@next/swc-darwin-arm64': 13.0.6 - '@next/swc-darwin-x64': 13.0.6 - '@next/swc-freebsd-x64': 13.0.6 - '@next/swc-linux-arm-gnueabihf': 13.0.6 - '@next/swc-linux-arm64-gnu': 13.0.6 - '@next/swc-linux-arm64-musl': 13.0.6 - '@next/swc-linux-x64-gnu': 13.0.6 - '@next/swc-linux-x64-musl': 13.0.6 - '@next/swc-win32-arm64-msvc': 13.0.6 - '@next/swc-win32-ia32-msvc': 13.0.6 - '@next/swc-win32-x64-msvc': 13.0.6 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - dev: false - - /nextra-theme-docs/2.2.14_d8d66b9d2170cddb63c39dddec8541b9: - resolution: {integrity: sha512-QQcHOcAXSfrpbSX3FqXgcQ2favKLnBAczqKWbSDVEtgHiUG6s7pVpxclpKm5F1c/fP47v19USRq3BL/SZ4JEIQ==} - peerDependencies: - next: '>=9.5.3' - nextra: 2.2.14 - react: '>=16.13.1' - react-dom: '>=16.13.1' - dependencies: - '@headlessui/react': 1.7.10_react-dom@18.2.0+react@18.2.0 - '@popperjs/core': 2.11.6 - clsx: 1.2.1 - flexsearch: 0.7.31 - focus-visible: 5.2.0 - git-url-parse: 13.1.0 - intersection-observer: 0.12.2 - match-sorter: 6.3.1 - next: 13.0.6_react-dom@18.2.0+react@18.2.0 - next-seo: 5.14.1_f26ff3bd08f1cd28b0f73422c76f5ffd - next-themes: 0.2.1_f26ff3bd08f1cd28b0f73422c76f5ffd - nextra: 2.2.14_f26ff3bd08f1cd28b0f73422c76f5ffd - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - scroll-into-view-if-needed: 3.0.4 - zod: 3.20.2 - dev: false - - /nextra/2.2.14_f26ff3bd08f1cd28b0f73422c76f5ffd: - resolution: {integrity: sha512-kToTiTiE4qrQsQ9snFRqCGLLSjKSFgFV/BJm3yp/SRmkmCr1WaWrlmUTAuXlxM7PREbNaZouNSOJ0hGS92rM8A==} - peerDependencies: - next: '>=9.5.3' - react: '>=16.13.1' - react-dom: '>=16.13.1' - dependencies: - '@mdx-js/mdx': 2.2.1 - '@mdx-js/react': 2.2.1_react@18.2.0 - '@napi-rs/simple-git': 0.1.8 - github-slugger: 2.0.0 - graceful-fs: 4.2.10 - gray-matter: 4.0.3 - katex: 0.16.4 - lodash.get: 4.4.2 - next: 13.0.6_react-dom@18.2.0+react@18.2.0 - next-mdx-remote: 4.3.0_react-dom@18.2.0+react@18.2.0 - p-limit: 3.1.0 - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - rehype-katex: 6.0.2 - rehype-pretty-code: 0.9.2_shiki@0.12.1 - remark-gfm: 3.0.1 - remark-math: 5.1.1 - remark-reading-time: 2.0.1 - shiki: 0.12.1 - slash: 3.0.0 - title: 3.5.3 - unist-util-remove: 3.1.1 - unist-util-visit: 4.1.1 - transitivePeerDependencies: - - supports-color - dev: false - - /npm-run-path/2.0.2: - resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} - engines: {node: '>=4'} - dependencies: - path-key: 2.0.1 - dev: false - - /p-finally/1.0.0: - resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} - engines: {node: '>=4'} - dev: false - - /p-limit/3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - dev: false - - /parse-entities/4.0.0: - resolution: {integrity: sha512-5nk9Fn03x3rEhGaX1FU6IDwG/k+GxLXlFAkgrbM1asuAFl3BhdQWvASaIsmwWypRNcZKHPYnIuOSfIWEyEQnPQ==} - dependencies: - '@types/unist': 2.0.6 - character-entities: 2.0.2 - character-entities-legacy: 3.0.0 - character-reference-invalid: 2.0.1 - decode-named-character-reference: 1.0.2 - is-alphanumerical: 2.0.1 - is-decimal: 2.0.1 - is-hexadecimal: 2.0.1 - dev: false - - /parse-numeric-range/1.3.0: - resolution: {integrity: sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==} - dev: false - - /parse-path/7.0.0: - resolution: {integrity: sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==} - dependencies: - protocols: 2.0.1 - dev: false - - /parse-url/8.1.0: - resolution: {integrity: sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==} - dependencies: - parse-path: 7.0.0 - dev: false - - /parse5/6.0.1: - resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} - dev: false - - /path-key/2.0.1: - resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} - engines: {node: '>=4'} - dev: false - - /periscopic/3.0.4: - resolution: {integrity: sha512-SFx68DxCv0Iyo6APZuw/AKewkkThGwssmU0QWtTlvov3VAtPX+QJ4CadwSaz8nrT5jPIuxdvJWB4PnD2KNDxQg==} - dependencies: - estree-walker: 3.0.1 - is-reference: 3.0.0 - dev: false - - /picocolors/1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - dev: false - - /postcss/8.4.14: - resolution: {integrity: sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.4 - picocolors: 1.0.0 - source-map-js: 1.0.2 - dev: false - - /property-information/6.2.0: - resolution: {integrity: sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==} - dev: false - - /protocols/2.0.1: - resolution: {integrity: sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==} - dev: false - - /pseudomap/1.0.2: - resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} - dev: false - - /react-dom/18.2.0_react@18.2.0: - resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} - peerDependencies: - react: ^18.2.0 - dependencies: - loose-envify: 1.4.0 - react: 18.2.0 - scheduler: 0.23.0 - dev: false - - /react/18.2.0: - resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} - engines: {node: '>=0.10.0'} - dependencies: - loose-envify: 1.4.0 - dev: false - - /reading-time/1.5.0: - resolution: {integrity: sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==} - dev: false - - /regenerator-runtime/0.13.11: - resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} - dev: false - - /rehype-katex/6.0.2: - resolution: {integrity: sha512-C4gDAlS1+l0hJqctyiU64f9CvT00S03qV1T6HiMzbSuLBgWUtcqydWHY9OpKrm0SpkK16FNd62CDKyWLwV2ppg==} - dependencies: - '@types/hast': 2.3.4 - '@types/katex': 0.11.1 - hast-util-to-text: 3.1.2 - katex: 0.15.6 - rehype-parse: 8.0.4 - unified: 10.1.2 - unist-util-remove-position: 4.0.1 - unist-util-visit: 4.1.1 - dev: false - - /rehype-parse/8.0.4: - resolution: {integrity: sha512-MJJKONunHjoTh4kc3dsM1v3C9kGrrxvA3U8PxZlP2SjH8RNUSrb+lF7Y0KVaUDnGH2QZ5vAn7ulkiajM9ifuqg==} - dependencies: - '@types/hast': 2.3.4 - hast-util-from-parse5: 7.1.1 - parse5: 6.0.1 - unified: 10.1.2 - dev: false - - /rehype-pretty-code/0.9.2_shiki@0.12.1: - resolution: {integrity: sha512-l369pvBK6ihBEuy2+VDpHU+zbbY8I+Z4LiyIOunHAt3xyw6selaOFKc/DnX94jI5OJb3+NgjbOxXx2yaAypjZw==} - engines: {node: ^12.16.0 || >=13.2.0} - peerDependencies: - shiki: '*' - dependencies: - hash-obj: 4.0.0 - nanoid: 4.0.1 - parse-numeric-range: 1.3.0 - shiki: 0.12.1 - dev: false - - /remark-gfm/3.0.1: - resolution: {integrity: sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==} - dependencies: - '@types/mdast': 3.0.10 - mdast-util-gfm: 2.0.1 - micromark-extension-gfm: 2.0.1 - unified: 10.1.2 - transitivePeerDependencies: - - supports-color - dev: false - - /remark-math/5.1.1: - resolution: {integrity: sha512-cE5T2R/xLVtfFI4cCePtiRn+e6jKMtFDR3P8V3qpv8wpKjwvHoBA4eJzvX+nVrnlNy0911bdGmuspCSwetfYHw==} - dependencies: - '@types/mdast': 3.0.10 - mdast-util-math: 2.0.2 - micromark-extension-math: 2.0.2 - unified: 10.1.2 - dev: false - - /remark-mdx/2.1.5: - resolution: {integrity: sha512-A8vw5s+BgOa968Irt8BO7DfWJTE0Fe7Ge3hX8zzDB1DnwMZTNdK6qF2IcFao+/7nzk1vSysKcFp+3ku4vhMpaQ==} - dependencies: - mdast-util-mdx: 2.0.0 - micromark-extension-mdxjs: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: false - - /remark-parse/10.0.1: - resolution: {integrity: sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw==} - dependencies: - '@types/mdast': 3.0.10 - mdast-util-from-markdown: 1.2.0 - unified: 10.1.2 - transitivePeerDependencies: - - supports-color - dev: false - - /remark-reading-time/2.0.1: - resolution: {integrity: sha512-fy4BKy9SRhtYbEHvp6AItbRTnrhiDGbqLQTSYVbQPGuRCncU1ubSsh9p/W5QZSxtYcUXv8KGL0xBgPLyNJA1xw==} - dependencies: - estree-util-is-identifier-name: 2.0.1 - estree-util-value-to-estree: 1.3.0 - reading-time: 1.5.0 - unist-util-visit: 3.1.0 - dev: false - - /remark-rehype/10.1.0: - resolution: {integrity: sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==} - dependencies: - '@types/hast': 2.3.4 - '@types/mdast': 3.0.10 - mdast-util-to-hast: 12.2.4 - unified: 10.1.2 - dev: false - - /remove-accents/0.4.2: - resolution: {integrity: sha1-CkPTqq4egNuRngeuJUsoXZ4ce7U=} - dev: false - - /sade/1.8.1: - resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} - engines: {node: '>=6'} - dependencies: - mri: 1.2.0 - dev: false - - /scheduler/0.23.0: - resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} - dependencies: - loose-envify: 1.4.0 - dev: false - - /scroll-into-view-if-needed/3.0.4: - resolution: {integrity: sha512-s+/F50jwTOUt+u5oEIAzum9MN2lUQNvWBe/zfEsVQcbaERjGkKLq1s+2wCHkahMLC8nMLbzMVKivx9JhunXaZg==} - dependencies: - compute-scroll-into-view: 2.0.4 - dev: false - - /section-matter/1.0.0: - resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} - engines: {node: '>=4'} - dependencies: - extend-shallow: 2.0.1 - kind-of: 6.0.3 - dev: false - - /shebang-command/1.2.0: - resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} - engines: {node: '>=0.10.0'} - dependencies: - shebang-regex: 1.0.0 - dev: false - - /shebang-regex/1.0.0: - resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} - engines: {node: '>=0.10.0'} - dev: false - - /shiki/0.12.1: - resolution: {integrity: sha512-aieaV1m349rZINEBkjxh2QbBvFFQOlgqYTNtCal82hHj4dDZ76oMlQIX+C7ryerBTDiga3e5NfH6smjdJ02BbQ==} - dependencies: - jsonc-parser: 3.2.0 - vscode-oniguruma: 1.7.0 - vscode-textmate: 8.0.0 - dev: false - - /signal-exit/3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: false - - /slash/3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: false - - /sort-keys/5.0.0: - resolution: {integrity: sha512-Pdz01AvCAottHTPQGzndktFNdbRA75BgOfeT1hH+AMnJFv8lynkPi42rfeEhpx1saTEI3YNMWxfqu0sFD1G8pw==} - engines: {node: '>=12'} - dependencies: - is-plain-obj: 4.1.0 - dev: false - - /source-map-js/1.0.2: - resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} - engines: {node: '>=0.10.0'} - dev: false - - /source-map/0.7.4: - resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} - engines: {node: '>= 8'} - dev: false - - /space-separated-tokens/2.0.2: - resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} - dev: false - - /sprintf-js/1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - dev: false - - /stringify-entities/4.0.3: - resolution: {integrity: sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==} - dependencies: - character-entities-html4: 2.1.0 - character-entities-legacy: 3.0.0 - dev: false - - /strip-bom-string/1.0.0: - resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} - engines: {node: '>=0.10.0'} - dev: false - - /strip-eof/1.0.0: - resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} - engines: {node: '>=0.10.0'} - dev: false - - /style-to-object/0.3.0: - resolution: {integrity: sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==} - dependencies: - inline-style-parser: 0.1.1 - dev: false - - /styled-jsx/5.1.0_react@18.2.0: - resolution: {integrity: sha512-/iHaRJt9U7T+5tp6TRelLnqBqiaIT0HsO0+vgyj8hK2KUk7aejFqRrumqPUlAqDwAj8IbS/1hk3IhBAAK/FCUQ==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@babel/core': '*' - babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' - peerDependenciesMeta: - '@babel/core': - optional: true - babel-plugin-macros: - optional: true - dependencies: - client-only: 0.0.1 - react: 18.2.0 - dev: false - - /supports-color/4.5.0: - resolution: {integrity: sha512-ycQR/UbvI9xIlEdQT1TQqwoXtEldExbCEAJgRo5YXlmSKjv6ThHnP9/vwGa1gr19Gfw+LkFd7KqYMhzrRC5JYw==} - engines: {node: '>=4'} - dependencies: - has-flag: 2.0.0 - dev: false - - /title/3.5.3: - resolution: {integrity: sha512-20JyowYglSEeCvZv3EZ0nZ046vLarO37prvV0mbtQV7C8DJPGgN967r8SJkqd3XK3K3lD3/Iyfp3avjfil8Q2Q==} - hasBin: true - dependencies: - arg: 1.0.0 - chalk: 2.3.0 - clipboardy: 1.2.2 - titleize: 1.0.0 - dev: false - - /titleize/1.0.0: - resolution: {integrity: sha1-fTUHIgYYMLpmF2MeDP0+oIOY2Vo=} - engines: {node: '>=0.10.0'} - dev: false - - /trim-lines/3.0.1: - resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} - dev: false - - /trough/2.1.0: - resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} - dev: false - - /tslib/2.4.1: - resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} - dev: false - - /type-fest/1.4.0: - resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} - engines: {node: '>=10'} - dev: false - - /typescript/4.9.3: - resolution: {integrity: sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==} - engines: {node: '>=4.2.0'} - hasBin: true - dev: true - - /unified/10.1.2: - resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} - dependencies: - '@types/unist': 2.0.6 - bail: 2.0.2 - extend: 3.0.2 - is-buffer: 2.0.5 - is-plain-obj: 4.1.0 - trough: 2.1.0 - vfile: 5.3.6 - dev: false - - /unist-builder/3.0.0: - resolution: {integrity: sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ==} - dependencies: - '@types/unist': 2.0.6 - dev: false - - /unist-util-find-after/4.0.1: - resolution: {integrity: sha512-QO/PuPMm2ERxC6vFXEPtmAutOopy5PknD+Oq64gGwxKtk4xwo9Z97t9Av1obPmGU0IyTa6EKYUfTrK2QJS3Ozw==} - dependencies: - '@types/unist': 2.0.6 - unist-util-is: 5.1.1 - dev: false - - /unist-util-generated/2.0.0: - resolution: {integrity: sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw==} - dev: false - - /unist-util-is/5.1.1: - resolution: {integrity: sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ==} - dev: false - - /unist-util-position-from-estree/1.1.1: - resolution: {integrity: sha512-xtoY50b5+7IH8tFbkw64gisG9tMSpxDjhX9TmaJJae/XuxQ9R/Kc8Nv1eOsf43Gt4KV/LkriMy9mptDr7XLcaw==} - dependencies: - '@types/unist': 2.0.6 - dev: false - - /unist-util-position/4.0.3: - resolution: {integrity: sha512-p/5EMGIa1qwbXjA+QgcBXaPWjSnZfQ2Sc3yBEEfgPwsEmJd8Qh+DSk3LGnmOM4S1bY2C0AjmMnB8RuEYxpPwXQ==} - dependencies: - '@types/unist': 2.0.6 - dev: false - - /unist-util-remove-position/4.0.1: - resolution: {integrity: sha512-0yDkppiIhDlPrfHELgB+NLQD5mfjup3a8UYclHruTJWmY74je8g+CIFr79x5f6AkmzSwlvKLbs63hC0meOMowQ==} - dependencies: - '@types/unist': 2.0.6 - unist-util-visit: 4.1.1 - dev: false - - /unist-util-remove/3.1.1: - resolution: {integrity: sha512-kfCqZK5YVY5yEa89tvpl7KnBBHu2c6CzMkqHUrlOqaRgGOMp0sMvwWOVrbAtj03KhovQB7i96Gda72v/EFE0vw==} - dependencies: - '@types/unist': 2.0.6 - unist-util-is: 5.1.1 - unist-util-visit-parents: 5.1.1 - dev: false - - /unist-util-stringify-position/3.0.2: - resolution: {integrity: sha512-7A6eiDCs9UtjcwZOcCpM4aPII3bAAGv13E96IkawkOAW0OhH+yRxtY0lzo8KiHpzEMfH7Q+FizUmwp8Iqy5EWg==} - dependencies: - '@types/unist': 2.0.6 - dev: false - - /unist-util-visit-parents/4.1.1: - resolution: {integrity: sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw==} - dependencies: - '@types/unist': 2.0.6 - unist-util-is: 5.1.1 - dev: false - - /unist-util-visit-parents/5.1.1: - resolution: {integrity: sha512-gks4baapT/kNRaWxuGkl5BIhoanZo7sC/cUT/JToSRNL1dYoXRFl75d++NkjYk4TAu2uv2Px+l8guMajogeuiw==} - dependencies: - '@types/unist': 2.0.6 - unist-util-is: 5.1.1 - dev: false - - /unist-util-visit/3.1.0: - resolution: {integrity: sha512-Szoh+R/Ll68QWAyQyZZpQzZQm2UPbxibDvaY8Xc9SUtYgPsDzx5AWSk++UUt2hJuow8mvwR+rG+LQLw+KsuAKA==} - dependencies: - '@types/unist': 2.0.6 - unist-util-is: 5.1.1 - unist-util-visit-parents: 4.1.1 - dev: false - - /unist-util-visit/4.1.1: - resolution: {integrity: sha512-n9KN3WV9k4h1DxYR1LoajgN93wpEi/7ZplVe02IoB4gH5ctI1AaF2670BLHQYbwj+pY83gFtyeySFiyMHJklrg==} - dependencies: - '@types/unist': 2.0.6 - unist-util-is: 5.1.1 - unist-util-visit-parents: 5.1.1 - dev: false - - /uvu/0.5.6: - resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==} - engines: {node: '>=8'} - hasBin: true - dependencies: - dequal: 2.0.3 - diff: 5.1.0 - kleur: 4.1.5 - sade: 1.8.1 - dev: false - - /vfile-location/4.0.1: - resolution: {integrity: sha512-JDxPlTbZrZCQXogGheBHjbRWjESSPEak770XwWPfw5mTc1v1nWGLB/apzZxsx8a0SJVfF8HK8ql8RD308vXRUw==} - dependencies: - '@types/unist': 2.0.6 - vfile: 5.3.6 - dev: false - - /vfile-matter/3.0.1: - resolution: {integrity: sha512-CAAIDwnh6ZdtrqAuxdElUqQRQDQgbbIrYtDYI8gCjXS1qQ+1XdLoK8FIZWxJwn0/I+BkSSZpar3SOgjemQz4fg==} - dependencies: - '@types/js-yaml': 4.0.5 - is-buffer: 2.0.5 - js-yaml: 4.1.0 - dev: false - - /vfile-message/3.1.3: - resolution: {integrity: sha512-0yaU+rj2gKAyEk12ffdSbBfjnnj+b1zqTBv3OQCTn8yEB02bsPizwdBPrLJjHnK+cU9EMMcUnNv938XcZIkmdA==} - dependencies: - '@types/unist': 2.0.6 - unist-util-stringify-position: 3.0.2 - dev: false - - /vfile/5.3.6: - resolution: {integrity: sha512-ADBsmerdGBs2WYckrLBEmuETSPyTD4TuLxTrw0DvjirxW1ra4ZwkbzG8ndsv3Q57smvHxo677MHaQrY9yxH8cA==} - dependencies: - '@types/unist': 2.0.6 - is-buffer: 2.0.5 - unist-util-stringify-position: 3.0.2 - vfile-message: 3.1.3 - dev: false - - /vscode-oniguruma/1.7.0: - resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} - dev: false - - /vscode-textmate/8.0.0: - resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} - dev: false - - /web-namespaces/2.0.1: - resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} - dev: false - - /which/1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: false - - /yallist/2.1.2: - resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} - dev: false - - /yocto-queue/0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: false - - /zod/3.20.2: - resolution: {integrity: sha512-1MzNQdAvO+54H+EaK5YpyEy0T+Ejo/7YLHS93G3RnYWh5gaotGHwGeN/ZO687qEDU2y4CdStQYXVHIgrUl5UVQ==} - dev: false - - /zwitch/2.0.4: - resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} - dev: false diff --git a/sdk/typescript/docs/theme.config.tsx b/sdk/typescript/docs/theme.config.tsx index 2db2901904..a04515cd8a 100644 --- a/sdk/typescript/docs/theme.config.tsx +++ b/sdk/typescript/docs/theme.config.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import { DocsThemeConfig, useConfig } from 'nextra-theme-docs'; -import { useRouter } from 'next/router'; +import { DocsThemeConfig } from 'nextra-theme-docs'; +import { Footer } from './components/footer'; const config: DocsThemeConfig = { - logo: Nym Typescript SDK, + logo: Nym TypeScript SDK, project: { link: 'https://github.com/nymtech/nym', }, @@ -12,32 +12,16 @@ const config: DocsThemeConfig = { }, docsRepositoryBase: 'https://github.com/nymtech/nym/tree/develop/sdk/typescript/docs', footer: { - text: 'Nym Typescript SDK', + text: Footer, }, - useNextSeoProps() { - return { - titleTemplate: '%s | Nym Typescript SDK', - }; + darkMode: false, + nextThemes: { + forcedTheme: 'dark', + }, + primaryHue: { + dark: 30, + light: 30, }, - // head: () => { - // const { asPath, defaultLocale, locale } = useRouter(); - // const { frontMatter } = useConfig(); - // const url = `https://nymtech.net/docs/sdk/typescript/${defaultLocale === locale ? asPath : `/${locale}${asPath}`}`; - // - // return ( - // <> - // - // - // - // - // ); - // }, }; export default config; diff --git a/sdk/typescript/docs/tsconfig.json b/sdk/typescript/docs/tsconfig.json index 1563f3e878..5020c55e5a 100644 --- a/sdk/typescript/docs/tsconfig.json +++ b/sdk/typescript/docs/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es5", + "target": "esnext", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, diff --git a/sdk/typescript/docs/typings/txt.d.ts b/sdk/typescript/docs/typings/txt.d.ts new file mode 100644 index 0000000000..c20aff5ada --- /dev/null +++ b/sdk/typescript/docs/typings/txt.d.ts @@ -0,0 +1,5 @@ +declare module '*.txt' { + const content: any; + export default content; + } + \ No newline at end of file diff --git a/sdk/typescript/examples/mix-fetch/browser/README.md b/sdk/typescript/examples/mix-fetch/browser/README.md new file mode 100644 index 0000000000..d76aec193e --- /dev/null +++ b/sdk/typescript/examples/mix-fetch/browser/README.md @@ -0,0 +1,30 @@ +# mixFetch Usage Example + +This is a simple project to show you how to use mixFetch. + +Basic usage is as simple as replacing `fetch` with `mixFetch` in your code: + +```ts +import { mixFetch } from '@nymproject/mix-fetch'; + +// HTTP GET +const response = await mixFetch('https://nymtech.net'); +const html = await response.text(); + +// HTTP POST +const apiResponse = await mixFetch('https://api.example.com', { + method: 'POST', + body: JSON.stringify({ foo: 'bar' }), + headers: { [`Content-Type`]: 'application/json', Authorization: `Bearer ${AUTH_TOKEN}` } +}); +``` + +## Running the example + +``` +npm install +npm run start +``` + +Open a browser at http://localhost:1234 and as the example loads, a connection will be made to the Nym Mixnet +and a text file and image will be downloaded and displayed in the browser. diff --git a/sdk/typescript/examples/mix-fetch/browser/package.json b/sdk/typescript/examples/mix-fetch/browser/package.json new file mode 100644 index 0000000000..7d6f737298 --- /dev/null +++ b/sdk/typescript/examples/mix-fetch/browser/package.json @@ -0,0 +1,15 @@ +{ + "name": "@nymproject/mix-fetch-example-parcel", + "version": "1.0.0", + "license": "Apache-2.0", + "source": "src/index.html", + "dependencies": { + "parcel": "^2.9.3", + "@nymproject/mix-fetch": ">=1.2.0-rc.7 || ^1" + }, + "scripts": { + "start": "parcel --no-cache", + "build": "parcel build --no-cache --no-content-hash", + "serve": "serve dist" + } +} diff --git a/sdk/typescript/examples/mix-fetch/browser/src/index.html b/sdk/typescript/examples/mix-fetch/browser/src/index.html new file mode 100644 index 0000000000..564a10a1a6 --- /dev/null +++ b/sdk/typescript/examples/mix-fetch/browser/src/index.html @@ -0,0 +1,23 @@ + + + + + + + Internal Tester + + + + + +

mixFetch

+

+
+ + + diff --git a/sdk/typescript/examples/mix-fetch/browser/src/index.ts b/sdk/typescript/examples/mix-fetch/browser/src/index.ts new file mode 100644 index 0000000000..6680813059 --- /dev/null +++ b/sdk/typescript/examples/mix-fetch/browser/src/index.ts @@ -0,0 +1,46 @@ +import { mixFetch } from '@nymproject/mix-fetch'; +import { appendOutput, appendImageOutput } from './utils'; + +async function main() { + // options for mixFetch (you can also set these with the `createMixFetch` function + const mixFetchOptions = { + preferredGateway: 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM', // with WSS + preferredNetworkRequester: + 'GiRjFWrMxt58pEMuusm4yT3RxoMD1MMPrR9M2N4VWRJP.3CNZBPq4vg7v7qozjGjdPMXcvDmkbWPCgbGCjQVw9n6Z@2xU4CBE6QiiYt6EyBXSALwxkNvM7gqJfjHXaMkjiFmYW', + mixFetchOverride: { + requestTimeoutMs: 60_000, + }, + }; + + // disable CORS (in your app, you probably don't want to disable CORS, it is a good thing to leave it enabled) + const args = { mode: 'unsafe-ignore-cors' }; + + // this is the URL of standard list of allow hosts the you can request data from with mixFetch and the Nym SOCKS5 + // client - you can request to have more hosts added by getting in touch on Discord or Telegram + let url = 'https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt'; + + appendOutput('Get a text file:'); + appendOutput(`Downloading ${url}...\n`); + let resp = await mixFetch(url, args, mixFetchOptions); // NB: you only need to pass options to the 1st call + console.log({ resp }); + + const text = await resp.text(); + appendOutput(text); + + // get an image + appendOutput('\nGet an image:\n'); + url = 'https://nymtech.net/favicon.svg'; + resp = await mixFetch(url, args); + console.log({ resp }); + + const buffer = await resp.arrayBuffer(); + const type = resp.headers.get('Content-Type') || 'image/svg'; + const blobUrl = URL.createObjectURL(new Blob([buffer], { type })); + appendImageOutput(blobUrl); +} + +// wait for the html to load +window.addEventListener('DOMContentLoaded', () => { + // let's do this! + main(); +}); diff --git a/sdk/typescript/examples/mix-fetch/browser/src/utils.ts b/sdk/typescript/examples/mix-fetch/browser/src/utils.ts new file mode 100644 index 0000000000..4935229eb7 --- /dev/null +++ b/sdk/typescript/examples/mix-fetch/browser/src/utils.ts @@ -0,0 +1,12 @@ +export function appendOutput(value: string) { + const el = document.getElementById('output') as HTMLPreElement; + const text = document.createTextNode(`${value}\n`); + el.appendChild(text); +} + +export function appendImageOutput(url: string) { + const el = document.getElementById('outputImage') as HTMLPreElement; + const imgNode = document.createElement('img'); + imgNode.src = url; + el.appendChild(imgNode); +} diff --git a/sdk/typescript/packages/.gitignore b/sdk/typescript/packages/.gitignore new file mode 100644 index 0000000000..d8f8d46921 --- /dev/null +++ b/sdk/typescript/packages/.gitignore @@ -0,0 +1 @@ +docs diff --git a/sdk/typescript/packages/mix-fetch/README-CommonJS-full-fat.md b/sdk/typescript/packages/mix-fetch/README-CommonJS-full-fat.md index d22f063aeb..a8c0c858dc 100644 --- a/sdk/typescript/packages/mix-fetch/README-CommonJS-full-fat.md +++ b/sdk/typescript/packages/mix-fetch/README-CommonJS-full-fat.md @@ -5,12 +5,10 @@ This package is a drop-in replacement for `fetch` to send HTTP requests over the ## Usage ```js -const { createMixFetch } = require('@nymproject/mix-fetch'); +const { mixFetch } = require('@nymproject/mix-fetch'); ... -const mixFetch = await createMixFetch(); - const response = await mixFetch('https://nymtech.net'); const html = await response.text(); ``` diff --git a/sdk/typescript/packages/mix-fetch/README-CommonJS.md b/sdk/typescript/packages/mix-fetch/README-CommonJS.md index d22f063aeb..a8c0c858dc 100644 --- a/sdk/typescript/packages/mix-fetch/README-CommonJS.md +++ b/sdk/typescript/packages/mix-fetch/README-CommonJS.md @@ -5,12 +5,10 @@ This package is a drop-in replacement for `fetch` to send HTTP requests over the ## Usage ```js -const { createMixFetch } = require('@nymproject/mix-fetch'); +const { mixFetch } = require('@nymproject/mix-fetch'); ... -const mixFetch = await createMixFetch(); - const response = await mixFetch('https://nymtech.net'); const html = await response.text(); ``` diff --git a/sdk/typescript/packages/mix-fetch/README-full-fat.md b/sdk/typescript/packages/mix-fetch/README-full-fat.md index abb83e2a20..afe683d42f 100644 --- a/sdk/typescript/packages/mix-fetch/README-full-fat.md +++ b/sdk/typescript/packages/mix-fetch/README-full-fat.md @@ -5,12 +5,10 @@ This package is a drop-in replacement for `fetch` to send HTTP requests over the ## Usage ```js -import { createMixFetch } from '@nymproject/mix-fetch'; +import { mixFetch } from '@nymproject/mix-fetch'; ... -const mixFetch = await createMixFetch(); - const response = await mixFetch('https://nymtech.net'); const html = await response.text(); ``` diff --git a/sdk/typescript/packages/mix-fetch/README.md b/sdk/typescript/packages/mix-fetch/README.md index 8772e69ffd..f2f7b92879 100644 --- a/sdk/typescript/packages/mix-fetch/README.md +++ b/sdk/typescript/packages/mix-fetch/README.md @@ -7,12 +7,10 @@ This package is a drop-in replacement for `fetch` to send HTTP requests over the Use `mixFetch` in your own project with: ```js -import { createMixFetch } from '@nymproject/mix-fetch'; +import { mixFetch } from '@nymproject/mix-fetch'; ... -const mixFetch = await createMixFetch(); - const response = await mixFetch('https://nymtech.net'); const html = await response.text(); ``` diff --git a/sdk/typescript/packages/mix-fetch/internal-dev/README.md b/sdk/typescript/packages/mix-fetch/internal-dev/README.md index 21c25c7d90..3ef80f55ea 100644 --- a/sdk/typescript/packages/mix-fetch/internal-dev/README.md +++ b/sdk/typescript/packages/mix-fetch/internal-dev/README.md @@ -26,7 +26,7 @@ yarn start Or do a single build: ``` -yarn build:dev:esm +yarn build:dev:esm-no-inline ``` Then, in another terminal: diff --git a/sdk/typescript/packages/mix-fetch/internal-dev/package.json b/sdk/typescript/packages/mix-fetch/internal-dev/package.json index 549143b0d1..6ea459f549 100644 --- a/sdk/typescript/packages/mix-fetch/internal-dev/package.json +++ b/sdk/typescript/packages/mix-fetch/internal-dev/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "license": "Apache-2.0", "dependencies": { - "@nymproject/mix-fetch": ">=1.2.0-rc.2 || ^1" + "@nymproject/mix-fetch": ">=1.2.0-rc.7 || ^1" }, "devDependencies": { "@babel/core": "^7.22.10", diff --git a/sdk/typescript/packages/mix-fetch/internal-dev/parcel/package.json b/sdk/typescript/packages/mix-fetch/internal-dev/parcel/package.json index d0ae96d225..886012198e 100644 --- a/sdk/typescript/packages/mix-fetch/internal-dev/parcel/package.json +++ b/sdk/typescript/packages/mix-fetch/internal-dev/parcel/package.json @@ -4,7 +4,7 @@ "license": "Apache-2.0", "source": "../src/index.html", "dependencies": { - "@nymproject/mix-fetch": ">=1.2.0-rc.2 || ^1" + "@nymproject/mix-fetch": ">=1.2.0-rc.7 || ^1" }, "scripts": { "start": "npx parcel --no-cache", diff --git a/sdk/typescript/packages/mix-fetch/internal-dev/src/index.ts b/sdk/typescript/packages/mix-fetch/internal-dev/src/index.ts index d6804dbd4d..d6c3795331 100644 --- a/sdk/typescript/packages/mix-fetch/internal-dev/src/index.ts +++ b/sdk/typescript/packages/mix-fetch/internal-dev/src/index.ts @@ -1,4 +1,4 @@ -import { createMixFetch } from '@nymproject/mix-fetch'; +import { createMixFetch, disconnectMixFetch } from '@nymproject/mix-fetch'; function appendOutput(value: string) { const el = document.getElementById('output') as HTMLPreElement; @@ -54,8 +54,12 @@ async function main() { appendOutput(JSON.stringify(resp, null, 2)); appendOutput(JSON.stringify({ text }, null, 2)); + console.log('disconnecting'); + await disconnectMixFetch(); + console.log('disconnected! all further usages should fail'); + // get an image - url = 'https://nymtech.net/images/token/pie-classic-2.svg'; + url = 'https://nymtech.net/favicon.svg'; resp = await mixFetch(url, args); console.log({ resp }); const buffer = await resp.arrayBuffer(); diff --git a/sdk/typescript/packages/mix-fetch/package.json b/sdk/typescript/packages/mix-fetch/package.json index e5779983e3..49c51d05da 100644 --- a/sdk/typescript/packages/mix-fetch/package.json +++ b/sdk/typescript/packages/mix-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/mix-fetch", - "version": "1.2.0-rc.2", + "version": "1.2.0-rc.9", "description": "This package is a drop-in replacement for `fetch` to send HTTP requests over the Nym Mixnet.", "license": "Apache-2.0", "author": "Nym Technologies SA", @@ -17,6 +17,7 @@ "build:dev:esm": "MIX_FETCH_DEV_MODE=true scripts/build-dev-esm.sh", "build:dev:esm-no-inline": "scripts/build-dev-esm.sh", "build:worker": "rollup -c rollup-worker.config.mjs", + "build:worker:full-fat": "rollup -c rollup-worker-full-fat.config.mjs", "clean": "rimraf dist", "docs:dev": "run-p docs:watch docs:serve ", "docs:generate": "typedoc", @@ -32,7 +33,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/mix-fetch-wasm": ">=1.2.0-rc.0 || 1", + "@nymproject/mix-fetch-wasm": ">=1.2.0-rc.7 || 1", "comlink": "^4.3.1" }, "devDependencies": { @@ -80,4 +81,4 @@ "private": false, "type": "module", "types": "./dist/esm/index.d.ts" -} +} \ No newline at end of file diff --git a/sdk/typescript/packages/mix-fetch/rollup-worker-full-fat.config.mjs b/sdk/typescript/packages/mix-fetch/rollup-worker-full-fat.config.mjs new file mode 100644 index 0000000000..1c56e076e8 --- /dev/null +++ b/sdk/typescript/packages/mix-fetch/rollup-worker-full-fat.config.mjs @@ -0,0 +1,8 @@ +import { getConfig } from './rollup/worker.mjs'; + +export default { + ...getConfig({ + inlineWasm: true, + format: 'cjs', + }), +}; diff --git a/sdk/typescript/packages/mix-fetch/rollup-worker.config.mjs b/sdk/typescript/packages/mix-fetch/rollup-worker.config.mjs index 54d6fd774b..b3207449b7 100644 --- a/sdk/typescript/packages/mix-fetch/rollup-worker.config.mjs +++ b/sdk/typescript/packages/mix-fetch/rollup-worker.config.mjs @@ -1,37 +1,5 @@ -import typescript from '@rollup/plugin-typescript'; -import resolve from '@rollup/plugin-node-resolve'; -import { wasm } from '@rollup/plugin-wasm'; -import replace from '@rollup/plugin-replace'; - -const extensions = ['.js', '.jsx', '.ts', '.tsx']; +import { getConfig } from './rollup/worker.mjs'; export default { - input: 'src/worker/index.ts', - output: { - dir: 'dist', - format: process.env.MIX_FETCH_BUNDLE_INLINE_WORKER === true ? 'cjs' : 'es', - // format: 'cjs', - }, - plugins: [ - resolve({ extensions }), - // this is some nasty monkey patching that removes the WASM URL (because it is handled by the `wasm` plugin) - replace({ - values: { "input = new URL('mix_fetch_wasm_bg.wasm', import.meta.url);": 'input = undefined;' }, - delimiters: ['', ''], - preventAssignment: true, - }), - wasm({ - targetEnv: 'browser', - fileName: '[name].wasm', - // force the wasm plugin to embed the wasm bundle - this means no downstream bundlers have to worry about handling it - maxFileSize: process.env.MIX_FETCH_BUNDLE_INLINE_WASM === 'true' ? 10000000 : undefined, - }), - typescript({ - compilerOptions: { - declaration: false, - target: process.env.MIX_FETCH_BUNDLE_INLINE_WORKER === true ? 'es5' : 'es6', - // target: 'es5', - }, - }), - ], + ...getConfig(), }; diff --git a/sdk/typescript/packages/mix-fetch/rollup/esm.mjs b/sdk/typescript/packages/mix-fetch/rollup/esm.mjs index e2b5efea66..ebb886839b 100644 --- a/sdk/typescript/packages/mix-fetch/rollup/esm.mjs +++ b/sdk/typescript/packages/mix-fetch/rollup/esm.mjs @@ -23,12 +23,16 @@ export const getConfig = (opts) => ({ replace({ // when loading the web worker as a full ES module, tell pass `new Worker({ type: 'module'})` to tell // the browser to load and allow imports inside the worker code. Also load as a URL so relative paths work. - values: opts.inline - ? undefined - : { - "createURLWorkerFactory('web-worker-0.js')": - "createURLWorkerFactory(new URL('web-worker-0.js', import.meta.url))", - }, + // values: opts.inline + // ? undefined + // : { + // "createURLWorkerFactory('web-worker-0.js')": + // "createURLWorkerFactory(new URL('web-worker-0.js', import.meta.url))", + // }, + values: { + "createURLWorkerFactory('web-worker-0.js')": + "createURLWorkerFactory(new URL('web-worker-0.js', import.meta.url))", + }, delimiters: ['', ''], preventAssignment: true, }), diff --git a/sdk/typescript/packages/mix-fetch/rollup-worker-new.config.mjs b/sdk/typescript/packages/mix-fetch/rollup/worker.mjs similarity index 56% rename from sdk/typescript/packages/mix-fetch/rollup-worker-new.config.mjs rename to sdk/typescript/packages/mix-fetch/rollup/worker.mjs index 54d6fd774b..82c7761417 100644 --- a/sdk/typescript/packages/mix-fetch/rollup-worker-new.config.mjs +++ b/sdk/typescript/packages/mix-fetch/rollup/worker.mjs @@ -5,12 +5,19 @@ import replace from '@rollup/plugin-replace'; const extensions = ['.js', '.jsx', '.ts', '.tsx']; -export default { +/** + * Configure worker output + * + * @param opts + * `format`: `es` or `cjs`, + * `inlineWasm`: true or false, + * `tsTarget`: `es5` or `es6` + */ +export const getConfig = (opts) => ({ input: 'src/worker/index.ts', output: { dir: 'dist', - format: process.env.MIX_FETCH_BUNDLE_INLINE_WORKER === true ? 'cjs' : 'es', - // format: 'cjs', + format: opts?.format || 'es', }, plugins: [ resolve({ extensions }), @@ -20,18 +27,17 @@ export default { delimiters: ['', ''], preventAssignment: true, }), - wasm({ - targetEnv: 'browser', - fileName: '[name].wasm', - // force the wasm plugin to embed the wasm bundle - this means no downstream bundlers have to worry about handling it - maxFileSize: process.env.MIX_FETCH_BUNDLE_INLINE_WASM === 'true' ? 10000000 : undefined, - }), + opts?.inlineWasm === true + ? wasm({ maxFileSize: 10_000_000, targetEnv: 'browser' }) // force the wasm plugin to embed the wasm bundle - this means no downstream bundlers have to worry about handling it + : wasm({ + targetEnv: 'browser', + fileName: '[name].wasm', + }), typescript({ compilerOptions: { declaration: false, - target: process.env.MIX_FETCH_BUNDLE_INLINE_WORKER === true ? 'es5' : 'es6', - // target: 'es5', + target: opts?.tsTarget || 'es6', }, }), ], -}; +}); diff --git a/sdk/typescript/packages/mix-fetch/scripts/build.sh b/sdk/typescript/packages/mix-fetch/scripts/build.sh index 14aeba0085..ab9bd0aec8 100755 --- a/sdk/typescript/packages/mix-fetch/scripts/build.sh +++ b/sdk/typescript/packages/mix-fetch/scripts/build.sh @@ -31,6 +31,9 @@ mv dist/*.wasm dist/worker # build the SDK as a ESM bundle rollup -c rollup-esm.config.mjs +# move WASM files into place +cp dist/worker/*.wasm dist/esm + #------------------------------------------------------- # COMMON JS #------------------------------------------------------- @@ -41,9 +44,24 @@ rollup -c rollup-esm.config.mjs rollup -c rollup-cjs.config.mjs # move WASM files into place -cp dist/worker/*.wasm dist/esm +cp dist/worker/*.wasm dist/cjs node scripts/postBuildReplace.mjs dist +#------------------------------------------------------- +# WEB WORKER (full-fat) +#------------------------------------------------------- + +# build the worker +rollup -c rollup-worker-full-fat.config.mjs + +# move it next to the Typescript `src/index.ts` so it can be inlined by rollup +rm -f src/worker/*.js +rm -f src/worker/*.wasm +mv dist/index.js src/worker/worker.js + +# move WASM files out of build area +mkdir -p dist/worker + #------------------------------------------------------- # ESM (full-fat) #------------------------------------------------------- diff --git a/sdk/typescript/packages/mix-fetch/scripts/postBuildReplace.mjs b/sdk/typescript/packages/mix-fetch/scripts/postBuildReplace.mjs index f3e307c96a..39d6546b9f 100644 --- a/sdk/typescript/packages/mix-fetch/scripts/postBuildReplace.mjs +++ b/sdk/typescript/packages/mix-fetch/scripts/postBuildReplace.mjs @@ -22,6 +22,12 @@ console.log(`Replacing files in "${path.resolve(basePathToFindFilesIn)}"...`); Object.keys(replaceConfig).forEach((filename) => { const absFilename = path.resolve(basePathToFindFilesIn, filename); + + if (!fs.existsSync(absFilename)) { + console.log(`Skipping replacing ${filename} as does not exist`); + return; + } + const content = fs.readFileSync(absFilename).toString(); console.log(`Replacing values in "${absFilename}"...`); diff --git a/sdk/typescript/packages/mix-fetch/src/create-mix-fetch.ts b/sdk/typescript/packages/mix-fetch/src/create-mix-fetch.ts index d45b74704e..9739042932 100644 --- a/sdk/typescript/packages/mix-fetch/src/create-mix-fetch.ts +++ b/sdk/typescript/packages/mix-fetch/src/create-mix-fetch.ts @@ -70,6 +70,7 @@ export const createMixFetch = async (): Promise => { const body = Object.values(workerResponse.body)[0]; // we are expecting only one value to be set in `.body` return new Response(body, { headers, status, statusText }); }, + disconnectMixFetch: wrappedWorker.disconnectMixFetch, }; return mixFetchWebWorker; diff --git a/sdk/typescript/packages/mix-fetch/src/index.ts b/sdk/typescript/packages/mix-fetch/src/index.ts index 701b30daa6..9b60a5977e 100644 --- a/sdk/typescript/packages/mix-fetch/src/index.ts +++ b/sdk/typescript/packages/mix-fetch/src/index.ts @@ -2,6 +2,9 @@ import type { SetupMixFetchOps, IMixFetchFn, IMixFetch } from './types'; import { createMixFetch as createMixFetchInternal } from './create-mix-fetch'; +// this is the default timeout for getting a response +const REQUEST_TIMEOUT_MILLISECONDS = 60_000; + export * from './types'; declare global { @@ -19,10 +22,20 @@ declare global { * @param opts Optional settings */ export const createMixFetch = async (opts?: SetupMixFetchOps) => { + if (!window) { + throw new Error('`window` is not defined'); + } + if (!window.__mixFetchGlobal) { // load the worker and set up mixFetch with defaults window.__mixFetchGlobal = await createMixFetchInternal(); await window.__mixFetchGlobal.setupMixFetch(opts); + + window.onunload = async () => { + if (window.__mixFetchGlobal) { + await window.__mixFetchGlobal.disconnectMixFetch(); + } + }; } return window.__mixFetchGlobal; }; @@ -32,11 +45,35 @@ export const createMixFetch = async (opts?: SetupMixFetchOps) => { * * @param url The URL to fetch from. * @param args Fetch options. + * @param opts Optionally configure mixFetch when it gets created. This only happens once, the first time it gets used. */ -export const mixFetch: IMixFetchFn = async (url, args) => { +export const mixFetch: IMixFetchFn = async (url, args, opts?: SetupMixFetchOps) => { // ensure mixFetch instance exists - const instance = await createMixFetch(); + const instance = await createMixFetch({ + mixFetchOverride: { + requestTimeoutMs: REQUEST_TIMEOUT_MILLISECONDS, + }, + ...opts, + }); // execute user request return instance.mixFetch(url, args); }; + +/** + * Stops the usage of mixFetch and disconnect the client from the mixnet. + */ +export const disconnectMixFetch = async (): Promise => { + if (!window) { + throw new Error('`window` is not defined'); + } + + // JS: I'm ignoring this lint (no-else-return) because I want to explicitly state + // that `__mixFetchGlobal` is definitely not null in the else branch. + if (!window.__mixFetchGlobal) { + throw new Error("mixFetch hasn't been setup"); + // eslint-disable-next-line no-else-return + } else { + return window.__mixFetchGlobal.disconnectMixFetch(); + } +}; diff --git a/sdk/typescript/packages/mix-fetch/src/types.ts b/sdk/typescript/packages/mix-fetch/src/types.ts index 56aa56cb96..553c02cc09 100644 --- a/sdk/typescript/packages/mix-fetch/src/types.ts +++ b/sdk/typescript/packages/mix-fetch/src/types.ts @@ -3,7 +3,7 @@ import type { MixFetchOpts } from '@nymproject/mix-fetch-wasm'; type IMixFetchWorkerFn = (url: string, args: any) => Promise; // export type IMixFetchFn = typeof fetch; -export type IMixFetchFn = (url: string, args: any) => Promise; +export type IMixFetchFn = (url: string, args: any, opts?: SetupMixFetchOps) => Promise; export type SetupMixFetchOps = MixFetchOpts & { responseBodyConfigMap?: ResponseBodyConfigMap; @@ -12,11 +12,13 @@ export type SetupMixFetchOps = MixFetchOpts & { export interface IMixFetchWebWorker { mixFetch: IMixFetchWorkerFn; setupMixFetch: (opts?: SetupMixFetchOps) => Promise; + disconnectMixFetch: () => Promise; } export interface IMixFetch { mixFetch: IMixFetchFn; setupMixFetch: (opts?: SetupMixFetchOps) => Promise; + disconnectMixFetch: () => Promise; } export enum EventKinds { @@ -77,8 +79,8 @@ export interface ResponseBodyConfigMap { */ export const ResponseBodyConfigMapDefaults: ResponseBodyConfigMap = { uint8array: ['application/octet-stream'], - json: ['application/json', 'text/json'], - text: ['text/plain', /test\/plain\+.*/, 'text/html', /test\/html\+.*/], + json: ['application/json', 'text/json', /application\/json.*/, /text\/json\+.*/], + text: ['text/plain', /text\/plain.*/, 'text/html', /text\/html.*/], formData: ['application/x-www-form-urlencoded', 'multipart/form-data'], blob: [/image\/.*/, /video\/.*/], fallback: 'blob', diff --git a/sdk/typescript/packages/mix-fetch/src/worker/handle-response-mime-types.test.ts b/sdk/typescript/packages/mix-fetch/src/worker/handle-response-mime-types.test.ts index 68c96e4999..eb29ae5bba 100644 --- a/sdk/typescript/packages/mix-fetch/src/worker/handle-response-mime-types.test.ts +++ b/sdk/typescript/packages/mix-fetch/src/worker/handle-response-mime-types.test.ts @@ -13,6 +13,27 @@ describe('handleResponseMimeTypes', () => { ); expect(resp.text).toBe(TEXT); }); + test('handles text (charset=utf-8)', async () => { + const TEXT = 'This is text'; + const resp = await handleResponseMimeTypes( + new Response(TEXT, { headers: new Headers([['Content-Type', 'text/plain; charset=utf-8']]) }), + ); + expect(resp.text).toBe(TEXT); + }); + test('handles html', async () => { + const TEXT = 'This is html'; + const resp = await handleResponseMimeTypes( + new Response(TEXT, { headers: new Headers([['Content-Type', 'text/html']]) }), + ); + expect(resp.text).toBe(TEXT); + }); + test('handles html (charset=utf-8)', async () => { + const TEXT = 'This is html'; + const resp = await handleResponseMimeTypes( + new Response(TEXT, { headers: new Headers([['Content-Type', 'text/html; charset=utf-8']]) }), + ); + expect(resp.text).toBe(TEXT); + }); test('handles images', async () => { const DATA = new Uint8Array([0, 1, 2, 3]).buffer; const resp = await handleResponseMimeTypes( @@ -42,4 +63,11 @@ describe('handleResponseMimeTypes', () => { ); expect(resp.text).toBe(json); }); + test('handles JSON data (charset=utf-8)', async () => { + const json = '{ "foo": "bar", "baz": 42 }'; + const resp = await handleResponseMimeTypes( + new Response(json, { headers: new Headers([['Content-Type', 'application/json; charset=utf-8']]) }), + ); + expect(resp.text).toBe(json); + }); }); diff --git a/sdk/typescript/packages/mix-fetch/src/worker/main.ts b/sdk/typescript/packages/mix-fetch/src/worker/main.ts index fee270b055..f126f68bb8 100644 --- a/sdk/typescript/packages/mix-fetch/src/worker/main.ts +++ b/sdk/typescript/packages/mix-fetch/src/worker/main.ts @@ -1,5 +1,5 @@ /* eslint-disable no-restricted-globals */ -import { setupMixFetch } from '@nymproject/mix-fetch-wasm'; +import { setupMixFetch, disconnectMixFetch } from '@nymproject/mix-fetch-wasm'; import * as Comlink from 'comlink'; import type { IMixFetchWebWorker, LoadedEvent } from '../types'; import { EventKinds, ResponseBodyConfigMap, ResponseBodyConfigMapDefaults } from '../types'; @@ -53,6 +53,11 @@ export async function run() { } await setupMixFetch(opts || {}); }, + disconnectMixFetch: async () => { + console.log('[Worker] --- disconnectMixFetch ---'); + + await disconnectMixFetch(); + }, }; // start comlink listening for messages and handle them above diff --git a/sdk/typescript/packages/node-tester/package.json b/sdk/typescript/packages/node-tester/package.json index 33ab25cbbf..4a52628bb1 100644 --- a/sdk/typescript/packages/node-tester/package.json +++ b/sdk/typescript/packages/node-tester/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/node-tester", - "version": "1.2.0-rc.2", + "version": "1.2.0-rc.9", "description": "This package provides a tester that can send test packets to mixnode that is part of the Nym Mixnet.", "license": "Apache-2.0", "author": "Nym Technologies SA", @@ -25,7 +25,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/nym-node-tester-wasm": ">=1.2.0-rc.0 || ^1", + "@nymproject/nym-node-tester-wasm": ">=1.2.0-rc.7 || ^1", "comlink": "^4.3.1" }, "devDependencies": { diff --git a/sdk/typescript/packages/nodejs-client/.eslintrc.json b/sdk/typescript/packages/nodejs-client/.eslintrc.json new file mode 100644 index 0000000000..83e95d88a7 --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "parserOptions": { + "project": "./tsconfig.eslint.json" + } +} diff --git a/sdk/typescript/packages/nodejs-client/package.json b/sdk/typescript/packages/nodejs-client/package.json new file mode 100644 index 0000000000..906a603198 --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/package.json @@ -0,0 +1,80 @@ +{ + "name": "@nymproject/nodejs-client", + "version": "1.2.0-rc.5", + "license": "Apache-2.0", + "author": "Nym Technologies SA", + "files": [ + "dist/**/*" + ], + "main": "dist/index.mjs", + "scripts": { + "build": "scripts/build-prod.sh", + "build:dev": "scripts/build.sh", + "build:dev:esm": "scripts/build-dev-esm.sh", + "build:worker": "rollup -c rollup-worker.config.mjs", + "clean": "rimraf dist", + "docs:dev": "run-p docs:watch docs:serve ", + "docs:generate": "typedoc", + "docs:generate:prod": "typedoc --basePath ./docs/tsdoc/nymproject/sdk/", + "docs:prod:build": "scripts/build-prod-docs-collect.sh", + "docs:serve": "reload -b -d ./docs -p 3000", + "docs:watch": "nodemon --ext ts --watch './src/**/*' --watch './typedoc.json' --exec \"yarn docs:generate\"", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "start": "tsc -w", + "start:dev": "nodemon --watch src -e ts,json --exec 'yarn build:dev:esm'", + "test": "node --experimental-vm-modules --no-warnings node_modules/jest/bin/jest.js -c=jest.config.mjs --no-cache", + "tsc": "tsc --noEmit true" + }, + "dependencies": { + "@nymproject/nym-client-wasm-node": ">=1.2.0-rc.7 || ^1", + "comlink": "^4.3.1" + }, + "devDependencies": { + "@babel/core": "^7.15.0", + "@babel/plugin-transform-async-to-generator": "^7.14.5", + "@babel/preset-env": "^7.15.0", + "@babel/preset-react": "^7.14.5", + "@babel/preset-typescript": "^7.15.0", + "@nymproject/eslint-config-react-typescript": "^1.0.0", + "@rollup/plugin-commonjs": "^24.0.1", + "@rollup/plugin-inject": "^5.0.3", + "@rollup/plugin-json": "^6.0.0", + "@rollup/plugin-node-resolve": "^15.0.1", + "@rollup/plugin-replace": "^5.0.2", + "@rollup/plugin-terser": "^0.2.1", + "@rollup/plugin-typescript": "^10.0.1", + "@rollup/plugin-url": "^8.0.1", + "@rollup/plugin-wasm": "^6.1.1", + "@types/jest": "^27.0.1", + "@types/node": "^16.7.13", + "@typescript-eslint/eslint-plugin": "^5.13.0", + "@typescript-eslint/parser": "^5.13.0", + "eslint": "^8.10.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-config-airbnb-typescript": "^16.1.0", + "eslint-config-prettier": "^8.5.0", + "eslint-import-resolver-root-import": "^1.0.4", + "eslint-plugin-import": "^2.25.4", + "eslint-plugin-jest": "^26.1.1", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-prettier": "^4.0.0", + "eslint-plugin-react": "^7.29.2", + "eslint-plugin-react-hooks": "^4.3.0", + "handlebars": "^4.7.8", + "jest": "^29.5.0", + "nodemon": "3.0.1", + "reload": "^3.2.1", + "rimraf": "^3.0.2", + "rollup": "^3.9.1", + "rollup-plugin-base64": "^1.0.1", + "rollup-plugin-web-worker-loader": "^1.6.1", + "ts-jest": "^29.1.0", + "ts-loader": "^9.4.2", + "typedoc": "^0.24.8", + "typescript": "^4.8.4" + }, + "private": false, + "type": "module", + "types": "./dist/index.d.ts" +} diff --git a/sdk/typescript/packages/nodejs-client/scripts/build-prod-docs-collect.sh b/sdk/typescript/packages/nodejs-client/scripts/build-prod-docs-collect.sh new file mode 100755 index 0000000000..9cd137bcde --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/scripts/build-prod-docs-collect.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +rm -rf ../../../../dist/ts/docs/tsdoc/nymproject/sdk || true + +# run the build +yarn docs:generate:prod + +# move the output outside of the yarn/npm workspaces +mkdir -p ../../../../dist/ts/docs/tsdoc/nymproject +mv docs ../../../../dist/ts/docs/tsdoc/nymproject/sdk + +echo "Output can be found in:" +realpath ../../../../dist/ts/docs/tsdoc/nymproject/sdk diff --git a/sdk/typescript/packages/nodejs-client/src/index.ts b/sdk/typescript/packages/nodejs-client/src/index.ts new file mode 100644 index 0000000000..e124b7136c --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/src/index.ts @@ -0,0 +1,131 @@ +import * as Comlink from 'comlink'; +import InlineWasmWebWorker from 'web-worker:./worker'; +import { + BinaryMessageReceivedEvent, + ConnectedEvent, + EventKinds, + IWebWorker, + Client, + Events, + LoadedEvent, + MimeTypes, + RawMessageReceivedEvent, + StringMessageReceivedEvent, +} from './types'; +import { createSubscriptions } from './subscriptions'; + +/** + * Options for the Nym mixnet client. + * @property autoConvertStringMimeTypes - An array of mime types. + * @example + * ```typescript + * const client = await createNymMixnetClient({ + * autoConvertStringMimeTypes: [MimeTypes.ApplicationJson, MimeTypes.TextPlain], + * }); + * ``` + */ + +export interface NymMixnetClientOptions { + autoConvertStringMimeTypes?: string[] | MimeTypes[]; +} + +/** + * The client for the Nym mixnet which gives access to client methods and event subscriptions. + * Returned by the {@link createNymMixnetClient} function. + * + */ +export interface NymMixnetClient { + client: Client; + events: Events; +} + +/** + * Create a client to send and receive traffic from the Nym mixnet. + * @required + * @returns + * @example + * ```typescript + * const client = await createNymMixnetClient(); + * ``` + */ +export const createNymMixnetClient = async (options?: NymMixnetClientOptions): Promise => { + // create a web worker that runs the WASM client on another thread and wait until it signals that it is ready + // eslint-disable-next-line @typescript-eslint/no-use-before-define + const worker = await createWorker(); + + const subscriptions = createSubscriptions(); + const { getSubscriptions, addSubscription } = subscriptions; + + // listen to messages from the worker, parse them and let the subscribers handle them, catching any unhandled exceptions + worker.addEventListener('message', (msg) => { + if (msg.data && msg.data.kind) { + const subscribers = getSubscriptions(msg.data.kind); + (subscribers || []).forEach((s) => { + try { + // let the subscriber handle the message + s(msg.data); + } catch (e) { + // eslint-disable-next-line no-console + console.error('Unhandled error in event handler', msg.data, e); + } + }); + } + }); + + // manage the subscribers, returning self-unsubscribe methods + const events: Events = { + subscribeToConnected: (handler) => addSubscription(EventKinds.Connected, handler), + subscribeToLoaded: (handler) => addSubscription(EventKinds.Loaded, handler), + subscribeToTextMessageReceivedEvent: (handler) => + addSubscription(EventKinds.StringMessageReceived, handler), + subscribeToBinaryMessageReceivedEvent: (handler) => + addSubscription(EventKinds.BinaryMessageReceived, handler), + subscribeToRawMessageReceivedEvent: (handler) => + addSubscription(EventKinds.RawMessageReceived, handler), + }; + + // let comlink handle interop with the web worker + const client: Client = Comlink.wrap(worker); + + // set any options + if (options?.autoConvertStringMimeTypes) { + await client.setTextMimeTypes(options.autoConvertStringMimeTypes); + } else { + // set some sensible defaults for text mime types + await client.setTextMimeTypes([MimeTypes.ApplicationJson, MimeTypes.TextPlain]); + } + + // pass the client interop and subscription manage back to the caller + return { + client, + events, + }; +}; + +/** + * Async method to create a web worker that runs the Nym client on another thread. It will only return once the worker + * has passed back a `Loaded` event to the calling thread. + * + * @return The instance of the web worker. + */ +const createWorker = async () => + new Promise((resolve, reject) => { + // rollup will inline the built worker script, so that when the SDK is used in + // other projects, they will not need to mess around trying to bundle it + // however, it will make this SDK bundle bigger because of Base64 inline data + const worker = new InlineWasmWebWorker(); + + worker.addEventListener('error', reject); + worker.addEventListener( + 'message', + (msg) => { + worker.removeEventListener('error', reject); + if (msg.data?.kind === EventKinds.Loaded) { + resolve(worker); + } else { + reject(msg); + } + }, + { once: true }, + ); + }); diff --git a/sdk/typescript/packages/nodejs-client/src/subscriptions.ts b/sdk/typescript/packages/nodejs-client/src/subscriptions.ts new file mode 100644 index 0000000000..d819591f8b --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/src/subscriptions.ts @@ -0,0 +1,69 @@ +import type { EventHandlerFn } from './types'; +import { EventKinds } from './types'; + +type ISubscriptions = { + [key: string]: Array>; +}; + +/** + * Creates a subscription manager. + */ +export const createSubscriptions = () => { + // stores the subscriptions for events + const subscriptions: ISubscriptions = {}; + + /** + * Helper method to get typed subscriptions. + */ + const getSubscriptions = (key: EventKinds): Array> => { + if (!subscriptions[key]) { + subscriptions[key] = []; + } + return subscriptions[key] as Array>; + }; + + /** + * Remove a subscription. + */ + const removeSubscription = (key: EventKinds, handler: EventHandlerFn) => { + if (!subscriptions[key]) { + subscriptions[key] = []; + } + const items: Array> = (subscriptions[key] as Array>).filter( + (h) => h !== handler, + ); + subscriptions[key] = items; + }; + + /** + * Add typed subscription. + */ + const addSubscription = (key: EventKinds, handler: EventHandlerFn) => { + getSubscriptions(key).push(handler as EventHandlerFn); + + return () => { + removeSubscription(key, handler); + }; + }; + + /** + * Fires an event. + */ + const fireEvent = (key: EventKinds, event: E) => { + getSubscriptions(key).forEach((handler) => { + try { + handler(event); + } catch (e: any) { + console.error(`Unhandled exception in handler for ${key}: `, e); + } + }); + }; + + return { + getSubscriptions, + addSubscription, + removeSubscription, + fireEvent, + subscriptions, + }; +}; diff --git a/sdk/typescript/packages/nodejs-client/src/types.ts b/sdk/typescript/packages/nodejs-client/src/types.ts new file mode 100644 index 0000000000..c395877f76 --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/src/types.ts @@ -0,0 +1,348 @@ +import type { DebugWasm } from '@nymproject/nym-client-wasm'; + +/** + * + * @ignore + * @hidden + * @internal + */ +export interface IWebWorker { + start: (config: NymClientConfig) => void; + stop: () => void; + selfAddress: () => string | undefined; + setTextMimeTypes: (mimeTypes: string[]) => void; + getTextMimeTypes: () => string[]; + send: (args: { payload: Payload; recipient: string; replySurbs?: number }) => void; + rawSend: (args: { payload: Uint8Array; recipient: string; replySurbs?: number }) => void; +} + +export interface Client { + /** + * Start the client. + * + * @example + * + * ```typescript + * const client = await createNymMixnetClient(); + * await client.start({ + * clientId: 'my-client', + * nymApiUrl: 'https://validator.nymtech.net/api', + * }); + * + */ + start: (config: NymClientConfig) => Promise; + /** + * Stop the client. + * @example + * ```typescript + * const client = await createNymMixnetClient(); + * await client.start({ + * clientId: 'my-client', + * nymApiUrl: 'https://validator.nymtech.net/api', + * }); + * await client.stop(); + * ``` + */ + stop: () => Promise; + /** + * Get the client address + * @example + * ```typescript + * const client = await createNymMixnetClient(); + * await client.start({ + * clientId: 'my-client', + * nymApiUrl: 'https://validator.nymtech.net/api', + * }); + * const address = await client.selfAddress(); + * ``` + */ + selfAddress: () => Promise; + /** + * Set the mime-types that should be used when using the {@link Client.send} method. + * @example + * ```typescript + * const client = await createNymMixnetClient(); + * await client.start({ + * clientId: 'my-client', + * nymApiUrl: 'https://validator.nymtech.net/api', + * }); + * await client.setTextMimeTypes(['text/plain', 'application/json']); + * ``` + * @param mimeTypes + * @see {@link MimeTypes} + * @see {@link Client.send} + * @see {@link Client.getTextMimeTypes} + */ + setTextMimeTypes: (mimeTypes: string[]) => void; + /** + * Get the mime-types that are automatically converted to strings. + * @example + * ```typescript + * const client = await createNymMixnetClient(); + * await client.start({ + * clientId: 'my-client', + * nymApiUrl: 'https://validator.nymtech.net/api', + * }); + * const mimeTypes = await client.getTextMimeTypes(); + * ``` + * @see {@link MimeTypes} + * @see {@link Payload} + * @see {@link Client.send} + * @see {@link Client.setTextMimeTypes} + */ + getTextMimeTypes: () => Promise; + /** + * Send some data through the mixnet message. + * @example + * ```typescript + * const client = await createNymMixnetClient(); + * await client.start({ + * clientId: 'my-client', + * nymApiUrl: 'https://validator.nymtech.net/api', + * }); + * await client.send({ + * payload: 'Hello world', + * recipient: // recipient address, + * }); + * ``` + * @see {@link MimeTypes} + * @see {@link Payload} + */ + send: (args: { payload: Payload; recipient: string; replySurbs?: number }) => Promise; + /** + * Send a raw payload, without any mime-type conversion. + * @example + * ```typescript + * const client = await createNymMixnetClient(); + * await client.start({ + * clientId: 'my-client', + * nymApiUrl: 'https://validator.nymtech.net/api', + * }); + * const payload = new Uint8Array([1, 2, 3]); + * await client.rawSend({ + * payload, + * recipient: // recipient address, + * }); + * ``` + * @see {@link MimeTypes} + * @see {@link Payload} + */ + rawSend: (args: { payload: Uint8Array; recipient: string; replySurbs?: number }) => Promise; +} + +/** + * The configuration passed to the {@link Client.start} method of the {@link Client} + */ +export interface NymClientConfig { + /** + * A human-readable id for the client. + */ + clientId: string; + + /** + * The URL of a validator API to query for the network topology. + */ + nymApiUrl: string; + + /** + * Optional. The identity key of the preferred gateway to connect to. + */ + preferredGatewayIdentityKey?: string; + + /** + * Optional. The listener websocket of the preferred gateway to connect to. + */ + gatewayListener?: string; + + /** + * Optional. Settings for the WASM client. + */ + debug?: DebugWasm; +} + +export interface Events { + /** + * @see {@link LoadedEvent} + * @example + * ```typescript + * events.subscribeToLoaded((e) => { + * console.log(e.args); // { loaded: true } + * }); + * ``` + */ + subscribeToLoaded: EventHandlerSubscribeFn; + /** + * @see {@link ConnectedEvent} + * @example + * ```typescript + * events.subscribeConnected((e) => { + * console.log(e.args.address); // Client address + * }); + * + */ + subscribeToConnected: EventHandlerSubscribeFn; + /** + * @returns {@link EventHandlerUnsubscribeFn} + * @see {@link StringMessageReceivedEvent} + * @example + * ```typescript + * const unsubscribe = events.subscribeToTextMessageReceivedEvent((e) => { + * console.log(e.args.payload); // string + * }); + * + * // Stop listening to the event + * unsubscribe(); + * ``` + */ + subscribeToTextMessageReceivedEvent: EventHandlerSubscribeFn; + /** + * @returns {@link EventHandlerUnsubscribeFn} + * @see {@link BinaryMessageReceivedEvent} + * @example + * ```typescript + * const unsubscribe = events.subscribeToBinaryMessageReceivedEvent((e) => { + * console.log(e.args.payload); // Uint8Array + * }); + * + * // Stop listening to the event + * unsubscribe(); + * ``` + */ + subscribeToBinaryMessageReceivedEvent: EventHandlerSubscribeFn; + /** + * @returns {@link EventHandlerUnsubscribeFn} + * @see {@link RawMessageReceivedEvent} + * @example + * ```typescript + * const unsubscribe = events.subscribeToRawMessageReceivedEvent((e) => { + * console.log(e.args.payload); // Uint8Array + * }); + * + * // Stop listening to the event + * unsubscribe(); + * ``` + */ + subscribeToRawMessageReceivedEvent: EventHandlerSubscribeFn; +} + +/** + * Enum representing various event kinds. + * @enum + */ +export enum EventKinds { + /** + * The event emitted when the nodetester is ready to be used. + */ + Loaded = 'Loaded', + + /** + * The event emitted when connection to the gateway is established. + */ + Connected = 'Connected', + + /** + * The event for when a message is received and interpreted as a string. + */ + StringMessageReceived = 'StringMessageReceived', + + /** + * The event for when a binary message is received. BinaryMessage is a type of message that contains additional metadata, such as MIME type and some headers, along with the actual payload data. + */ + BinaryMessageReceived = 'BinaryMessageReceived', + + /** + * The event for when a raw message is received. RawMessage represents the bytes that are received directly from the mixnet with no further parsing or interpretation done on them. + */ + RawMessageReceived = 'RawMessageReceived', +} + +export interface LoadedEvent { + kind: EventKinds.Loaded; + args: { + loaded: true; + }; +} + +export interface ConnectedEvent { + kind: EventKinds.Connected; + args: { + address?: string; + }; +} + +export interface StringMessageReceivedEvent { + kind: EventKinds.StringMessageReceived; + args: { + mimeType: MimeTypes; + payload: string; + payloadRaw: Uint8Array; + headers?: string; + }; +} +export interface BinaryMessageReceivedEvent { + kind: EventKinds.BinaryMessageReceived; + args: { + mimeType: MimeTypes; + payload: Uint8Array; + headers?: string; + }; +} + +export interface RawMessageReceivedEvent { + kind: EventKinds.RawMessageReceived; + args: { + payload: Uint8Array; + }; +} + +/** + * Some common mime types, however, you can always just specify the mime-type as a string + */ +export enum MimeTypes { + ApplicationOctetStream = 'application/octet-stream', + TextPlain = 'text/plain', + ApplicationJson = 'application/json', +} + +export interface Payload { + message: string | Uint8Array; + mimeType?: MimeTypes | string; + headers?: string; +} + +/** + * @ignore + * @internal + */ +export type OnPayloadFn = (payload: Payload) => void; +/** + * @ignore + * @internal + */ +export type OnRawPayloadFn = (payload: Uint8Array) => void; + +/** + * The **EventHandlerSubscribeFn** is a function that takes a callback of type {@link EventHandlerFn} + * + * @see {@link Events} + * @see {@link EventHandlerFn} + * @see {@link EventHandlerUnsubscribeFn} + */ +export type EventHandlerSubscribeFn = (fn: EventHandlerFn) => EventHandlerUnsubscribeFn; + +/** + * The **EventHandlerFn** is a callback function that is passed to the {@link EventHandlerSubscribeFn} + * @see {@link Events} + * @see {@link EventHandlerFn} + * @see {@link EventHandlerSubscribeFn} + */ +export type EventHandlerFn = (e: E) => void | Promise; + +/** + * The **EventHandlerUnsubscribeFn** function is returned by the {@link EventHandlerSubscribeFn} + * and can be used to stop listening for particular events + * @see {@link Events} + * @see {@link EventHandlerFn} + * @see {@link EventHandlerSubscribeFn} + */ +export type EventHandlerUnsubscribeFn = () => void; diff --git a/sdk/typescript/packages/nodejs-client/src/typings/rollup-worker.d.ts b/sdk/typescript/packages/nodejs-client/src/typings/rollup-worker.d.ts new file mode 100644 index 0000000000..ead3d9e1f4 --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/src/typings/rollup-worker.d.ts @@ -0,0 +1,4 @@ +declare module 'web-worker:*' { + const WorkerFactory: new () => Worker; + export default WorkerFactory; +} diff --git a/sdk/typescript/packages/nodejs-client/src/worker.ts b/sdk/typescript/packages/nodejs-client/src/worker.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/sdk/typescript/packages/nodejs-client/tsconfig.eslint.json b/sdk/typescript/packages/nodejs-client/tsconfig.eslint.json new file mode 100644 index 0000000000..f7973eb336 --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/tsconfig.eslint.json @@ -0,0 +1,19 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true + }, + "include": [ + ".storybook/*.js", + "src/**/*.js", + "src/**/*.jsx", + "src/**/*.ts", + "src/**/*.tsx", + "src/**/*.stories.*", + "*.mjs", + ], + "exclude": [ + "node_modules", + "dist" + ] +} diff --git a/sdk/typescript/packages/nodejs-client/tsconfig.json b/sdk/typescript/packages/nodejs-client/tsconfig.json new file mode 100644 index 0000000000..d613d363a3 --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/tsconfig.json @@ -0,0 +1,42 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "lib": [ + "es2021", + "dom", + "dom.iterable", + "esnext", + "webworker" + ], + "outDir": "./dist/", + "module": "esnext", + "target": "esnext", + "allowJs": false, + "strict": true, + "moduleResolution": "node", + "skipLibCheck": true, + "skipDefaultLibCheck": true, + "declaration": true, + "baseUrl": "." + }, + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "jest.config.js", + "webpack.config.js", + "webpack.prod.js", + "webpack.common.js", + "node_modules", + "**/node_modules", + "dist", + "**/dist", + "scripts", + "jest", + "__tests__", + "**/__tests__", + "__jest__", + "**/__jest__", + "config/*", + ] +} diff --git a/sdk/typescript/packages/nodejs-client/typedoc.json b/sdk/typescript/packages/nodejs-client/typedoc.json new file mode 100644 index 0000000000..06d3f53b2e --- /dev/null +++ b/sdk/typescript/packages/nodejs-client/typedoc.json @@ -0,0 +1,32 @@ +{ + "sort": ["kind"], + "entryPoints": ["./src/index.ts"], + "out": "./docs", + "exclude": ["./src/worker.ts"], + "kindSortOrder": [ + "Function", + "Interface", + "TypeAlias", + "Reference", + "Project", + "Module", + "Namespace", + "Enum", + "EnumMember", + "Class", + "Constructor", + "Property", + "Variable", + "Accessor", + "Method", + "ObjectLiteral", + "Parameter", + "TypeParameter", + "TypeLiteral", + "CallSignature", + "ConstructorSignature", + "IndexSignature", + "GetSignature", + "SetSignature" + ] +} diff --git a/sdk/typescript/packages/sdk-react/README.md b/sdk/typescript/packages/sdk-react/README.md index ebc7451f0f..5a9a9403a6 100644 --- a/sdk/typescript/packages/sdk-react/README.md +++ b/sdk/typescript/packages/sdk-react/README.md @@ -3,5 +3,107 @@ This package provides useful React components to interact with the Nym Mixnet: - a provider and hook to send messages over the Mixnet + +## Install + + +Install this package in your project: + +``` +npm install @nymproject/sdk-react +``` + +Install the SDK: + +``` +npm install @nymproject/sdk +``` + +If you need to use one of the other variants you will need to use the following for NPM in `package.json` (remember to set the exact version): + +```json +{ + "overrides": { + "@nymproject/sdk": { + "@nymproject/sdk-full-fat": "1" + } + } + } +``` + +For `yarn` the syntax is slightly different (again in package.json): + +```json +{ + "resolutions": { + "@nymproject/sdk-full-fat": "1" + } +} +``` + +## Usage + +Add the provider near the top of your React app: + +```jsx +import { MixnetContextProvider } from '@nymproject/sdk-react'; + +export const App = () => ( + + + +); +``` + +And then use the hook in your components: + +```tsx +import { useMixnetContext } from '@nymproject/sdk-react'; +import type { EventHandlerFn, StringMessageReceivedEvent } from '@nymproject/sdk'; + +export const SomeComponent = () => { + const { isReady, address, sendTextMessage, events } = useMixnetContext(); + + const handleMessage = React.useCallback>((e) => { + console.log('Received message: ', e.args.payload); + }, []); + + // when the context is ready, register some events + React.useEffect(() => { + if (!events || !isReady) { + return undefined; + } + + // subscribe and get the unsubscribe function + const unsubscribeFn = events.subscribeToTextMessageReceivedEvent(handleMessage); + + // when unmounting unsubscribe will be called + return unsubscribeFn; + }, [isReady]); + + // send a message to yourself + const handleSendToSelf = async (message: string) => { + await sendTextMessage({ payload: message, recipient: address }); + }; + + if (!isReady) { + return ( +
+

Nym SDK Mixnet React Context

+
Loading...
+
+ ); + } + + return ( + + ); +} +``` + +## Coming Soon + +In future releases of this package you will be able to use: + - a provider and hook to manage Coconut credentials - a provider and hook to sign and broadcast messages to send to the Nyx blockchain RPC nodes diff --git a/sdk/typescript/packages/sdk-react/package.json b/sdk/typescript/packages/sdk-react/package.json index 4dcad819d5..fb66fa108a 100644 --- a/sdk/typescript/packages/sdk-react/package.json +++ b/sdk/typescript/packages/sdk-react/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/sdk-react", - "version": "1.2.0-rc.2", + "version": "1.2.0-rc.9", "license": "Apache-2.0", "author": "Nym Technologies SA", "files": [ @@ -8,7 +8,8 @@ ], "browser": "dist/index.js", "scripts": { - "build": "tsc --noEmit false", + "build:old": "./scripts/build.sh", + "build:tsc": "tsc --noEmit false", "clean": "rimraf dist", "lint": "eslint src", "lint:fix": "eslint src --fix", @@ -19,7 +20,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/sdk": ">=1.2.0-rc.1 || ^1" + "@nymproject/sdk": ">=1.2.0-rc.7 || ^1" }, "devDependencies": { "@babel/core": "^7.17.5", @@ -66,4 +67,4 @@ "private": false, "type": "module", "types": "./dist/index.d.ts" -} +} \ No newline at end of file diff --git a/sdk/typescript/packages/sdk-react/scripts/build.sh b/sdk/typescript/packages/sdk-react/scripts/build.sh new file mode 100755 index 0000000000..1cedb1fc94 --- /dev/null +++ b/sdk/typescript/packages/sdk-react/scripts/build.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +rm -rf dist || true + +# build +yarn build:tsc + +# add README and prod package.json +node scripts/buildPackageJson.mjs +cp README.md dist + +# move the output outside of the yarn/npm workspaces +mkdir -p ../../../../dist/ts/sdk-react +mv dist ../../../../dist/ts/sdk-react +mv ../../../../dist/ts/sdk-react/dist ../../../../dist/ts/sdk/sdk-react + +echo "Output can be found in:" +realpath ../../../../dist/ts/sdk/sdk-react + diff --git a/sdk/typescript/packages/sdk-react/scripts/buildPackageJson.mjs b/sdk/typescript/packages/sdk-react/scripts/buildPackageJson.mjs new file mode 100644 index 0000000000..fbb63c8e23 --- /dev/null +++ b/sdk/typescript/packages/sdk-react/scripts/buildPackageJson.mjs @@ -0,0 +1,24 @@ +import * as fs from 'fs'; + +// parse the package.json from the SDK, so we can keep fields like the name and version +const json = JSON.parse(fs.readFileSync('package.json').toString()); + +// defaults (NB: these are in the output file locations) +const browser = 'index.js'; +const main = 'index.js'; +const types = 'index.d.ts'; + +const getPackageJson = () => ({ + name: json.name, + version: json.version, + license: json.license, + author: json.author, + type, + browser, + main, + types, + peerDependencies: json.dependencies, +}); + +fs.writeFileSync('dist/package.json', JSON.stringify(getPackageJson(), null, 2)); + diff --git a/sdk/typescript/packages/sdk-react/src/context/mixnet.tsx b/sdk/typescript/packages/sdk-react/src/context/mixnet.tsx index 509e5893f7..dec3d8a2b8 100644 --- a/sdk/typescript/packages/sdk-react/src/context/mixnet.tsx +++ b/sdk/typescript/packages/sdk-react/src/context/mixnet.tsx @@ -52,7 +52,7 @@ export const MixnetContextProvider: FCWithChildren<{ (async () => { nym.current = await createNymMixnetClient(); if (nym.current?.events) { - nym.current.events.subscribeToConnected((e) => { + nym.current.events.subscribeToConnected((e: any) => { setAddress(e.args.address); setReady(true); }); @@ -64,11 +64,16 @@ export const MixnetContextProvider: FCWithChildren<{ nymApiUrl, preferredGatewayIdentityKey, }) - .catch((e) => console.error('Failed to start client', e)); + .catch((e: any) => console.error('Failed to start client', e)); } })(); - // + // on unmount stop the client + return () => { + if (nym.current) { + nym.current.client.stop(); + } + }; }, []); const sendTextMessage = async (args: { payload: string; recipient: string }) => { diff --git a/sdk/typescript/packages/sdk/README-CommonJS-full-fat.md b/sdk/typescript/packages/sdk/README-CommonJS-full-fat.md index 8d5582a164..4b3327d7cb 100644 --- a/sdk/typescript/packages/sdk/README-CommonJS-full-fat.md +++ b/sdk/typescript/packages/sdk/README-CommonJS-full-fat.md @@ -1,14 +1,9 @@ -# Nym SDK (Typescript) CommonJS and ES5 +# Nym SDK (Typescript) CommonJS and ES5 - 🥛🥛🥛 Full Fat -``` -⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠ -⚠ WARNING: ES5 & CommonJS with inline blobs ⚠ -⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠ -``` +#### ⚠ WARNING: ES5 & CommonJS with inline blobs ⚠ +#### Please note: this is a CommonJS package targeting ES5. Use this for older projects or when you have bundling issues. It includes inline blobs that will interfere with CSPs that disallow them. -### Please note: this is a CommonJS package targeting ES5. Use this for older projects or when you have bundling issues. It includes inline blobs that will interfere with CSPs that disallow them. - -If you are looking for an ESM version please use https://www.npmjs.com/package/@nymproject/sdk. +{{>variants}} ---------------------------- @@ -24,8 +19,8 @@ npm install @nymproject/sdk-commonjs Open a connection to a Gateway on the Nym Mixnet: -```ts -import { createNymMixnetClient } from '@nymproject/sdk-commonjs'; +```js +const { createNymMixnetClient } = require('@nymproject/sdk-commonjs'); const main = async () => { const nym = await createNymMixnetClient(); diff --git a/sdk/typescript/packages/sdk/README-CommonJS.md b/sdk/typescript/packages/sdk/README-CommonJS.md index a8282888f3..6f0d452a40 100644 --- a/sdk/typescript/packages/sdk/README-CommonJS.md +++ b/sdk/typescript/packages/sdk/README-CommonJS.md @@ -1,14 +1,9 @@ # Nym SDK (Typescript) CommonJS and ES5 -``` -⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠ -⚠ WARNING: ES5 & CommonJS ⚠ -⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠ -``` +#### ⚠ WARNING: ES5 & CommonJS that requires bundling ⚠ +#### Please note: this is a CommonJS package targeting ES5. Use this for older projects that can't process `import` syntax. You will need to handle bundling of the web-workers and WASM. -### Please note: this is a CommonJS package targeting ES5. Use this for older projects or when you have bundling issues - -If you are looking for an ESM version please use https://www.npmjs.com/package/@nymproject/sdk. +{{>variants}} ---------------------------- @@ -24,8 +19,8 @@ npm install @nymproject/sdk-commonjs Open a connection to a Gateway on the Nym Mixnet: -```ts -import { createNymMixnetClient } from '@nymproject/sdk-commonjs'; +```js +const { createNymMixnetClient } = require('@nymproject/sdk-commonjs'); const main = async () => { const nym = await createNymMixnetClient(); diff --git a/sdk/typescript/packages/sdk/README-full-fat.md b/sdk/typescript/packages/sdk/README-full-fat.md index 5abd214313..f72a198d1c 100644 --- a/sdk/typescript/packages/sdk/README-full-fat.md +++ b/sdk/typescript/packages/sdk/README-full-fat.md @@ -1,19 +1,12 @@ -# Nym SDK (Typescript) +# Nym SDK (Typescript) - 🥛🥛🥛 Full Fat -``` -⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠ -⚠ WARNING: ESM with inline blobs ⚠ -⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠ -``` +#### ⚠ WARNING: ESM with inline blobs ⚠ +#### Please note: this is an ESM package targeting ES6. Use this when you have bundling issues. It includes inline blobs that will interfere with CSPs that disallow them. -### Please note: this is a CommonJS package targeting ES5. Use this for older projects or when you have bundling issues. It includes inline blobs that will interfere with CSPs that disallow them. - -If you are looking for an ESM version please use https://www.npmjs.com/package/@nymproject/sdk. +{{>variants}} ---------------------------- -The Nym SDK for Typescript will get you creating apps that can use the Nym Mixnet and Coconut credentials quickly. - ## TL;DR Include the SDK in your project: diff --git a/sdk/typescript/packages/sdk/README.md b/sdk/typescript/packages/sdk/README.md index be82e53a84..86406633b5 100644 --- a/sdk/typescript/packages/sdk/README.md +++ b/sdk/typescript/packages/sdk/README.md @@ -48,3 +48,5 @@ Send a message to another user (you will need to know their address at a Gateway const recipient = '<< RECIPIENT ADDRESS GOES HERE >>'; await nym.client.send({ payload, recipient }); ``` + +{{>variants}} diff --git a/sdk/typescript/packages/sdk/package.json b/sdk/typescript/packages/sdk/package.json index b6aa91c84b..83b82cca23 100644 --- a/sdk/typescript/packages/sdk/package.json +++ b/sdk/typescript/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/sdk", - "version": "1.2.0-rc.2", + "version": "1.2.0-rc.9", "license": "Apache-2.0", "author": "Nym Technologies SA", "files": [ @@ -30,7 +30,7 @@ "tsc": "tsc --noEmit true" }, "dependencies": { - "@nymproject/nym-client-wasm": ">=1.2.0-rc.0 || ^1", + "@nymproject/nym-client-wasm": ">=1.2.0-rc.7 || ^1", "comlink": "^4.3.1" }, "devDependencies": { @@ -64,6 +64,7 @@ "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-react": "^7.29.2", "eslint-plugin-react-hooks": "^4.3.0", + "handlebars": "^4.7.8", "jest": "^29.5.0", "nodemon": "3.0.1", "reload": "^3.2.1", @@ -79,4 +80,4 @@ "private": false, "type": "module", "types": "./dist/esm/index.d.ts" -} +} \ No newline at end of file diff --git a/sdk/typescript/packages/sdk/partials/variants.md b/sdk/typescript/packages/sdk/partials/variants.md new file mode 100644 index 0000000000..ff4c1173f3 --- /dev/null +++ b/sdk/typescript/packages/sdk/partials/variants.md @@ -0,0 +1,23 @@ +## Find the right package for you + +Browsers: +- **`ESM` 🥛** - [@nymproject/sdk](https://www.npmjs.com/package/@nymproject/sdk), not bundled, use `import` syntax, you will need to bundle it +- **`ESM` 🥛🥛🥛** - [@nymproject/sdk-full-fat](https://www.npmjs.com/package/@nymproject/sdk-full-fat), use `import` syntax, pre-bundled with inlined workers and WASM bundles +- **`CJS` 🥛** - [@nymproject/sdk](https://www.npmjs.com/package/@nymproject/sdk-commonjs), targets ES5, not bundled, you will need to bundle it +- **`CJS` 🥛🥛🥛** - [@nymproject/sdk-full-fat](https://www.npmjs.com/package/@nymproject/sdk-commonjs-full-fat), targets ES5, pre-bundled with inlined workers and WASM bundles + +NodeJS: +- **`ESM`** - [@nymproject/sdk-nodejs](https://www.npmjs.com/package/@nymproject/sdk-nodejs), use `import` syntax in NodeJS 18 and later +- **`CJS`** - [@nymproject/sdk-nodejs-cjs](https://www.npmjs.com/package/@nymproject/sdk-nodejs-cjs), use `require` syntax in older NodeJS versions + +Why have all these variations? Each project is different, so hopefully we have something for you! + +Choose a package depending on how your project is transpiled and packaged: + +- `ESM`: use `import` syntax and have your bundler copy the WASM bundles into your output distribution +- `CJS`: you have an older project that needs ES5 Javascript +- `nodejs`: you want to write your project server-side or locally without the browser on NodeJS + +And then, to use `*-full-fat` or not, how do I choose? We have `*-full-fat` packages that are pre-bundled by including all web-workers and WASM as inline Base64. + +Use the `*-full-fat` packages when you have trouble changing your bundler settings, or you can use an open CSP. diff --git a/sdk/typescript/packages/sdk/scripts/build.sh b/sdk/typescript/packages/sdk/scripts/build.sh index bde7b47bdc..97e6571bbf 100755 --- a/sdk/typescript/packages/sdk/scripts/build.sh +++ b/sdk/typescript/packages/sdk/scripts/build.sh @@ -55,10 +55,12 @@ rollup -c rollup-cjs-full-fat.config.mjs # CLEAN UP #------------------------------------------------------- +rm -rf dist/worker + # copy README -cp README.md dist/esm -cp README-CommonJS.md dist/cjs/README.md -cp README-full-fat.md dist/esm-full-fat -cp README-CommonJS-full-fat.md dist/cjs-full-fat/README.md +node scripts/hbs.mjs README.md ./dist/esm/README.md +node scripts/hbs.mjs README-CommonJS.md ./dist/cjs/README.md +node scripts/hbs.mjs README-full-fat.md ./dist/esm-full-fat/README.md +node scripts/hbs.mjs README-CommonJS-full-fat.md ./dist/cjs-full-fat/README.md diff --git a/sdk/typescript/packages/sdk/scripts/hbs.mjs b/sdk/typescript/packages/sdk/scripts/hbs.mjs new file mode 100644 index 0000000000..275a79d468 --- /dev/null +++ b/sdk/typescript/packages/sdk/scripts/hbs.mjs @@ -0,0 +1,23 @@ +import Handlebars from "handlebars"; +import fs from 'fs'; +import path from 'path'; +import glob from 'glob'; + +const filename = process.argv[2]; +const outputFilename = process.argv[3]; +console.log(`Processing file ${filename} as ${outputFilename}...`); +const template = Handlebars.compile(fs.readFileSync(filename).toString()); + +glob.sync('./partials/*.md').forEach(g => { + const key = path.parse(g).name; + console.log(`Registering partial ${g} as ${key}...`); + Handlebars.registerPartial(key, fs.readFileSync(g).toString()); +}); + +console.log('Done'); +console.log(); + +const output = template({}); + +console.log(fs.writeFileSync(outputFilename, output)); + diff --git a/sdk/typescript/packages/validator-client/package.json b/sdk/typescript/packages/validator-client/package.json index 2f3eb4e02e..8c415c119e 100644 --- a/sdk/typescript/packages/validator-client/package.json +++ b/sdk/typescript/packages/validator-client/package.json @@ -1,6 +1,6 @@ { "name": "@nymproject/nym-validator-client", - "version": "1.2.0-rc.2", + "version": "1.2.0-rc.9", "description": "A TypeScript client for interacting with smart contracts in Nym validators", "license": "Apache-2.0", "author": "Nym Technologies SA (https://nymtech.net)", diff --git a/sdk/typescript/scripts/publish.sh b/sdk/typescript/scripts/publish.sh index d6eaeb6a84..43084f930b 100755 --- a/sdk/typescript/scripts/publish.sh +++ b/sdk/typescript/scripts/publish.sh @@ -10,17 +10,43 @@ set -o pipefail cd dist +#packages=( +#chat-app/parcel +#chat-app/plain-html +#chat-app/react-webpack-with-theme-example +#chrome-extension +#firefox-extension +#node-tester/parcel +#node-tester/plain-html +#node-tester/react +#react/mui-theme +#react/sdk-react +#) packages=( -chat-app/parcel -chat-app/plain-html -chat-app/react-webpack-with-theme-example -chrome-extension -firefox-extension -node-tester/parcel -node-tester/plain-html -node-tester/react -react/mui-theme -react/sdk-react +"wasm/client" +"wasm/mix-fetch" +"wasm/node-tester" +"wasm/extension-storage" + +"node/wasm/client" +"node/wasm/mix-fetch" + +"ts/sdk/mix-fetch/cjs" +"ts/sdk/mix-fetch/cjs-full-fat" +"ts/sdk/mix-fetch/esm" +"ts/sdk/mix-fetch/esm-full-fat" + +"ts/sdk/node-tester/cjs" +"ts/sdk/node-tester/cjs-full-fat" +"ts/sdk/node-tester/esm" +"ts/sdk/node-tester/esm-full-fat" + +"ts/sdk/sdk/cjs" +"ts/sdk/sdk/cjs-full-fat" +"ts/sdk/sdk/esm" +"ts/sdk/sdk/esm-full-fat" + +"ts/sdk/contract-clients" ) pushd () { @@ -43,10 +69,13 @@ done echo "" echo "" +COUNTER=0 + for item in "${packages[@]}" do + (( COUNTER++ )) pushd "$item" - echo "🚀 Publishing $item..." + echo "🚀 Publishing $item... (${COUNTER} of ${#packages[@]})" cat package.json | jq -r '. | .name + " " +.version' npm publish --access=public popd diff --git a/sdk/typescript/scripts/release.sh b/sdk/typescript/scripts/release.sh new file mode 100755 index 0000000000..5f30eb18bc --- /dev/null +++ b/sdk/typescript/scripts/release.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +# Build WASM packages +make sdk-wasm-build + +# Build Typescript packages +yarn +yarn build:sdk + +# Publish to NPM +./sdk/typescript/scripts/publish.sh diff --git a/sdk/typescript/tests/integration-tests/mix-fetch/.gitignore b/sdk/typescript/tests/integration-tests/mix-fetch/.gitignore new file mode 100644 index 0000000000..86d4c2dd38 --- /dev/null +++ b/sdk/typescript/tests/integration-tests/mix-fetch/.gitignore @@ -0,0 +1 @@ +generated diff --git a/sdk/typescript/tests/integration-tests/mix-fetch/generate-tests.mjs b/sdk/typescript/tests/integration-tests/mix-fetch/generate-tests.mjs new file mode 100644 index 0000000000..40efab76cb --- /dev/null +++ b/sdk/typescript/tests/integration-tests/mix-fetch/generate-tests.mjs @@ -0,0 +1,188 @@ +/* eslint-disable no-await-in-loop,no-restricted-syntax */ +import fs from 'fs'; +import path from 'path'; +import child_process from 'child_process'; +import http from 'http'; +import handler from 'serve-handler'; +import { runTests } from './tests/tests.mjs'; + +const GENERATED_DIR = 'generated'; +const OUTPUT_DIR = `${GENERATED_DIR}/packages`; +const BASE_DIST_PATH = '../../../../../dist/ts/sdk/mix-fetch'; +const packages = ['cjs', 'cjs-full-fat', 'esm', 'esm-full-fat']; + +const doBuild = true; +const logTests = true; + +// disabling deleting to preserve node_modules +// fs.rmSync(OUTPUT_DIR, { recursive: true, force: true }); + +fs.mkdirSync(OUTPUT_DIR, { recursive: true }); + +async function serve(publicDir) { + const server = http.createServer((request, response) => + // see https://github.com/vercel/serve-handler#options for more options + handler(request, response, { public: publicDir }), + ); + + server.listen(3000, () => { + console.log(` 🌈 Running at http://localhost:3000, serving ${publicDir}...`); + }); + + return server; +} +function changeFileLocation(packageJsonPath, dependencyPath, kind) { + const packageJson = JSON.parse(fs.readFileSync(packageJsonPath).toString()); + packageJson.name = `${packageJson.name}-${kind}`; + delete packageJson.dependencies['@nymproject/mix-fetch']; + packageJson.dependencies[`@nymproject/mix-fetch${kind}`] = `file:${dependencyPath}`; + fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)); +} + +console.log('🚚 Copying workspace...'); +fs.cpSync('template/workspace/package.json', path.resolve(`${GENERATED_DIR}/package.json`)); + +packages.forEach((p) => { + const dir = `${OUTPUT_DIR}/${p}`; + if (doBuild) { + fs.rmSync(dir, { recursive: true, force: true }); + } + console.log(`🚚 Creating ${dir}...`); + + let kind = p.startsWith('cjs') ? '-commonjs' : ''; + if (p.endsWith('-full-fat')) { + kind += '-full-fat'; + } + + const importScript = ''; + const importStatement = `import { mixFetch } from '@nymproject/mix-fetch${kind}';`; + const pluginPackageJsonName = `@nymproject/mix-fetch${kind}`; + + const src = fs.readFileSync('template/src/index.ts').toString().replace("'$IMPORT_STATEMENT';", importStatement); + const html = fs.readFileSync('template/src/index.html').toString().replace('', importScript); + const plugins = fs + .readFileSync('template/webpack/webpack.plugins.js') + .toString() + .replaceAll('$PACKAGE', pluginPackageJsonName); + + const pluginsEmpty = 'module.exports = { plugins: [] };'; + + fs.cpSync('template/parcel', `${dir}/parcel`, { recursive: true }); + fs.cpSync('template/src', `${dir}/parcel/src`, { recursive: true }); + + fs.cpSync('template/webpack', `${dir}/webpack`, { recursive: true }); + fs.cpSync('template/src', `${dir}/webpack/src`, { recursive: true }); + + fs.writeFileSync(`${dir}/webpack/src/index.ts`, src); + fs.writeFileSync(`${dir}/parcel/src/index.ts`, src); + // fs.writeFileSync(`${dir}/webpack/src/index.html`, html); + fs.writeFileSync(`${dir}/parcel/src/index.html`, html); + fs.writeFileSync(`${dir}/webpack/webpack.plugins.js`, p.endsWith('-full-fat') ? pluginsEmpty : plugins); + + changeFileLocation(`${dir}/parcel/package.json`, path.resolve(`${BASE_DIST_PATH}/${p}`), kind); + changeFileLocation(`${dir}/webpack/package.json`, path.resolve(`${BASE_DIST_PATH}/${p}`), kind); +}); + +console.log('✅ Generated\n'); + +console.log(`🚀 Installing workspace packages in ${path.resolve(OUTPUT_DIR)}...`); +const resultNpmInstall = child_process.spawnSync('npm', ['install'], { cwd: path.resolve(OUTPUT_DIR) }); +if (resultNpmInstall.status !== 0) { + console.log(resultNpmInstall.stdout.toString()); + console.log(resultNpmInstall.stderr.toString()); + console.log('❌ Failed to install dependencies'); + process.exit(-1); +} + +if (doBuild) { + packages.forEach((p) => { + const dir = `${OUTPUT_DIR}/${p}`; + + ['parcel', 'webpack'].forEach((kind) => { + const project = `${dir}/${kind}`; + console.log(`🚀 Building ${path.resolve(project)}...`); + + const result = child_process.spawnSync('npm', ['run', 'build'], { cwd: path.resolve(project) }); + + if (result.status !== 0) { + console.log(`❌ Failed to build ${project}`); + console.log(result.stdout.toString()); + console.log(result.stderr.toString()); + process.exit(-1); + } else { + console.log( + child_process.spawnSync('ls', ['-lah'], { cwd: `${path.resolve(project)}/dist` }).stdout.toString(), + ); + } + }); + }); +} + +console.log('✅ Built\n'); + +console.log('👀 Testing...'); + +const summary = []; +let totalTimeMilliseconds = 0; +let failures = 0; +for (const p of packages) { + const dir = `${OUTPUT_DIR}/${p}`; + + const kinds = [ + 'parcel', // simple parcel project + 'webpack', // webpack, sometimes with the CopyPlugin to add the WASM bundles + ]; + for (const kind of kinds) { + const project = `${dir}/${kind}`; + console.log(`🔎 Testing ${path.resolve(project)}...`); + + const server = await serve(path.resolve(project, 'dist')); + + const start = performance.now(); + let success = false; + let errors = []; + try { + console.log('🚀 About to run tests...'); + errors = await runTests(logTests); + if (errors.length > 0) { + errors.forEach((e) => console.log(e.text)); + } else { + success = true; + } + } catch (e) { + failures += 1; + errors.push({ text: e.message, type: 'error' }); + } finally { + server.closeAllConnections(); + server.close(); + } + const end = performance.now(); + const duration = Math.floor(end - start); + totalTimeMilliseconds += duration; + + if (errors.length) { + console.log(`❌ Tests failed for ${project} with ${errors.length} errors:`); + console.table(errors); + } else { + console.log('✅ OK'); + } + + summary.push({ + variant: p, + bundler: kind, + duration: `${duration}ms`, + success: success ? '✅ OK' : `❌ Failed with ${errors.length} errors`, + errors: errors.map((e) => e.text).join('\n'), + }); + + console.log(); + } +} + +console.log(); +console.log('Summary:'); +console.table(summary); + +console.log(); +console.log(`Tests took ${Math.floor(totalTimeMilliseconds / 1000)} seconds to run`); +console.log(`${failures > 0 ? `❌ Done with ${failures} errors` : '✅ Done'}`); diff --git a/sdk/typescript/tests/integration-tests/mix-fetch/package-lock.json b/sdk/typescript/tests/integration-tests/mix-fetch/package-lock.json new file mode 100644 index 0000000000..8659d27038 --- /dev/null +++ b/sdk/typescript/tests/integration-tests/mix-fetch/package-lock.json @@ -0,0 +1,1216 @@ +{ + "name": "mix-fetch-tests-runner", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "mix-fetch-tests-runner", + "version": "1.0.0", + "dependencies": { + "puppeteer": "^21.1.1", + "serve-handler": "^6.1.5" + } + }, + "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==", + "dependencies": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz", + "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz", + "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.5", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@puppeteer/browsers": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.7.0.tgz", + "integrity": "sha512-sl7zI0IkbQGak/+IE3VEEZab5SSOlI5F6558WvzWGC1n3+C722rfewC1ZIkcF9dsoGSsxhsONoseVlNQG4wWvQ==", + "dependencies": { + "debug": "4.3.4", + "extract-zip": "2.0.1", + "progress": "2.0.3", + "proxy-agent": "6.3.0", + "tar-fs": "3.0.4", + "unbzip2-stream": "1.4.3", + "yargs": "17.7.1" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" + }, + "engines": { + "node": ">=16.3.0" + } + }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" + }, + "node_modules/@types/node": { + "version": "20.6.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.0.tgz", + "integrity": "sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==", + "optional": true + }, + "node_modules/@types/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "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": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "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/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/b4a": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", + "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==" + }, + "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/basic-ftp": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.3.tgz", + "integrity": "sha512-QHX8HLlncOLpy54mh+k/sWIFd0ThmRqwe9ZjELybGZK+tZ8rUb9VO0saKJUROTbE+KhzDUT7xziGpGrW8Kmd+g==", + "engines": { + "node": ">=10.0.0" + } + }, + "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==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "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-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "engines": { + "node": "*" + } + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "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==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chromium-bidi": { + "version": "0.4.22", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.22.tgz", + "integrity": "sha512-wR7Y9Ioez+cNXT4ZP7VNM1HRTljpNnMSLw4/RnwhhZUP4yCU7kIQND00YiktuHekch68jklGPK1q9Jkb29+fQg==", + "dependencies": { + "mitt": "3.0.1" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, + "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/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-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/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cosmiconfig": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz", + "integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==", + "dependencies": { + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/cross-fetch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", + "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", + "dependencies": { + "node-fetch": "^2.6.12" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-5.0.1.tgz", + "integrity": "sha512-a9l6T1qqDogvvnw0nKlfZzqsyikEBZBClF39V3TFoKhDtGBqHu2HkuomJc02j5zft8zrUaXEuoicLeW54RkzPg==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/devtools-protocol": { + "version": "0.0.1159816", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1159816.tgz", + "integrity": "sha512-2cZlHxC5IlgkIWe2pSDmCrDiTzbSJWywjbDDnupOImEBcG31CQgBLV8wWE+5t+C4rimcjHsbzy7CBzf9oFjboA==" + }, + "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/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/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==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "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==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "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==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" + }, + "node_modules/fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", + "dependencies": { + "punycode": "^1.3.2" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "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-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-uri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.1.tgz", + "integrity": "sha512-7ZqONUVqaabogsYNWlYj0t3YZaL6dhuEueZXGF+/YVmf6dHmaFg8/6psJKqhx9QykIDKzpGcy2cn4oV4YC7V/Q==", + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^5.0.1", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">= 14" + } + }, + "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==" + }, + "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==", + "engines": { + "node": ">=4" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "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/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ip": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", + "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==" + }, + "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==" + }, + "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/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "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/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==" + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dependencies": { + "mime-db": "~1.33.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==" + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "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==" + }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "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/pac-proxy-agent": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", + "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "pac-resolver": "^7.0.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.0.tgz", + "integrity": "sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==", + "dependencies": { + "degenerator": "^5.0.0", + "ip": "^1.1.8", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "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==", + "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==", + "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-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==" + }, + "node_modules/path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/proxy-agent": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.0.tgz", + "integrity": "sha512-0LdR757eTj/JfuU7TL2YCuAZnxWXu3tkJbg4Oq3geW/qFNT/32T0sp2HnZ9O0lMR4q3vwAt0+xCA8SR0WAD0og==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.0", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "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/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": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" + }, + "node_modules/puppeteer": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-21.1.1.tgz", + "integrity": "sha512-2TLntjGA4qLrI9/8N0UK/5OoZJ2Ue7QgphN2SD+RsaHiha12AEiVyMGsB+i6LY1IoPAtEgYIjblQ7lw3kWDNRw==", + "hasInstallScript": true, + "dependencies": { + "@puppeteer/browsers": "1.7.0", + "cosmiconfig": "8.2.0", + "puppeteer-core": "21.1.1" + }, + "engines": { + "node": ">=16.3.0" + } + }, + "node_modules/puppeteer-core": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-21.1.1.tgz", + "integrity": "sha512-Tlcajcf44zwfa9Sbwv3T8BtaNMJ69wtpHIxwl2NOBTyTK3D1wppQovXTjfw0TDOm3a16eCfQ+5BMi3vRQ4kuAQ==", + "dependencies": { + "@puppeteer/browsers": "1.7.0", + "chromium-bidi": "0.4.22", + "cross-fetch": "4.0.0", + "debug": "4.3.4", + "devtools-protocol": "0.0.1159816", + "ws": "8.13.0" + }, + "engines": { + "node": ">=16.3.0" + } + }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" + }, + "node_modules/range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", + "engines": { + "node": ">= 0.6" + } + }, + "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-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/serve-handler": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", + "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", + "dependencies": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "fast-url-parser": "1.1.3", + "mime-types": "2.1.18", + "minimatch": "3.1.2", + "path-is-inside": "1.0.2", + "path-to-regexp": "2.2.1", + "range-parser": "1.2.0" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", + "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/socks/node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, + "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==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/streamx": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.1.tgz", + "integrity": "sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA==", + "dependencies": { + "fast-fifo": "^1.1.0", + "queue-tick": "^1.0.1" + } + }, + "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/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/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/tar-fs": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", + "integrity": "sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==", + "dependencies": { + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + } + }, + "node_modules/tar-stream": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.6.tgz", + "integrity": "sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "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/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "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/wrap-ansi/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/wrap-ansi/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/wrap-ansi/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/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/ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "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/yargs": { + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "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/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + } +} diff --git a/sdk/typescript/tests/integration-tests/mix-fetch/package.json b/sdk/typescript/tests/integration-tests/mix-fetch/package.json new file mode 100644 index 0000000000..c1d3ae39df --- /dev/null +++ b/sdk/typescript/tests/integration-tests/mix-fetch/package.json @@ -0,0 +1,8 @@ +{ + "name": "mix-fetch-tests-runner", + "version": "1.0.0", + "dependencies": { + "serve-handler": "^6.1.5", + "puppeteer": "^21.1.1" + } +} diff --git a/sdk/typescript/tests/integration-tests/mix-fetch/template/parcel/package.json b/sdk/typescript/tests/integration-tests/mix-fetch/template/parcel/package.json new file mode 100644 index 0000000000..ea5e8f909a --- /dev/null +++ b/sdk/typescript/tests/integration-tests/mix-fetch/template/parcel/package.json @@ -0,0 +1,14 @@ +{ + "name": "@nymproject/mix-fetch-tester-parcel", + "version": "1.0.0", + "license": "Apache-2.0", + "source": "src/index.html", + "dependencies": { + "@nymproject/mix-fetch": "file:../../../../../../dist/ts/sdk/mix-fetch/esm" + }, + "scripts": { + "start": "npx parcel --no-cache", + "build": "npx parcel build --no-cache --no-optimize", + "serve": "npx serve dist" + } +} diff --git a/sdk/typescript/tests/integration-tests/mix-fetch/template/src/index.html b/sdk/typescript/tests/integration-tests/mix-fetch/template/src/index.html new file mode 100644 index 0000000000..d1c190494a --- /dev/null +++ b/sdk/typescript/tests/integration-tests/mix-fetch/template/src/index.html @@ -0,0 +1,18 @@ + + + + + + + Internal Tester + + + + +

Internal tester

+

Open dev tools to see more output and errors

+

+
+ + + diff --git a/sdk/typescript/tests/integration-tests/mix-fetch/template/src/index.ts b/sdk/typescript/tests/integration-tests/mix-fetch/template/src/index.ts new file mode 100644 index 0000000000..fea3c689fc --- /dev/null +++ b/sdk/typescript/tests/integration-tests/mix-fetch/template/src/index.ts @@ -0,0 +1,59 @@ +'$IMPORT_STATEMENT'; + +function appendOutput(value: string, id?: string) { + const el = document.getElementById('output') as HTMLPreElement; + const div = document.createElement('div'); + if (id) { + div.id = id; + } + const text = document.createTextNode(`${value}\n`); + div.appendChild(text); + el.appendChild(div); +} + +function appendImageOutput(url: string) { + const el = document.getElementById('outputImage') as HTMLPreElement; + const imgNode = document.createElement('img'); + imgNode.src = url; + el.appendChild(imgNode); +} + +/** + * The main entry point + */ +async function main() { + appendOutput('Tester is starting up...', 'starting'); + + const url = 'https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt'; + appendOutput(`Using mixFetch to get ${url}...`); + const args = { mode: 'unsafe-ignore-cors' }; + + const resp = await mixFetch(url, args, { + preferredGateway: '2BuMSfMW3zpeAjKXyKLhmY4QW1DXurrtSPEJ6CjX3SEh', + preferredNetworkRequester: + 'GiRjFWrMxt58pEMuusm4yT3RxoMD1MMPrR9M2N4VWRJP.3CNZBPq4vg7v7qozjGjdPMXcvDmkbWPCgbGCjQVw9n6Z@2xU4CBE6QiiYt6EyBXSALwxkNvM7gqJfjHXaMkjiFmYW', + }); + console.log({ resp }); + const text = await resp.text(); + + appendOutput(JSON.stringify(resp, null, 2), 'text-output'); + appendOutput(JSON.stringify({ text }, null, 2)); + + // // get an image + // url = 'https://nymtech.net/favicon.svg'; + // resp = await mixFetch(url, args); + // console.log({ resp }); + // const buffer = await resp.arrayBuffer(); + // const type = resp.headers.get('Content-Type') || 'image/svg'; + // const blobUrl = URL.createObjectURL(new Blob([buffer], { type })); + // appendOutput(JSON.stringify({ bufferBytes: buffer.byteLength, blobUrl }, null, 2), 'image-output'); + // appendImageOutput(blobUrl); + + appendOutput('✅ Done', 'done'); +} + +// wait for the html to load +window.addEventListener('DOMContentLoaded', () => { + // let's do this! + main(); +}); diff --git a/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/package.json b/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/package.json new file mode 100644 index 0000000000..47de127c34 --- /dev/null +++ b/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/package.json @@ -0,0 +1,57 @@ +{ + "name": "@nymproject/mix-fetch-tester-webpack", + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@nymproject/mix-fetch": "file:../../../../../../dist/ts/sdk/mix-fetch/esm" + }, + "devDependencies": { + "@babel/core": "^7.15.0", + "@babel/plugin-transform-async-to-generator": "^7.14.5", + "@babel/preset-env": "^7.15.0", + "@babel/preset-typescript": "^7.15.0", + "@types/jest": "^27.0.1", + "@types/node": "^16.7.13", + "@typescript-eslint/eslint-plugin": "^5.13.0", + "@typescript-eslint/parser": "^5.13.0", + "babel-loader": "^8.3.0", + "babel-plugin-root-import": "^5.1.0", + "clean-webpack-plugin": "^4.0.0", + "copy-webpack-plugin": "^11.0.0", + "css-loader": "^6.7.3", + "css-minimizer-webpack-plugin": "^3.0.2", + "dotenv-webpack": "^7.0.3", + "eslint": "^8.10.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-config-airbnb-typescript": "^16.1.0", + "eslint-config-prettier": "^8.5.0", + "eslint-import-resolver-root-import": "^1.0.4", + "eslint-plugin-import": "^2.25.4", + "eslint-plugin-jest": "^26.1.1", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-prettier": "^4.0.0", + "file-loader": "^6.2.0", + "fork-ts-checker-webpack-plugin": "^7.2.1", + "html-webpack-plugin": "^5.3.2", + "jest": "^27.1.0", + "mini-css-extract-plugin": "^2.2.2", + "npm-run-all": "^4.1.5", + "prettier": "^2.8.7", + "style-loader": "^3.3.1", + "thread-loader": "^3.0.4", + "ts-jest": "^27.0.5", + "ts-loader": "^9.4.2", + "tsconfig-paths-webpack-plugin": "^3.5.2", + "typescript": "^4.6.2", + "url-loader": "^4.1.1", + "webpack": "^5.75.0", + "webpack-cli": "^4.8.0", + "webpack-dev-server": "^4.5.0", + "webpack-merge": "^5.8.0" + }, + "scripts": { + "start": "webpack serve --progress --port 3000", + "build": "webpack build --progress --config webpack.prod.js", + "serve": "npx serve dist" + } +} diff --git a/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/tsconfig.json b/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/tsconfig.json new file mode 100644 index 0000000000..2d9ec75afa --- /dev/null +++ b/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../../../../../tsconfig.json", + "compilerOptions": { + "module": "ESNext", + "outDir": "./dist" + }, + "exclude": ["node_modules", "build", "dist"] +} diff --git a/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/webpack.base.js b/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/webpack.base.js new file mode 100644 index 0000000000..fb9a7f2f5b --- /dev/null +++ b/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/webpack.base.js @@ -0,0 +1,91 @@ +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); +// const { CleanWebpackPlugin } = require('clean-webpack-plugin'); +const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); +const WebpackFavicons = require('webpack-favicons'); +const Dotenv = require('dotenv-webpack'); +const path = require('path'); +const os = require('os'); + +/** + * Creates the default Webpack config + * @param baseDir The base directory path, e.g. pass `__dirname` of the webpack config file using this method + */ +const webpackCommon = (baseDir, htmlPath) => ({ + module: { + rules: [ + { + test: /\.tsx?$/, + use: [ + { + loader: 'thread-loader', + options: { workers: Math.max(2, os.cpus().length - 1) }, + }, + { loader: 'ts-loader', options: { happyPackMode: true } }, + ], + exclude: /node_modules/, + }, + { + test: /\.css$/i, + use: ['style-loader', 'css-loader'], + }, + { + test: /\.svg$/i, + issuer: /\.[jt]sx?$/, + use: ['@svgr/webpack'], + }, + { + test: /\.(png|jpe?g|gif|md|webp)$/i, + // More information here https://webpack.js.org/guides/asset-modules/ + type: 'asset', + }, + { + // See https://webpack.js.org/guides/asset-management/#loading-fonts + test: /\.(woff|woff2|eot|ttf|otf)$/i, + type: 'asset/resource', + }, + { + test: /\.ya?ml$/, + type: 'json', + use: 'yaml-loader', + }, + ], + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + plugins: [new TsconfigPathsPlugin()], + alias: { + 'react/jsx-runtime': require.resolve('react/jsx-runtime'), + }, + }, + plugins: [ + // new CleanWebpackPlugin(), + + ...(Array.isArray(htmlPath) + ? htmlPath.map((item) => new HtmlWebpackPlugin(item)) + : [ + new HtmlWebpackPlugin({ + filename: 'index.html', + template: path.resolve(baseDir, htmlPath || 'src/index.html'), + }), + ]), + + new ForkTsCheckerWebpackPlugin({ + typescript: { + mode: 'write-references', + diagnosticOptions: { + semantic: true, + syntactic: true, + }, + }, + }), + ], + output: { + path: path.resolve(baseDir, 'dist'), + publicPath: '/', + }, +}); + +module.exports = { + webpackCommon, +}; diff --git a/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/webpack.common.js b/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/webpack.common.js new file mode 100644 index 0000000000..9d86d2bc80 --- /dev/null +++ b/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/webpack.common.js @@ -0,0 +1,30 @@ +const path = require('path'); +const { mergeWithRules } = require('webpack-merge'); +const { webpackCommon } = require('./webpack.base'); + +module.exports = mergeWithRules({ + module: { + rules: { + test: 'match', + use: 'replace', + }, + }, +})( + webpackCommon(__dirname, [ + { + inject: true, + filename: 'index.html', + template: path.resolve(__dirname, 'src/index.html'), + chunks: ['index'], + }, + ]), + { + entry: { + index: path.resolve(__dirname, 'src/index.ts'), + }, + output: { + path: path.resolve(__dirname, 'dist'), + publicPath: '/', + }, + }, +); diff --git a/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/webpack.config.js b/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/webpack.config.js new file mode 100644 index 0000000000..3558bfdade --- /dev/null +++ b/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/webpack.config.js @@ -0,0 +1,71 @@ +const { mergeWithRules } = require('webpack-merge'); +const webpack = require('webpack'); +const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); +const ReactRefreshTypeScript = require('react-refresh-typescript'); +const commonConfig = require('./webpack.common'); + +module.exports = mergeWithRules({ + module: { + rules: { + test: 'match', + use: 'replace', + }, + }, +})(commonConfig, { + mode: 'development', + devtool: 'inline-source-map', + module: { + rules: [ + { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/, + options: { + getCustomTransformers: () => ({ + before: [ReactRefreshTypeScript()], + }), + // `ts-loader` does not work with HMR unless `transpileOnly` is used. + // If you need type checking, `ForkTsCheckerWebpackPlugin` is an alternative. + transpileOnly: true, + }, + }, + { + test: /\.wasm$/, + type: 'asset', + }, + ], + }, + plugins: [ + new ReactRefreshWebpackPlugin(), + + // this can be included automatically by the dev server, however build mode fails if missing + new webpack.HotModuleReplacementPlugin(), + ], + + target: 'web', + + devServer: { + headers: { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type, Authorization', + }, + historyApiFallback: true, + }, + + // recommended for faster rebuild + optimization: { + runtimeChunk: true, + removeAvailableModules: false, + removeEmptyChunks: false, + splitChunks: false, + }, + + cache: { + type: 'filesystem', + buildDependencies: { + // restart on config change + config: ['./webpack.config.js'], + }, + }, +}); diff --git a/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/webpack.plugins.js b/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/webpack.plugins.js new file mode 100644 index 0000000000..d1d3af9d2b --- /dev/null +++ b/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/webpack.plugins.js @@ -0,0 +1,19 @@ +const path = require('path'); +const CopyPlugin = require('copy-webpack-plugin'); + +module.exports = { + plugins: [ + new CopyPlugin({ + patterns: [ + { + from: path.resolve(path.dirname(require.resolve('$PACKAGE/package.json')), '*.wasm'), + to: '[name][ext]', + }, + { + from: path.resolve(path.dirname(require.resolve('$PACKAGE/package.json')), '*worker*.js'), + to: '[name][ext]', + }, + ], + }), + ], +}; diff --git a/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/webpack.prod.js b/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/webpack.prod.js new file mode 100644 index 0000000000..9bf9d4fdde --- /dev/null +++ b/sdk/typescript/tests/integration-tests/mix-fetch/template/webpack/webpack.prod.js @@ -0,0 +1,44 @@ +const { mergeWithRules } = require('webpack-merge'); +const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); +const commonConfig = require('./webpack.common'); +const { plugins } = require('./webpack.plugins'); + +module.exports = mergeWithRules({ + module: { + rules: { + test: 'match', + use: 'replace', + }, + }, +})(commonConfig, { + mode: 'production', + + // TODO: no source maps, add back + devtool: false, + + module: { + rules: [ + { + test: /\.css$/, + use: [MiniCssExtractPlugin.loader, 'css-loader'], + }, + ], + }, + optimization: { + minimizer: ['...', new CssMinimizerPlugin()], + splitChunks: { + chunks: 'all', + }, + }, + plugins: [ + new MiniCssExtractPlugin({ + filename: '[name].[contenthash].css', + }), + ...plugins, + ], + output: { + pathinfo: false, + filename: '[name].[contenthash].js', + }, +}); diff --git a/sdk/typescript/tests/integration-tests/mix-fetch/template/workspace/package.json b/sdk/typescript/tests/integration-tests/mix-fetch/template/workspace/package.json new file mode 100644 index 0000000000..c6e6e1f1cb --- /dev/null +++ b/sdk/typescript/tests/integration-tests/mix-fetch/template/workspace/package.json @@ -0,0 +1,9 @@ +{ + "name": "integration-tests-workspace", + "version": "1.0.0", + "private": true, + "license": "Apache 2.0", + "workspaces": [ + "packages/**" + ] +} diff --git a/sdk/typescript/tests/integration-tests/mix-fetch/tests/tests.mjs b/sdk/typescript/tests/integration-tests/mix-fetch/tests/tests.mjs new file mode 100644 index 0000000000..d74f89b6c3 --- /dev/null +++ b/sdk/typescript/tests/integration-tests/mix-fetch/tests/tests.mjs @@ -0,0 +1,88 @@ +/* eslint-disable no-await-in-loop */ +import puppeteer from 'puppeteer'; + +const TIMEOUT = 30_000; + +function sleep(time) { + return new Promise((resolve) => { + setTimeout(resolve, time); + }); +} + +export async function runTests(log) { + console.log('🟡 Starting puppeteer'); + // launch Chrome and navigate + const browser = await puppeteer.launch({ headless: 'new' }); + const page = await browser.newPage(); + await page.setDefaultNavigationTimeout(TIMEOUT); // timeout 60 seconds now + + const errors = []; + + page.on('console', (message) => { + let isError = false; + if (message.type() === 'error') { + if (!message.location()?.url?.endsWith('favicon.ico')) { + isError = true; + const { url } = message.location(); + const type = message.type(); + const text = message.text ? message.text() : undefined; + errors.push({ type, url, text }); + } + } + if (log || isError) { + console.log(` Message: [${message.type()}] ${message.text()}`); + if (isError) { + message.stackTrace().forEach((args) => console.log(` - ${args.lineNumber}:${args.columnNumber} ${args.url}`)); + } + } + }); + + console.log(' 🟡 Navigating'); + let count = 0; + do { + await sleep(1000); + try { + const res = await page.goto('http://localhost:3000', {}); + if (res.ok()) { + break; + } + } catch (e) { + console.log(' ❌ Error', e.message); + } + count += 1; + } while (count < 5); + if (count > 5) { + await browser.close(); + throw new Error('Failed to navigate'); + } else { + console.log(' 🟡 Navigated'); + } + + // wait for start output + await page.waitForSelector('#starting'); + + if (errors.find((e) => e.url.includes('worker'))) { + console.log(' ❌ Error - worker did not load'); + return errors; + } + if (errors.length) { + console.log(' ❌ Error - worker error'); + return errors; + } + + console.log(' 🟢 Started'); + + await page.waitForSelector('#text-output', { timeout: TIMEOUT }); + console.log(' 🟢 Got text output'); + // await page.waitForSelector('#image-output'); + // console.log(' 🟢 Got image output'); + await page.waitForSelector('#done'); + console.log(' 🟢 Got done'); + + await page.close(); + await browser.close(); + + console.log(' ✅ test complete'); + + return errors; +} diff --git a/service-providers/network-requester/Cargo.toml b/service-providers/network-requester/Cargo.toml index 88c1446563..7e63ac74c1 100644 --- a/service-providers/network-requester/Cargo.toml +++ b/service-providers/network-requester/Cargo.toml @@ -3,13 +3,17 @@ [package] name = "nym-network-requester" -version = "1.1.29" +version = "1.1.30" authors.workspace = true edition.workspace = true rust-version = "1.65" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +name = "nym_network_requester" +path = "src/lib.rs" + [dependencies] async-trait = { workspace = true } bs58 = "0.4.0" diff --git a/service-providers/network-requester/src/allowed_hosts/filter.rs b/service-providers/network-requester/src/allowed_hosts/filter.rs index 77dbc6c94b..bb33bb931d 100644 --- a/service-providers/network-requester/src/allowed_hosts/filter.rs +++ b/service-providers/network-requester/src/allowed_hosts/filter.rs @@ -60,6 +60,14 @@ impl OutboundRequestFilter { } } + pub(crate) fn standard_list(&self) -> StandardList { + self.standard_list.clone() + } + + pub(crate) fn allowed_hosts(&self) -> StoredAllowedHosts { + self.allowed_hosts.clone() + } + async fn check_allowed_hosts(&self, host: &RequestHost) -> bool { let guard = self.allowed_hosts.get().await; self.check_group(&guard.data, host) diff --git a/service-providers/network-requester/src/cli/init.rs b/service-providers/network-requester/src/cli/init.rs index 24b887c039..21786c9486 100644 --- a/service-providers/network-requester/src/cli/init.rs +++ b/service-providers/network-requester/src/cli/init.rs @@ -13,7 +13,10 @@ use nym_bin_common::output_format::OutputFormat; use nym_client_core::client::base_client::storage::gateway_details::OnDiskGatewayDetails; use nym_client_core::client::key_manager::persistence::OnDiskKeys; use nym_client_core::config::GatewayEndpointConfig; -use nym_client_core::init::GatewaySetup; +use nym_client_core::error::ClientCoreError; +use nym_client_core::init::helpers::current_gateways; +use nym_client_core::init::types::GatewaySetup; +use nym_client_core::init::types::{GatewayDetails, GatewaySelectionSpecification}; use nym_crypto::asymmetric::identity; use nym_sphinx::addressing::clients::Recipient; use serde::Serialize; @@ -91,14 +94,18 @@ impl From for OverrideConfig { #[derive(Debug, Serialize)] pub struct InitResults { #[serde(flatten)] - client_core: nym_client_core::init::InitResults, + client_core: nym_client_core::init::types::InitResults, client_address: String, } impl InitResults { fn new(config: &Config, address: &Recipient, gateway: &GatewayEndpointConfig) -> Self { Self { - client_core: nym_client_core::init::InitResults::new(&config.base, address, gateway), + client_core: nym_client_core::init::types::InitResults::new( + &config.base, + address, + gateway, + ), client_address: address.to_string(), } } @@ -150,9 +157,10 @@ pub(crate) async fn execute(args: &Init) -> Result<(), NetworkRequesterError> { // Attempt to use a user-provided gateway, if possible let user_chosen_gateway_id = args.gateway; - let gateway_setup = GatewaySetup::new_fresh( + let selection_spec = GatewaySelectionSpecification::new( user_chosen_gateway_id.map(|id| id.to_base58_string()), Some(args.latency_based_selection), + false, ); // Load and potentially override config @@ -164,16 +172,22 @@ pub(crate) async fn execute(args: &Init) -> Result<(), NetworkRequesterError> { let key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone()); let details_store = OnDiskGatewayDetails::new(&config.storage_paths.common_paths.gateway_details); - let init_details = nym_client_core::init::setup_gateway( - gateway_setup, - &key_store, - &details_store, - register_gateway, - Some(&config.base.client.nym_api_urls), - ) - .await - .tap_err(|err| log::error!("Failed to setup gateway\nError: {err}"))? - .details; + + let available_gateways = { + let mut rng = rand::thread_rng(); + current_gateways(&mut rng, &config.base.client.nym_api_urls).await? + }; + + let gateway_setup = GatewaySetup::New { + specification: selection_spec, + available_gateways, + overwrite_data: register_gateway, + }; + + let init_details = + nym_client_core::init::setup_gateway(gateway_setup, &key_store, &details_store) + .await + .tap_err(|err| log::error!("Failed to setup gateway\nError: {err}"))?; let config_save_location = config.default_location(); config.save_to_default_location().tap_err(|_| { @@ -188,7 +202,10 @@ pub(crate) async fn execute(args: &Init) -> Result<(), NetworkRequesterError> { log::info!("Client configuration completed.\n"); - let init_results = InitResults::new(&config, &address, &init_details.gateway_details); + let GatewayDetails::Configured(gateway_details) = init_details.gateway_details else { + return Err(ClientCoreError::UnexpectedPersistedCustomGatewayDetails)?; + }; + let init_results = InitResults::new(&config, &address, &gateway_details); println!("{}", args.output.format(&init_results)); Ok(()) diff --git a/service-providers/network-requester/src/cli/mod.rs b/service-providers/network-requester/src/cli/mod.rs index 8a2140166e..5566de0e93 100644 --- a/service-providers/network-requester/src/cli/mod.rs +++ b/service-providers/network-requester/src/cli/mod.rs @@ -20,7 +20,6 @@ use nym_client_core::client::key_manager::persistence::OnDiskKeys; use nym_client_core::config::GatewayEndpointConfig; use nym_client_core::error::ClientCoreError; use nym_config::OptionalSet; -use nym_sphinx::params::PacketSize; mod build_info; mod init; @@ -88,32 +87,42 @@ pub(crate) struct OverrideConfig { statistics_recipient: Option, } -pub(crate) fn override_config(config: Config, args: OverrideConfig) -> Config { - // These flags have overlapping effects, meaning the order matters here. Making it a bit messy. - // Since a big chunk of these are hidden experimental flags there is hope we can remove them - // soonish and clean this up. +// NOTE: make sure this is in sync with `gateway/src/commands/helpers.rs::override_network_requester_config` +pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config { + // as of 12.09.23 the below is true (not sure how this comment will rot in the future) + // medium_toggle: + // - sets secondary packet size to 16kb + // - disables poisson distribution of the main traffic stream + // - sets the cover traffic stream to 1 packet / 5s (on average) + // - disables per hop delay + // + // fastmode (to be renamed to `fast-poisson`): + // - sets average per hop delay to 10ms + // - sets the cover traffic stream to 1 packet / 2000s (on average); for all intents and purposes it disables the stream + // - sets the poisson distribution of the main traffic stream to 4ms, i.e. 250 packets / s on average + // + // no_cover: + // - disables poisson distribution of the main traffic stream + // - disables the secondary cover traffic stream + + // disable poisson rate in the BASE client if the NR option is enabled + if config.network_requester.disable_poisson_rate { + config.set_no_poisson_process(); + } + + // those should be enforced by `clap` when parsing the arguments + if args.medium_toggle { + assert!(!args.fastmode); + assert!(!args.no_cover); - let disable_cover_traffic_with_keepalive = - config.network_requester.disable_poisson_rate || args.medium_toggle; - let secondary_packet_size = args.medium_toggle.then_some(PacketSize::ExtendedPacket16); - let no_per_hop_delays = args.medium_toggle; + config.set_medium_toggle(); + } config .with_base( BaseClientConfig::with_high_default_traffic_volume, args.fastmode, ) - .with_base( - // NOTE: This interacts with disabling cover traffic fully, so we want to this to be set before - BaseClientConfig::with_disabled_cover_traffic_with_keepalive, - disable_cover_traffic_with_keepalive, - ) - .with_base( - BaseClientConfig::with_secondary_packet_size, - secondary_packet_size, - ) - .with_base(BaseClientConfig::with_no_per_hop_delays, no_per_hop_delays) - // NOTE: see comment above about the order of the other disble cover traffic config .with_base(BaseClientConfig::with_disabled_cover_traffic, args.no_cover) .with_optional_base_custom_env( BaseClientConfig::with_custom_nym_apis, @@ -162,7 +171,7 @@ fn persist_gateway_details( source: Box::new(source), }) })?; - let persisted_details = PersistedGatewayDetails::new(details, &shared_keys); + let persisted_details = PersistedGatewayDetails::new(details.into(), Some(&shared_keys))?; details_store .store_to_disk(&persisted_details) .map_err(|source| { diff --git a/service-providers/network-requester/src/cli/run.rs b/service-providers/network-requester/src/cli/run.rs index a2ca949675..577e14f8e0 100644 --- a/service-providers/network-requester/src/cli/run.rs +++ b/service-providers/network-requester/src/cli/run.rs @@ -38,16 +38,21 @@ pub(crate) struct Run { /// Mostly debug-related option to increase default traffic rate so that you would not need to /// modify config post init - #[arg(long, hide = true)] + #[arg(long, hide = true, conflicts_with = "medium_toggle")] fastmode: bool, /// Disable loop cover traffic and the Poisson rate limiter (for debugging only) - #[arg(long, hide = true)] + #[arg(long, hide = true, conflicts_with = "medium_toggle")] no_cover: bool, /// Enable medium mixnet traffic, for experiments only. /// This includes things like disabling cover traffic, no per hop delays, etc. - #[arg(long, hide = true)] + #[arg( + long, + hide = true, + conflicts_with = "no_cover", + conflicts_with = "fastmode" + )] medium_toggle: bool, } @@ -94,6 +99,6 @@ pub(crate) async fn execute(args: &Run) -> Result<(), NetworkRequesterError> { } log::info!("Starting socks5 service provider"); - let server = crate::core::NRServiceProviderBuilder::new(config).await; + let server = crate::core::NRServiceProviderBuilder::new(config); server.run_service_provider().await } diff --git a/service-providers/network-requester/src/config/mod.rs b/service-providers/network-requester/src/config/mod.rs index 0298d6caaa..b26ec1ff20 100644 --- a/service-providers/network-requester/src/config/mod.rs +++ b/service-providers/network-requester/src/config/mod.rs @@ -17,6 +17,7 @@ use std::time::Duration; pub use nym_client_core::config::Config as BaseClientConfig; pub use nym_client_core::config::{DebugConfig, GatewayEndpointConfig}; +use nym_sphinx::params::PacketSize; pub mod old_config_v1_1_13; pub mod old_config_v1_1_20; @@ -56,7 +57,7 @@ pub fn default_data_directory>(id: P) -> PathBuf { .join(DEFAULT_DATA_DIR) } -#[derive(Debug, Deserialize, PartialEq, Serialize)] +#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)] #[serde(deny_unknown_fields)] pub struct Config { #[serde(flatten)] @@ -74,7 +75,7 @@ pub struct Config { } impl NymConfigTemplate for Config { - fn template() -> &'static str { + fn template(&self) -> &'static str { CONFIG_TEMPLATE } } @@ -84,12 +85,20 @@ impl Config { Config { base: BaseClientConfig::new(id.as_ref(), env!("CARGO_PKG_VERSION")), network_requester: Default::default(), - storage_paths: NetworkRequesterPaths::new_default(default_data_directory(id.as_ref())), + storage_paths: NetworkRequesterPaths::new_base(default_data_directory(id.as_ref())), network_requester_debug: Default::default(), logging: Default::default(), } } + // this is a false positive, this method is actually called when used as a library + // but clippy complains about it when building the binary + #[allow(unused)] + pub fn with_data_directory>(mut self, data_directory: P) -> Self { + self.storage_paths = NetworkRequesterPaths::new_base(data_directory); + self + } + pub fn read_from_toml_file>(path: P) -> io::Result { read_config_from_toml_file(path) } @@ -112,6 +121,20 @@ impl Config { self.base.validate() } + /// Enable medium mixnet traffic, for experiments only. + /// This includes things like disabling cover traffic, no per hop delays, etc. + #[doc(hidden)] + pub fn set_medium_toggle(&mut self) { + self.base.set_no_cover_traffic_with_keepalive(); + self.base.set_no_per_hop_delays(); + self.base.debug.traffic.secondary_packet_size = Some(PacketSize::ExtendedPacket16); + } + + #[doc(hidden)] + pub fn set_no_poisson_process(&mut self) { + self.base.set_no_poisson_process() + } + #[must_use] pub fn with_open_proxy(mut self, open_proxy: bool) -> Self { self.network_requester.open_proxy = open_proxy; @@ -190,9 +213,8 @@ pub struct NetworkRequester { /// in case of enabled statistics, specifies mixnet client address where a statistics aggregator is running pub statistics_recipient: Option, - /// Disable Poisson sending rate, and only send cover traffic occasionally as keepalive messages. + /// Disable Poisson sending rate. /// This is equivalent to setting debug.traffic.disable_main_poisson_packet_distribution = true, - /// and debug.cover_traffic.loop_cover_traffic_average_delay = 5s. pub disable_poisson_rate: bool, } diff --git a/service-providers/network-requester/src/config/persistence.rs b/service-providers/network-requester/src/config/persistence.rs index a8aa09f18e..563116933d 100644 --- a/service-providers/network-requester/src/config/persistence.rs +++ b/service-providers/network-requester/src/config/persistence.rs @@ -27,11 +27,11 @@ pub struct NetworkRequesterPaths { } impl NetworkRequesterPaths { - pub fn new_default>(base_data_directory: P) -> Self { + pub fn new_base>(base_data_directory: P) -> Self { let base_dir = base_data_directory.as_ref(); NetworkRequesterPaths { - common_paths: CommonClientPaths::new_default(base_dir), + common_paths: CommonClientPaths::new_base(base_dir), allowed_list_location: base_dir.join(DEFAULT_ALLOWED_LIST_FILENAME), unknown_list_location: base_dir.join(DEFAULT_UNKNOWN_LIST_FILENAME), nr_description: base_dir.join(DEFAULT_DESCRIPTION_FILENAME), diff --git a/service-providers/network-requester/src/config/template.rs b/service-providers/network-requester/src/config/template.rs index 1c701f5f94..a6aebee454 100644 --- a/service-providers/network-requester/src/config/template.rs +++ b/service-providers/network-requester/src/config/template.rs @@ -91,9 +91,8 @@ enabled_statistics = {{ network_requester.enabled_statistics }} # in case of enabled statistics, specifies mixnet client address where a statistics aggregator is running statistics_recipient = '{{ network_requester.statistics_recipient }}' -# Disable Poisson sending rate, and only send cover traffic occasionally as keepalive messages. +# Disable Poisson sending rate # This is equivalent to setting debug.traffic.disable_main_poisson_packet_distribution = true, -# and debug.cover_traffic.loop_cover_traffic_average_delay = 5s. disable_poisson_rate = {{ network_requester.disable_poisson_rate }} ##### logging configuration options ##### diff --git a/service-providers/network-requester/src/core.rs b/service-providers/network-requester/src/core.rs index 8d743e3c03..0bad4c36e7 100644 --- a/service-providers/network-requester/src/core.rs +++ b/service-providers/network-requester/src/core.rs @@ -1,7 +1,6 @@ // Copyright 2020-2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::allowed_hosts; use crate::allowed_hosts::standard_list::StandardListUpdater; use crate::allowed_hosts::stored_allowed_hosts::{start_allowed_list_reloader, StoredAllowedHosts}; use crate::allowed_hosts::{OutboundRequestFilter, StandardList}; @@ -9,14 +8,17 @@ use crate::config::{BaseClientConfig, Config}; use crate::error::NetworkRequesterError; use crate::reply::MixnetMessage; use crate::statistics::ServiceStatisticsCollector; -use crate::{reply, socks5}; +use crate::{allowed_hosts, reply, socks5}; use async_trait::async_trait; -use futures::channel::mpsc; -use log::warn; +use futures::channel::{mpsc, oneshot}; +use futures::stream::StreamExt; +use log::{debug, warn}; use nym_bin_common::bin_info_owned; +use nym_client_core::client::mix_traffic::transceiver::GatewayTransceiver; use nym_client_core::config::disk_persistence::CommonClientPaths; +use nym_client_core::HardcodedTopologyProvider; use nym_network_defaults::NymNetworkDetails; -use nym_sdk::mixnet::MixnetMessageSender; +use nym_sdk::mixnet::{MixnetMessageSender, TopologyProvider}; use nym_service_providers_common::interface::{ BinaryInformation, ProviderInterfaceVersion, Request, RequestVersion, }; @@ -33,9 +35,12 @@ use nym_socks5_requests::{ use nym_sphinx::addressing::clients::Recipient; use nym_sphinx::anonymous_replies::requests::AnonymousSenderTag; use nym_sphinx::params::PacketSize; +use nym_sphinx::receiver::ReconstructedMessage; use nym_statistics_common::collector::StatisticsSender; use nym_task::connections::LaneQueueLengths; -use nym_task::{TaskClient, TaskManager}; +use nym_task::manager::TaskHandle; +use nym_task::TaskClient; +use std::path::Path; use std::sync::atomic::{AtomicUsize, Ordering}; // Since it's an atomic, it's safe to be kept static and shared across threads @@ -48,25 +53,40 @@ pub(crate) fn new_legacy_request_version() -> RequestVersion { } } +pub struct OnStartData { + // to add more fields as required + pub address: Recipient, +} + +impl OnStartData { + fn new(address: Recipient) -> Self { + Self { address } + } +} + // TODO: 'Builder' is not the most appropriate name here, but I needed // ... something ... pub struct NRServiceProviderBuilder { config: Config, outbound_request_filter: OutboundRequestFilter, - standard_list: StandardList, - allowed_hosts: StoredAllowedHosts, + + wait_for_gateway: bool, + custom_topology_provider: Option>, + custom_gateway_transceiver: Option>, + shutdown: Option, + on_start: Option>, } -struct NRServiceProvider { +pub struct NRServiceProvider { config: Config, - outbound_request_filter: OutboundRequestFilter, - mixnet_client: nym_sdk::mixnet::MixnetClient, + mixnet_client: nym_sdk::mixnet::MixnetClient, controller_sender: ControllerSender, + mix_input_sender: MixProxySender, stats_collector: Option, - shutdown: TaskManager, + shutdown: TaskHandle, } #[async_trait] @@ -78,6 +98,7 @@ impl ServiceProvider for NRServiceProvider { sender: Option, request: Request, ) -> Result<(), Self::ServiceProviderError> { + // TODO: this should perhaps be parallelised log::debug!("on_request {:?}", request); if let Some(response) = self.handle_request(sender, request).await? { // TODO: this (i.e. `reply::MixnetAddress`) should be incorporated into the actual interface @@ -157,7 +178,7 @@ impl ServiceProvider for NRServiceProvider { } impl NRServiceProviderBuilder { - pub async fn new(config: Config) -> NRServiceProviderBuilder { + pub fn new(config: Config) -> NRServiceProviderBuilder { let standard_list = StandardList::new(); let allowed_hosts = StoredAllowedHosts::new(&config.storage_paths.allowed_list_location); @@ -170,11 +191,77 @@ impl NRServiceProviderBuilder { NRServiceProviderBuilder { config, outbound_request_filter, - standard_list, - allowed_hosts, + wait_for_gateway: false, + custom_topology_provider: None, + custom_gateway_transceiver: None, + shutdown: None, + on_start: None, } } + #[must_use] + // this is a false positive, this method is actually called when used as a library + // but clippy complains about it when building the binary + #[allow(unused)] + pub fn with_shutdown(mut self, shutdown: TaskClient) -> Self { + self.shutdown = Some(shutdown); + self + } + + #[must_use] + // this is a false positive, this method is actually called when used as a library + // but clippy complains about it when building the binary + #[allow(unused)] + pub fn with_custom_gateway_transceiver( + mut self, + gateway_transceiver: Box, + ) -> Self { + self.custom_gateway_transceiver = Some(gateway_transceiver); + self + } + + #[must_use] + // this is a false positive, this method is actually called when used as a library + // but clippy complains about it when building the binary + #[allow(unused)] + pub fn with_wait_for_gateway(mut self, wait_for_gateway: bool) -> Self { + self.wait_for_gateway = wait_for_gateway; + self + } + + #[must_use] + // this is a false positive, this method is actually called when used as a library + // but clippy complains about it when building the binary + #[allow(unused)] + pub fn with_on_start(mut self, on_start: oneshot::Sender) -> Self { + self.on_start = Some(on_start); + self + } + + #[must_use] + // this is a false positive, this method is actually called when used as a library + // but clippy complains about it when building the binary + #[allow(unused)] + pub fn with_custom_topology_provider( + mut self, + topology_provider: Box, + ) -> Self { + self.custom_topology_provider = Some(topology_provider); + self + } + + // this is a false positive, this method is actually called when used as a library + // but clippy complains about it when building the binary + #[allow(unused)] + pub fn with_stored_topology>( + mut self, + file: P, + ) -> Result { + self.custom_topology_provider = + Some(Box::new(HardcodedTopologyProvider::new_from_file(file)?)); + Ok(self) + } + /// Start all subsystems pub async fn run_service_provider(self) -> Result<(), NetworkRequesterError> { let stats_provider_addr = self @@ -186,22 +273,30 @@ impl NRServiceProviderBuilder { .transpose() .unwrap_or(None); + // Used to notify tasks to shutdown. Not all tasks fully supports this (yet). + let shutdown: TaskHandle = self.shutdown.map(Into::into).unwrap_or_default(); + // Connect to the mixnet - let mixnet_client = - create_mixnet_client(&self.config.base, &self.config.storage_paths.common_paths) - .await?; + let mixnet_client = create_mixnet_client( + &self.config.base, + shutdown.get_handle().named("nym_sdk::MixnetClient"), + self.custom_gateway_transceiver, + self.custom_topology_provider, + self.wait_for_gateway, + &self.config.storage_paths.common_paths, + ) + .await?; // channels responsible for managing messages that are to be sent to the mix network. The receiver is // going to be used by `mixnet_response_listener` let (mix_input_sender, mix_input_receiver) = tokio::sync::mpsc::channel::(1); - // Used to notify tasks to shutdown. Not all tasks fully supports this (yet). - let shutdown = nym_task::TaskManager::default(); - // Controller for managing all active connections. let (mut active_connections_controller, controller_sender) = Controller::new( mixnet_client.connection_command_sender(), - shutdown.subscribe(), + shutdown + .get_handle() + .named("nym_socks5_proxy_helpers::connection_controller::Controller"), ); tokio::spawn(async move { @@ -242,15 +337,19 @@ impl NRServiceProviderBuilder { self.config .network_requester_debug .standard_list_update_interval, - self.standard_list, - shutdown.subscribe(), + self.outbound_request_filter.standard_list(), + shutdown.get_handle().named("StandardListUpdater"), ) .start(); // start the allowed.list watcher and updater - start_allowed_list_reloader(self.allowed_hosts, shutdown.subscribe()).await; + start_allowed_list_reloader( + self.outbound_request_filter.allowed_hosts(), + shutdown.get_handle().named("stored_allowed_hosts_reloader"), + ) + .await; - let service_provider = NRServiceProvider { + let mut service_provider = NRServiceProvider { config: self.config, outbound_request_filter: self.outbound_request_filter, mixnet_client, @@ -260,40 +359,61 @@ impl NRServiceProviderBuilder { shutdown, }; - log::info!("The address of this client is: {}", self_address); + log::info!("The address of this client is: {self_address}"); log::info!("All systems go. Press CTRL-C to stop the server."); + + if let Some(on_start) = self.on_start { + if on_start.send(OnStartData::new(self_address)).is_err() { + // the parent has dropped the channel before receiving the response + return Err(NetworkRequesterError::DisconnectedParent); + } + } + service_provider.run().await } } impl NRServiceProvider { - async fn run(mut self) -> Result<(), NetworkRequesterError> { - // TODO: incorporate graceful shutdowns - while let Some(reconstructed_messages) = self.mixnet_client.wait_for_messages().await { - for reconstructed in reconstructed_messages { - let sender = reconstructed.sender_tag; - let request = match Socks5ProviderRequest::try_from_bytes(&reconstructed.message) { - Ok(req) => req, - Err(err) => { - // TODO: or should it even be further lowered to debug/trace? - log::warn!("Failed to deserialize received message: {err}"); - continue; + async fn run(&mut self) -> Result<(), NetworkRequesterError> { + let mut shutdown = self.shutdown.fork("main_loop"); + while !shutdown.is_shutdown() { + tokio::select! { + biased; + _ = shutdown.recv() => { + debug!("NRServiceProvider [main loop]: received shutdown") + }, + msg = self.mixnet_client.next() => match msg { + Some(msg) => self.on_message(msg).await, + None => { + log::trace!("NRServiceProvider::run: Stopping since channel closed"); + break; } - }; - - if let Err(err) = self.on_request(sender, request).await { - // TODO: again, should it be a warning? - // we should also probably log some information regarding the origin of the request - // so that it would be easier to debug it - log::warn!("failed to resolve the received request: {err}"); - } + }, } } - log::error!("Network requester exited unexpectedly"); Ok(()) } + async fn on_message(&mut self, reconstructed: ReconstructedMessage) { + let sender = reconstructed.sender_tag; + let request = match Socks5ProviderRequest::try_from_bytes(&reconstructed.message) { + Ok(req) => req, + Err(err) => { + // TODO: or should it even be further lowered to debug/trace? + log::warn!("Failed to deserialize received message: {err}"); + return; + } + }; + + if let Err(err) = self.on_request(sender, request).await { + // TODO: again, should it be a warning? + // we should also probably log some information regarding the origin of the request + // so that it would be easier to debug it + log::warn!("failed to resolve the received request: {err}"); + } + } + /// Listens for any messages from `mix_reader` that should be written back to the mix network /// via the `websocket_writer`. async fn mixnet_response_listener( @@ -352,11 +472,7 @@ impl NRServiceProvider { { Ok(conn) => conn, Err(err) => { - log::error!( - "error while connecting to {:?} ! - {:?}", - remote_addr.clone(), - err - ); + log::error!("error while connecting to {remote_addr}: {err}",); // inform the remote that the connection is closed before it even was established let mixnet_message = MixnetMessage::new_network_data_response( @@ -386,8 +502,7 @@ impl NRServiceProvider { let old_count = ACTIVE_PROXIES.fetch_add(1, Ordering::SeqCst); log::info!( - "Starting proxy for {} (currently there are {} proxies being handled)", - remote_addr, + "Starting proxy for {remote_addr} (currently there are {} proxies being handled)", old_count + 1 ); @@ -409,8 +524,7 @@ impl NRServiceProvider { let old_count = ACTIVE_PROXIES.fetch_sub(1, Ordering::SeqCst); log::info!( - "Proxy for {} is finished (currently there are {} proxies being handled)", - remote_addr, + "Proxy for {remote_addr} is finished (currently there are {} proxies being handled)", old_count - 1 ); } @@ -436,7 +550,7 @@ impl NRServiceProvider { let open_proxy = self.config.network_requester.open_proxy; if !open_proxy && !self.outbound_request_filter.check(&remote_addr).await { let log_msg = format!("Domain {remote_addr:?} failed filter check"); - log::info!("{}", log_msg); + log::info!("{log_msg}"); let msg = MixnetMessage::new_connection_error( return_address, remote_version, @@ -458,7 +572,7 @@ impl NRServiceProvider { let controller_sender_clone = self.controller_sender.clone(); let mix_input_sender_clone = self.mix_input_sender.clone(); let lane_queue_lengths_clone = self.mixnet_client.shared_lane_queue_lengths(); - let shutdown = self.shutdown.subscribe(); + let shutdown = self.shutdown.get_handle(); // and start the proxy for this connection tokio::spawn(async move { @@ -506,8 +620,13 @@ impl NRServiceProvider { // Helper function to create the mixnet client. // This is NOT in the SDK since we don't want to expose any of the client-core config types. // We could however consider moving it to a crate in common in the future. +// TODO: refactor this function and its arguments async fn create_mixnet_client( config: &BaseClientConfig, + shutdown: TaskClient, + custom_transceiver: Option>, + custom_topology_provider: Option>, + wait_for_gateway: bool, paths: &CommonClientPaths, ) -> Result { let debug_config = config.debug; @@ -519,14 +638,21 @@ async fn create_mixnet_client( .await .map_err(|err| NetworkRequesterError::FailedToSetupMixnetClient { source: err })? .network_details(NymNetworkDetails::new_from_env()) - .debug_config(debug_config); + .debug_config(debug_config) + .custom_shutdown(shutdown) + .with_wait_for_gateway(wait_for_gateway); if !config.get_disabled_credentials_mode() { client_builder = client_builder.enable_credentials_mode(); } + if let Some(gateway_transceiver) = custom_transceiver { + client_builder = client_builder.custom_gateway_transceiver(gateway_transceiver); + } + if let Some(topology_provider) = custom_topology_provider { + client_builder = client_builder.custom_topology_provider(topology_provider); + } let mixnet_client = client_builder .build() - .await .map_err(|err| NetworkRequesterError::FailedToSetupMixnetClient { source: err })?; mixnet_client diff --git a/service-providers/network-requester/src/error.rs b/service-providers/network-requester/src/error.rs index 9248273d4b..cb71cd715a 100644 --- a/service-providers/network-requester/src/error.rs +++ b/service-providers/network-requester/src/error.rs @@ -1,4 +1,4 @@ -use nym_client_core::error::ClientCoreError; +pub use nym_client_core::error::ClientCoreError; use nym_socks5_requests::Socks5RequestError; #[derive(thiserror::Error, Debug)] @@ -30,4 +30,7 @@ pub enum NetworkRequesterError { #[error("failed to connect to mixnet: {source}")] FailedToConnectToMixnet { source: nym_sdk::Error }, + + #[error("the entity wrapping the network requester has disconnected")] + DisconnectedParent, } diff --git a/service-providers/network-requester/src/lib.rs b/service-providers/network-requester/src/lib.rs new file mode 100644 index 0000000000..cc3915c481 --- /dev/null +++ b/service-providers/network-requester/src/lib.rs @@ -0,0 +1,27 @@ +// Copyright 2023 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub mod allowed_hosts; +pub mod config; +pub mod core; +pub mod error; +mod reply; +mod socks5; +mod statistics; + +pub use crate::core::{NRServiceProvider, NRServiceProviderBuilder}; +pub use config::Config; +pub use nym_client_core::{ + client::{ + base_client::storage::{gateway_details::OnDiskGatewayDetails, OnDiskPersistent}, + key_manager::persistence::OnDiskKeys, + mix_traffic::transceiver::*, + }, + init::{ + setup_gateway, + types::{ + CustomGatewayDetails, GatewayDetails, GatewaySelectionSpecification, GatewaySetup, + InitResults, InitialisationResult, + }, + }, +}; diff --git a/service-providers/network-requester/src/main.rs b/service-providers/network-requester/src/main.rs index 89ac717d37..76e9349a7e 100644 --- a/service-providers/network-requester/src/main.rs +++ b/service-providers/network-requester/src/main.rs @@ -2,11 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 use clap::{crate_name, crate_version, Parser}; +use error::NetworkRequesterError; use nym_bin_common::logging::{maybe_print_banner, setup_logging}; use nym_network_defaults::setup_env; -use error::NetworkRequesterError; - mod allowed_hosts; mod cli; mod config; diff --git a/service-providers/network-statistics/Cargo.toml b/service-providers/network-statistics/Cargo.toml index 3c40a1ee53..97d9d36cbc 100644 --- a/service-providers/network-statistics/Cargo.toml +++ b/service-providers/network-statistics/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-network-statistics" -version = "1.1.29" +version = "1.1.30" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tools/internal/sdk-version-bump/src/main.rs b/tools/internal/sdk-version-bump/src/main.rs index fe827b54a8..8ff338a2b7 100644 --- a/tools/internal/sdk-version-bump/src/main.rs +++ b/tools/internal/sdk-version-bump/src/main.rs @@ -181,16 +181,22 @@ fn initialise_internal_packages>(root: P) -> InternalPackages { packages.register_json("sdk/typescript/packages/sdk"); packages.register_json("sdk/typescript/packages/sdk-react"); packages.register_json("sdk/typescript/packages/validator-client"); + packages.register_json("sdk/typescript/codegen/contract-clients"); + packages.register_json("sdk/typescript/docs"); // dependencies that will have their versions adjusted in the above packages packages.register_known_js_dependency("@nymproject/mix-fetch"); + packages.register_known_js_dependency("@nymproject/mix-fetch-full-fat"); packages.register_known_js_dependency("@nymproject/mui-theme"); packages.register_known_js_dependency("@nymproject/node-tester"); packages.register_known_js_dependency("@nymproject/react-components"); packages.register_known_js_dependency("@nymproject/sdk"); + packages.register_known_js_dependency("@nymproject/sdk-full-fat"); packages.register_known_js_dependency("@nymproject/sdk-react"); packages.register_known_js_dependency("@nymproject/react"); packages.register_known_js_dependency("@nymproject/nym-validator-client"); + packages.register_known_js_dependency("@nymproject/ts-sdk-docs"); + packages.register_known_js_dependency("@nymproject/contract-clients"); packages } diff --git a/tools/nym-cli/Cargo.toml b/tools/nym-cli/Cargo.toml index deaa5dd10b..def3dc32eb 100644 --- a/tools/nym-cli/Cargo.toml +++ b/tools/nym-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nym-cli" -version = "1.1.29" +version = "1.1.30" authors.workspace = true edition = "2021" diff --git a/tools/nym-nr-query/src/main.rs b/tools/nym-nr-query/src/main.rs index 2de1c08468..362e1312ff 100644 --- a/tools/nym-nr-query/src/main.rs +++ b/tools/nym-nr-query/src/main.rs @@ -1,5 +1,3 @@ -use std::fmt; - use clap::{Parser, ValueEnum}; use nym_bin_common::output_format::OutputFormat; use nym_sdk::mixnet::{self, IncludedSurbs, MixnetMessageSender}; @@ -10,6 +8,7 @@ use nym_socks5_requests::{ QueryRequest, QueryResponse, Socks5ProtocolVersion, Socks5Request, Socks5Response, }; use serde::Serialize; +use std::fmt; use tokio::time::{timeout, Duration}; const RESPONSE_TIMEOUT: Duration = Duration::from_secs(10); @@ -109,7 +108,6 @@ async fn connect_to_mixnet(gateway: Option) -> mixnet::Mix Some(gateway) => mixnet::MixnetClientBuilder::new_ephemeral() .request_gateway(gateway.to_base58_string()) .build() - .await .expect("Failed to create mixnet client") .connect_to_mixnet() .await diff --git a/wasm/client/Cargo.toml b/wasm/client/Cargo.toml index 1642f95ec1..9d56ca70f8 100644 --- a/wasm/client/Cargo.toml +++ b/wasm/client/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "nym-client-wasm" authors = ["Dave Hrycyszyn ", "Jedrzej Stuczynski "] -version = "1.2.0-rc.2" +version = "1.2.0-rc.9" edition = "2021" keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy", "client"] license = "Apache-2.0" @@ -40,7 +40,3 @@ node-tester = ["nym-node-tester-wasm", "nym-node-tester-utils"] [package.metadata.wasm-pack.profile.release] wasm-opt = false - -[profile.release] -lto = true -opt-level = 'z' diff --git a/wasm/client/Makefile b/wasm/client/Makefile index 43a0cf5940..37afc17cff 100644 --- a/wasm/client/Makefile +++ b/wasm/client/Makefile @@ -2,6 +2,11 @@ build: wasm-pack build --scope nymproject --target web --out-dir ../../dist/wasm/client wasm-opt -Oz -o ../../dist/wasm/client/nym_client_wasm_bg.wasm ../../dist/wasm/client/nym_client_wasm_bg.wasm -build-node: +build-rust-node: wasm-pack build --scope nymproject --target nodejs --out-dir ../../dist/node/wasm/client - wasm-opt -Oz -o ../../dist/node/wasm/client/nym_client_wasm_bg.wasm ../../dist/node/wasm/client/nym_client_wasm_bg.wasm \ No newline at end of file + wasm-opt -Oz -o ../../dist/node/wasm/client/nym_client_wasm_bg.wasm ../../dist/node/wasm/client/nym_client_wasm_bg.wasm + +build-package-json-node: + node build-node.mjs + +build-node: build-rust-node build-package-json-node diff --git a/wasm/client/build-node.mjs b/wasm/client/build-node.mjs new file mode 100644 index 0000000000..15f22c9a25 --- /dev/null +++ b/wasm/client/build-node.mjs @@ -0,0 +1,7 @@ +import fs from 'fs'; + +const packageJson = JSON.parse(fs.readFileSync('../../dist/node/wasm/client/package.json').toString()); + +packageJson.name = `${packageJson.name}-node`; + +fs.writeFileSync('../../dist/node/wasm/client/package.json', JSON.stringify(packageJson, null, 2)); diff --git a/wasm/client/internal-dev/yarn.lock b/wasm/client/internal-dev/yarn.lock index 3555ea6145..d74175fc43 100644 --- a/wasm/client/internal-dev/yarn.lock +++ b/wasm/client/internal-dev/yarn.lock @@ -74,7 +74,7 @@ fastq "^1.6.0" "@nymproject/nym-client-wasm@file:../../../dist/wasm/client": - version "1.1.1" + version "1.2.0-rc.2" "@types/body-parser@*": version "1.19.2" @@ -445,11 +445,6 @@ array-flatten@^2.1.2: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== -array-union@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-3.0.1.tgz#da52630d327f8b88cfbfb57728e2af5cd9b6b975" - integrity sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw== - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -642,14 +637,14 @@ cookie@0.5.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== -copy-webpack-plugin@^10.2.4: - version "10.2.4" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz#6c854be3fdaae22025da34b9112ccf81c63308fe" - integrity sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg== +copy-webpack-plugin@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz#96d4dbdb5f73d02dd72d0528d1958721ab72e04a" + integrity sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ== dependencies: - fast-glob "^3.2.7" + fast-glob "^3.2.11" glob-parent "^6.0.1" - globby "^12.0.2" + globby "^13.1.1" normalize-path "^3.0.0" schema-utils "^4.0.0" serialize-javascript "^6.0.0" @@ -873,10 +868,10 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.2.7: - version "3.2.12" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" - integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== +fast-glob@^3.2.11, fast-glob@^3.3.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -1016,15 +1011,14 @@ glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -globby@^12.0.2: - version "12.2.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-12.2.0.tgz#2ab8046b4fba4ff6eede835b29f678f90e3d3c22" - integrity sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA== +globby@^13.1.1: + version "13.2.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-13.2.2.tgz#63b90b1bf68619c2135475cbd4e71e66aa090592" + integrity sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w== dependencies: - array-union "^3.0.1" dir-glob "^3.0.1" - fast-glob "^3.2.7" - ignore "^5.1.9" + fast-glob "^3.3.0" + ignore "^5.2.4" merge2 "^1.4.1" slash "^4.0.0" @@ -1138,7 +1132,7 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -ignore@^5.1.9: +ignore@^5.2.4: version "5.2.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== diff --git a/wasm/client/src/client.rs b/wasm/client/src/client.rs index e736d972b2..7586281e23 100644 --- a/wasm/client/src/client.rs +++ b/wasm/client/src/client.rs @@ -19,12 +19,12 @@ use wasm_client_core::config::r#override::DebugWasmOverride; use wasm_client_core::helpers::{ parse_recipient, parse_sender_tag, setup_from_topology, setup_gateway_from_api, }; -use wasm_client_core::init::GatewaySetup; +use wasm_client_core::init::types::GatewaySetup; use wasm_client_core::nym_task::connections::TransmissionLane; use wasm_client_core::nym_task::TaskManager; use wasm_client_core::storage::core_client_traits::FullWasmClientStorage; use wasm_client_core::storage::ClientStorage; -use wasm_client_core::topology::WasmNymTopology; +use wasm_client_core::topology::{SerializableNymTopology, SerializableTopologyExt}; use wasm_client_core::{ HardcodedTopologyProvider, IdentityKey, NymTopology, PacketType, QueryReqwestRpcNyxdClient, TopologyProvider, @@ -95,7 +95,7 @@ impl NymClientBuilder { // NOTE: you most likely want to use `[NymNodeTester]` instead. #[cfg(feature = "node-tester")] pub fn new_tester( - topology: WasmNymTopology, + topology: SerializableNymTopology, on_message: js_sys::Function, gateway: Option, ) -> Result { @@ -149,9 +149,9 @@ impl NymClientBuilder { // if we provided hardcoded topology, get gateway from it, otherwise get it the 'standard' way let init_res = if let Some(topology) = &self.custom_topology { - setup_from_topology(user_chosen, topology, &client_store).await? + setup_from_topology(user_chosen, false, topology, &client_store).await? } else { - setup_gateway_from_api(&client_store, user_chosen, &nym_api_endpoints).await? + setup_gateway_from_api(&client_store, false, user_chosen, &nym_api_endpoints).await? }; let packet_type = self.config.base.debug.traffic.packet_type; @@ -166,11 +166,9 @@ impl NymClientBuilder { if let Some(topology_provider) = maybe_topology_provider { base_builder = base_builder.with_topology_provider(topology_provider); } - if let Some(authenticated_ephemeral_client) = init_res.authenticated_ephemeral_client { - base_builder = base_builder.with_gateway_setup(GatewaySetup::ReuseConnection { - authenticated_ephemeral_client, - details: init_res.details, - }); + + if let Ok(reuse_setup) = GatewaySetup::try_reuse_connection(init_res) { + base_builder = base_builder.with_gateway_setup(reuse_setup); } let mut started_client = base_builder.start_base().await?; @@ -186,7 +184,8 @@ impl NymClientBuilder { client_input: Arc::new(client_input), client_state: Arc::new(started_client.client_state), _full_topology: None, - _task_manager: started_client.task_manager, + // this cannot failed as we haven't passed an external task manager + _task_manager: started_client.task_handle.try_into_task_manager().unwrap(), packet_type, }) } @@ -315,7 +314,7 @@ impl NymClient { .mix_test_request(test_id, mixnode_identity, num_test_packets) } - pub fn change_hardcoded_topology(&self, topology: WasmNymTopology) -> Promise { + pub fn change_hardcoded_topology(&self, topology: SerializableNymTopology) -> Promise { self.client_state.change_hardcoded_topology(topology) } diff --git a/wasm/client/src/helpers.rs b/wasm/client/src/helpers.rs index c4c234c880..16650294c7 100644 --- a/wasm/client/src/helpers.rs +++ b/wasm/client/src/helpers.rs @@ -8,7 +8,7 @@ use wasm_bindgen_futures::future_to_promise; use wasm_client_core::client::base_client::{ClientInput, ClientState}; use wasm_client_core::client::inbound_messages::InputMessage; use wasm_client_core::error::WasmCoreError; -use wasm_client_core::topology::WasmNymTopology; +use wasm_client_core::topology::SerializableNymTopology; use wasm_client_core::{MixLayer, NymTopology}; use wasm_utils::error::simple_js_error; use wasm_utils::{check_promise_result, console_log}; @@ -36,7 +36,7 @@ pub struct NymClientTestRequest { #[cfg(feature = "node-tester")] #[wasm_bindgen] impl NymClientTestRequest { - pub fn injectable_topology(&self) -> WasmNymTopology { + pub fn injectable_topology(&self) -> SerializableNymTopology { self.testable_topology.clone().into() } } @@ -78,7 +78,7 @@ impl InputSender for Arc { pub(crate) trait WasmTopologyExt { /// Changes the current network topology to the provided value. - fn change_hardcoded_topology(&self, topology: WasmNymTopology) -> Promise; + fn change_hardcoded_topology(&self, topology: SerializableNymTopology) -> Promise; /// Returns the current network topology. fn current_topology(&self) -> Promise; @@ -99,7 +99,7 @@ pub(crate) trait WasmTopologyTestExt { } impl WasmTopologyExt for Arc { - fn change_hardcoded_topology(&self, topology: WasmNymTopology) -> Promise { + fn change_hardcoded_topology(&self, topology: SerializableNymTopology) -> Promise { let nym_topology: NymTopology = check_promise_result!(topology.try_into()); let this = Arc::clone(self); @@ -116,10 +116,10 @@ impl WasmTopologyExt for Arc { let this = Arc::clone(self); future_to_promise(async move { match this.topology_accessor.current_topology().await { - Some(topology) => Ok(serde_wasm_bindgen::to_value(&WasmNymTopology::from( + Some(topology) => Ok(serde_wasm_bindgen::to_value(&SerializableNymTopology::from( topology, )) - .expect("WasmNymTopology failed serialization")), + .expect("SerializableNymTopology failed serialization")), None => Err(WasmCoreError::UnavailableNetworkTopology.into()), } }) diff --git a/wasm/full-nym-wasm/Cargo.toml b/wasm/full-nym-wasm/Cargo.toml index 4570ba5a04..22f6619647 100644 --- a/wasm/full-nym-wasm/Cargo.toml +++ b/wasm/full-nym-wasm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "nym-wasm-sdk" authors = ["Jedrzej Stuczynski "] -version = "1.2.0-rc.2" +version = "1.2.0-rc.9" edition = "2021" keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy"] license = "Apache-2.0" @@ -27,6 +27,3 @@ mix-fetch = ["mix-fetch-wasm"] [package.metadata.wasm-pack.profile.release] wasm-opt = false -[profile.release] -lto = true -opt-level = 'z' diff --git a/wasm/mix-fetch/Cargo.toml b/wasm/mix-fetch/Cargo.toml index 96f3526363..31ac8360a5 100644 --- a/wasm/mix-fetch/Cargo.toml +++ b/wasm/mix-fetch/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "mix-fetch-wasm" authors = ["Jedrzej Stuczynski "] -version = "1.2.0-rc.2" +version = "1.2.0-rc.9" edition = "2021" keywords = ["nym", "fetch", "wasm", "webassembly", "privacy"] license = "Apache-2.0" @@ -17,7 +17,7 @@ crate-type = ["cdylib", "rlib"] futures = { workspace = true } js-sys = { workspace = true } rand = { version = "0.7.3", features = ["wasm-bindgen"] } -reqwest = { workspace = true, default-features = false } +reqwest = { workspace = true } serde = { workspace = true, features = ["derive"] } serde-wasm-bindgen = { workspace = true } tokio = { workspace = true, features = ["sync"] } @@ -35,7 +35,3 @@ wasm-utils = { path = "../../common/wasm/utils" } [package.metadata.wasm-pack.profile.release] wasm-opt = false - -[profile.release] -lto = true -opt-level = 'z' diff --git a/wasm/mix-fetch/Makefile b/wasm/mix-fetch/Makefile index 776d6d35bb..56cf621097 100644 --- a/wasm/mix-fetch/Makefile +++ b/wasm/mix-fetch/Makefile @@ -2,6 +2,10 @@ build: build-go-opt build-rust build-package-json check-fmt: check-fmt-go check-fmt-rust +build-debug-dev: + wasm-pack build --scope nymproject --target no-modules + $(MAKE) -C go-mix-conn build-debug-dev + build-go: $(MAKE) -C go-mix-conn build-go diff --git a/wasm/mix-fetch/build-node.mjs b/wasm/mix-fetch/build-node.mjs index 3782ce7941..5bd3128c04 100644 --- a/wasm/mix-fetch/build-node.mjs +++ b/wasm/mix-fetch/build-node.mjs @@ -2,6 +2,8 @@ import fs from 'fs'; const packageJson = JSON.parse(fs.readFileSync('../../dist/node/wasm/mix-fetch/package.json').toString()); +packageJson.name = `${packageJson.name}-node`; + if (!packageJson.files.includes('go_conn.wasm')) { packageJson.files.push('go_conn.wasm'); } @@ -9,4 +11,4 @@ if (!packageJson.files.includes('wasm_exec.js')) { packageJson.files.push('wasm_exec.js'); } -fs.writeFileSync('../../dist/node/wasm/mix-fetch/package.json', JSON.stringify(packageJson, null, 2)); \ No newline at end of file +fs.writeFileSync('../../dist/node/wasm/mix-fetch/package.json', JSON.stringify(packageJson, null, 2)); diff --git a/wasm/mix-fetch/go-mix-conn/Makefile b/wasm/mix-fetch/go-mix-conn/Makefile index 462cb68126..6874b7d5f0 100644 --- a/wasm/mix-fetch/go-mix-conn/Makefile +++ b/wasm/mix-fetch/go-mix-conn/Makefile @@ -9,6 +9,10 @@ ifndef $(TINYGOROOT) export TINYGOROOT endif +build-debug-dev: + GOOS=js GOARCH=wasm go build -o build/go_conn.wasm ./cmd/wasm + cp "$(GOROOT)/misc/wasm/wasm_exec.js" build + build-go: GOOS=js GOARCH=wasm go build -o ../../../dist/wasm/mix-fetch/go_conn.wasm ./cmd/wasm cp "$(GOROOT)/misc/wasm/wasm_exec.js" ../../../dist/wasm/mix-fetch diff --git a/wasm/mix-fetch/go-mix-conn/build/go_conn.wasm b/wasm/mix-fetch/go-mix-conn/build/go_conn.wasm new file mode 100755 index 0000000000..0066e6d4fd Binary files /dev/null and b/wasm/mix-fetch/go-mix-conn/build/go_conn.wasm differ diff --git a/wasm/mix-fetch/go-mix-conn/internal/bridge/go_bridge/go_bridge.go b/wasm/mix-fetch/go-mix-conn/internal/bridge/go_bridge/go_bridge.go index e44c8cb9d7..db84d033f3 100644 --- a/wasm/mix-fetch/go-mix-conn/internal/bridge/go_bridge/go_bridge.go +++ b/wasm/mix-fetch/go-mix-conn/internal/bridge/go_bridge/go_bridge.go @@ -55,7 +55,7 @@ func setLoggingLevel(_ js.Value, args []js.Value) any { func mixFetch(_ js.Value, args []js.Value) (any, error) { if !rust_bridge.RsIsInitialised() { - return nil, errors.New("mix fetch hasn't been initialised") + return nil, errors.New("mix fetch is not available") } if len(args) == 0 { diff --git a/wasm/mix-fetch/internal-dev/package.json b/wasm/mix-fetch/internal-dev/package.json index 105582d79b..439def5de3 100644 --- a/wasm/mix-fetch/internal-dev/package.json +++ b/wasm/mix-fetch/internal-dev/package.json @@ -35,7 +35,7 @@ "webpack-dev-server": "^4.7.4" }, "dependencies": { - "@nymproject/nym-mix-fetch": "file:../pkg", + "@nymproject/mix-fetch-wasm": "file:../pkg", "go-mix-conn": "file:../go-mix-conn/build" } } diff --git a/wasm/mix-fetch/internal-dev/worker.js b/wasm/mix-fetch/internal-dev/worker.js index fd56187f68..57fbcf1161 100644 --- a/wasm/mix-fetch/internal-dev/worker.js +++ b/wasm/mix-fetch/internal-dev/worker.js @@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -const RUST_WASM_URL = "nym_mix_fetch_bg.wasm" -const GO_WASM_URL = "main.wasm" +const RUST_WASM_URL = "mix_fetch_wasm_bg.wasm" +const GO_WASM_URL = "go_conn.wasm" -importScripts('nym_mix_fetch.js'); +importScripts('mix_fetch_wasm.js'); importScripts('wasm_exec.js'); console.log('Initializing worker'); @@ -33,6 +33,7 @@ const { send_client_data, start_new_mixnet_connection, setupMixFetch, + disconnectMixFetch, setupMixFetchWithConfig, mix_fetch_initialised, finish_mixnet_connection} = wasm_bindgen; @@ -120,12 +121,12 @@ async function wasm_bindgenSetup() { } async function nativeSetup() { - const preferredGateway = "6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM"; - const validator = 'https://qa-nym-api.qa.nymte.ch/api'; + // const preferredGateway = "6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM"; + // const validator = 'https://qa-nym-api.qa.nymte.ch/api'; // local - const mixFetchNetworkRequesterAddress= "2o47bhnXWna6VEyt4mXMGQQAbXfpKmX7BkjkxUz8uQVi.6uQGnCqSczpXwh86NdbsCoDDXuqZQM9Uwko8GE7uC9g8@6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM"; - // const mixFetchNetworkRequesterAddress= "GqiGWmKRCbGQFSqH88BzLKijvZgipnqhmbNFsmkZw84t.4L8sXFuAUyUYyHZYgMdM3AtiusKnYUft6Pd8e41rrCHA@6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM"; + // const preferredNetworkRequester= "2o47bhnXWna6VEyt4mXMGQQAbXfpKmX7BkjkxUz8uQVi.6uQGnCqSczpXwh86NdbsCoDDXuqZQM9Uwko8GE7uC9g8@6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM"; + // const preferredNetworkRequester= "GqiGWmKRCbGQFSqH88BzLKijvZgipnqhmbNFsmkZw84t.4L8sXFuAUyUYyHZYgMdM3AtiusKnYUft6Pd8e41rrCHA@6qQYb4ArXANU6HJDxzH4PFCUqYb39Dae2Gem2KpxescM"; // those are just some examples, there are obviously more permutations; // note, the extra optional argument is of the following type: @@ -147,9 +148,9 @@ async function nativeSetup() { */ // #1 - // await setupMixFetch(mixFetchNetworkRequesterAddress) + // await setupMixFetch(preferredNetworkRequester) // #2 - // await setupMixFetch(mixFetchNetworkRequesterAddress, { nymApiUrl: validator }) + // await setupMixFetch(preferredNetworkRequester, { nymApiUrl: validator }) // // #3 const noCoverTrafficOverride = { traffic: { disableMainPoissonPacketDistribution: true }, @@ -159,7 +160,29 @@ async function nativeSetup() { requestTimeoutMs: 10000 } - await setupMixFetch(mixFetchNetworkRequesterAddress, { storagePassphrase: "foomp", nymApiUrl: validator, clientId: "my-client", clientOverride: noCoverTrafficOverride, mixFetchOverride }) + const extra = { + hiddenGateways: [ + { + owner: "LoveIslandEnjoyer", + host: "gateway1.nymtech.net", + explicitIp: "213.219.38.119", + identityKey: "E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM", + sphinxKey: "CYcrjoJ8GT7Dp54zViUyyRUfegeRCyPifWQZHRgMZrfX" + } + ] + } + + await setupMixFetch({ + // preferredNetworkRequester, + preferredGateway: "E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM", + storagePassphrase: "foomp", + forceTls: true, + // nymApiUrl: validator, + clientId: "my-client", + clientOverride: noCoverTrafficOverride, + mixFetchOverride, + extra + }) } async function testMixFetch() { @@ -179,27 +202,37 @@ async function testMixFetch() { const {target} = event.data.args; const url = target; - const controller = new AbortController(); - const signal = controller.signal; - - const args = { mode: "cors", redirect: "manual", signal } - // const args = { mode: "unsafe-ignore-cors" } - - setTimeout(() => { - console.warn("timeout") - controller.abort() - }, 10000) - + // const args = { mode: "ors", redirect: "manual", signal } + const args = { mode: "unsafe-ignore-cors" } try { console.log('using mixFetch...'); const mixFetchRes = await mixFetch(url, args) console.log(">>> MIX FETCH") await logFetchResult(mixFetchRes) + + console.log('done') + } catch(e) { console.error("mix fetch request failure: ", e) } + // console.log("will disconnect"); + // await disconnectMixFetch() + // + // try { + // console.log('using mixFetch...'); + // const mixFetchRes = await mixFetch(url, args) + // console.log(">>> MIX FETCH") + // await logFetchResult(mixFetchRes) + // + // console.log('done') + // + // } catch(e) { + // console.error("mix fetch request failure: ", e) + // } + + // try { // console.log('using normal Fetch...'); // const fetchRes = await fetch(url, args) diff --git a/wasm/mix-fetch/internal-dev/yarn.lock b/wasm/mix-fetch/internal-dev/yarn.lock index efd9b8367d..35415a23c9 100644 --- a/wasm/mix-fetch/internal-dev/yarn.lock +++ b/wasm/mix-fetch/internal-dev/yarn.lock @@ -73,8 +73,8 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@nymproject/nym-client-wasm@file:../pkg": - version "1.1.1" +"@nymproject/mix-fetch-wasm@file:../pkg": + version "1.2.0-rc.8" "@types/body-parser@*": version "1.19.2" @@ -445,11 +445,6 @@ array-flatten@^2.1.2: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== -array-union@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-3.0.1.tgz#da52630d327f8b88cfbfb57728e2af5cd9b6b975" - integrity sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw== - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -642,14 +637,14 @@ cookie@0.5.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== -copy-webpack-plugin@^10.2.4: - version "10.2.4" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz#6c854be3fdaae22025da34b9112ccf81c63308fe" - integrity sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg== +copy-webpack-plugin@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz#96d4dbdb5f73d02dd72d0528d1958721ab72e04a" + integrity sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ== dependencies: - fast-glob "^3.2.7" + fast-glob "^3.2.11" glob-parent "^6.0.1" - globby "^12.0.2" + globby "^13.1.1" normalize-path "^3.0.0" schema-utils "^4.0.0" serialize-javascript "^6.0.0" @@ -873,10 +868,10 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.2.7: - version "3.2.12" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" - integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== +fast-glob@^3.2.11, fast-glob@^3.3.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -1016,15 +1011,14 @@ glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -globby@^12.0.2: - version "12.2.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-12.2.0.tgz#2ab8046b4fba4ff6eede835b29f678f90e3d3c22" - integrity sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA== +globby@^13.1.1: + version "13.2.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-13.2.2.tgz#63b90b1bf68619c2135475cbd4e71e66aa090592" + integrity sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w== dependencies: - array-union "^3.0.1" dir-glob "^3.0.1" - fast-glob "^3.2.7" - ignore "^5.1.9" + fast-glob "^3.3.0" + ignore "^5.2.4" merge2 "^1.4.1" slash "^4.0.0" @@ -1141,7 +1135,7 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -ignore@^5.1.9: +ignore@^5.2.4: version "5.2.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== diff --git a/wasm/mix-fetch/src/active_requests.rs b/wasm/mix-fetch/src/active_requests.rs index a7407aa317..3d4e8a5f31 100644 --- a/wasm/mix-fetch/src/active_requests.rs +++ b/wasm/mix-fetch/src/active_requests.rs @@ -39,6 +39,14 @@ impl ActiveRequests { request_id } + pub async fn invalidate_all(&self) { + let mut guard = self.inner.lock().await; + for (id, _req) in guard.drain() { + let err = MixFetchError::AbortedRequest { request_id: id }; + goWasmInjectConnError(id.to_string(), err.to_string()) + } + } + pub async fn get_sending_sequence(&self, id: RequestId) -> Option { let mut guard = self.inner.lock().await; if let Some(req) = guard.get_mut(&id) { diff --git a/wasm/mix-fetch/src/client.rs b/wasm/mix-fetch/src/client.rs index 27f871feda..0f8ce4a682 100644 --- a/wasm/mix-fetch/src/client.rs +++ b/wasm/mix-fetch/src/client.rs @@ -4,28 +4,35 @@ use crate::active_requests::ActiveRequests; use crate::config::MixFetchConfig; use crate::error::MixFetchError; +use crate::fetch::HackOpts; use crate::go_bridge::goWasmSetMixFetchRequestTimeout; +use crate::helpers::{_hack__get_topology_provider, get_combined_gateways}; use crate::request_writer::RequestWriter; use crate::socks_helpers::{socks5_connect_request, socks5_data_request}; use crate::{config, RequestId}; use js_sys::Promise; use nym_socks5_requests::RemoteAddress; +use std::sync::atomic::{AtomicBool, Ordering}; +use tokio::sync::Mutex; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::future_to_promise; use wasm_client_core::client::base_client::{BaseClientBuilder, ClientInput, ClientOutput}; use wasm_client_core::client::inbound_messages::InputMessage; -use wasm_client_core::helpers::setup_gateway_from_api; -use wasm_client_core::init::GatewaySetup; +use wasm_client_core::helpers::setup_gateway_wasm; +use wasm_client_core::init::types::GatewaySetup; use wasm_client_core::nym_task::connections::TransmissionLane; use wasm_client_core::nym_task::TaskManager; use wasm_client_core::storage::core_client_traits::FullWasmClientStorage; use wasm_client_core::storage::ClientStorage; +use wasm_client_core::topology::SerializableGateway; use wasm_client_core::{IdentityKey, QueryReqwestRpcNyxdClient, Recipient}; use wasm_utils::console_log; use wasm_utils::error::PromisableResult; #[wasm_bindgen] pub struct MixFetchClient { + invalidated: AtomicBool, + mix_fetch_config: config::MixFetch, self_address: Recipient, @@ -34,15 +41,16 @@ pub struct MixFetchClient { requests: ActiveRequests, - // even though we don't use graceful shutdowns, other components rely on existence of this struct - // and if it's dropped, everything will start going offline - _task_manager: TaskManager, + // this has to be guarded by a mutex to be able to disconnect with an immutable reference + _task_manager: Mutex, } #[wasm_bindgen] pub struct MixFetchClientBuilder { config: MixFetchConfig, preferred_gateway: Option, + force_tls: bool, + hidden_gateways: Vec, storage_passphrase: Option, } @@ -52,12 +60,19 @@ impl MixFetchClientBuilder { #[wasm_bindgen(constructor)] pub fn new( config: MixFetchConfig, + force_tls: bool, preferred_gateway: Option, storage_passphrase: Option, + hack_opts: Option, ) -> Self { MixFetchClientBuilder { config, preferred_gateway, + force_tls, + hidden_gateways: hack_opts + .unwrap_or_default() + .hidden_gateways + .unwrap_or_default(), storage_passphrase, } } @@ -90,9 +105,12 @@ impl MixFetchClientBuilder { ClientStorage::new_async(&self.config.base.client.id, self.storage_passphrase.take()) .await?; + let uses_hidden = !self.hidden_gateways.is_empty(); let user_chosen = self.preferred_gateway.clone(); + let gateways = get_combined_gateways(self.hidden_gateways, &nym_api_endpoints).await?; let init_res = - setup_gateway_from_api(&client_store, user_chosen, &nym_api_endpoints).await?; + setup_gateway_wasm(&client_store, self.force_tls, user_chosen, &gateways).await?; + let storage = Self::initialise_storage(&self.config, client_store); let mut base_builder = BaseClientBuilder::::new( @@ -100,12 +118,16 @@ impl MixFetchClientBuilder { storage, None, ); - if let Some(authenticated_ephemeral_client) = init_res.authenticated_ephemeral_client { - base_builder = base_builder.with_gateway_setup(GatewaySetup::ReuseConnection { - authenticated_ephemeral_client, - details: init_res.details, - }); + + if let Ok(reuse_setup) = GatewaySetup::try_reuse_connection(init_res) { + base_builder = base_builder.with_gateway_setup(reuse_setup); } + if uses_hidden { + base_builder = base_builder.with_topology_provider(Box::new( + _hack__get_topology_provider(gateways, &nym_api_endpoints).await?, + )) + } + let mut started_client = base_builder.start_base().await?; let self_address = started_client.address; @@ -118,11 +140,13 @@ impl MixFetchClientBuilder { Self::start_reconstructor(client_output, active_requests.clone()); Ok(MixFetchClient { + invalidated: AtomicBool::new(false), mix_fetch_config: self.config.mix_fetch, self_address, client_input, requests: active_requests, - _task_manager: started_client.task_manager, + // this cannot failed as we haven't passed an external task manager + _task_manager: Mutex::new(started_client.task_handle.try_into_task_manager().unwrap()), }) } } @@ -131,28 +155,64 @@ impl MixFetchClientBuilder { impl MixFetchClient { pub(crate) async fn new_async( config: MixFetchConfig, + force_tls: bool, preferred_gateway: Option, storage_passphrase: Option, + hack_opts: Option, ) -> Result { - MixFetchClientBuilder::new(config, preferred_gateway, storage_passphrase) - .start_client_async() - .await + MixFetchClientBuilder::new( + config, + force_tls, + preferred_gateway, + storage_passphrase, + hack_opts, + ) + .start_client_async() + .await } #[wasm_bindgen(constructor)] #[allow(clippy::new_ret_no_self)] pub fn new( config: MixFetchConfig, + force_tls: bool, preferred_gateway: Option, storage_passphrase: Option, + hack_opts: Option, ) -> Promise { future_to_promise(async move { - Self::new_async(config, preferred_gateway, storage_passphrase) - .await - .into_promise_result() + Self::new_async( + config, + force_tls, + preferred_gateway, + storage_passphrase, + hack_opts, + ) + .await + .into_promise_result() }) } + pub fn active(&self) -> bool { + !self.invalidated.load(Ordering::Relaxed) + } + + pub async fn disconnect(&self) -> Result<(), MixFetchError> { + self.invalidated.store(true, Ordering::Relaxed); + + console_log!("sending shutdown signal"); + let mut shutdown_guard = self._task_manager.lock().await; + shutdown_guard.signal_shutdown().ok(); + + console_log!("waiting for shutdown to complete"); + shutdown_guard.wait_for_shutdown().await; + + self.requests.invalidate_all().await; + + console_log!("done"); + Ok(()) + } + pub fn self_address(&self) -> String { self.self_address.to_string() } diff --git a/wasm/mix-fetch/src/error.rs b/wasm/mix-fetch/src/error.rs index 5333f1849c..8bdb7ae9bb 100644 --- a/wasm/mix-fetch/src/error.rs +++ b/wasm/mix-fetch/src/error.rs @@ -40,6 +40,9 @@ pub enum MixFetchError { #[error("mix fetch has already been initialised before")] AlreadyInitialised, + #[error("mix fetch client has already been disconnected")] + Disconnected, + #[error("provided mix fetch url wasn't a string")] NotStringMixFetchUrl, diff --git a/wasm/mix-fetch/src/fetch.rs b/wasm/mix-fetch/src/fetch.rs index 2e2adef992..995b27e2b2 100644 --- a/wasm/mix-fetch/src/fetch.rs +++ b/wasm/mix-fetch/src/fetch.rs @@ -13,6 +13,7 @@ use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; use wasm_bindgen_futures::future_to_promise; use wasm_client_core::config::r#override::DebugWasmOverride; +use wasm_client_core::topology::SerializableGateway; use wasm_utils::console_log; use wasm_utils::error::PromisableResultError; @@ -43,6 +44,9 @@ pub struct MixFetchOpts { #[tsify(optional)] pub(crate) mix_fetch_override: Option, + + #[tsify(optional)] + pub(crate) extra: HackOpts, } #[derive(Tsify, Debug, Clone, Serialize, Deserialize)] @@ -56,10 +60,22 @@ pub struct MixFetchOptsSimple { #[tsify(optional)] pub(crate) preferred_network_requester: Option, + #[tsify(optional)] + pub(crate) force_tls: Option, + #[tsify(optional)] pub(crate) storage_passphrase: Option, } +#[derive(Tsify, Debug, Default, Clone, Serialize, Deserialize)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[serde(rename_all = "camelCase")] +#[doc(hidden)] +pub struct HackOpts { + #[tsify(optional)] + pub(crate) hidden_gateways: Option>, +} + impl<'a> From<&'a MixFetchOpts> for MixFetchConfigOpts { fn from(value: &'a MixFetchOpts) -> Self { MixFetchConfigOpts { @@ -102,7 +118,7 @@ pub fn setup_mix_fetch(opts: MixFetchOpts) -> Promise { config.override_mix_fetch_debug(dbg) } - setup_mix_fetch_async(config, opts.base) + setup_mix_fetch_async(config, opts.base, opts.extra) .await .map(|_| JsValue::undefined()) .map_promise_err() @@ -116,13 +132,27 @@ pub fn setup_mix_fetch_with_config(config: MixFetchConfig, opts: MixFetchOptsSim } future_to_promise(async move { - setup_mix_fetch_async(config, opts) + setup_mix_fetch_async(config, opts, Default::default()) + .await + .map(|_| JsValue::undefined()) + .map_promise_err() + }) +} + +#[wasm_bindgen(js_name = disconnectMixFetch)] +pub async fn disconnect_mix_fetch() -> Promise { + future_to_promise(async move { + disconnect_mix_fetch_async() .await .map(|_| JsValue::undefined()) .map_promise_err() }) } +async fn disconnect_mix_fetch_async() -> Result<(), MixFetchError> { + mix_fetch_client()?.disconnect().await +} + pub(super) fn set_mix_fetch_client(mix_fetch_client: MixFetchClient) -> Result<(), MixFetchError> { MIX_FETCH .set(mix_fetch_client) @@ -130,16 +160,30 @@ pub(super) fn set_mix_fetch_client(mix_fetch_client: MixFetchClient) -> Result<( } pub(super) fn mix_fetch_client() -> Result<&'static MixFetchClient, MixFetchError> { - MIX_FETCH.get().ok_or(MixFetchError::Uninitialised) + let mix_fetch = MIX_FETCH.get().ok_or(MixFetchError::Uninitialised)?; + if !mix_fetch.active() { + return Err(MixFetchError::Disconnected); + } + + Ok(mix_fetch) } async fn setup_mix_fetch_async( config: MixFetchConfig, opts: MixFetchOptsSimple, + hack_opts: HackOpts, ) -> Result<(), MixFetchError> { let preferred_gateway = opts.preferred_gateway; let storage_passphrase = opts.storage_passphrase; - let client = MixFetchClient::new_async(config, preferred_gateway, storage_passphrase).await?; + let force_tls = opts.force_tls.unwrap_or_default(); + let client = MixFetchClient::new_async( + config, + force_tls, + preferred_gateway, + storage_passphrase, + Some(hack_opts), + ) + .await?; set_mix_fetch_client(client)?; Ok(()) } diff --git a/wasm/mix-fetch/src/go_bridge.rs b/wasm/mix-fetch/src/go_bridge.rs index d9acd8d37c..2069572b8e 100644 --- a/wasm/mix-fetch/src/go_bridge.rs +++ b/wasm/mix-fetch/src/go_bridge.rs @@ -1,7 +1,8 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use crate::{mix_fetch_client, MIX_FETCH}; +use crate::error::MixFetchError; +use crate::mix_fetch_client; use js_sys::Promise; use wasm_bindgen::prelude::*; use wasm_bindgen::JsValue; @@ -26,7 +27,7 @@ pub fn send_client_data(stringified_request_id: String, data: Vec) -> Promis future_to_promise(async move { // this error should be impossible in normal use // (unless, of course, user is messing around, but then it's their fault for this panic) - let mix_fetch = mix_fetch_client().expect("mix fetch hasn't been setup"); + let mix_fetch = mix_fetch_client().map_err(JsValue::from)?; mix_fetch.forward_request_content(request_id, data).await?; Ok(JsValue::undefined()) }) @@ -44,7 +45,7 @@ pub fn start_new_mixnet_connection(target: String) -> Promise { future_to_promise(async move { // this error should be impossible in normal use // (unless, of course, user is messing around, but then it's their fault for this panic) - let mix_fetch = mix_fetch_client().expect("mix fetch hasn't been setup"); + let mix_fetch = mix_fetch_client().map_err(JsValue::from)?; mix_fetch .connect_to_mixnet(target) .await @@ -54,8 +55,9 @@ pub fn start_new_mixnet_connection(target: String) -> Promise { } #[wasm_bindgen] -pub fn mix_fetch_initialised() -> bool { - MIX_FETCH.get().is_some() +pub fn mix_fetch_initialised() -> Result { + mix_fetch_client()?; + Ok(true) } /// Called by go runtime whenever it's done with a connection @@ -76,7 +78,7 @@ pub fn finish_mixnet_connection(stringified_request_id: String) -> Promise { future_to_promise(async move { // this error should be impossible in normal use // (unless, of course, user is messing around, but then it's their fault for this panic) - let mix_fetch = mix_fetch_client().expect("mix fetch hasn't been setup"); + let mix_fetch = mix_fetch_client().map_err(JsValue::from)?; mix_fetch.disconnect_from_mixnet(request_id).await?; Ok(JsValue::undefined()) }) diff --git a/wasm/mix-fetch/src/helpers.rs b/wasm/mix-fetch/src/helpers.rs index aee8cb1e7f..0ba09bacea 100644 --- a/wasm/mix-fetch/src/helpers.rs +++ b/wasm/mix-fetch/src/helpers.rs @@ -5,7 +5,12 @@ use crate::error::MixFetchError; use crate::harbourmaster; use rand::seq::SliceRandom; use rand::thread_rng; -use wasm_utils::console_log; +use std::collections::HashMap; +use url::Url; +use wasm_client_core::init::helpers::{current_gateways, current_mixnodes}; +use wasm_client_core::topology::{gateway, SerializableGateway}; +use wasm_client_core::{HardcodedTopologyProvider, NymTopology}; +use wasm_utils::{console_log, console_warn}; // since this client is temporary (and will be properly integrated into nym-api eventually), // we're using hardcoded URL for mainnet @@ -34,3 +39,55 @@ pub(crate) async fn get_network_requester( .cloned() .ok_or(MixFetchError::NoNetworkRequesters) } + +pub(crate) async fn get_combined_gateways( + hidden: Vec, + nym_apis: &[Url], +) -> Result, MixFetchError> { + let mut rng = thread_rng(); + + let mut api_gateways = current_gateways(&mut rng, nym_apis).await?; + if !hidden.is_empty() { + // make sure to override duplicates + let mut gateways: HashMap<_, _> = api_gateways + .into_iter() + .map(|g| (g.identity_key.to_base58_string(), g)) + .collect(); + + for node in hidden { + let id = node.identity_key.clone(); + let converted: Result = node.try_into(); + match converted { + Err(err) => { + console_warn!("failed to add gateway '{id}' into the topology: {err}"); + } + Ok(gateway) => { + if gateways + .insert(gateway.identity_key.to_base58_string(), gateway) + .is_some() + { + console_warn!("overridden gateway '{id}'") + } + } + } + } + + api_gateways = gateways.into_values().collect(); + } + + Ok(api_gateways) +} + +#[allow(non_snake_case)] +pub(crate) async fn _hack__get_topology_provider( + combined_gateways: Vec, + nym_apis: &[Url], +) -> Result { + let mut rng = thread_rng(); + + let mixnodes = current_mixnodes(&mut rng, nym_apis).await?; + Ok(HardcodedTopologyProvider::new(NymTopology::new_unordered( + mixnodes, + combined_gateways, + ))) +} diff --git a/wasm/mix-fetch/src/lib.rs b/wasm/mix-fetch/src/lib.rs index f2e9b695c5..1f3f62111b 100644 --- a/wasm/mix-fetch/src/lib.rs +++ b/wasm/mix-fetch/src/lib.rs @@ -23,7 +23,7 @@ mod request_writer; mod socks_helpers; #[cfg(target_arch = "wasm32")] -pub(crate) use fetch::{mix_fetch_client, RequestId, MIX_FETCH}; +pub(crate) use fetch::{mix_fetch_client, RequestId}; #[cfg(target_arch = "wasm32")] use wasm_bindgen::prelude::*; diff --git a/wasm/mix-fetch/src/request_writer.rs b/wasm/mix-fetch/src/request_writer.rs index 7a91c93a61..fa55b746d2 100644 --- a/wasm/mix-fetch/src/request_writer.rs +++ b/wasm/mix-fetch/src/request_writer.rs @@ -9,13 +9,17 @@ use nym_socks5_requests::{Socks5ProviderResponse, Socks5ResponseContent}; use wasm_bindgen_futures::spawn_local; use wasm_client_core::client::base_client::ClientOutput; use wasm_client_core::client::received_buffer::{ - ReceivedBufferMessage, ReconstructedMessagesReceiver, + ReceivedBufferMessage, ReceivedBufferRequestSender, ReconstructedMessagesReceiver, }; use wasm_client_core::ReconstructedMessage; use wasm_utils::console_error; pub(crate) struct RequestWriter { reconstructed_receiver: ReconstructedMessagesReceiver, + + // we need to keep that channel alive as not to trigger the shutdown + _received_buffer_request_sender: ReceivedBufferRequestSender, + requests: ActiveRequests, } @@ -34,6 +38,7 @@ impl RequestWriter { RequestWriter { reconstructed_receiver, + _received_buffer_request_sender: client_output.received_buffer_request_sender, requests, } } diff --git a/wasm/node-tester/Cargo.toml b/wasm/node-tester/Cargo.toml index b5a59e1641..2afba46306 100644 --- a/wasm/node-tester/Cargo.toml +++ b/wasm/node-tester/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "nym-node-tester-wasm" authors = ["Jedrzej Stuczynski "] -version = "1.2.0-rc.2" +version = "1.2.0-rc.9" edition = "2021" keywords = ["nym", "sphinx", "webassembly", "privacy", "tester"] license = "Apache-2.0" @@ -33,7 +33,3 @@ wasm-utils = { path = "../../common/wasm/utils" } [package.metadata.wasm-pack.profile.release] wasm-opt = false - -[profile.release] -lto = true -opt-level = 'z' diff --git a/wasm/node-tester/src/tester.rs b/wasm/node-tester/src/tester.rs index 5a5d7f5f34..1da2ee7a4f 100644 --- a/wasm/node-tester/src/tester.rs +++ b/wasm/node-tester/src/tester.rs @@ -20,15 +20,16 @@ use tokio::sync::Mutex as AsyncMutex; use tsify::Tsify; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::future_to_promise; +use wasm_client_core::client::mix_traffic::transceiver::PacketRouter; use wasm_client_core::helpers::{ current_network_topology_async, setup_from_topology, EphemeralCredentialStorage, }; +use wasm_client_core::init::types::GatewayDetails; use wasm_client_core::storage::ClientStorage; -use wasm_client_core::topology::WasmNymTopology; +use wasm_client_core::topology::SerializableNymTopology; use wasm_client_core::{ - nym_task, BandwidthController, GatewayClient, IdentityKey, InitialisationDetails, - InitialisationResult, ManagedKeys, NodeIdentity, NymTopology, QueryReqwestRpcNyxdClient, - Recipient, + nym_task, BandwidthController, GatewayClient, GatewayConfig, IdentityKey, InitialisationResult, + ManagedKeys, NodeIdentity, NymTopology, QueryReqwestRpcNyxdClient, Recipient, }; use wasm_utils::check_promise_result; use wasm_utils::error::PromisableResult; @@ -95,7 +96,7 @@ pub struct NymNodeTesterOpts { nym_api: Option, #[tsify(optional)] - topology: Option, + topology: Option, #[tsify(optional)] gateway: Option, @@ -136,13 +137,16 @@ impl NymNodeTesterBuilder { &self, client_store: &ClientStorage, ) -> Result { - if let Ok(loaded) = InitialisationDetails::try_load(client_store, client_store).await { - Ok(loaded.into()) + if let Ok(loaded) = InitialisationResult::try_load(client_store, client_store).await { + Ok(loaded) } else { - Ok( - setup_from_topology(self.gateway.clone(), &self.base_topology, client_store) - .await?, + Ok(setup_from_topology( + self.gateway.clone(), + false, + &self.base_topology, + client_store, ) + .await?) } } @@ -157,38 +161,46 @@ impl NymNodeTesterBuilder { let client_store = ClientStorage::new_async(&storage_id, None).await?; let initialisation_result = self.gateway_info(&client_store).await?; - let init_details = initialisation_result.details; - let managed_keys = init_details.managed_keys; - let gateway_endpoint = init_details.gateway_details; - let gateway_identity = gateway_endpoint.try_get_gateway_identity_key()?; + let GatewayDetails::Configured(gateway_endpoint) = initialisation_result.gateway_details + else { + // don't bother supporting it + panic!("unsupported custom gateway configuration in wasm node tester") + }; + + let managed_keys = initialisation_result.managed_keys; let (mixnet_message_sender, mixnet_message_receiver) = mpsc::unbounded(); let (ack_sender, ack_receiver) = mpsc::unbounded(); + let gateway_task = task_manager.subscribe().named("gateway_client"); + let packet_router = PacketRouter::new( + ack_sender, + mixnet_message_sender, + gateway_task.fork("packet_router"), + ); + + let gateway_config: GatewayConfig = gateway_endpoint.try_into()?; + let gateway_identity = gateway_config.gateway_identity; + let mut gateway_client = if let Some(existing_client) = initialisation_result.authenticated_ephemeral_client { existing_client.upgrade( - mixnet_message_sender, - ack_sender, - Duration::from_secs(10), + packet_router, self.bandwidth_controller.take(), - task_manager.subscribe(), + gateway_task, ) } else { GatewayClient::new( - gateway_endpoint.gateway_listener, + gateway_config, managed_keys.identity_keypair(), - gateway_identity, Some(managed_keys.must_get_gateway_shared_key()), - mixnet_message_sender, - ack_sender, - Duration::from_secs(10), + packet_router, self.bandwidth_controller.take(), - task_manager.subscribe(), + gateway_task, ) - }; + } + .with_disabled_credentials_mode(true); - gateway_client.set_disabled_credentials_mode(true); gateway_client.authenticate_and_start().await?; // TODO: make those values configurable later diff --git a/yarn.lock b/yarn.lock index d6dc50eb8e..024fb6dd07 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8,9 +8,9 @@ integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== "@adobe/css-tools@^4.0.1": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.2.0.tgz#e1a84fca468f4b337816fcb7f0964beb620ba855" - integrity sha512-E09FiIft46CmH5Qnjb0wsW54/YQd69LsxeKUOWawmws1XWvyFGURnAChH0mlr7YPFR1ofwvUQfcL0J3lMxXqPA== + version "4.3.1" + resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.3.1.tgz#abfccb8ca78075a2b6187345c26243c1a0842f28" + integrity sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg== "@ampproject/remapping@^2.2.0": version "2.2.1" @@ -27,14 +27,7 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.22.5", "@babel/code-frame@^7.5.5", "@babel/code-frame@^7.8.3": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.5.tgz#234d98e1551960604f1246e6475891a570ad5658" - integrity sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ== - dependencies: - "@babel/highlight" "^7.22.5" - -"@babel/code-frame@^7.22.13": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.22.5", "@babel/code-frame@^7.5.5", "@babel/code-frame@^7.8.3": version "7.22.13" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== @@ -42,17 +35,7 @@ "@babel/highlight" "^7.22.13" chalk "^2.4.2" -"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.5.tgz#b1f6c86a02d85d2dd3368a2b67c09add8cd0c255" - integrity sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA== - -"@babel/compat-data@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.6.tgz#15606a20341de59ba02cd2fcc5086fcbe73bf544" - integrity sha512-29tfsWTq2Ftu7MXmimyC0C5FDZv5DYxOZkh3XD3+QW4V/BYuv/LyEsjj3c0hqedEaDt6DBfDvexMKU8YevdqFg== - -"@babel/compat-data@^7.22.9": +"@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.22.9": version "7.22.9" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.9.tgz#71cdb00a1ce3a329ce4cbec3a44f9fef35669730" integrity sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ== @@ -79,80 +62,28 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.1.0", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.15.0", "@babel/core@^7.17.5", "@babel/core@^7.19.6", "@babel/core@^7.7.2", "@babel/core@^7.7.5", "@babel/core@^7.8.0": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.5.tgz#d67d9747ecf26ee7ecd3ebae1ee22225fe902a89" - integrity sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.22.5" - "@babel/generator" "^7.22.5" - "@babel/helper-compilation-targets" "^7.22.5" - "@babel/helper-module-transforms" "^7.22.5" - "@babel/helpers" "^7.22.5" - "@babel/parser" "^7.22.5" - "@babel/template" "^7.22.5" - "@babel/traverse" "^7.22.5" - "@babel/types" "^7.22.5" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.2" - semver "^6.3.0" - -"@babel/core@^7.11.6": - version "7.22.8" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.8.tgz#386470abe884302db9c82e8e5e87be9e46c86785" - integrity sha512-75+KxFB4CZqYRXjx4NlR4J7yGvKumBuZTmV4NV6v09dVXXkuYVYLT68N6HCzLvfJ+fWCxQsntNzKwwIXL4bHnw== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.22.5" - "@babel/generator" "^7.22.7" - "@babel/helper-compilation-targets" "^7.22.6" - "@babel/helper-module-transforms" "^7.22.5" - "@babel/helpers" "^7.22.6" - "@babel/parser" "^7.22.7" - "@babel/template" "^7.22.5" - "@babel/traverse" "^7.22.8" - "@babel/types" "^7.22.5" - "@nicolo-ribaudo/semver-v6" "^6.3.3" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.2" - -"@babel/core@^7.22.10": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.15.tgz#15d4fd03f478a459015a4b94cfbb3bd42c48d2f4" - integrity sha512-PtZqMmgRrvj8ruoEOIwVA3yoF91O+Hgw9o7DAUTNBA6Mo2jpu31clx9a7Nz/9JznqetTR6zwfC4L3LAjKQXUwA== +"@babel/core@^7.1.0", "@babel/core@^7.11.6", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.15.0", "@babel/core@^7.17.5", "@babel/core@^7.19.6", "@babel/core@^7.22.10", "@babel/core@^7.7.2", "@babel/core@^7.7.5", "@babel/core@^7.8.0": + version "7.22.17" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.17.tgz#2f9b0b395985967203514b24ee50f9fd0639c866" + integrity sha512-2EENLmhpwplDux5PSsZnSbnSkB3tZ6QTksgO25xwEL7pIDcNOMhF5v/s6RzwjMZzZzw9Ofc30gHv5ChCC8pifQ== dependencies: "@ampproject/remapping" "^2.2.0" "@babel/code-frame" "^7.22.13" "@babel/generator" "^7.22.15" "@babel/helper-compilation-targets" "^7.22.15" - "@babel/helper-module-transforms" "^7.22.15" + "@babel/helper-module-transforms" "^7.22.17" "@babel/helpers" "^7.22.15" - "@babel/parser" "^7.22.15" + "@babel/parser" "^7.22.16" "@babel/template" "^7.22.15" - "@babel/traverse" "^7.22.15" - "@babel/types" "^7.22.15" + "@babel/traverse" "^7.22.17" + "@babel/types" "^7.22.17" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.22.5", "@babel/generator@^7.7.2": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.5.tgz#1e7bf768688acfb05cf30b2369ef855e82d984f7" - integrity sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA== - dependencies: - "@babel/types" "^7.22.5" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" - jsesc "^2.5.1" - -"@babel/generator@^7.22.15": +"@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.22.15", "@babel/generator@^7.7.2": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.15.tgz#1564189c7ec94cb8f77b5e8a90c4d200d21b2339" integrity sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA== @@ -162,16 +93,6 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" -"@babel/generator@^7.22.7": - version "7.22.7" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.7.tgz#a6b8152d5a621893f2c9dacf9a4e286d520633d5" - integrity sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ== - dependencies: - "@babel/types" "^7.22.5" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" - jsesc "^2.5.1" - "@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" @@ -180,24 +101,13 @@ "@babel/types" "^7.22.5" "@babel/helper-builder-binary-assignment-operator-visitor@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.5.tgz#a3f4758efdd0190d8927fcffd261755937c71878" - integrity sha512-m1EP3lVOPptR+2DwD125gziZNcmoNSHGmJROKoy87loWUQyJaVXDgpmruWqDARZSmtYQ+Dl25okU8+qhVzuykw== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz#fc7319fc54c5e2fa14b2909cf3c5fd3046813e02" - integrity sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw== + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz#5426b109cf3ad47b91120f8328d8ab1be8b0b956" + integrity sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw== dependencies: - "@babel/compat-data" "^7.22.5" - "@babel/helper-validator-option" "^7.22.5" - browserslist "^4.21.3" - lru-cache "^5.1.1" - semver "^6.3.0" + "@babel/types" "^7.22.15" -"@babel/helper-compilation-targets@^7.22.15": +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.22.15", "@babel/helper-compilation-targets@^7.22.5", "@babel/helper-compilation-targets@^7.22.6": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz#0698fc44551a26cf29f18d4662d5bf545a6cfc52" integrity sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw== @@ -208,33 +118,7 @@ lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-compilation-targets@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.6.tgz#e30d61abe9480aa5a83232eb31c111be922d2e52" - integrity sha512-534sYEqWD9VfUm3IPn2SLcH4Q3P86XL+QvqdC7ZsFrzyyPF3T4XGiVghF6PTYNdWg6pXuoqXxNQAhbYeEInTzA== - dependencies: - "@babel/compat-data" "^7.22.6" - "@babel/helper-validator-option" "^7.22.5" - "@nicolo-ribaudo/semver-v6" "^6.3.3" - browserslist "^4.21.9" - lru-cache "^5.1.1" - -"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0", "@babel/helper-create-class-features-plugin@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.5.tgz#2192a1970ece4685fbff85b48da2c32fcb130b7c" - integrity sha512-xkb58MyOYIslxu3gKmVXmjTtUPvBU4odYzbiIQbWwLKIHCsx6UGZGX6F1IznMFVnDdirseUZopzN+ZRt8Xb33Q== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-function-name" "^7.22.5" - "@babel/helper-member-expression-to-functions" "^7.22.5" - "@babel/helper-optimise-call-expression" "^7.22.5" - "@babel/helper-replace-supers" "^7.22.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.5" - semver "^6.3.0" - -"@babel/helper-create-class-features-plugin@^7.22.11", "@babel/helper-create-class-features-plugin@^7.22.15": +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0", "@babel/helper-create-class-features-plugin@^7.22.11", "@babel/helper-create-class-features-plugin@^7.22.15", "@babel/helper-create-class-features-plugin@^7.22.5": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz#97a61b385e57fe458496fad19f8e63b63c867de4" integrity sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg== @@ -250,13 +134,13 @@ semver "^6.3.1" "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.5.tgz#bb2bf0debfe39b831986a4efbf4066586819c6e4" - integrity sha512-1VpEFOIbMRaXyDeUwUfmTIxExLwQ+zkW+Bh5zXpApA3oQedBx9v/updixWxnx/bZpKw7u8VxWjb/qWpIcmPq8A== + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz#5ee90093914ea09639b01c711db0d6775e558be1" + integrity sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w== dependencies: "@babel/helper-annotate-as-pure" "^7.22.5" regexpu-core "^5.3.1" - semver "^6.3.0" + semver "^6.3.1" "@babel/helper-define-polyfill-provider@^0.1.5": version "0.1.5" @@ -272,18 +156,6 @@ resolve "^1.14.2" semver "^6.1.2" -"@babel/helper-define-polyfill-provider@^0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.0.tgz#487053f103110f25b9755c5980e031e93ced24d8" - integrity sha512-RnanLx5ETe6aybRi1cO/edaRH+bNYWaryCEmjDDYyNr4wnSzyOp8T0dWipmqVHKEY3AbVKUom50AKSlj1zmKbg== - dependencies: - "@babel/helper-compilation-targets" "^7.17.7" - "@babel/helper-plugin-utils" "^7.16.7" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" - semver "^6.1.2" - "@babel/helper-define-polyfill-provider@^0.4.2": version "0.4.2" resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz#82c825cadeeeee7aad237618ebbe8fa1710015d7" @@ -315,52 +187,24 @@ dependencies: "@babel/types" "^7.22.5" -"@babel/helper-member-expression-to-functions@^7.22.15": +"@babel/helper-member-expression-to-functions@^7.22.15", "@babel/helper-member-expression-to-functions@^7.22.5": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.15.tgz#b95a144896f6d491ca7863576f820f3628818621" integrity sha512-qLNsZbgrNh0fDQBCPocSL8guki1hcPvltGDv/NxvUoABwFq7GkKSu1nRXeJkVZc+wJvne2E0RKQz+2SQrz6eAA== dependencies: "@babel/types" "^7.22.15" -"@babel/helper-member-expression-to-functions@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.5.tgz#0a7c56117cad3372fbf8d2fb4bf8f8d64a1e76b2" - integrity sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz#1a8f4c9f4027d23f520bd76b364d44434a72660c" - integrity sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-module-imports@^7.22.15": +"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.22.15", "@babel/helper-module-imports@^7.22.5": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== dependencies: "@babel/types" "^7.22.15" -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz#0f65daa0716961b6e96b164034e737f60a80d2ef" - integrity sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw== - dependencies: - "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-module-imports" "^7.22.5" - "@babel/helper-simple-access" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.5" - "@babel/helper-validator-identifier" "^7.22.5" - "@babel/template" "^7.22.5" - "@babel/traverse" "^7.22.5" - "@babel/types" "^7.22.5" - -"@babel/helper-module-transforms@^7.22.15", "@babel/helper-module-transforms@^7.22.9": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.15.tgz#40ad2f6950f143900e9c1c72363c0b431a606082" - integrity sha512-l1UiX4UyHSFsYt17iQ3Se5pQQZZHa22zyIXURmvkmLCD4t/aU+dvNWHatKac/D9Vm9UES7nvIqHs4jZqKviUmQ== +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.22.15", "@babel/helper-module-transforms@^7.22.17", "@babel/helper-module-transforms@^7.22.5", "@babel/helper-module-transforms@^7.22.9": + version "7.22.17" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.17.tgz#7edf129097a51ccc12443adbc6320e90eab76693" + integrity sha512-XouDDhQESrLHTpnBtCKExJdyY4gJCdrvH2Pyv8r8kovX2U8G0dRUOT45T9XlbLtuu9CLXP15eusnkprhoPV5iQ== dependencies: "@babel/helper-environment-visitor" "^7.22.5" "@babel/helper-module-imports" "^7.22.15" @@ -380,43 +224,21 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== -"@babel/helper-remap-async-to-generator@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.5.tgz#14a38141a7bf2165ad38da61d61cf27b43015da2" - integrity sha512-cU0Sq1Rf4Z55fgz7haOakIyM7+x/uCFwXpLPaeRzfoUtAEAuUZjZvFPjL/rk5rW693dIgn2hng1W7xbT7lWT4g== +"@babel/helper-remap-async-to-generator@^7.22.5", "@babel/helper-remap-async-to-generator@^7.22.9": + version "7.22.17" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.17.tgz#dabaa50622b3b4670bd6546fc8db23eb12d89da0" + integrity sha512-bxH77R5gjH3Nkde6/LuncQoLaP16THYPscurp1S8z7S9ZgezCyV3G8Hc+TZiCmY8pz4fp8CvKSgtJMW0FkLAxA== dependencies: "@babel/helper-annotate-as-pure" "^7.22.5" "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-wrap-function" "^7.22.5" - "@babel/types" "^7.22.5" + "@babel/helper-wrap-function" "^7.22.17" -"@babel/helper-remap-async-to-generator@^7.22.9": - version "7.22.9" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz#53a25b7484e722d7efb9c350c75c032d4628de82" - integrity sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-wrap-function" "^7.22.9" - -"@babel/helper-replace-supers@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.5.tgz#71bc5fb348856dea9fdc4eafd7e2e49f585145dc" - integrity sha512-aLdNM5I3kdI/V9xGNyKSF3X/gTyMUBohTZ+/3QdQKAA9vxIiy12E+8E2HoOP1/DjeqU+g6as35QHJNMDDYpuCg== - dependencies: - "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-member-expression-to-functions" "^7.22.5" - "@babel/helper-optimise-call-expression" "^7.22.5" - "@babel/template" "^7.22.5" - "@babel/traverse" "^7.22.5" - "@babel/types" "^7.22.5" - -"@babel/helper-replace-supers@^7.22.9": +"@babel/helper-replace-supers@^7.22.5", "@babel/helper-replace-supers@^7.22.9": version "7.22.9" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz#cbdc27d6d8d18cd22c81ae4293765a5d9afd0779" integrity sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg== @@ -439,13 +261,6 @@ dependencies: "@babel/types" "^7.22.5" -"@babel/helper-split-export-declaration@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz#88cf11050edb95ed08d596f7a044462189127a08" - integrity sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ== - dependencies: - "@babel/types" "^7.22.5" - "@babel/helper-split-export-declaration@^7.22.6": version "7.22.6" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" @@ -458,55 +273,26 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== -"@babel/helper-validator-identifier@^7.22.15": +"@babel/helper-validator-identifier@^7.22.15", "@babel/helper-validator-identifier@^7.22.5": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz#601fa28e4cc06786c18912dca138cec73b882044" integrity sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ== -"@babel/helper-validator-identifier@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" - integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== - "@babel/helper-validator-option@^7.22.15": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040" integrity sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA== -"@babel/helper-validator-option@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz#de52000a15a177413c8234fa3a8af4ee8102d0ac" - integrity sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw== - -"@babel/helper-wrap-function@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.5.tgz#44d205af19ed8d872b4eefb0d2fa65f45eb34f06" - integrity sha512-bYqLIBSEshYcYQyfks8ewYA8S30yaGSeRslcvKMvoUk6HHPySbxHq9YRi6ghhzEU+yhQv9bP/jXnygkStOcqZw== - dependencies: - "@babel/helper-function-name" "^7.22.5" - "@babel/template" "^7.22.5" - "@babel/traverse" "^7.22.5" - "@babel/types" "^7.22.5" - -"@babel/helper-wrap-function@^7.22.9": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.10.tgz#d845e043880ed0b8c18bd194a12005cb16d2f614" - integrity sha512-OnMhjWjuGYtdoO3FmsEFWvBStBAe2QOgwOLsLNDjN+aaiMD8InJk1/O3HSD8lkqTjCgg5YI34Tz15KNNA3p+nQ== +"@babel/helper-wrap-function@^7.22.17": + version "7.22.17" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.17.tgz#222ac3ff9cc8f9b617cc1e5db75c0b538e722801" + integrity sha512-nAhoheCMlrqU41tAojw9GpVEKDlTS8r3lzFmF0lP52LwblCPbuFSO7nGIZoIcoU5NIm1ABrna0cJExE4Ay6l2Q== dependencies: "@babel/helper-function-name" "^7.22.5" - "@babel/template" "^7.22.5" - "@babel/types" "^7.22.10" - -"@babel/helpers@^7.12.5", "@babel/helpers@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.5.tgz#74bb4373eb390d1ceed74a15ef97767e63120820" - integrity sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q== - dependencies: - "@babel/template" "^7.22.5" - "@babel/traverse" "^7.22.5" - "@babel/types" "^7.22.5" + "@babel/template" "^7.22.15" + "@babel/types" "^7.22.17" -"@babel/helpers@^7.22.15": +"@babel/helpers@^7.12.5", "@babel/helpers@^7.22.15": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.15.tgz#f09c3df31e86e3ea0b7ff7556d85cdebd47ea6f1" integrity sha512-7pAjK0aSdxOwR+CcYAqgWOGy5dcfvzsTIfFTb2odQqW47MDfv14UaJDY6eng8ylM2EaeKXdxaSWESbkmaQHTmw== @@ -515,25 +301,7 @@ "@babel/traverse" "^7.22.15" "@babel/types" "^7.22.15" -"@babel/helpers@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.6.tgz#8e61d3395a4f0c5a8060f309fb008200969b5ecd" - integrity sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA== - dependencies: - "@babel/template" "^7.22.5" - "@babel/traverse" "^7.22.6" - "@babel/types" "^7.22.5" - -"@babel/highlight@^7.10.4", "@babel/highlight@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.5.tgz#aa6c05c5407a67ebce408162b7ede789b4d22031" - integrity sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw== - dependencies: - "@babel/helper-validator-identifier" "^7.22.5" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/highlight@^7.22.13": +"@babel/highlight@^7.10.4", "@babel/highlight@^7.22.13": version "7.22.13" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.13.tgz#9cda839e5d3be9ca9e8c26b6dd69e7548f0cbf16" integrity sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ== @@ -542,20 +310,10 @@ chalk "^2.4.2" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.5.tgz#721fd042f3ce1896238cf1b341c77eb7dee7dbea" - integrity sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q== - -"@babel/parser@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.15.tgz#d34592bfe288a32e741aa0663dbc4829fcd55160" - integrity sha512-RWmQ/sklUN9BvGGpCDgSubhHWfAx24XDTDObup4ffvxaYsptOg2P3KG0j+1eWKLxpkX0j0uHxmpq2Z1SP/VhxA== - -"@babel/parser@^7.22.7": - version "7.22.7" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.7.tgz#df8cf085ce92ddbdbf668a7f186ce848c9036cae" - integrity sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q== +"@babel/parser@^7.1.0", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.22.16": + version "7.22.16" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.16.tgz#180aead7f247305cce6551bea2720934e2fa2c95" + integrity sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA== "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.15": version "7.22.15" @@ -564,13 +322,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz#87245a21cd69a73b0b81bcda98d443d6df08f05e" - integrity sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.22.15": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz#2aeb91d337d4e1a1e7ce85b76a37f5301781200f" @@ -580,15 +331,6 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" "@babel/plugin-transform-optional-chaining" "^7.22.15" -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.5.tgz#fef09f9499b1f1c930da8a0c419db42167d792ca" - integrity sha512-31Bb65aZaUwqCbWMnZPduIZxCBngHFlzyN6Dq6KAJjtx+lx6ohKHubc61OomYi7XwVD4Ol0XCVz4h+pYFR048g== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - "@babel/plugin-transform-optional-chaining" "^7.22.5" - "@babel/plugin-proposal-class-properties@^7.12.1": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" @@ -598,20 +340,20 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-proposal-decorators@^7.12.12": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.22.5.tgz#dc8cdda048e5aea947efda920e030199806b868d" - integrity sha512-h8hlezQ4dl6ixodgXkH8lUfcD7x+WAuIqPUjwGoItynrXOAv4a4Tci1zA/qjzQjjcl0v3QpLdc2LM6ZACQuY7A== + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.22.15.tgz#dc774eae73ab8c28a644d490b45aa47a85bb0bf5" + integrity sha512-kc0VvbbUyKelvzcKOSyQUSVVXS5pT3UhRB0e3c9An86MvLqs+gx0dN4asllrDluqSa3m9YyooXKGOFVomnyFkg== dependencies: - "@babel/helper-create-class-features-plugin" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.22.15" "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-replace-supers" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.5" - "@babel/plugin-syntax-decorators" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.9" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/plugin-syntax-decorators" "^7.22.10" "@babel/plugin-proposal-export-default-from@^7.12.1": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.22.5.tgz#825924eda1fad382c3de4db6fe1711b6fa03362f" - integrity sha512-UCe1X/hplyv6A5g2WnQ90tnHRvYL29dabCWww92lO7VdfMVTVReBTRrhiMrKQejHD9oVkdnRdwYuzUZkBVQisg== + version "7.22.17" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.22.17.tgz#91b60cd338f501cccdf549af2308768911ec5fbb" + integrity sha512-cop/3quQBVvdz6X5SJC6AhUv3C9DrVTM06LUEXimEdWAhCSyOJIr9NiZDU9leHZ0/aiG0Sh7Zmvaku5TWYNgbA== dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-export-default-from" "^7.22.5" @@ -676,14 +418,6 @@ "@babel/helper-plugin-utils" "^7.20.2" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e" - integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" @@ -712,10 +446,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-decorators@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.22.5.tgz#329fe2907c73de184033775637dbbc507f09116a" - integrity sha512-avpUOBS7IU6al8MmF1XpAyj9QYeLPuSDJI5D4pVMSMdL7xQokKqJPYQC67RCT0aCTashUXPiGwMJ0DEXXCEmMA== +"@babel/plugin-syntax-decorators@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.22.10.tgz#7d83ea04d893c442b78ebf4c3cbac59a7211deff" + integrity sha512-z1KTVemBjnz+kSEilAsI4lbkPOl5TvJH7YDSY1CTIzvLWJ+KHXp+mRe8VPmfnyvqOPqar1V2gid2PleKzRUstQ== dependencies: "@babel/helper-plugin-utils" "^7.22.5" @@ -877,16 +611,6 @@ "@babel/helper-remap-async-to-generator" "^7.22.9" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-transform-async-generator-functions@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.5.tgz#7336356d23380eda9a56314974f053a020dab0c3" - integrity sha512-gGOEvFzm3fWoyD5uZq7vVTD57pPJ3PczPUD/xCFGjzBpUosnklmXyKnGQbbbGs1NPNPskFex0j93yKbHt0cHyg== - dependencies: - "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-remap-async-to-generator" "^7.22.5" - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-transform-async-to-generator@^7.14.5", "@babel/plugin-transform-async-to-generator@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz#c7a85f44e46f8952f6d27fe57c2ed3cc084c3775" @@ -903,14 +627,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-block-scoping@^7.12.12", "@babel/plugin-transform-block-scoping@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.5.tgz#8bfc793b3a4b2742c0983fadc1480d843ecea31b" - integrity sha512-EcACl1i5fSQ6bt+YGuU/XGCeZKStLmyVGytWkpyhCLeQVA0eu6Wtiw92V+I1T/hnezUv7j74dA/Ro69gWcU+hg== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-block-scoping@^7.22.15": +"@babel/plugin-transform-block-scoping@^7.12.12", "@babel/plugin-transform-block-scoping@^7.22.15": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.15.tgz#494eb82b87b5f8b1d8f6f28ea74078ec0a10a841" integrity sha512-G1czpdJBZCtngoK1sJgloLiOHUnkb/bLZwqVZD8kXmq0ZnVfTTWUcs9OWtp0mBtYJ+4LQY1fllqBkOIPhXmFmw== @@ -934,31 +651,7 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-class-static-block" "^7.14.5" -"@babel/plugin-transform-class-static-block@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.5.tgz#3e40c46f048403472d6f4183116d5e46b1bff5ba" - integrity sha512-SPToJ5eYZLxlnp1UzdARpOGeC2GbHvr9d/UV0EukuVx8atktg194oe+C5BqQ8jRTkgLRVOPYeXRSBg1IlMoVRA== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.22.5" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - -"@babel/plugin-transform-classes@^7.12.1", "@babel/plugin-transform-classes@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.5.tgz#635d4e98da741fad814984639f4c0149eb0135e1" - integrity sha512-2edQhLfibpWpsVBx2n/GKOz6JdGQvLruZQfGr9l1qes2KQaWswjBzhQF7UDUZMNaMMQeYnQzxwOMPsbYF7wqPQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-compilation-targets" "^7.22.5" - "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-function-name" "^7.22.5" - "@babel/helper-optimise-call-expression" "^7.22.5" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-replace-supers" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.5" - globals "^11.1.0" - -"@babel/plugin-transform-classes@^7.22.15": +"@babel/plugin-transform-classes@^7.12.1", "@babel/plugin-transform-classes@^7.22.15": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz#aaf4753aee262a232bbc95451b4bdf9599c65a0b" integrity sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw== @@ -981,21 +674,14 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/template" "^7.22.5" -"@babel/plugin-transform-destructuring@^7.12.1", "@babel/plugin-transform-destructuring@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.5.tgz#d3aca7438f6c26c78cdd0b0ba920a336001b27cc" - integrity sha512-GfqcFuGW8vnEqTUBM7UtPd5A4q797LTvvwKxXTgRsFjoqaJiEg9deBG6kWeQYkVEL569NpnmpC0Pkr/8BLKGnQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-destructuring@^7.22.15": +"@babel/plugin-transform-destructuring@^7.12.1", "@babel/plugin-transform-destructuring@^7.22.15": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.15.tgz#e7404ea5bb3387073b9754be654eecb578324694" integrity sha512-HzG8sFl1ZVGTme74Nw+X01XsUTqERVQ6/RLHo3XjGRzm7XD6QTtfS3NJotVgCGy8BzkDqRjRBD8dAyJn5TuvSQ== dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-dotall-regex@^7.22.5", "@babel/plugin-transform-dotall-regex@^7.4.4": +"@babel/plugin-transform-dotall-regex@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz#dbb4f0e45766eb544e193fb00e65a1dd3b2a4165" integrity sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw== @@ -1018,14 +704,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-transform-dynamic-import@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.5.tgz#d6908a8916a810468c4edff73b5b75bda6ad393e" - integrity sha512-0MC3ppTB1AMxd8fXjSrbPa7LT9hrImt+/fcj+Pg5YMD7UQyWp/02+JWpdnCymmsXwIx5Z+sYn1bwCn4ZJNvhqQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-transform-exponentiation-operator@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz#402432ad544a1f9a480da865fda26be653e48f6a" @@ -1042,14 +720,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-transform-export-namespace-from@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.5.tgz#57c41cb1d0613d22f548fddd8b288eedb9973a5b" - integrity sha512-X4hhm7FRnPgd4nDA4b/5V280xCx6oL7Oob5+9qVS5C13Zq4bh1qq7LU0GgRU6b5dBWBvhGaXYVB4AcN6+ol6vg== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-transform-flow-strip-types@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.22.5.tgz#0bb17110c7bf5b35a60754b2f00c58302381dee2" @@ -1058,14 +728,7 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-flow" "^7.22.5" -"@babel/plugin-transform-for-of@^7.12.1", "@babel/plugin-transform-for-of@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.5.tgz#ab1b8a200a8f990137aff9a084f8de4099ab173f" - integrity sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-for-of@^7.22.15": +"@babel/plugin-transform-for-of@^7.12.1", "@babel/plugin-transform-for-of@^7.22.15": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz#f64b4ccc3a4f131a996388fae7680b472b306b29" integrity sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA== @@ -1089,14 +752,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-transform-json-strings@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.5.tgz#14b64352fdf7e1f737eed68de1a1468bd2a77ec0" - integrity sha512-DuCRB7fu8MyTLbEQd1ew3R85nx/88yMoqo2uPSjevMj3yoN7CDM8jkgrY0wmVxfJZyJ/B9fE1iq7EQppWQmR5A== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-transform-literals@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz#e9341f4b5a167952576e23db8d435849b1dd7920" @@ -1112,14 +767,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-transform-logical-assignment-operators@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.5.tgz#66ae5f068fd5a9a5dc570df16f56c2a8462a9d6c" - integrity sha512-MQQOUW1KL8X0cDWfbwYP+TbVbZm16QmQXJQ+vndPtH/BoO0lOKpVoEDMI7+PskYxH+IiE0tS8xZye0qr1lGzSA== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-transform-member-expression-literals@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz#4fcc9050eded981a468347dd374539ed3e058def" @@ -1144,15 +791,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-simple-access" "^7.22.5" -"@babel/plugin-transform-modules-commonjs@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz#7d9875908d19b8c0536085af7b053fd5bd651bfa" - integrity sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA== - dependencies: - "@babel/helper-module-transforms" "^7.22.5" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-simple-access" "^7.22.5" - "@babel/plugin-transform-modules-systemjs@^7.22.11": version "7.22.11" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.11.tgz#3386be5875d316493b517207e8f1931d93154bb1" @@ -1163,16 +801,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-validator-identifier" "^7.22.5" -"@babel/plugin-transform-modules-systemjs@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.5.tgz#18c31410b5e579a0092638f95c896c2a98a5d496" - integrity sha512-emtEpoaTMsOs6Tzz+nbmcePl6AKVtS1yC4YNAeMun9U8YCsgadPNxnOPQ8GhHFB2qdx+LZu9LgoC0Lthuu05DQ== - dependencies: - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-module-transforms" "^7.22.5" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-validator-identifier" "^7.22.5" - "@babel/plugin-transform-modules-umd@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz#4694ae40a87b1745e3775b6a7fe96400315d4f98" @@ -1204,14 +832,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@babel/plugin-transform-nullish-coalescing-operator@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.5.tgz#f8872c65776e0b552e0849d7596cddd416c3e381" - integrity sha512-6CF8g6z1dNYZ/VXok5uYkkBBICHZPiGEl7oDnAx2Mt1hlHVHOSIKWJaXHjQJA5VB43KZnXZDIexMchY4y2PGdA== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-transform-numeric-separator@^7.22.11": version "7.22.11" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz#498d77dc45a6c6db74bb829c02a01c1d719cbfbd" @@ -1220,14 +840,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-transform-numeric-separator@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.5.tgz#57226a2ed9e512b9b446517ab6fa2d17abb83f58" - integrity sha512-NbslED1/6M+sXiwwtcAB/nieypGw02Ejf4KtDeMkCEpP6gWFMX1wI9WKYua+4oBneCCEmulOkRpwywypVZzs/g== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-transform-object-rest-spread@^7.22.15": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.15.tgz#21a95db166be59b91cde48775310c0df6e1da56f" @@ -1239,17 +851,6 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-transform-parameters" "^7.22.15" -"@babel/plugin-transform-object-rest-spread@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.5.tgz#9686dc3447df4753b0b2a2fae7e8bc33cdc1f2e1" - integrity sha512-Kk3lyDmEslH9DnvCDA1s1kkd3YWQITiBOHngOtDL9Pt6BZjzqb6hiOlb8VfjiiQJ2unmegBqZu0rx5RxJb5vmQ== - dependencies: - "@babel/compat-data" "^7.22.5" - "@babel/helper-compilation-targets" "^7.22.5" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.22.5" - "@babel/plugin-transform-object-super@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz#794a8d2fcb5d0835af722173c1a9d704f44e218c" @@ -1266,14 +867,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-transform-optional-catch-binding@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.5.tgz#842080be3076703be0eaf32ead6ac8174edee333" - integrity sha512-pH8orJahy+hzZje5b8e2QIlBWQvGpelS76C63Z+jhZKsmzfNaPQ+LaW6dcJ9bxTpo1mtXbgHwy765Ro3jftmUg== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-transform-optional-chaining@^7.22.15": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.15.tgz#d7a5996c2f7ca4ad2ad16dbb74444e5c4385b1ba" @@ -1283,23 +876,7 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-transform-optional-chaining@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.5.tgz#1003762b9c14295501beb41be72426736bedd1e0" - integrity sha512-AconbMKOMkyG+xCng2JogMCDcqW8wedQAqpVIL4cOSescZ7+iW8utC6YDZLMCSUIReEA733gzRSaOSXMAt/4WQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - -"@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.20.7", "@babel/plugin-transform-parameters@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.5.tgz#c3542dd3c39b42c8069936e48717a8d179d63a18" - integrity sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-parameters@^7.22.15": +"@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.20.7", "@babel/plugin-transform-parameters@^7.22.15": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz#719ca82a01d177af358df64a514d64c2e3edb114" integrity sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ== @@ -1324,16 +901,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/plugin-transform-private-property-in-object@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.5.tgz#07a77f28cbb251546a43d175a1dda4cf3ef83e32" - integrity sha512-/9xnaTTJcVoBtSSmrVyhtSvO3kbqS2ODoh2juEU72c3aYonNF0OMGiaz2gjukyKM2wBBYJP38S4JiE0Wfb5VMQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-create-class-features-plugin" "^7.22.5" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - "@babel/plugin-transform-property-literals@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz#b5ddabd73a4f7f26cd0e20f5db48290b88732766" @@ -1362,16 +929,16 @@ dependencies: "@babel/plugin-transform-react-jsx" "^7.22.5" -"@babel/plugin-transform-react-jsx@^7.12.12", "@babel/plugin-transform-react-jsx@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.5.tgz#932c291eb6dd1153359e2a90cb5e557dcf068416" - integrity sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA== +"@babel/plugin-transform-react-jsx@^7.12.12", "@babel/plugin-transform-react-jsx@^7.22.15", "@babel/plugin-transform-react-jsx@^7.22.5": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.15.tgz#7e6266d88705d7c49f11c98db8b9464531289cd6" + integrity sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA== dependencies: "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-module-imports" "^7.22.5" + "@babel/helper-module-imports" "^7.22.15" "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-jsx" "^7.22.5" - "@babel/types" "^7.22.5" + "@babel/types" "^7.22.15" "@babel/plugin-transform-react-pure-annotations@^7.22.5": version "7.22.5" @@ -1389,14 +956,6 @@ "@babel/helper-plugin-utils" "^7.22.5" regenerator-transform "^0.15.2" -"@babel/plugin-transform-regenerator@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.5.tgz#cd8a68b228a5f75fa01420e8cc2fc400f0fc32aa" - integrity sha512-rR7KePOE7gfEtNTh9Qw+iO3Q/e4DEsoQ+hdvM6QUDH7JRJ5qxq5AA52ZzBWbI5i9lfNuvySgOGP8ZN7LAmaiPw== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - regenerator-transform "^0.15.1" - "@babel/plugin-transform-reserved-words@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz#832cd35b81c287c4bcd09ce03e22199641f964fb" @@ -1446,17 +1005,7 @@ integrity sha512-1uirS0TnijxvQLnlv5wQBwOX3E1wCFX7ITv+9pBV2wKEk4K+M5tqDaoNXnTH8tjEIYHLO98MwiTWO04Ggz4XuA== dependencies: "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-create-class-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-typescript" "^7.22.5" - -"@babel/plugin-transform-typescript@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.5.tgz#5c0f7adfc1b5f38c4dbc8f79b1f0f8074134bd7d" - integrity sha512-SMubA9S7Cb5sGSFFUlqxyClTA9zWJ8qGQrppNUm05LtFuN1ELRFNndkix4zUJrC9F+YivWwa1dHMSyo0e0N9dA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-create-class-features-plugin" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.22.15" "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-typescript" "^7.22.5" @@ -1467,13 +1016,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-unicode-escapes@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.5.tgz#ce0c248522b1cb22c7c992d88301a5ead70e806c" - integrity sha512-biEmVg1IYB/raUO5wT1tgfacCef15Fbzhkx493D3urBI++6hpJ+RFG4SrWMn0NEZLfvilqKf3QDrRVZHo08FYg== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-transform-unicode-property-regex@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz#098898f74d5c1e86660dc112057b2d11227f1c81" @@ -1498,93 +1040,7 @@ "@babel/helper-create-regexp-features-plugin" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" -"@babel/preset-env@^7.12.11", "@babel/preset-env@^7.15.0", "@babel/preset-env@^7.19.4": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.22.5.tgz#3da66078b181f3d62512c51cf7014392c511504e" - integrity sha512-fj06hw89dpiZzGZtxn+QybifF07nNiZjZ7sazs2aVDcysAZVGjW7+7iFYxg6GLNM47R/thYfLdrXc+2f11Vi9A== - dependencies: - "@babel/compat-data" "^7.22.5" - "@babel/helper-compilation-targets" "^7.22.5" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-validator-option" "^7.22.5" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.22.5" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.22.5" - "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-class-properties" "^7.12.13" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-import-assertions" "^7.22.5" - "@babel/plugin-syntax-import-attributes" "^7.22.5" - "@babel/plugin-syntax-import-meta" "^7.10.4" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@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-private-property-in-object" "^7.14.5" - "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" - "@babel/plugin-transform-arrow-functions" "^7.22.5" - "@babel/plugin-transform-async-generator-functions" "^7.22.5" - "@babel/plugin-transform-async-to-generator" "^7.22.5" - "@babel/plugin-transform-block-scoped-functions" "^7.22.5" - "@babel/plugin-transform-block-scoping" "^7.22.5" - "@babel/plugin-transform-class-properties" "^7.22.5" - "@babel/plugin-transform-class-static-block" "^7.22.5" - "@babel/plugin-transform-classes" "^7.22.5" - "@babel/plugin-transform-computed-properties" "^7.22.5" - "@babel/plugin-transform-destructuring" "^7.22.5" - "@babel/plugin-transform-dotall-regex" "^7.22.5" - "@babel/plugin-transform-duplicate-keys" "^7.22.5" - "@babel/plugin-transform-dynamic-import" "^7.22.5" - "@babel/plugin-transform-exponentiation-operator" "^7.22.5" - "@babel/plugin-transform-export-namespace-from" "^7.22.5" - "@babel/plugin-transform-for-of" "^7.22.5" - "@babel/plugin-transform-function-name" "^7.22.5" - "@babel/plugin-transform-json-strings" "^7.22.5" - "@babel/plugin-transform-literals" "^7.22.5" - "@babel/plugin-transform-logical-assignment-operators" "^7.22.5" - "@babel/plugin-transform-member-expression-literals" "^7.22.5" - "@babel/plugin-transform-modules-amd" "^7.22.5" - "@babel/plugin-transform-modules-commonjs" "^7.22.5" - "@babel/plugin-transform-modules-systemjs" "^7.22.5" - "@babel/plugin-transform-modules-umd" "^7.22.5" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.22.5" - "@babel/plugin-transform-new-target" "^7.22.5" - "@babel/plugin-transform-nullish-coalescing-operator" "^7.22.5" - "@babel/plugin-transform-numeric-separator" "^7.22.5" - "@babel/plugin-transform-object-rest-spread" "^7.22.5" - "@babel/plugin-transform-object-super" "^7.22.5" - "@babel/plugin-transform-optional-catch-binding" "^7.22.5" - "@babel/plugin-transform-optional-chaining" "^7.22.5" - "@babel/plugin-transform-parameters" "^7.22.5" - "@babel/plugin-transform-private-methods" "^7.22.5" - "@babel/plugin-transform-private-property-in-object" "^7.22.5" - "@babel/plugin-transform-property-literals" "^7.22.5" - "@babel/plugin-transform-regenerator" "^7.22.5" - "@babel/plugin-transform-reserved-words" "^7.22.5" - "@babel/plugin-transform-shorthand-properties" "^7.22.5" - "@babel/plugin-transform-spread" "^7.22.5" - "@babel/plugin-transform-sticky-regex" "^7.22.5" - "@babel/plugin-transform-template-literals" "^7.22.5" - "@babel/plugin-transform-typeof-symbol" "^7.22.5" - "@babel/plugin-transform-unicode-escapes" "^7.22.5" - "@babel/plugin-transform-unicode-property-regex" "^7.22.5" - "@babel/plugin-transform-unicode-regex" "^7.22.5" - "@babel/plugin-transform-unicode-sets-regex" "^7.22.5" - "@babel/preset-modules" "^0.1.5" - "@babel/types" "^7.22.5" - babel-plugin-polyfill-corejs2 "^0.4.3" - babel-plugin-polyfill-corejs3 "^0.8.1" - babel-plugin-polyfill-regenerator "^0.5.0" - core-js-compat "^3.30.2" - semver "^6.3.0" - -"@babel/preset-env@^7.22.10": +"@babel/preset-env@^7.12.11", "@babel/preset-env@^7.15.0", "@babel/preset-env@^7.19.4", "@babel/preset-env@^7.22.10": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.22.15.tgz#142716f8e00bc030dae5b2ac6a46fbd8b3e18ff8" integrity sha512-tZFHr54GBkHk6hQuVA8w4Fmq+MSPsfvMG0vPnOYyTnJpyfMqybL8/MbNCPRT9zc2KBO2pe4tq15g6Uno4Jpoag== @@ -1671,12 +1127,12 @@ semver "^6.3.1" "@babel/preset-flow@^7.12.1": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.22.5.tgz#876f24ab6b38bd79703a93f32020ca2162312784" - integrity sha512-ta2qZ+LSiGCrP5pgcGt8xMnnkXQrq8Sa4Ulhy06BOlF5QbLw9q5hIx7bn5MrsvyTGAfh6kTOo07Q+Pfld/8Y5Q== + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.22.15.tgz#30318deb9b3ebd9f5738e96da03a531e0cd3165d" + integrity sha512-dB5aIMqpkgbTfN5vDdTRPzjqtWiZcRESNR88QYnoPR+bmdYoluOzMX9tQerTv0XzSgZYctPfO1oc0N5zdog1ew== dependencies: "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-validator-option" "^7.22.5" + "@babel/helper-validator-option" "^7.22.15" "@babel/plugin-transform-flow-strip-types" "^7.22.5" "@babel/preset-modules@0.1.6-no-external-plugins": @@ -1688,41 +1144,19 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-modules@^0.1.5": - version "0.1.5" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" - integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" - "@babel/plugin-transform-dotall-regex" "^7.4.4" - "@babel/types" "^7.4.4" - esutils "^2.0.2" - "@babel/preset-react@^7.12.10", "@babel/preset-react@^7.14.5", "@babel/preset-react@^7.18.6": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.22.5.tgz#c4d6058fbf80bccad02dd8c313a9aaa67e3c3dd6" - integrity sha512-M+Is3WikOpEJHgR385HbuCITPTaPRaNkibTEa9oiofmJvIsrceb4yp9RL9Kb+TE8LznmeyZqpP+Lopwcx59xPQ== + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.22.15.tgz#9a776892b648e13cc8ca2edf5ed1264eea6b6afc" + integrity sha512-Csy1IJ2uEh/PecCBXXoZGAZBeCATTuePzCSB7dLYWS0vOEj6CNpjxIhW4duWwZodBNueH7QO14WbGn8YyeuN9w== dependencies: "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-validator-option" "^7.22.5" + "@babel/helper-validator-option" "^7.22.15" "@babel/plugin-transform-react-display-name" "^7.22.5" - "@babel/plugin-transform-react-jsx" "^7.22.5" + "@babel/plugin-transform-react-jsx" "^7.22.15" "@babel/plugin-transform-react-jsx-development" "^7.22.5" "@babel/plugin-transform-react-pure-annotations" "^7.22.5" -"@babel/preset-typescript@^7.12.7", "@babel/preset-typescript@^7.15.0", "@babel/preset-typescript@^7.18.6": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.22.5.tgz#16367d8b01d640e9a507577ed4ee54e0101e51c8" - integrity sha512-YbPaal9LxztSGhmndR46FmAbkJ/1fAsw293tSU+I5E5h+cnJ3d4GTwyUgGYmOXJYdGA+uNePle4qbaRzj2NISQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-validator-option" "^7.22.5" - "@babel/plugin-syntax-jsx" "^7.22.5" - "@babel/plugin-transform-modules-commonjs" "^7.22.5" - "@babel/plugin-transform-typescript" "^7.22.5" - -"@babel/preset-typescript@^7.22.5": +"@babel/preset-typescript@^7.12.7", "@babel/preset-typescript@^7.15.0", "@babel/preset-typescript@^7.18.6", "@babel/preset-typescript@^7.22.5": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.22.15.tgz#43db30516fae1d417d748105a0bc95f637239d48" integrity sha512-HblhNmh6yM+cU4VwbBRpxFhxsTdfS1zsvH9W+gEjD0ARV9+8B4sNfpI6GuhePti84nuvhiwKS539jKPFHskA9A== @@ -1734,9 +1168,9 @@ "@babel/plugin-transform-typescript" "^7.22.15" "@babel/register@^7.12.1": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.22.5.tgz#e4d8d0f615ea3233a27b5c6ada6750ee59559939" - integrity sha512-vV6pm/4CijSQ8Y47RH5SopXzursN35RQINfGJkmOlcpAtGuf94miFvIPhCKGQN7WGIcsgG1BHEX2KVdTYwTwUQ== + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.22.15.tgz#c2c294a361d59f5fa7bcc8b97ef7319c32ecaec7" + integrity sha512-V3Q3EqoQdn65RCgTLwauZaTfd1ShhwPmbBv+1dkZV/HpCGMKVyn6oFcRlI7RaKqiDQjX2Qd3AuoEguBgdjIKlg== dependencies: clone-deep "^4.0.1" find-cache-dir "^2.0.0" @@ -1756,12 +1190,12 @@ dependencies: regenerator-runtime "^0.13.2" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.9", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.5.tgz#8564dd588182ce0047d55d7a75e93921107b57ec" - integrity sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA== +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.9", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.10", "@babel/runtime@^7.22.6", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.15.tgz#38f46494ccf6cf020bd4eed7124b425e83e523b8" + integrity sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA== dependencies: - regenerator-runtime "^0.13.11" + regenerator-runtime "^0.14.0" "@babel/runtime@~7.5.4": version "7.5.5" @@ -1770,16 +1204,7 @@ dependencies: regenerator-runtime "^0.13.2" -"@babel/template@^7.12.7", "@babel/template@^7.22.5", "@babel/template@^7.3.3": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec" - integrity sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw== - dependencies: - "@babel/code-frame" "^7.22.5" - "@babel/parser" "^7.22.5" - "@babel/types" "^7.22.5" - -"@babel/template@^7.22.15": +"@babel/template@^7.12.7", "@babel/template@^7.22.15", "@babel/template@^7.22.5", "@babel/template@^7.3.3": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== @@ -1788,26 +1213,10 @@ "@babel/parser" "^7.22.15" "@babel/types" "^7.22.15" -"@babel/traverse@^7.1.6", "@babel/traverse@^7.12.11", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.22.5", "@babel/traverse@^7.7.2": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.5.tgz#44bd276690db6f4940fdb84e1cb4abd2f729ccd1" - integrity sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ== - dependencies: - "@babel/code-frame" "^7.22.5" - "@babel/generator" "^7.22.5" - "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-function-name" "^7.22.5" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.5" - "@babel/parser" "^7.22.5" - "@babel/types" "^7.22.5" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/traverse@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.15.tgz#75be4d2d6e216e880e93017f4e2389aeb77ef2d9" - integrity sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ== +"@babel/traverse@^7.1.6", "@babel/traverse@^7.12.11", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.22.15", "@babel/traverse@^7.22.17", "@babel/traverse@^7.7.2": + version "7.22.17" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.17.tgz#b23c203ab3707e3be816043081b4a994fcacec44" + integrity sha512-xK4Uwm0JnAMvxYZxOVecss85WxTEIbTa7bnGyf/+EgCL5Zt3U7htUpEOWv9detPlamGKuRzCqw74xVglDWpPdg== dependencies: "@babel/code-frame" "^7.22.13" "@babel/generator" "^7.22.15" @@ -1815,40 +1224,15 @@ "@babel/helper-function-name" "^7.22.5" "@babel/helper-hoist-variables" "^7.22.5" "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.22.15" - "@babel/types" "^7.22.15" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8": - version "7.22.8" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.8.tgz#4d4451d31bc34efeae01eac222b514a77aa4000e" - integrity sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw== - dependencies: - "@babel/code-frame" "^7.22.5" - "@babel/generator" "^7.22.7" - "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-function-name" "^7.22.5" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.22.7" - "@babel/types" "^7.22.5" + "@babel/parser" "^7.22.16" + "@babel/types" "^7.22.17" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.12.11", "@babel/types@^7.12.7", "@babel/types@^7.2.0", "@babel/types@^7.20.0", "@babel/types@^7.20.7", "@babel/types@^7.22.5", "@babel/types@^7.3.3", "@babel/types@^7.4.4": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe" - integrity sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA== - dependencies: - "@babel/helper-string-parser" "^7.22.5" - "@babel/helper-validator-identifier" "^7.22.5" - to-fast-properties "^2.0.0" - -"@babel/types@^7.22.10", "@babel/types@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.15.tgz#266cb21d2c5fd0b3931e7a91b6dd72d2f617d282" - integrity sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA== +"@babel/types@^7.0.0", "@babel/types@^7.12.11", "@babel/types@^7.12.7", "@babel/types@^7.2.0", "@babel/types@^7.20.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.17", "@babel/types@^7.22.5", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.22.17" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.17.tgz#f753352c4610ffddf9c8bc6823f9ff03e2303eee" + integrity sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg== dependencies: "@babel/helper-string-parser" "^7.22.5" "@babel/helper-validator-identifier" "^7.22.15" @@ -2352,10 +1736,10 @@ dependencies: eslint-visitor-keys "^3.3.0" -"@eslint-community/regexpp@^4.4.0": - version "4.5.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.1.tgz#cdd35dce4fa1a89a4fd42b1599eb35b3af408884" - integrity sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ== +"@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1": + version "4.8.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.8.1.tgz#8c4bb756cc2aa7eaf13cfa5e69c83afb3260c20c" + integrity sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ== "@eslint/eslintrc@^0.4.3": version "0.4.3" @@ -2372,14 +1756,14 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" -"@eslint/eslintrc@^2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.3.tgz#4910db5505f4d503f27774bf356e3704818a0331" - integrity sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ== +"@eslint/eslintrc@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.2.tgz#c6936b4b328c64496692f76944e755738be62396" + integrity sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.5.2" + espree "^9.6.0" globals "^13.19.0" ignore "^5.2.0" import-fresh "^3.2.1" @@ -2387,10 +1771,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.43.0": - version "8.43.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.43.0.tgz#559ca3d9ddbd6bf907ad524320a0d14b85586af0" - integrity sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg== +"@eslint/js@8.49.0": + version "8.49.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.49.0.tgz#86f79756004a97fa4df866835093f1df3d03c333" + integrity sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w== "@favware/rollup-type-bundler@^2.0.0": version "2.0.0" @@ -2405,19 +1789,34 @@ rollup-plugin-dts "^5.0.0" typescript "^4.8.4" -"@floating-ui/core@^1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.3.1.tgz#4d795b649cc3b1cbb760d191c80dcb4353c9a366" - integrity sha512-Bu+AMaXNjrpjh41znzHqaz3r2Nr8hHuHZT6V2LBKMhyMl0FgKA62PNYbqnfgmzOhoWZj70Zecisbo4H1rotP5g== +"@floating-ui/core@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.4.1.tgz#0d633f4b76052668afb932492ac452f7ebe97f17" + integrity sha512-jk3WqquEJRlcyu7997NtR5PibI+y5bi+LS3hPmguVClypenMsCY3CBa3LAQnozRCtCrYWSEtAdiskpamuJRFOQ== + dependencies: + "@floating-ui/utils" "^0.1.1" -"@floating-ui/dom@^1.0.0": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.4.3.tgz#0854a3297ea03894932381f3ea1403fab3a6e602" - integrity sha512-nB/68NyaQlcdY22L+Fgd1HERQ7UGv7XFN+tPxwrEfQL4nKtAP/jIZnZtpUlXbtV+VEGHh6W/63Gy2C5biWI3sA== +"@floating-ui/dom@^1.0.0", "@floating-ui/dom@^1.5.1": + version "1.5.2" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.5.2.tgz#6812e89d1d4d4ea32f10d15c3b81feb7f9836d89" + integrity sha512-6ArmenS6qJEWmwzczWyhvrXRdI/rI78poBcW0h/456+onlabit+2G+QxHx5xTOX60NBJQXjsCLFbW2CmsXpUog== + dependencies: + "@floating-ui/core" "^1.4.1" + "@floating-ui/utils" "^0.1.1" + +"@floating-ui/react-dom@^2.0.1": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.0.2.tgz#fab244d64db08e6bed7be4b5fcce65315ef44d20" + integrity sha512-5qhlDvjaLmAst/rKb3VdlCinwTF4EYMiVxuuc/HVUjs46W0zgtbMmAZ1UTsDrRTxRmUEzl92mOtWbeeXL26lSQ== dependencies: - "@floating-ui/core" "^1.3.1" + "@floating-ui/dom" "^1.5.1" + +"@floating-ui/utils@^0.1.1": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.1.2.tgz#b7e9309ccce5a0a40ac482cb894f120dba2b357f" + integrity sha512-ou3elfqG/hZsbmF4bxeJhPHIf3G2pm0ujc39hYEZrfVqt7Vk/Zji6CXc3W0pmYM8BW1g40U+akTl9DKZhFhInQ== -"@gar/promisify@^1.0.1", "@gar/promisify@^1.1.3": +"@gar/promisify@^1.0.1": version "1.1.3" resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== @@ -2427,10 +1826,10 @@ resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-2.9.11.tgz#9ce96e7746625a89239f68ca57c4f654264c17ef" integrity sha512-bA3aZ79UgcHj7tFV7RlgThzwSSHZgvfbt2wprldRkYBcMopdMvHyO17Wwp/twcJasNFischFfS7oz8Katz8DdQ== -"@humanwhocodes/config-array@^0.11.10": - version "0.11.10" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2" - integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ== +"@humanwhocodes/config-array@^0.11.11": + version "0.11.11" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.11.tgz#88a04c570dbbc7dd943e4712429c3df09bc32844" + integrity sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA== dependencies: "@humanwhocodes/object-schema" "^1.2.1" debug "^4.1.1" @@ -2472,11 +1871,6 @@ wrap-ansi "^8.1.0" wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" -"@isaacs/string-locale-compare@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz#291c227e93fd407a96ecd59879a35809120e432b" - integrity sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ== - "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -2505,16 +1899,16 @@ jest-util "^27.5.1" slash "^3.0.0" -"@jest/console@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.6.1.tgz#b48ba7b9c34b51483e6d590f46e5837f1ab5f639" - integrity sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q== +"@jest/console@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" + integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== dependencies: - "@jest/types" "^29.6.1" + "@jest/types" "^29.6.3" "@types/node" "*" chalk "^4.0.0" - jest-message-util "^29.6.1" - jest-util "^29.6.1" + jest-message-util "^29.7.0" + jest-util "^29.7.0" slash "^3.0.0" "@jest/core@^27.5.1": @@ -2551,37 +1945,37 @@ slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/core@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.6.1.tgz#fac0d9ddf320490c93356ba201451825231e95f6" - integrity sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ== +"@jest/core@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" + integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== dependencies: - "@jest/console" "^29.6.1" - "@jest/reporters" "^29.6.1" - "@jest/test-result" "^29.6.1" - "@jest/transform" "^29.6.1" - "@jest/types" "^29.6.1" + "@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.5.0" - jest-config "^29.6.1" - jest-haste-map "^29.6.1" - jest-message-util "^29.6.1" - jest-regex-util "^29.4.3" - jest-resolve "^29.6.1" - jest-resolve-dependencies "^29.6.1" - jest-runner "^29.6.1" - jest-runtime "^29.6.1" - jest-snapshot "^29.6.1" - jest-util "^29.6.1" - jest-validate "^29.6.1" - jest-watcher "^29.6.1" + 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.6.1" + pretty-format "^29.7.0" slash "^3.0.0" strip-ansi "^6.0.0" @@ -2595,15 +1989,15 @@ "@types/node" "*" jest-mock "^27.5.1" -"@jest/environment@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.6.1.tgz#ee358fff2f68168394b4a50f18c68278a21fe82f" - integrity sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A== +"@jest/environment@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" + integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== dependencies: - "@jest/fake-timers" "^29.6.1" - "@jest/types" "^29.6.1" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" "@types/node" "*" - jest-mock "^29.6.1" + jest-mock "^29.7.0" "@jest/expect-utils@^28.1.3": version "28.1.3" @@ -2612,27 +2006,20 @@ dependencies: jest-get-type "^28.0.2" -"@jest/expect-utils@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.5.0.tgz#f74fad6b6e20f924582dc8ecbf2cb800fe43a036" - integrity sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg== - dependencies: - jest-get-type "^29.4.3" - -"@jest/expect-utils@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.6.1.tgz#ab83b27a15cdd203fe5f68230ea22767d5c3acc5" - integrity sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw== +"@jest/expect-utils@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" + integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== dependencies: - jest-get-type "^29.4.3" + jest-get-type "^29.6.3" -"@jest/expect@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.6.1.tgz#fef18265188f6a97601f1ea0a2912d81a85b4657" - integrity sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg== +"@jest/expect@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" + integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== dependencies: - expect "^29.6.1" - jest-snapshot "^29.6.1" + expect "^29.7.0" + jest-snapshot "^29.7.0" "@jest/fake-timers@^27.5.1": version "27.5.1" @@ -2646,17 +2033,17 @@ jest-mock "^27.5.1" jest-util "^27.5.1" -"@jest/fake-timers@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.6.1.tgz#c773efddbc61e1d2efcccac008139f621de57c69" - integrity sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg== +"@jest/fake-timers@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" + integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== dependencies: - "@jest/types" "^29.6.1" + "@jest/types" "^29.6.3" "@sinonjs/fake-timers" "^10.0.2" "@types/node" "*" - jest-message-util "^29.6.1" - jest-mock "^29.6.1" - jest-util "^29.6.1" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-util "^29.7.0" "@jest/globals@^27.5.1": version "27.5.1" @@ -2667,15 +2054,15 @@ "@jest/types" "^27.5.1" expect "^27.5.1" -"@jest/globals@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.6.1.tgz#c8a8923e05efd757308082cc22893d82b8aa138f" - integrity sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A== +"@jest/globals@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" + integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== dependencies: - "@jest/environment" "^29.6.1" - "@jest/expect" "^29.6.1" - "@jest/types" "^29.6.1" - jest-mock "^29.6.1" + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/types" "^29.6.3" + jest-mock "^29.7.0" "@jest/reporters@^27.5.1": version "27.5.1" @@ -2708,16 +2095,16 @@ terminal-link "^2.0.0" v8-to-istanbul "^8.1.0" -"@jest/reporters@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.6.1.tgz#3325a89c9ead3cf97ad93df3a427549d16179863" - integrity sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA== +"@jest/reporters@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" + integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^29.6.1" - "@jest/test-result" "^29.6.1" - "@jest/transform" "^29.6.1" - "@jest/types" "^29.6.1" + "@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" @@ -2726,13 +2113,13 @@ glob "^7.1.3" graceful-fs "^4.2.9" istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^5.1.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.6.1" - jest-util "^29.6.1" - jest-worker "^29.6.1" + 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" @@ -2745,20 +2132,6 @@ dependencies: "@sinclair/typebox" "^0.24.1" -"@jest/schemas@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.4.3.tgz#39cf1b8469afc40b6f5a2baaa146e332c4151788" - integrity sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg== - dependencies: - "@sinclair/typebox" "^0.25.16" - -"@jest/schemas@^29.6.0": - version "29.6.0" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.0.tgz#0f4cb2c8e3dca80c135507ba5635a4fd755b0040" - integrity sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ== - dependencies: - "@sinclair/typebox" "^0.27.8" - "@jest/schemas@^29.6.3": version "29.6.3" resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" @@ -2775,10 +2148,10 @@ graceful-fs "^4.2.9" source-map "^0.6.0" -"@jest/source-map@^29.6.0": - version "29.6.0" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.0.tgz#bd34a05b5737cb1a99d43e1957020ac8e5b9ddb1" - integrity sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA== +"@jest/source-map@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" + integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== dependencies: "@jridgewell/trace-mapping" "^0.3.18" callsites "^3.0.0" @@ -2794,13 +2167,13 @@ "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-result@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.6.1.tgz#850e565a3f58ee8ca6ec424db00cb0f2d83c36ba" - integrity sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw== +"@jest/test-result@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" + integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== dependencies: - "@jest/console" "^29.6.1" - "@jest/types" "^29.6.1" + "@jest/console" "^29.7.0" + "@jest/types" "^29.6.3" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" @@ -2814,14 +2187,14 @@ jest-haste-map "^27.5.1" jest-runtime "^27.5.1" -"@jest/test-sequencer@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz#e3e582ee074dd24ea9687d7d1aaf05ee3a9b068e" - integrity sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg== +"@jest/test-sequencer@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" + integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== dependencies: - "@jest/test-result" "^29.6.1" + "@jest/test-result" "^29.7.0" graceful-fs "^4.2.9" - jest-haste-map "^29.6.1" + jest-haste-map "^29.7.0" slash "^3.0.0" "@jest/transform@^26.6.2": @@ -2866,22 +2239,22 @@ source-map "^0.6.1" write-file-atomic "^3.0.0" -"@jest/transform@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.6.1.tgz#acb5606019a197cb99beda3c05404b851f441c92" - integrity sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg== +"@jest/transform@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" + integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== dependencies: "@babel/core" "^7.11.6" - "@jest/types" "^29.6.1" + "@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.6.1" - jest-regex-util "^29.4.3" - jest-util "^29.6.1" + 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" @@ -2921,30 +2294,6 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" -"@jest/types@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.5.0.tgz#f59ef9b031ced83047c67032700d8c807d6e1593" - integrity sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog== - dependencies: - "@jest/schemas" "^29.4.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" - -"@jest/types@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.1.tgz#ae79080278acff0a6af5eb49d063385aaa897bf2" - integrity sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw== - dependencies: - "@jest/schemas" "^29.6.0" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" - "@jest/types@^29.6.3": version "29.6.3" resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" @@ -2966,12 +2315,7 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/resolve-uri@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== - -"@jridgewell/resolve-uri@^3.0.3": +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": version "3.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== @@ -2982,19 +2326,14 @@ integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== "@jridgewell/source-map@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.3.tgz#8108265659d4c33e72ffe14e33d6cc5eb59f2fda" - integrity sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg== + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91" + integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ== dependencies: "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/sourcemap-codec@1.4.14": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13": +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15": version "1.4.15" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== @@ -3008,113 +2347,97 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.18" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" - integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== + version "0.3.19" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz#f8a3249862f91be48d3127c3cfe992f79b4b8811" + integrity sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw== dependencies: - "@jridgewell/resolve-uri" "3.1.0" - "@jridgewell/sourcemap-codec" "1.4.14" + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" "@leichtgewicht/ip-codec@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== -"@lerna/child-process@6.6.2": - version "6.6.2" - resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-6.6.2.tgz#5d803c8dee81a4e013dc428292e77b365cba876c" - integrity sha512-QyKIWEnKQFnYu2ey+SAAm1A5xjzJLJJj3bhIZd3QKyXKKjaJ0hlxam/OsWSltxTNbcyH1jRJjC6Cxv31usv0Ag== +"@lerna/child-process@7.3.0": + version "7.3.0" + resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-7.3.0.tgz#c56488a8a881f22a64793bf9339c5a2450a18559" + integrity sha512-rA+fGUo2j/LEq6w1w8s6oVikLbJTWoIDVpYMc7bUCtwDOUuZKMQiRtjmpavY3fTm7ltu42f4AKflc2A70K4wvA== dependencies: chalk "^4.1.0" execa "^5.0.0" strong-log-transformer "^2.1.0" -"@lerna/create@6.6.2": - version "6.6.2" - resolved "https://registry.yarnpkg.com/@lerna/create/-/create-6.6.2.tgz#39a36d80cddb355340c297ed785aa76f4498177f" - integrity sha512-xQ+1Y7D+9etvUlE+unhG/TwmM6XBzGIdFBaNoW8D8kyOa9M2Jf3vdEtAxVa7mhRz66CENfhL/+I/QkVaa7pwbQ== +"@lerna/create@7.3.0": + version "7.3.0" + resolved "https://registry.yarnpkg.com/@lerna/create/-/create-7.3.0.tgz#5438c231f617b8e825731390d394f8684af471d5" + integrity sha512-fjgiKjg9VXwQ4ZKKsrXICEKRiC3yo6+FprR0mc55uz0s5e9xupoSGLobUTTBdE7ncNB3ibqml8dfaAn/+ESajQ== dependencies: - "@lerna/child-process" "6.6.2" - dedent "^0.7.0" - fs-extra "^9.1.0" - init-package-json "^3.0.2" - npm-package-arg "8.1.1" - p-reduce "^2.1.0" - pacote "15.1.1" - pify "^5.0.0" - semver "^7.3.4" - slash "^3.0.0" - validate-npm-package-license "^3.0.4" - validate-npm-package-name "^4.0.0" - yargs-parser "20.2.4" - -"@lerna/legacy-package-management@6.6.2": - version "6.6.2" - resolved "https://registry.yarnpkg.com/@lerna/legacy-package-management/-/legacy-package-management-6.6.2.tgz#411c395e72e563ab98f255df77e4068627a85bb0" - integrity sha512-0hZxUPKnHwehUO2xC4ldtdX9bW0W1UosxebDIQlZL2STnZnA2IFmIk2lJVUyFW+cmTPQzV93jfS0i69T9Z+teg== - dependencies: - "@npmcli/arborist" "6.2.3" - "@npmcli/run-script" "4.1.7" - "@nrwl/devkit" ">=15.5.2 < 16" - "@octokit/rest" "19.0.3" - byte-size "7.0.0" + "@lerna/child-process" "7.3.0" + "@npmcli/run-script" "6.0.2" + "@nx/devkit" ">=16.5.1 < 17" + "@octokit/plugin-enterprise-rest" "6.0.1" + "@octokit/rest" "19.0.11" + byte-size "8.1.1" chalk "4.1.0" clone-deep "4.0.1" - cmd-shim "5.0.0" + cmd-shim "6.0.1" columnify "1.6.0" - config-chain "1.1.12" - conventional-changelog-core "4.2.4" - conventional-recommended-bump "6.1.0" - cosmiconfig "7.0.0" + conventional-changelog-core "5.0.1" + conventional-recommended-bump "7.0.1" + cosmiconfig "^8.2.0" dedent "0.7.0" - dot-prop "6.0.1" execa "5.0.0" - file-url "3.0.0" - find-up "5.0.0" - fs-extra "9.1.0" - get-port "5.1.1" + fs-extra "^11.1.1" get-stream "6.0.0" git-url-parse "13.1.0" glob-parent "5.1.2" globby "11.1.0" - graceful-fs "4.2.10" + graceful-fs "4.2.11" has-unicode "2.0.1" - inquirer "8.2.4" - is-ci "2.0.0" + ini "^1.3.8" + init-package-json "5.0.0" + inquirer "^8.2.4" + is-ci "3.0.1" is-stream "2.0.0" - libnpmpublish "7.1.4" + js-yaml "4.1.0" + libnpmpublish "7.3.0" load-json-file "6.2.0" - make-dir "3.1.0" + lodash "^4.17.21" + make-dir "4.0.0" minimatch "3.0.5" multimatch "5.0.0" node-fetch "2.6.7" npm-package-arg "8.1.1" npm-packlist "5.1.1" - npm-registry-fetch "14.0.3" - npmlog "6.0.2" + npm-registry-fetch "^14.0.5" + npmlog "^6.0.2" + nx ">=16.5.1 < 17" p-map "4.0.0" p-map-series "2.1.0" p-queue "6.6.2" - p-waterfall "2.1.1" - pacote "15.1.1" + p-reduce "^2.1.0" + pacote "^15.2.0" pify "5.0.0" - pretty-format "29.4.3" - read-cmd-shim "3.0.0" - read-package-json "5.0.1" + read-cmd-shim "4.0.0" + read-package-json "6.0.4" resolve-from "5.0.0" - semver "7.3.8" + rimraf "^4.4.1" + semver "^7.3.4" signal-exit "3.0.7" - slash "3.0.0" - ssri "9.0.1" + slash "^3.0.0" + ssri "^9.0.1" strong-log-transformer "2.1.0" tar "6.1.11" temp-dir "1.0.0" - tempy "1.0.0" upath "2.0.1" - uuid "8.3.2" - write-file-atomic "4.0.1" + uuid "^9.0.0" + validate-npm-package-license "^3.0.4" + validate-npm-package-name "5.0.0" + write-file-atomic "5.0.1" write-pkg "4.0.0" yargs "16.2.0" + yargs-parser "20.2.4" "@mdx-js/loader@^2.1.5": version "2.3.0" @@ -3190,108 +2513,96 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" -"@mui/base@5.0.0-beta.4": - version "5.0.0-beta.4" - resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.4.tgz#e3f4f4a056b88ab357194a245e223177ce35e0b0" - integrity sha512-ejhtqYJpjDgHGEljjMBQWZ22yEK0OzIXNa7toJmmXsP4TT3W7xVy8bTJ0TniPDf+JNjrsgfgiFTDGdlEhV1E+g== - dependencies: - "@babel/runtime" "^7.21.0" - "@emotion/is-prop-valid" "^1.2.1" - "@mui/types" "^7.2.4" - "@mui/utils" "^5.13.1" - "@popperjs/core" "^2.11.8" - clsx "^1.2.1" - prop-types "^15.8.1" - react-is "^18.2.0" - -"@mui/base@5.0.0-beta.5": - version "5.0.0-beta.5" - resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.5.tgz#b566f3beb1eb2823139eabaf52014cf7be900015" - integrity sha512-vy3TWLQYdGNecTaufR4wDNQFV2WEg6wRPi6BVbx6q1vP3K1mbxIn1+XOqOzfYBXjFHvMx0gZAo2TgWbaqfgvAA== +"@mui/base@5.0.0-beta.14": + version "5.0.0-beta.14" + resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.14.tgz#315b67b0fd231cbd47e8d54f8f92be23122e4d66" + integrity sha512-Je/9JzzYObsuLCIClgE8XvXNFb55IEz8n2NtStUfASfNiVrwiR8t6VVFFuhofehkyTIN34tq1qbBaOjCnOovBw== dependencies: - "@babel/runtime" "^7.22.5" + "@babel/runtime" "^7.22.10" "@emotion/is-prop-valid" "^1.2.1" + "@floating-ui/react-dom" "^2.0.1" "@mui/types" "^7.2.4" - "@mui/utils" "^5.13.6" + "@mui/utils" "^5.14.8" "@popperjs/core" "^2.11.8" - clsx "^1.2.1" + clsx "^2.0.0" prop-types "^15.8.1" react-is "^18.2.0" -"@mui/core-downloads-tracker@^5.13.4": - version "5.13.4" - resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.13.4.tgz#7e4b491d8081b6d45ae51556d82cb16b31315a19" - integrity sha512-yFrMWcrlI0TqRN5jpb6Ma9iI7sGTHpytdzzL33oskFHNQ8UgrtPas33Y1K7sWAMwCrr1qbWDrOHLAQG4tAzuSw== +"@mui/core-downloads-tracker@^5.14.8": + version "5.14.8" + resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.8.tgz#9117bd29e94e96dc376f93a28e024666a2456696" + integrity sha512-8V7ZOC/lKkM03TRHqaThQFIq6bWPnj7L/ZWPh0ymldYFFyh8XdF0ywTgafsofDNYT4StlNknbaTjVHBma3SNjQ== "@mui/icons-material@^5.0.0", "@mui/icons-material@^5.2.0": - version "5.11.16" - resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.11.16.tgz#417fa773c56672e39d6ccfed9ac55591985f0d38" - integrity sha512-oKkx9z9Kwg40NtcIajF9uOXhxiyTZrrm9nmIJ4UjkU2IdHpd4QVLbCc/5hZN/y0C6qzi2Zlxyr9TGddQx2vx2A== + version "5.14.8" + resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.14.8.tgz#e07418e792050eae611afd74f810ed1c234be687" + integrity sha512-YXcReLydTuNWb1/PxduAH5LgnHNH6spSQBaA0JOz9HD4J+vwst0IanAQgsXy9KKCJSjCsHywE3DB8X+w/b4eeQ== dependencies: - "@babel/runtime" "^7.21.0" + "@babel/runtime" "^7.22.10" "@mui/lab@^5.0.0-alpha.72": - version "5.0.0-alpha.134" - resolved "https://registry.yarnpkg.com/@mui/lab/-/lab-5.0.0-alpha.134.tgz#e48c108fce91fbb89446dcf86ca35e7e761bc078" - integrity sha512-GhvuM2dNOi6hzjbeGEocWVozgyyeUn7RBmZhLFtniROauxmPCZMcTsEU+GAxmpyYppqHuI8flP6tGKgMuEAK/g== + version "5.0.0-alpha.143" + resolved "https://registry.yarnpkg.com/@mui/lab/-/lab-5.0.0-alpha.143.tgz#0fef89f8780f819a28d7f7e62383ab964d121ae2" + integrity sha512-2lpzJCSyrb0yNhxzKK2G25w9+Tk+vjlmjgAXh+j8NS2fyRD7F992DuChRqNaoZmg1aoAbFli6qZh6XJE/5cymA== dependencies: - "@babel/runtime" "^7.21.0" - "@mui/base" "5.0.0-beta.4" - "@mui/system" "^5.13.5" + "@babel/runtime" "^7.22.10" + "@mui/base" "5.0.0-beta.14" + "@mui/system" "^5.14.8" "@mui/types" "^7.2.4" - "@mui/utils" "^5.13.1" - clsx "^1.2.1" + "@mui/utils" "^5.14.8" + "@mui/x-tree-view" "https://pkg.csb.dev/mui/mui-x/commit/1f23b33d/@mui/x-tree-view" + clsx "^2.0.0" prop-types "^15.8.1" react-is "^18.2.0" "@mui/material@^5.0.1", "@mui/material@^5.2.2": - version "5.13.6" - resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.13.6.tgz#caaba1e071e394c415208404ce6964e6c14c16d6" - integrity sha512-/c2ZApeQm2sTYdQXjqEnldaBMBcUEiyu2VRS6bS39ZeNaAcCLBQbYocLR46R+f0S5dgpBzB0T4AsOABPOFYZ5Q== - dependencies: - "@babel/runtime" "^7.22.5" - "@mui/base" "5.0.0-beta.5" - "@mui/core-downloads-tracker" "^5.13.4" - "@mui/system" "^5.13.6" + version "5.14.8" + resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.14.8.tgz#1cad40f106f7c983639376589c3f21485fb1d166" + integrity sha512-fqvDGGF1pXwOOL/f0Gw+KHo/67hasRpf2ApTIJkbuONOk9AUb2jnYMEqCWmL2sUcbbE3ShMbHl8N7HPSsRv1/A== + dependencies: + "@babel/runtime" "^7.22.10" + "@mui/base" "5.0.0-beta.14" + "@mui/core-downloads-tracker" "^5.14.8" + "@mui/system" "^5.14.8" "@mui/types" "^7.2.4" - "@mui/utils" "^5.13.6" + "@mui/utils" "^5.14.8" "@types/react-transition-group" "^4.4.6" - clsx "^1.2.1" + clsx "^2.0.0" csstype "^3.1.2" prop-types "^15.8.1" react-is "^18.2.0" react-transition-group "^4.4.5" -"@mui/private-theming@^5.13.1": - version "5.13.7" - resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.13.7.tgz#2f8ef5da066f3c6c6423bd4260d003a28d10b099" - integrity sha512-qbSr+udcij5F9dKhGX7fEdx2drXchq7htLNr2Qg2Ma+WJ6q0ERlEqGSBiPiVDJkptcjeVL4DGmcf1wl5+vD4EA== +"@mui/private-theming@^5.14.7", "@mui/private-theming@^5.14.8": + version "5.14.8" + resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.14.8.tgz#8e224cd10c531d12b871dc59b1f9376028dd13bb" + integrity sha512-iBzpcl3Mh92XaYpYPdgzzRxNGkjpoDz8rf8/q5m+EBPowFEHV+CCS9hC0Q2pOKLW3VFFikA7w/GHt7n++40JGQ== dependencies: - "@babel/runtime" "^7.22.5" - "@mui/utils" "^5.13.7" + "@babel/runtime" "^7.22.10" + "@mui/utils" "^5.14.8" prop-types "^15.8.1" -"@mui/styled-engine@^5.13.2": - version "5.13.2" - resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.13.2.tgz#c87bd61c0ab8086d34828b6defe97c02bcd642ef" - integrity sha512-VCYCU6xVtXOrIN8lcbuPmoG+u7FYuOERG++fpY74hPpEWkyFQG97F+/XfTQVYzlR2m7nPjnwVUgATcTCMEaMvw== +"@mui/styled-engine@^5.14.8": + version "5.14.8" + resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.14.8.tgz#b7a4d5dc6cbe3ecaa5af5189eb5ad90a62a255eb" + integrity sha512-LGwOav/Y40PZWZ2yDk4beUoRlc57Vg+Vpxi9V9BBtT2ESAucCgFobkt+T8eVLMWF9huUou5pwKgLSU5pF90hBg== dependencies: - "@babel/runtime" "^7.21.0" + "@babel/runtime" "^7.22.10" "@emotion/cache" "^11.11.0" csstype "^3.1.2" prop-types "^15.8.1" "@mui/styles@^5.0.1", "@mui/styles@^5.2.2": - version "5.13.2" - resolved "https://registry.yarnpkg.com/@mui/styles/-/styles-5.13.2.tgz#0d6c1b7c5437293cf4f0d98d1fd8c5cc02bb4138" - integrity sha512-gKNkVyk6azQ8wfCamh3yU/wLv1JscYrsQX9huQBwfwtE7kUTq2rgggdfJjRADjbcmT6IPX+oCHYjGfqqFgDIQQ== + version "5.14.7" + resolved "https://registry.yarnpkg.com/@mui/styles/-/styles-5.14.7.tgz#e704f465b39e6dbfcd30090b191cf8140f7a9e42" + integrity sha512-5qA81gIRBUd3ur2FtGO10UmArpqaGWL+eUGFVSf68SjhahhHr86/JgqsXqUPyW/LPnyW92SZxhQ6El6Co8i7AQ== dependencies: - "@babel/runtime" "^7.21.0" + "@babel/runtime" "^7.22.10" "@emotion/hash" "^0.9.1" - "@mui/private-theming" "^5.13.1" + "@mui/private-theming" "^5.14.7" "@mui/types" "^7.2.4" - "@mui/utils" "^5.13.1" - clsx "^1.2.1" + "@mui/utils" "^5.14.7" + clsx "^2.0.0" csstype "^3.1.2" hoist-non-react-statics "^3.3.2" jss "^10.10.0" @@ -3304,17 +2615,17 @@ jss-plugin-vendor-prefixer "^10.10.0" prop-types "^15.8.1" -"@mui/system@>= 5", "@mui/system@^5.0.1", "@mui/system@^5.13.5", "@mui/system@^5.13.6": - version "5.13.6" - resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.13.6.tgz#5bf4f84fad0c9ed771458f821e384f61abfa33ca" - integrity sha512-G3Xr28uLqU3DyF6r2LQkHGw/ku4P0AHzlKVe7FGXOPl7X1u+hoe2xxj8Vdiq/69II/mh9OP21i38yBWgWb7WgQ== +"@mui/system@>= 5", "@mui/system@^5.0.1", "@mui/system@^5.14.8": + version "5.14.8" + resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.14.8.tgz#1ca201b948310083e670352bae2d7963ad6f971e" + integrity sha512-Dxnasv7Pj5hYe4ZZFKJZu4ufKm6cxpitWt3A+qMPps22YhqyeEqgDBq/HsAB3GOjqDP40fTAvQvS/Hguf4SJuw== dependencies: - "@babel/runtime" "^7.22.5" - "@mui/private-theming" "^5.13.1" - "@mui/styled-engine" "^5.13.2" + "@babel/runtime" "^7.22.10" + "@mui/private-theming" "^5.14.8" + "@mui/styled-engine" "^5.14.8" "@mui/types" "^7.2.4" - "@mui/utils" "^5.13.6" - clsx "^1.2.1" + "@mui/utils" "^5.14.8" + clsx "^2.0.0" csstype "^3.1.2" prop-types "^15.8.1" @@ -3323,23 +2634,12 @@ resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.4.tgz#b6fade19323b754c5c6de679a38f068fd50b9328" integrity sha512-LBcwa8rN84bKF+f5sDyku42w1NTxaPgPyYKODsh01U1fVstTClbUoSA96oyRBnSNyEiAVjKm6Gwx9vjR+xyqHA== -"@mui/utils@^5.10.3", "@mui/utils@^5.13.1", "@mui/utils@^5.13.6", "@mui/utils@^5.7.0": - version "5.13.6" - resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.13.6.tgz#aa29d75de59577585b9f23891b03592d40459ed7" - integrity sha512-ggNlxl5NPSbp+kNcQLmSig6WVB0Id+4gOxhx644987v4fsji+CSXc+MFYLocFB/x4oHtzCUlSzbVHlJfP/fXoQ== - dependencies: - "@babel/runtime" "^7.22.5" - "@types/prop-types" "^15.7.5" - "@types/react-is" "^18.2.0" - prop-types "^15.8.1" - react-is "^18.2.0" - -"@mui/utils@^5.13.7": - version "5.13.7" - resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.13.7.tgz#7e6a8336e05eb2642667a5c02eb605351e27ec20" - integrity sha512-/3BLptG/q0u36eYED7Nhf4fKXmcKb6LjjT7ZMwhZIZSdSxVqDqSTmATW3a56n3KEPQUXCU9TpxAfCBQhs6brVA== +"@mui/utils@^5.10.3", "@mui/utils@^5.13.7", "@mui/utils@^5.14.7", "@mui/utils@^5.14.8", "@mui/utils@^5.7.0": + version "5.14.8" + resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.14.8.tgz#e1737d5fcd54aa413d6b1aaea3ea670af2919402" + integrity sha512-1Ls2FfyY2yVSz9NEqedh3J8JAbbZAnUWkOWLE2f4/Hc4T5UWHMfzBLLrCqExfqyfyU+uXYJPGeNIsky6f8Gh5Q== dependencies: - "@babel/runtime" "^7.22.5" + "@babel/runtime" "^7.22.10" "@types/prop-types" "^15.7.5" "@types/react-is" "^18.2.1" prop-types "^15.8.1" @@ -3356,15 +2656,21 @@ prop-types "^15.8.1" reselect "^4.1.6" -"@nicolo-ribaudo/semver-v6@^6.3.3": - version "6.3.3" - resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz#ea6d23ade78a325f7a52750aab1526b02b628c29" - integrity sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg== +"@mui/x-tree-view@https://pkg.csb.dev/mui/mui-x/commit/1f23b33d/@mui/x-tree-view": + version "6.0.0-alpha.0" + resolved "https://pkg.csb.dev/mui/mui-x/commit/1f23b33d/@mui/x-tree-view#93cbc61c818ed2d6c40554cdbada969f7dcbaab1" + dependencies: + "@babel/runtime" "^7.22.6" + "@mui/utils" "^5.13.7" + "@types/react-transition-group" "^4.4.6" + clsx "^1.2.1" + prop-types "^15.8.1" + react-transition-group "^4.4.5" "@noble/hashes@^1", "@noble/hashes@^1.0.0", "@noble/hashes@^1.2.0": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" - integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -3392,45 +2698,6 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@npmcli/arborist@6.2.3": - version "6.2.3" - resolved "https://registry.yarnpkg.com/@npmcli/arborist/-/arborist-6.2.3.tgz#31f8aed2588341864d3811151d929c01308f8e71" - integrity sha512-lpGOC2ilSJXcc2zfW9QtukcCTcMbl3fVI0z4wvFB2AFIl0C+Q6Wv7ccrpdrQa8rvJ1ZVuc6qkX7HVTyKlzGqKA== - dependencies: - "@isaacs/string-locale-compare" "^1.1.0" - "@npmcli/fs" "^3.1.0" - "@npmcli/installed-package-contents" "^2.0.0" - "@npmcli/map-workspaces" "^3.0.2" - "@npmcli/metavuln-calculator" "^5.0.0" - "@npmcli/name-from-folder" "^2.0.0" - "@npmcli/node-gyp" "^3.0.0" - "@npmcli/package-json" "^3.0.0" - "@npmcli/query" "^3.0.0" - "@npmcli/run-script" "^6.0.0" - bin-links "^4.0.1" - cacache "^17.0.4" - common-ancestor-path "^1.0.1" - hosted-git-info "^6.1.1" - json-parse-even-better-errors "^3.0.0" - json-stringify-nice "^1.1.4" - minimatch "^6.1.6" - nopt "^7.0.0" - npm-install-checks "^6.0.0" - npm-package-arg "^10.1.0" - npm-pick-manifest "^8.0.1" - npm-registry-fetch "^14.0.3" - npmlog "^7.0.1" - pacote "^15.0.8" - parse-conflict-json "^3.0.0" - proc-log "^3.0.0" - promise-all-reject-late "^1.0.0" - promise-call-limit "^1.0.1" - read-package-json-fast "^3.0.2" - semver "^7.3.7" - ssri "^10.0.1" - treeverse "^3.0.0" - walk-up-path "^1.0.0" - "@npmcli/fs@^1.0.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.1.1.tgz#72f719fe935e687c56a4faecf3c03d06ba593257" @@ -3439,14 +2706,6 @@ "@gar/promisify" "^1.0.1" semver "^7.3.5" -"@npmcli/fs@^2.1.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-2.1.2.tgz#a9e2541a4a2fec2e69c29b35e6060973da79b865" - integrity sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ== - dependencies: - "@gar/promisify" "^1.1.3" - semver "^7.3.5" - "@npmcli/fs@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-3.1.0.tgz#233d43a25a91d68c3a863ba0da6a3f00924a173e" @@ -3454,7 +2713,7 @@ dependencies: semver "^7.3.5" -"@npmcli/git@^4.0.0", "@npmcli/git@^4.1.0": +"@npmcli/git@^4.0.0": version "4.1.0" resolved "https://registry.yarnpkg.com/@npmcli/git/-/git-4.1.0.tgz#ab0ad3fd82bc4d8c1351b6c62f0fa56e8fe6afa6" integrity sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ== @@ -3468,33 +2727,13 @@ semver "^7.3.5" which "^3.0.0" -"@npmcli/installed-package-contents@^2.0.0", "@npmcli/installed-package-contents@^2.0.1": +"@npmcli/installed-package-contents@^2.0.1": version "2.0.2" resolved "https://registry.yarnpkg.com/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz#bfd817eccd9e8df200919e73f57f9e3d9e4f9e33" integrity sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ== dependencies: npm-bundled "^3.0.0" - npm-normalize-package-bin "^3.0.0" - -"@npmcli/map-workspaces@^3.0.2": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@npmcli/map-workspaces/-/map-workspaces-3.0.4.tgz#15ad7d854292e484f7ba04bc30187a8320dba799" - integrity sha512-Z0TbvXkRbacjFFLpVpV0e2mheCh+WzQpcqL+4xp49uNJOxOnIAPZyXtUxZ5Qn3QBTGKA11Exjd9a5411rBrhDg== - dependencies: - "@npmcli/name-from-folder" "^2.0.0" - glob "^10.2.2" - minimatch "^9.0.0" - read-package-json-fast "^3.0.0" - -"@npmcli/metavuln-calculator@^5.0.0": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@npmcli/metavuln-calculator/-/metavuln-calculator-5.0.1.tgz#426b3e524c2008bcc82dbc2ef390aefedd643d76" - integrity sha512-qb8Q9wIIlEPj3WeA1Lba91R4ZboPL0uspzV0F9uwP+9AYMVB2zOoa7Pbk12g6D2NHAinSbHh6QYmGuRyHZ874Q== - dependencies: - cacache "^17.0.0" - json-parse-even-better-errors "^3.0.0" - pacote "^15.0.0" - semver "^7.3.5" + npm-normalize-package-bin "^3.0.0" "@npmcli/move-file@^1.0.1": version "1.1.2" @@ -3504,48 +2743,11 @@ mkdirp "^1.0.4" rimraf "^3.0.2" -"@npmcli/move-file@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-2.0.1.tgz#26f6bdc379d87f75e55739bab89db525b06100e4" - integrity sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ== - dependencies: - mkdirp "^1.0.4" - rimraf "^3.0.2" - -"@npmcli/name-from-folder@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@npmcli/name-from-folder/-/name-from-folder-2.0.0.tgz#c44d3a7c6d5c184bb6036f4d5995eee298945815" - integrity sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg== - -"@npmcli/node-gyp@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@npmcli/node-gyp/-/node-gyp-2.0.0.tgz#8c20e53e34e9078d18815c1d2dda6f2420d75e35" - integrity sha512-doNI35wIe3bBaEgrlPfdJPaCpUR89pJWep4Hq3aRdh6gKazIVWfs0jHttvSSoq47ZXgC7h73kDsUl8AoIQUB+A== - "@npmcli/node-gyp@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz#101b2d0490ef1aa20ed460e4c0813f0db560545a" integrity sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA== -"@npmcli/package-json@^3.0.0": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@npmcli/package-json/-/package-json-3.1.1.tgz#5628332aac90fa1b4d6f98e03988c5958b35e0c5" - integrity sha512-+UW0UWOYFKCkvszLoTwrYGrjNrT8tI5Ckeb/h+Z1y1fsNJEctl7HmerA5j2FgmoqFaLI2gsA1X9KgMFqx/bRmA== - dependencies: - "@npmcli/git" "^4.1.0" - glob "^10.2.2" - json-parse-even-better-errors "^3.0.0" - normalize-package-data "^5.0.0" - npm-normalize-package-bin "^3.0.1" - proc-log "^3.0.0" - -"@npmcli/promise-spawn@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@npmcli/promise-spawn/-/promise-spawn-3.0.0.tgz#53283b5f18f855c6925f23c24e67c911501ef573" - integrity sha512-s9SgS+p3a9Eohe68cSI3fi+hpcZUmXq5P7w0kMlAsWVtR7XbK3ptkZqKT2cK1zLDObJ3sR+8P59sJE0w/KTL1g== - dependencies: - infer-owner "^1.0.4" - "@npmcli/promise-spawn@^6.0.0", "@npmcli/promise-spawn@^6.0.1": version "6.0.2" resolved "https://registry.yarnpkg.com/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz#c8bc4fa2bd0f01cb979d8798ba038f314cfa70f2" @@ -3553,25 +2755,7 @@ dependencies: which "^3.0.0" -"@npmcli/query@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@npmcli/query/-/query-3.0.0.tgz#51a0dfb85811e04f244171f164b6bc83b36113a7" - integrity sha512-MFNDSJNgsLZIEBVZ0Q9w9K7o07j5N4o4yjtdz2uEpuCZlXGMuPENiRaFYk0vRqAA64qVuUQwC05g27fRtfUgnA== - dependencies: - postcss-selector-parser "^6.0.10" - -"@npmcli/run-script@4.1.7": - version "4.1.7" - resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-4.1.7.tgz#b1a2f57568eb738e45e9ea3123fb054b400a86f7" - integrity sha512-WXr/MyM4tpKA4BotB81NccGAv8B48lNH0gRoILucbcAhTQXLCoi6HflMV3KdXubIqvP9SuLsFn68Z7r4jl+ppw== - dependencies: - "@npmcli/node-gyp" "^2.0.0" - "@npmcli/promise-spawn" "^3.0.0" - node-gyp "^9.0.0" - read-package-json-fast "^2.0.3" - which "^2.0.2" - -"@npmcli/run-script@^6.0.0": +"@npmcli/run-script@6.0.2", "@npmcli/run-script@^6.0.0": version "6.0.2" resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-6.0.2.tgz#a25452d45ee7f7fb8c16dfaf9624423c0c0eb885" integrity sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA== @@ -3582,75 +2766,83 @@ read-package-json-fast "^3.0.0" which "^3.0.0" -"@nrwl/cli@15.9.4": - version "15.9.4" - resolved "https://registry.yarnpkg.com/@nrwl/cli/-/cli-15.9.4.tgz#63b600dff1cdc126f234d16978a888f72c22a00c" - integrity sha512-FoiGFCLpb/r4HXCM3KYqT0xteP+MRV6bIHjz3bdPHIDLmBNQQnRRaV2K47jtJ6zjh1eOU5UHKyDtDDYf80Idpw== +"@nrwl/devkit@16.8.1": + version "16.8.1" + resolved "https://registry.yarnpkg.com/@nrwl/devkit/-/devkit-16.8.1.tgz#18f90c9bddbac182ca2cd6b08c90f09caf9f4aa0" + integrity sha512-Y7yYDh62Hi4q99Q4+ipIQ3K9iLuAld3WcwjLv6vtl6Livu+TU3eqbraBEno7DQL8JuIuwgBT4lX7Bp3w3N9RDg== dependencies: - nx "15.9.4" + "@nx/devkit" "16.8.1" -"@nrwl/devkit@>=15.5.2 < 16": - version "15.9.4" - resolved "https://registry.yarnpkg.com/@nrwl/devkit/-/devkit-15.9.4.tgz#3f0a43a9637fcd0a46c06df2a9c36012b27f006b" - integrity sha512-mUX1kXTuPMdTzFxIzH+MsSNvdppOmstPDOEtiGFZJTuJ625ki0HhNJILO3N2mJ7MeMrLqIlAiNdvelQaObxYsQ== +"@nrwl/tao@16.8.1": + version "16.8.1" + resolved "https://registry.yarnpkg.com/@nrwl/tao/-/tao-16.8.1.tgz#640522eef8905f358ce087e1f6a8489c69e3ebfb" + integrity sha512-hgGFLyEgONSofxnJsXN9NlUx4J8/YSLUkfZKdR8Qa97+JGZT8FEuk7NLFJOWdYYqROoCzXLHK0d+twFFNPS5BQ== dependencies: + nx "16.8.1" + tslib "^2.3.0" + +"@nx/devkit@16.8.1", "@nx/devkit@>=16.5.1 < 17": + version "16.8.1" + resolved "https://registry.yarnpkg.com/@nx/devkit/-/devkit-16.8.1.tgz#830a6f3daf774aabe1a95e257eb4c832ee85d497" + integrity sha512-I+Cg+lXk0wRz6KC9FZbWFuJWQTXAt5O3bNl9ksISmzqmEyuy72Cv+/MBHvF7o54Sq80DNw+RKWB1re5HFOsqCA== + dependencies: + "@nrwl/devkit" "16.8.1" ejs "^3.1.7" + enquirer "~2.3.6" ignore "^5.0.4" - semver "7.3.4" + semver "7.5.3" tmp "~0.2.1" tslib "^2.3.0" -"@nrwl/nx-darwin-arm64@15.9.4": - version "15.9.4" - resolved "https://registry.yarnpkg.com/@nrwl/nx-darwin-arm64/-/nx-darwin-arm64-15.9.4.tgz#e5a2f39d42a60397a01140a251f894788f5d1fda" - integrity sha512-XnvrnT9BJsgThY/4xUcYtE077ERq/img8CkRj7MOOBNOh0/nVcR4LGbBKDHtwE3HPk0ikyS/SxRyNa9msvi3QQ== - -"@nrwl/nx-darwin-x64@15.9.4": - version "15.9.4" - resolved "https://registry.yarnpkg.com/@nrwl/nx-darwin-x64/-/nx-darwin-x64-15.9.4.tgz#97a810d4ff6b4bf395a43e4740890c0def2372da" - integrity sha512-WKSfSlpVMLchpXkax0geeUNyhvNxwO7qUz/s0/HJWBekt8fizwKDwDj1gP7fOu+YWb/tHiSscbR1km8PtdjhQw== - -"@nrwl/nx-linux-arm-gnueabihf@15.9.4": - version "15.9.4" - resolved "https://registry.yarnpkg.com/@nrwl/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-15.9.4.tgz#b8dd23b8c755b7e640d744945ab2dec3fd3eda65" - integrity sha512-a/b4PP7lP/Cgrh0LjC4O2YTt5pyf4DQTGtuE8qlo8o486UiofCtk4QGJX72q80s23L0ejCaKY2ULKx/3zMLjuA== - -"@nrwl/nx-linux-arm64-gnu@15.9.4": - version "15.9.4" - resolved "https://registry.yarnpkg.com/@nrwl/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-15.9.4.tgz#5bc150c2bdb2e0a2eaf8721b3c5fdb2eb93f8739" - integrity sha512-ibBV8fMhSfLVd/2WzcDuUm32BoZsattuKkvMmOoyU6Pzoznc3AqyDjJR4xCIoAn5Rf+Nu1oeQONr5FAtb1Ugow== - -"@nrwl/nx-linux-arm64-musl@15.9.4": - version "15.9.4" - resolved "https://registry.yarnpkg.com/@nrwl/nx-linux-arm64-musl/-/nx-linux-arm64-musl-15.9.4.tgz#df2f18f813828000dc52f1b7668339947b1a0862" - integrity sha512-iIjvVYd7+uM4jVD461+PvU5XTALgSvJOODUaMRGOoDl0KlMuTe6pQZlw0eXjl5rcTd6paKaVFWT5j6awr8kj7w== - -"@nrwl/nx-linux-x64-gnu@15.9.4": - version "15.9.4" - resolved "https://registry.yarnpkg.com/@nrwl/nx-linux-x64-gnu/-/nx-linux-x64-gnu-15.9.4.tgz#55547b07e6aeb0c36a43e05bd07c15b013f2de9f" - integrity sha512-q4OyH72mdrE4KellBWtwpr5EwfxHKNoFP9//7FAILO68ROh0rpMd7YQMlTB7T04UEUHjKEEsFGTlVXIee3Viwg== - -"@nrwl/nx-linux-x64-musl@15.9.4": - version "15.9.4" - resolved "https://registry.yarnpkg.com/@nrwl/nx-linux-x64-musl/-/nx-linux-x64-musl-15.9.4.tgz#29cd644736f643566d9c0e1a1171c49a62a08c09" - integrity sha512-67+/XNMR1CgLPyeGX8jqSG6l8yYD0iiwUgcu1Vaxq6N05WwnqVisIW8XzLSRUtKt4WyVQgOWk3aspImpMVOG3Q== - -"@nrwl/nx-win32-arm64-msvc@15.9.4": - version "15.9.4" - resolved "https://registry.yarnpkg.com/@nrwl/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-15.9.4.tgz#55a38bf5dc201e9088729fb03e505dc63caf8b3a" - integrity sha512-2rEsq3eOGVCYpYJn2tTJkOGNJm/U8rP/FmqtZXYa6VJv/00XP3Gl00IXFEDaYV6rZo7SWqLxtEPUbjK5LwPzZA== - -"@nrwl/nx-win32-x64-msvc@15.9.4": - version "15.9.4" - resolved "https://registry.yarnpkg.com/@nrwl/nx-win32-x64-msvc/-/nx-win32-x64-msvc-15.9.4.tgz#56bb859bfe47d08d14f8d5822d9a31d9098d95a9" - integrity sha512-bogVju4Z/hy1jbppqaTNbmV1R4Kg0R5fKxXAXC2LaL7FL0dup31wPumdV+mXttXBNOBDjV8V/Oz1ZqdmxpOJUw== - -"@nrwl/tao@15.9.4": - version "15.9.4" - resolved "https://registry.yarnpkg.com/@nrwl/tao/-/tao-15.9.4.tgz#5e384af06d1fb68e326eda2c6a5d8f99ce1583b8" - integrity sha512-m90iz8UsXx1rgPm1dxsBQjSrCViWYZIrp8bpwjSCW24j3kifyilYSXGuKaRwZwUn7eNmH/kZcI9/8qeGIPF4Sg== - dependencies: - nx "15.9.4" +"@nx/nx-darwin-arm64@16.8.1": + version "16.8.1" + resolved "https://registry.yarnpkg.com/@nx/nx-darwin-arm64/-/nx-darwin-arm64-16.8.1.tgz#fd85ed007d63d232700272cd07138ecac046525d" + integrity sha512-xOflqyIVcyLPzdJOZcucI+5ClwnTgK8zIvpjbxHokrO9McJJglhfUyP0bbTHpEpWqzA+GaPA/6/Qdu0ATzqQBQ== + +"@nx/nx-darwin-x64@16.8.1": + version "16.8.1" + resolved "https://registry.yarnpkg.com/@nx/nx-darwin-x64/-/nx-darwin-x64-16.8.1.tgz#de75b5052cb7ec93e238af632f0ea0f2d8822e66" + integrity sha512-JJGrlOvEpDMWnM6YKaA1WOnzHgiw5vRKEowX9ba+jxhmCvtdjbLSxi228kv92JtQPPQ91zvtsNM+BFY0EbPOlA== + +"@nx/nx-freebsd-x64@16.8.1": + version "16.8.1" + resolved "https://registry.yarnpkg.com/@nx/nx-freebsd-x64/-/nx-freebsd-x64-16.8.1.tgz#733dbe731af814b87a1429d7c087c4879192536c" + integrity sha512-aZdJQ7cIQfXOmfk4vRXvVYxuV68xz8YyhNZ0IvBfJ16uZQ+YNl4BpklRLEIdaloSbwz9M1NNewmL+AgklEBxlA== + +"@nx/nx-linux-arm-gnueabihf@16.8.1": + version "16.8.1" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-16.8.1.tgz#3d1e2130d26ecc335df21bf8a8afa566bd6b4ed5" + integrity sha512-JzjrTf7FFgikoVUbRs0hKvwHRR6SyqT4yIdk/YyiCt2mWY9w4m5DWtHM/9kJzhckkH9MY66m+X/zG6+NKsEMvg== + +"@nx/nx-linux-arm64-gnu@16.8.1": + version "16.8.1" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-16.8.1.tgz#f0f96dc4be17cac8a387367eaafe71a6b1948fc3" + integrity sha512-CF0s981myBWusW7iW2+fKPa7ceYYe+NO5EdKe9l27fpHDkcA71KZU3q7U823QpO/7tYvVdBevJp3CCn2/GBURQ== + +"@nx/nx-linux-arm64-musl@16.8.1": + version "16.8.1" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-16.8.1.tgz#65ed581e702ef882afd9d7f25b660e34e4c13690" + integrity sha512-X4TobxRt1dALvoeKC3/t1CqZCMUqtEhGG+KQLT/51sG54HdxmTAWRFlvj8PvLH0QSBk4e+uRZAo45qpt3iSnBg== + +"@nx/nx-linux-x64-gnu@16.8.1": + version "16.8.1" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-16.8.1.tgz#cc5c782a67e5b17f4e395d358d87ea5076606dba" + integrity sha512-lHvv2FD14Lpxh7muMLStH2tC1opQOaepO4nXwb1LaaoIpMym7kBgCK8AQuI98/oNQiMDXMNDKWQZCjxnJGDIPw== + +"@nx/nx-linux-x64-musl@16.8.1": + version "16.8.1" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-16.8.1.tgz#2837fb7d6590b5fe9f2eb42603d0e064771a8ded" + integrity sha512-c4gQvNgIjggD1A5sYhftQEC1PtAhV3sEnv60X00v9wmjl57Wj4Ty0TgyzpYglLysVRiko/B58S8NYS0jKvMmeA== + +"@nx/nx-win32-arm64-msvc@16.8.1": + version "16.8.1" + resolved "https://registry.yarnpkg.com/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-16.8.1.tgz#d45d8abdd99f3b0dda83a673592299ffdc819895" + integrity sha512-GKHPy/MyGFoV9cdKgcWLZZK2vDdxt5bQ53ss0k+BDKRP+YwLKm7tJl23eeM7JdB4GLCBntEQPC+dBqxOA8Ze/w== + +"@nx/nx-win32-x64-msvc@16.8.1": + version "16.8.1" + resolved "https://registry.yarnpkg.com/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-16.8.1.tgz#6ec1930aaf4d9dea19149d6b3d100b2c7e69d582" + integrity sha512-yHZ5FAcx54rVc31R0yIpniepkHMPwaxG23l8E/ZYbL1iPwE/Wc1HeUzUvxUuSXtguRp7ihcRhaUEPkcSl2EAVw== "@nymproject/nym-validator-client@^0.18.0": version "0.18.0" @@ -3668,7 +2860,7 @@ resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-3.0.4.tgz#70e941ba742bdd2b49bdb7393e821dea8520a3db" integrity sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ== -"@octokit/core@^4.0.0": +"@octokit/core@^4.2.1": version "4.2.4" resolved "https://registry.yarnpkg.com/@octokit/core/-/core-4.2.4.tgz#d8769ec2b43ff37cc3ea89ec4681a20ba58ef907" integrity sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ== @@ -3699,16 +2891,6 @@ "@octokit/types" "^9.0.0" universal-user-agent "^6.0.0" -"@octokit/openapi-types@^12.11.0": - version "12.11.0" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-12.11.0.tgz#da5638d64f2b919bca89ce6602d059f1b52d3ef0" - integrity sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ== - -"@octokit/openapi-types@^14.0.0": - version "14.0.0" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-14.0.0.tgz#949c5019028c93f189abbc2fb42f333290f7134a" - integrity sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw== - "@octokit/openapi-types@^18.0.0": version "18.0.0" resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-18.0.0.tgz#f43d765b3c7533fd6fb88f3f25df079c24fccf69" @@ -3719,25 +2901,25 @@ resolved "https://registry.yarnpkg.com/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz#e07896739618dab8da7d4077c658003775f95437" integrity sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw== -"@octokit/plugin-paginate-rest@^3.0.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-3.1.0.tgz#86f8be759ce2d6d7c879a31490fd2f7410b731f0" - integrity sha512-+cfc40pMzWcLkoDcLb1KXqjX0jTGYXjKuQdFQDc6UAknISJHnZTiBqld6HDwRJvD4DsouDKrWXNbNV0lE/3AXA== +"@octokit/plugin-paginate-rest@^6.1.2": + version "6.1.2" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz#f86456a7a1fe9e58fec6385a85cf1b34072341f8" + integrity sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ== dependencies: - "@octokit/types" "^6.41.0" + "@octokit/tsconfig" "^1.0.2" + "@octokit/types" "^9.2.3" "@octokit/plugin-request-log@^1.0.4": version "1.0.4" resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85" integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA== -"@octokit/plugin-rest-endpoint-methods@^6.0.0": - version "6.8.1" - resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.8.1.tgz#97391fda88949eb15f68dc291957ccbe1d3e8ad1" - integrity sha512-QrlaTm8Lyc/TbU7BL/8bO49vp+RZ6W3McxxmmQTgYxf2sWkO8ZKuj4dLhPNJD6VCUW1hetCmeIM0m6FTVpDiEg== +"@octokit/plugin-rest-endpoint-methods@^7.1.2": + version "7.2.3" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.2.3.tgz#37a84b171a6cb6658816c82c4082ac3512021797" + integrity sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA== dependencies: - "@octokit/types" "^8.1.1" - deprecation "^2.3.1" + "@octokit/types" "^10.0.0" "@octokit/request-error@^3.0.0": version "3.0.3" @@ -3760,31 +2942,29 @@ node-fetch "^2.6.7" universal-user-agent "^6.0.0" -"@octokit/rest@19.0.3": - version "19.0.3" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-19.0.3.tgz#b9a4e8dc8d53e030d611c053153ee6045f080f02" - integrity sha512-5arkTsnnRT7/sbI4fqgSJ35KiFaN7zQm0uQiQtivNQLI8RQx8EHwJCajcTUwmaCMNDg7tdCvqAnc7uvHHPxrtQ== +"@octokit/rest@19.0.11": + version "19.0.11" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-19.0.11.tgz#2ae01634fed4bd1fca5b642767205ed3fd36177c" + integrity sha512-m2a9VhaP5/tUw8FwfnW2ICXlXpLPIqxtg3XcAiGMLj/Xhw3RSBfZ8le/466ktO1Gcjr8oXudGnHhxV1TXJgFxw== dependencies: - "@octokit/core" "^4.0.0" - "@octokit/plugin-paginate-rest" "^3.0.0" + "@octokit/core" "^4.2.1" + "@octokit/plugin-paginate-rest" "^6.1.2" "@octokit/plugin-request-log" "^1.0.4" - "@octokit/plugin-rest-endpoint-methods" "^6.0.0" + "@octokit/plugin-rest-endpoint-methods" "^7.1.2" -"@octokit/types@^6.41.0": - version "6.41.0" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.41.0.tgz#e58ef78d78596d2fb7df9c6259802464b5f84a04" - integrity sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg== - dependencies: - "@octokit/openapi-types" "^12.11.0" +"@octokit/tsconfig@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@octokit/tsconfig/-/tsconfig-1.0.2.tgz#59b024d6f3c0ed82f00d08ead5b3750469125af7" + integrity sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA== -"@octokit/types@^8.1.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-8.2.1.tgz#a6de091ae68b5541f8d4fcf9a12e32836d4648aa" - integrity sha512-8oWMUji8be66q2B9PmEIUyQm00VPDPun07umUWSaCwxmeaquFBro4Hcc3ruVoDo3zkQyZBlRvhIMEYS3pBhanw== +"@octokit/types@^10.0.0": + version "10.0.0" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-10.0.0.tgz#7ee19c464ea4ada306c43f1a45d444000f419a4a" + integrity sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg== dependencies: - "@octokit/openapi-types" "^14.0.0" + "@octokit/openapi-types" "^18.0.0" -"@octokit/types@^9.0.0": +"@octokit/types@^9.0.0", "@octokit/types@^9.2.3": version "9.3.2" resolved "https://registry.yarnpkg.com/@octokit/types/-/types-9.3.2.tgz#3f5f89903b69f6a2d196d78ec35f888c0013cac5" integrity sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA== @@ -3805,9 +2985,9 @@ integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== "@pmmmwh/react-refresh-webpack-plugin@^0.5.3", "@pmmmwh/react-refresh-webpack-plugin@^0.5.4": - version "0.5.10" - resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.10.tgz#2eba163b8e7dbabb4ce3609ab5e32ab63dda3ef8" - integrity sha512-j0Ya0hCFZPd4x40qLzbhGsh9TMtdb+CJQiso+WxLOPNasohq9cc5SNUcwsZaRH6++Xh91Xkm/xHCkuIiIu0LUA== + version "0.5.11" + resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.11.tgz#7c2268cedaa0644d677e8c4f377bc8fb304f714a" + integrity sha512-7j/6vdTym0+qZ6u4XbSAxrWBGYSdCfTzySkj7WAFgDLmSyWlOrWvpyzxlFh5jtw9dn0oL/jtW+06XfFiisN3JQ== dependencies: ansi-html-community "^0.0.8" common-path-prefix "^3.0.0" @@ -3877,10 +3057,10 @@ resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== -"@remix-run/router@1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.7.0.tgz#550a8d5760b78efc5d60f62b5829b0f74c1fde81" - integrity sha512-Eu1V3kz3mV0wUpVTiFHuaT8UD1gj/0VnoFHQYX35xlslQUpe8CuYoKFn9d4WZFHm3yDywz6ALZuGdnUPKrNeAw== +"@remix-run/router@1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.8.0.tgz#e848d2f669f601544df15ce2a313955e4bf0bafc" + integrity sha512-mrfKqIHnSZRyIzBcanNJmVQELTnX+qagEDlcKO90RgRBVOZGSGvZKeDihTRfWcqoDn5N/NkUcwWTccnpN18Tfg== "@rollup/plugin-commonjs@^24.0.1": version "24.1.0" @@ -3911,9 +3091,9 @@ "@rollup/pluginutils" "^5.0.1" "@rollup/plugin-node-resolve@^15.0.1": - version "15.1.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.1.0.tgz#9ffcd8e8c457080dba89bb9fcb583a6778dc757e" - integrity sha512-xeZHCgsiZ9pzYVgAo9580eCGqwh/XCEUM9q6iQfGNocjgkufHAqC3exA+45URvhiYV8sBF9RlBai650eNs7AsA== + version "15.2.1" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.1.tgz#a15b14fb7969229e26a30feff2816d39eff503f0" + integrity sha512-nsbUg588+GDSu8/NS8T4UAshO6xeaOfINNuXeVHcKV02LJtoRaM1SiOacClw4kws1SFiNhdLGxlbMY9ga/zs/w== dependencies: "@rollup/pluginutils" "^5.0.1" "@types/resolve" "1.20.2" @@ -3948,9 +3128,9 @@ resolve "^1.22.1" "@rollup/plugin-typescript@^11.0.0": - version "11.1.2" - resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-11.1.2.tgz#09eb5690a650bb0334bf84125bce9abd296442e4" - integrity sha512-0ghSOCMcA7fl1JM+0gYRf+Q/HWyg+zg7/gDSc+fRLmlJWcW5K1I+CLRzaRhXf4Y3DRyPnnDo4M2ktw+a6JcDEg== + version "11.1.3" + resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-11.1.3.tgz#8172858a1e5f4c181aebc61f8920002fd5e04b91" + integrity sha512-8o6cNgN44kQBcpsUJTbTXMTtb87oR1O0zgP3Dxm71hrNgparap3VujgofEilTYJo+ivf2ke6uy3/E5QEaiRlDA== dependencies: "@rollup/pluginutils" "^5.0.1" resolve "^1.22.1" @@ -3979,117 +3159,127 @@ picomatch "^2.2.2" "@rollup/pluginutils@^5.0.1": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.2.tgz#012b8f53c71e4f6f9cb317e311df1404f56e7a33" - integrity sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA== + version "5.0.4" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.4.tgz#74f808f9053d33bafec0cc98e7b835c9667d32ba" + integrity sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g== dependencies: "@types/estree" "^1.0.0" estree-walker "^2.0.2" picomatch "^2.3.1" "@sapphire/utilities@^3.11.0": - version "3.12.0" - resolved "https://registry.yarnpkg.com/@sapphire/utilities/-/utilities-3.12.0.tgz#3ee8330338aa79a7e0cab04d4d0eec9ed69fc9bf" - integrity sha512-y1JP4FdPBkZjJGJcb5Zx0ok64mtpGvz0TLOC49HTwYsfBQL8tsTct93yoYdEEMWSZFmOF1ZvV8L6jIJ1CW8bJw== - -"@sentry-internal/tracing@7.57.0": - version "7.57.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.57.0.tgz#cb761931b635f8f24c84be0eecfacb8516b20551" - integrity sha512-tpViyDd8AhQGYYhI94xi2aaDopXOPfL2Apwrtb3qirWkomIQ2K86W1mPmkce+B0cFOnW2Dxv/ZTFKz6ghjK75A== - dependencies: - "@sentry/core" "7.57.0" - "@sentry/types" "7.57.0" - "@sentry/utils" "7.57.0" + version "3.13.0" + resolved "https://registry.yarnpkg.com/@sapphire/utilities/-/utilities-3.13.0.tgz#04fd73281ad4cd63c2c87ffbac3faa393d77cf95" + integrity sha512-BD5ycPjZX5dXxrAb90dJTY8ukpPVBXgU17gA5ghK2memS4hwAzFYpvK+R+6zh4d6HYIKVuqrVhGXjvZenAa/Aw== + +"@sentry-internal/tracing@7.69.0": + version "7.69.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.69.0.tgz#8d8eb740b72967b6ba3fdc0a5173aa55331b7d35" + integrity sha512-4BgeWZUj9MO6IgfO93C9ocP3+AdngqujF/+zB2rFdUe+y9S6koDyUC7jr9Knds/0Ta72N/0D6PwhgSCpHK8s0Q== + dependencies: + "@sentry/core" "7.69.0" + "@sentry/types" "7.69.0" + "@sentry/utils" "7.69.0" tslib "^2.4.1 || ^1.9.3" -"@sentry/browser@7.57.0": - version "7.57.0" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.57.0.tgz#6e724c9eac680dba99ced0fdf81be8d1e3b3bceb" - integrity sha512-E0HaYYlaqHFiIRZXxcvOO8Odvlt+TR1vFFXzqUWXPOvDRxURglTOCQ3EN/u6bxtAGJ6y/Zc2obgihTtypuel/w== +"@sentry/browser@7.69.0": + version "7.69.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.69.0.tgz#65427c90fb71c1775e2c1e38431efb7f4aec1e34" + integrity sha512-5ls+zu2PrMhHCIIhclKQsWX5u6WH0Ez5/GgrCMZTtZ1d70ukGSRUvpZG9qGf5Cw1ezS1LY+1HCc3whf8x8lyPw== dependencies: - "@sentry-internal/tracing" "7.57.0" - "@sentry/core" "7.57.0" - "@sentry/replay" "7.57.0" - "@sentry/types" "7.57.0" - "@sentry/utils" "7.57.0" + "@sentry-internal/tracing" "7.69.0" + "@sentry/core" "7.69.0" + "@sentry/replay" "7.69.0" + "@sentry/types" "7.69.0" + "@sentry/utils" "7.69.0" tslib "^2.4.1 || ^1.9.3" -"@sentry/core@7.57.0": - version "7.57.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.57.0.tgz#65093d739c04f320a54395a21be955fcbe326acb" - integrity sha512-l014NudPH0vQlzybtXajPxYFfs9w762NoarjObC3gu76D1jzBBFzhdRelkGpDbSLNTIsKhEDDRpgAjBWJ9icfw== +"@sentry/core@7.69.0": + version "7.69.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.69.0.tgz#ebbe01df573f438f8613107020a4e18eb9adca4d" + integrity sha512-V6jvK2lS8bhqZDMFUtvwe2XvNstFQf5A+2LMKCNBOV/NN6eSAAd6THwEpginabjet9dHsNRmMk7WNKvrUfQhZw== dependencies: - "@sentry/types" "7.57.0" - "@sentry/utils" "7.57.0" + "@sentry/types" "7.69.0" + "@sentry/utils" "7.69.0" tslib "^2.4.1 || ^1.9.3" "@sentry/integrations@^7.54.0": - version "7.57.0" - resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.57.0.tgz#298085b3a2fe862cc70bc7f2143aa0fbc617322c" - integrity sha512-C3WZo5AGI2L0dj+mIjeZpdAwDEG2nDYvZbTzq5J9hVoHFdP3t7fOWBHSPkSFVtTdMaJrv+82aKnUefVCeAjxGg== + version "7.69.0" + resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.69.0.tgz#04c0206d9436ec7b79971e3bde5d6e1e9194595f" + integrity sha512-FEFtFqXuCo9+L7bENZxFpEAlIODwHl6FyW/DwLfniy9jOXHU7BhP/oICLrFE5J7rh1gNY7N/8VlaiQr3hCnS/g== dependencies: - "@sentry/types" "7.57.0" - "@sentry/utils" "7.57.0" + "@sentry/types" "7.69.0" + "@sentry/utils" "7.69.0" localforage "^1.8.1" tslib "^2.4.1 || ^1.9.3" "@sentry/react@^7.54.0": - version "7.57.0" - resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.57.0.tgz#cf91f0115bcd2a8306d6c8a39d8e8b53d4b21814" - integrity sha512-XGNTjIoCG3naSmCU8qObd+y+CqAB6NQkGWOp2yyBwp2inyKF2ehJvDh6bIQloBYq2TmOJDa4NfXdMrkilxaLFQ== + version "7.69.0" + resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.69.0.tgz#b9931ac590d8dad3390a9a03a516f1b1bd75615e" + integrity sha512-J+DciRRVuruf1nMmBOi2VeJkOLGeCb4vTOFmHzWTvRJNByZ0flyo8E/fyROL7+23kBq1YbcVY6IloUlH73hneQ== dependencies: - "@sentry/browser" "7.57.0" - "@sentry/types" "7.57.0" - "@sentry/utils" "7.57.0" + "@sentry/browser" "7.69.0" + "@sentry/types" "7.69.0" + "@sentry/utils" "7.69.0" hoist-non-react-statics "^3.3.2" tslib "^2.4.1 || ^1.9.3" -"@sentry/replay@7.57.0": - version "7.57.0" - resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.57.0.tgz#c8f7eae7b7edc9d32c3d2955b337f3b3c76dff39" - integrity sha512-pN4ryNS3J5EYbkXvR+O/+hseAJha7XDl8mPFtK0OGTHG10JzCi4tQJazblHQdpb5QBaMMPCeZ+isyfoQLDNXnw== +"@sentry/replay@7.69.0": + version "7.69.0" + resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.69.0.tgz#d727f96292d2b7c25df022fa53764fd39910fcda" + integrity sha512-oUqWyBPFUgShdVvgJtV65EQH9pVDmoYVQMOu59JI6FHVeL3ald7R5Mvz6GaNLXsirvvhp0yAkcAd2hc5Xi6hDw== dependencies: - "@sentry/core" "7.57.0" - "@sentry/types" "7.57.0" - "@sentry/utils" "7.57.0" + "@sentry/core" "7.69.0" + "@sentry/types" "7.69.0" + "@sentry/utils" "7.69.0" -"@sentry/types@7.57.0": - version "7.57.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.57.0.tgz#4fdb80cbd49ba034dd8d9be0c0005a016d5db3ce" - integrity sha512-D7ifoUfxuVCUyktIr5Gc+jXUbtcUMmfHdTtTbf1XCZHua5mJceK9wtl3YCg3eq/HK2Ppd52BKnTzEcS5ZKQM+w== +"@sentry/types@7.69.0": + version "7.69.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.69.0.tgz#012b8d90d270a473cc2a5cf58a56870542739292" + integrity sha512-zPyCox0mzitzU6SIa1KIbNoJAInYDdUpdiA+PoUmMn2hFMH1llGU/cS7f4w/mAsssTlbtlBi72RMnWUCy578bw== -"@sentry/utils@7.57.0": - version "7.57.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.57.0.tgz#8253c6fcf35138b4c424234b8da1596e11b98ad8" - integrity sha512-YXrkMCiNklqkXctn4mKYkrzNCf/dfVcRUQrkXjeBC+PHXbcpPyaJgInNvztR7Skl8lE3JPGPN4v5XhLxK1bUUg== +"@sentry/utils@7.69.0": + version "7.69.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.69.0.tgz#b7594e4eb2a88b9b25298770b841dd3f81bd2aa4" + integrity sha512-4eBixe5Y+0EGVU95R4NxH3jkkjtkE4/CmSZD4In8SCkWGSauogePtq6hyiLsZuP1QHdpPb9Kt0+zYiBb2LouBA== dependencies: - "@sentry/types" "7.57.0" + "@sentry/types" "7.69.0" tslib "^2.4.1 || ^1.9.3" -"@sigstore/protobuf-specs@^0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@sigstore/protobuf-specs/-/protobuf-specs-0.1.0.tgz#957cb64ea2f5ce527cc9cf02a096baeb0d2b99b4" - integrity sha512-a31EnjuIDSX8IXBUib3cYLDRlPMU36AWX4xS8ysLaNu4ZzUesDiPt83pgrW2X1YLMe5L2HbDyaKK5BrL4cNKaQ== +"@sigstore/bundle@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@sigstore/bundle/-/bundle-1.1.0.tgz#17f8d813b09348b16eeed66a8cf1c3d6bd3d04f1" + integrity sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog== + dependencies: + "@sigstore/protobuf-specs" "^0.2.0" + +"@sigstore/protobuf-specs@^0.2.0": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz#be9ef4f3c38052c43bd399d3f792c97ff9e2277b" + integrity sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A== -"@sigstore/tuf@^1.0.0": +"@sigstore/sign@^1.0.0": version "1.0.0" - resolved "https://registry.yarnpkg.com/@sigstore/tuf/-/tuf-1.0.0.tgz#13b69323e7bf8de458cd6c952c57acd1169772a5" - integrity sha512-bLzi9GeZgMCvjJeLUIfs8LJYCxrPRA8IXQkzUtaFKKVPTz0mucRyqFcV2U20yg9K+kYAD0YSitzGfRZCFLjdHQ== + resolved "https://registry.yarnpkg.com/@sigstore/sign/-/sign-1.0.0.tgz#6b08ebc2f6c92aa5acb07a49784cb6738796f7b4" + integrity sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA== dependencies: - "@sigstore/protobuf-specs" "^0.1.0" + "@sigstore/bundle" "^1.1.0" + "@sigstore/protobuf-specs" "^0.2.0" make-fetch-happen "^11.0.1" - tuf-js "^1.1.3" + +"@sigstore/tuf@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@sigstore/tuf/-/tuf-1.0.3.tgz#2a65986772ede996485728f027b0514c0b70b160" + integrity sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg== + dependencies: + "@sigstore/protobuf-specs" "^0.2.0" + tuf-js "^1.1.7" "@sinclair/typebox@^0.24.1": version "0.24.51" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.51.tgz#645f33fe4e02defe26f2f5c0410e1c094eac7f5f" integrity sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA== -"@sinclair/typebox@^0.25.16": - version "0.25.24" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.24.tgz#8c7688559979f7079aacaf31aa881c3aa410b718" - integrity sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ== - "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" @@ -4489,18 +3679,6 @@ qs "^6.10.0" telejson "^6.0.8" -"@storybook/channel-postmessage@7.0.24": - version "7.0.24" - resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-7.0.24.tgz#789bd121cf64e306737ec0f3b096ea0ac6f47bf5" - integrity sha512-QLtLXjEeTEwBN/7pB888mBaykmRU9Jy2BitvZuLJWyHHygTYm3vYZOaGR37DT+q/6Ob5GaZ0tURZmCSNDe8IIA== - dependencies: - "@storybook/channels" "7.0.24" - "@storybook/client-logger" "7.0.24" - "@storybook/core-events" "7.0.24" - "@storybook/global" "^5.0.0" - qs "^6.10.0" - telejson "^7.0.3" - "@storybook/channel-websocket@6.5.16": version "6.5.16" resolved "https://registry.yarnpkg.com/@storybook/channel-websocket/-/channel-websocket-6.5.16.tgz#41f69ca9444a4dfbf72580b4696900c5b1d2b817" @@ -4521,10 +3699,17 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/channels@7.0.24": - version "7.0.24" - resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-7.0.24.tgz#fcfe7a1a5599265506f07fe81d03b0585303fc15" - integrity sha512-NZVLwMhtzy6cZrNRjshFvMAD9mQTmJDNwhohodSkM/YFCDVFhmxQk9tgizVGh9MwY3CYGJ1SI96RUejGosb49Q== +"@storybook/channels@7.4.1": + version "7.4.1" + resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-7.4.1.tgz#20ec7a52db11c1bbcebf9ce209dc391181276026" + integrity sha512-gnE1mNrRF+9oCVRMq6MS/tLXJbYmf9P02PCC3KpMLcSsABdH5jcrACejzJVo/kE223knFH7NJc4BBj7+5h0uXA== + dependencies: + "@storybook/client-logger" "7.4.1" + "@storybook/core-events" "7.4.1" + "@storybook/global" "^5.0.0" + qs "^6.10.0" + telejson "^7.2.0" + tiny-invariant "^1.3.1" "@storybook/client-api@6.5.16": version "6.5.16" @@ -4560,10 +3745,10 @@ core-js "^3.8.2" global "^4.4.0" -"@storybook/client-logger@7.0.24", "@storybook/client-logger@^6.4.0 || >=6.5.0-0": - version "7.0.24" - resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-7.0.24.tgz#7be57ce1f90e65c6e9da7a88ed9ca7c5ce3c6536" - integrity sha512-4zRTb+QQ1hWaRqad/UufZNRfi2d/cf5a40My72Ct97VwjhJFE6aQ3K+hl1Xt6hh8dncDL2JK3cgziw6ElqjT0w== +"@storybook/client-logger@7.4.1", "@storybook/client-logger@^6.4.0 || >=6.5.0-0": + version "7.4.1" + resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-7.4.1.tgz#2973878a201c4d563a831165b90f2b11ffa2e71b" + integrity sha512-2j0DQlKlPNY8XAaEZv+mUYEUm4dOWg6/Q92UNbvYPRK5qbXUvbMiQco5nmvg4LvMT6y99LhRSW2xrwEx5xKAKw== dependencies: "@storybook/global" "^5.0.0" @@ -4670,10 +3855,12 @@ dependencies: core-js "^3.8.2" -"@storybook/core-events@7.0.24": - version "7.0.24" - resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-7.0.24.tgz#3fa4b2b3af64a86525b4cf07f49a7410125ef810" - integrity sha512-xkf/rihCkhqMeh5EA8lVp90/mzbb2gcg6I3oeFWw2hognVcTnPXg6llhWdU4Spqd0cals7GEFmQugIILCmH8GA== +"@storybook/core-events@7.4.1": + version "7.4.1" + resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-7.4.1.tgz#4346db1717495b39404ca14b12e58afa03c07fbd" + integrity sha512-F1tGb32XZ4FRfbtXdi4b+zdzWUjFz5rn3TF18mSuBGGXvxKU+4tywgjGQ3dKGdvuP754czn3poSdz2ZW08bLsQ== + dependencies: + ts-dedent "^2.0.0" "@storybook/core-server@6.5.16": version "6.5.16" @@ -4805,15 +3992,15 @@ global "^4.4.0" "@storybook/instrumenter@^6.4.0 || >=6.5.0-0": - version "7.0.24" - resolved "https://registry.yarnpkg.com/@storybook/instrumenter/-/instrumenter-7.0.24.tgz#fbc81250f25b0d5f3da3a3aa9dad48cdc82642f9" - integrity sha512-XQ4Whq0rqW9eFMTtRpLxcl6bCf+KO3UZYcm+H63EDn9TstDyopmqv1fDg2tmJOpqLo143F8qLVC89rI7M/lO6w== + version "7.4.1" + resolved "https://registry.yarnpkg.com/@storybook/instrumenter/-/instrumenter-7.4.1.tgz#de55b3d2acd3cc917815b816e49d9339583b1b9b" + integrity sha512-Nwu6MErUORKqQv/cYCZfWcvycuQQFOP5fEYAsbtgD2pRn+DXXOWeFyv6iHEbekqzfG2YTQ72koR0lZEFWnDl4w== dependencies: - "@storybook/channels" "7.0.24" - "@storybook/client-logger" "7.0.24" - "@storybook/core-events" "7.0.24" + "@storybook/channels" "7.4.1" + "@storybook/client-logger" "7.4.1" + "@storybook/core-events" "7.4.1" "@storybook/global" "^5.0.0" - "@storybook/preview-api" "7.0.24" + "@storybook/preview-api" "7.4.1" "@storybook/manager-webpack4@6.5.16": version "6.5.16" @@ -4929,18 +4116,17 @@ dependencies: core-js "^3.8.2" -"@storybook/preview-api@7.0.24": - version "7.0.24" - resolved "https://registry.yarnpkg.com/@storybook/preview-api/-/preview-api-7.0.24.tgz#93634c060aa43bb10fb233f28ae83b7d74b98aad" - integrity sha512-psycU07tuB5nyJvfAJiDN/9e8cjOdJ+5lrCSYC3vPzH86LxADDIN0/8xFb1CaQWcXZsADEFJGpHKWbRhjym5ew== +"@storybook/preview-api@7.4.1": + version "7.4.1" + resolved "https://registry.yarnpkg.com/@storybook/preview-api/-/preview-api-7.4.1.tgz#392b8bf0d25266f65772850288efef7b28db3afb" + integrity sha512-swmosWK73lP0CXDKMOwYIaaId28+muPDYX2V/0JmIOA+45HFXimeXZs3XsgVgQMutVF51QqnDA0pfrNgRofHgQ== dependencies: - "@storybook/channel-postmessage" "7.0.24" - "@storybook/channels" "7.0.24" - "@storybook/client-logger" "7.0.24" - "@storybook/core-events" "7.0.24" + "@storybook/channels" "7.4.1" + "@storybook/client-logger" "7.4.1" + "@storybook/core-events" "7.4.1" "@storybook/csf" "^0.1.0" "@storybook/global" "^5.0.0" - "@storybook/types" "7.0.24" + "@storybook/types" "7.4.1" "@types/qs" "^6.9.5" dequal "^2.0.2" lodash "^4.17.21" @@ -5121,12 +4307,12 @@ memoizerific "^1.11.3" regenerator-runtime "^0.13.7" -"@storybook/types@7.0.24": - version "7.0.24" - resolved "https://registry.yarnpkg.com/@storybook/types/-/types-7.0.24.tgz#22b2f6658f9a091ff584e1a0643ee1ea9a54ed39" - integrity sha512-SZh/XBHP1TT5bmEk0W52nT0v6fUnYwmZVls3da5noutdgOAiwL7TANtl41XrNjG+UDr8x0OE3PVVJi+LhwUaNA== +"@storybook/types@7.4.1": + version "7.4.1" + resolved "https://registry.yarnpkg.com/@storybook/types/-/types-7.4.1.tgz#1eb706f2a73e634694c2a6d576cda7160d689f05" + integrity sha512-bjt1YDG9AocFBhIFRvGGbYZPlD223p+qAFcFgYdezU16fFE4ZGFUzUuq2ERkOofL7a2+OzLTCQ/SKe1jFkXCxQ== dependencies: - "@storybook/channels" "7.0.24" + "@storybook/channels" "7.4.1" "@types/babel__core" "^7.0.0" "@types/express" "^4.7.0" file-system-cache "2.3.0" @@ -5353,9 +4539,9 @@ pretty-format "^27.0.2" "@testing-library/jest-dom@^5.14.1": - version "5.16.5" - resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz#3912846af19a29b2dbf32a6ae9c31ef52580074e" - integrity sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA== + version "5.17.0" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz#5e97c8f9a15ccf4656da00fecab505728de81e0c" + integrity sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg== dependencies: "@adobe/css-tools" "^4.0.1" "@babel/runtime" "^7.9.2" @@ -5477,9 +4663,9 @@ "@babel/types" "^7.20.7" "@types/big.js@^6.1.6": - version "6.1.6" - resolved "https://registry.yarnpkg.com/@types/big.js/-/big.js-6.1.6.tgz#3d417e758483d55345a03a087f7e0c87137ca444" - integrity sha512-0r9J+Zz9rYm2hOTwiMAVkm3XFQ4u5uTK37xrQMhc9bysn/sf/okzovWMYYIBMFTn/yrEZ11pusgLEaoarTlQbA== + version "6.2.0" + resolved "https://registry.yarnpkg.com/@types/big.js/-/big.js-6.2.0.tgz#e1f6a9a6ce64bc7c131137e71fbad34a5574f987" + integrity sha512-ubLURWoc4tCw/8Yds0P3CE9cBG5q+aoycwWBiXXx4gp7XPYZy9ch0L9+Pv6osSoSRgvuQNqJdlwEhP5QhKKl6w== "@types/body-parser@*": version "1.19.2" @@ -5504,24 +4690,24 @@ base-x "^3.0.6" "@types/connect-history-api-fallback@^1.3.5": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz#9fd20b3974bdc2bcd4ac6567e2e0f6885cb2cf41" - integrity sha512-4x5FkPpLipqwthjPsF7ZRbOv3uoLUFkTA9G9v583qi4pACvq0uTELrB8OLUzPWUI4IJIyvM85vzkV1nyiI2Lig== + version "1.5.1" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.1.tgz#6e5e3602d93bda975cebc3449e1a318340af9e20" + integrity sha512-iaQslNbARe8fctL5Lk+DsmgWOM83lM+7FzP0eQUJs1jd3kBE8NWqBTIT2S8SqQOJjxvt2eyIjpOuYeRXq2AdMw== dependencies: "@types/express-serve-static-core" "*" "@types/node" "*" "@types/connect@*": - version "3.4.35" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" - integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + version "3.4.36" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.36.tgz#e511558c15a39cb29bd5357eebb57bd1459cd1ab" + integrity sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w== dependencies: "@types/node" "*" "@types/d3-array@^3.0.3": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.0.5.tgz#857c1afffd3f51319bbc5b301956aca68acaa7b8" - integrity sha512-Qk7fpJ6qFp+26VeQ47WY0mkwXaiq8+76RJcncDEfMc2ocRzXLO67bLFRNI4OX1aGBoPzsM5Y2T+/m1pldOgD+A== + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.0.7.tgz#b128a0c0b0d9481d3281df47de0955730db384a1" + integrity sha512-4/Q0FckQ8TBjsB0VdGFemJOG8BLXUB2KKlL0VmZ+eOYeOnTb/wDRQqYWpBmQ6IlvWkXwkYiot+n9Px2aTJ7zGQ== "@types/d3-color@*": version "3.1.0" @@ -5534,9 +4720,9 @@ integrity sha512-fYtiVLBYy7VQX+Kx7wU/uOIkGQn8aAEY8oWMoyja3N4dLd8Yf6XgSIR/4yWvMuveNOH5VShnqCgRqqh/UNanBA== "@types/d3-dsv@*": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-3.0.1.tgz#c51a3505cee42653454b74a00f8713dc3548c362" - integrity sha512-76pBHCMTvPLt44wFOieouXcGXWOF0AJCceUvaFkxSZEu4VDUdv93JfpMa6VGNFs01FHfuP4a5Ou68eRG1KBfTw== + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-3.0.2.tgz#0504c17388714e28a601dcaaf400147271ea14c2" + integrity sha512-DooW5AOkj4AGmseVvbwHvwM/Ltu0Ks0WrhG6r5FG9riHT5oUUTHz6xHsHqJSVU8ZmPkOqlUEY2obS5C9oCIi2g== "@types/d3-ease@^3.0.0": version "3.0.0" @@ -5544,9 +4730,9 @@ integrity sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA== "@types/d3-fetch@^3.0.1": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-3.0.2.tgz#fe1f335243e07c9bd520c9a71756fed8330c54b1" - integrity sha512-gllwYWozWfbep16N9fByNBDTkJW/SyhH6SGRlXloR7WdtAaBui4plTP+gbUgiEot7vGw/ZZop1yDZlgXXSuzjA== + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-3.0.3.tgz#ae55cc49bd71b448182deff0cc4b448eff1f9b33" + integrity sha512-/EsDKRiQkby3Z/8/AiZq8bsuLDo/tYHnNIZkUpSeEHWV7fHUl6QFBjvMPbhkKGk9jZutzfOkGygCV7eR/MkcXA== dependencies: "@types/d3-dsv" "*" @@ -5558,9 +4744,9 @@ "@types/geojson" "*" "@types/d3-geo@^3.0.2": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-3.0.3.tgz#535e5f24be13722964c52354301be09b752f5d6e" - integrity sha512-bK9uZJS3vuDCNeeXQ4z3u0E7OeJZXjUgzFdSOtNtMCJCLvDtWDwfpRVWlyt3y8EvRzI0ccOu9xlMVirawolSCw== + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-3.0.4.tgz#fa38f02256c3023ea3b88cb011cff1426eb7ff52" + integrity sha512-kmUK8rVVIBPKJ1/v36bk2aSgwRj2N/ZkjDT+FkMT5pgedZoPlyhaG62J+9EgNIgUXE6IIL0b7bkLxCzhE6U4VQ== dependencies: "@types/geojson" "*" @@ -5584,9 +4770,9 @@ integrity sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg== "@types/d3-scale@^4.0.1", "@types/d3-scale@^4.0.2": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.3.tgz#7a5780e934e52b6f63ad9c24b105e33dd58102b5" - integrity sha512-PATBiMCpvHJSMtZAMEhc2WyL+hnzarKzI6wAHYjhsonjWJYGq5BXTzQjv4l8m2jO183/4wZ90rKvSeT7o72xNQ== + version "4.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.4.tgz#3c5e2263eea5a3670cd91043b9f4d150a94c43f1" + integrity sha512-eq1ZeTj0yr72L8MQk6N6heP603ubnywSDRfNpi5enouR112HzGLS6RIvExCzZTraFF4HdzNpJMwA/zGiMoHUUw== dependencies: "@types/d3-time" "*" @@ -5596,9 +4782,9 @@ integrity sha512-GjKQWVZO6Sa96HiKO6R93VBE8DUW+DDkFpIMf9vpY5S78qZTlRRSNUsHr/afDpF7TvLDV7VxrUFOWW7vdIlYkA== "@types/d3-shape@^3.1.0": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.1.tgz#15cc497751dac31192d7aef4e67a8d2c62354b95" - integrity sha512-6Uh86YFF7LGg4PQkuO2oG6EMBRLuW9cbavUW46zkIO5kuS2PfTqo2o9SkgtQzguBHbLgNnU90UNsITpsX1My+A== + version "3.1.2" + resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.2.tgz#a3d421d8b0bc0c6c67cb3f4b4471ddc133cb0117" + integrity sha512-NN4CXr3qeOUNyK5WasVUV8NCSAx/CRVcwcb0BuuS1PiTqwIm6ABi1SyasLZ/vsVCFDArF+W4QiGzSry1eKYQ7w== dependencies: "@types/d3-path" "*" @@ -5636,9 +4822,9 @@ "@types/estree" "*" "@types/eslint@*": - version "8.40.2" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.40.2.tgz#2833bc112d809677864a4b0e7d1de4f04d7dac2d" - integrity sha512-PRVjQ4Eh9z9pmmtaq8nTjZjQwKFk7YIHIud3lRoKRBgUQjgjRmoGxxGEPXQkF+lH7QkHJRNr5F4aBgYCW0lqpQ== + version "8.44.2" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.44.2.tgz#0d21c505f98a89b8dd4d37fa162b09da6089199a" + integrity sha512-sdPRb9K6iL5XZOmBubg8yiFp5yS/JdUDQsq5e6h95km91MCYMuvp7mh1fjPEYUhvHepKpZOjnEaMBR4PxjWDzg== dependencies: "@types/estree" "*" "@types/json-schema" "*" @@ -5666,9 +4852,9 @@ integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33": - version "4.17.35" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz#c95dd4424f0d32e525d23812aa8ab8e4d3906c4f" - integrity sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg== + version "4.17.36" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.36.tgz#baa9022119bdc05a4adfe740ffc97b5f9360e545" + integrity sha512-zbivROJ0ZqLAtMzgzIUC4oNqDG9iF0lSsAqpOD9kbs5xcIM3dTiyuHvBc7R8MtWBp3AAWGaovJa+wzWPjLYW7Q== dependencies: "@types/node" "*" "@types/qs" "*" @@ -5726,11 +4912,11 @@ "@types/node" "*" "@types/hast@^2.0.0": - version "2.3.4" - resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" - integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g== + version "2.3.5" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.5.tgz#08caac88b44d0fdd04dc17a19142355f43bd8a7a" + integrity sha512-SvQi0L/lNpThgPoleH53cdjB3y9zpLlVjRbqB3rH8hx1jiRSBGAhyjV3H+URFjNVRqt2EdYNrbZE5IsGlNfpRg== dependencies: - "@types/unist" "*" + "@types/unist" "^2" "@types/html-minifier-terser@^5.0.0": version "5.1.2" @@ -5779,9 +4965,9 @@ "@types/istanbul-lib-report" "*" "@types/jest@*": - version "29.5.2" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.2.tgz#86b4afc86e3a8f3005b297ed8a72494f89e6395b" - integrity sha512-mSoZVJF5YzGVCk+FsDxzDuH7s+SCkzrgKZzf0Z0T2WudhBUPoF6ktoTPC4R0ZoCPCV5xUvuU6ias5NvxcBcMMg== + version "29.5.4" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.4.tgz#9d0a16edaa009a71e6a71a999acd582514dab566" + integrity sha512-PhglGmhWeD46FYOVLt3X7TiWjzwuVGW9wG/4qocPevXMjCmrIc5b6db9WjeGE4QYVpUAWMDv3v0IiBwObY289A== dependencies: expect "^29.0.0" pretty-format "^29.0.0" @@ -5805,9 +4991,9 @@ integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== "@types/lodash@^4.14.167", "@types/lodash@^4.14.175": - version "4.14.195" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.195.tgz#bafc975b252eb6cea78882ce8a7b6bf22a6de632" - integrity sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg== + version "4.14.198" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.198.tgz#4d27465257011aedc741a809f1269941fa2c5d4c" + integrity sha512-trNJ/vtMZYMLhfN45uLq4ShQSw0/S7xCTLLVM+WM1rmFpba/VS42jVUgaO3w/NOLiWR/09lnYk0yMaA/atdIsg== "@types/long@^4.0.1": version "4.0.2" @@ -5820,16 +5006,16 @@ integrity sha512-oCavjEjRXuR6URJEtQm0eBdfsBiEcGBZbq21of8iGkeKxU1+1xgKuFPClaBZl2KB8ZZBSWlgk61tH6Mf+nvZVw== "@types/mdast@^3.0.0": - version "3.0.11" - resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.11.tgz#dc130f7e7d9306124286f6d6cee40cf4d14a3dc0" - integrity sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw== + version "3.0.12" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.12.tgz#beeb511b977c875a5b0cc92eab6fcac2f0895514" + integrity sha512-DT+iNIRNX884cx0/Q1ja7NyUPpZuv0KPyL5rGNxm1WC1OtHstl7n4Jb7nk+xacNShQMbczJjt8uFzznpp6kYBg== dependencies: - "@types/unist" "*" + "@types/unist" "^2" "@types/mdx@^2.0.0": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@types/mdx/-/mdx-2.0.5.tgz#9a85a8f70c7c4d9e695a21d5ae5c93645eda64b1" - integrity sha512-76CqzuD6Q7LC+AtbPqrvD9AqsN0k8bsYo2bM2J8pmNldP1aIPAbzUQ7QbobyXL4eLr1wK5x8FZFe8eF/ubRuBg== + version "2.0.7" + resolved "https://registry.yarnpkg.com/@types/mdx/-/mdx-2.0.7.tgz#c7482e995673e01b83f8e96df83b3843ea76401f" + integrity sha512-BG4tyr+4amr3WsSEmHn/fXPqaCba/AYZ7dsaQTiavihQunHSIxk+uAtqsjvicNpyHN6cm+B9RVrUOtW9VzIKHw== "@types/mime@*": version "3.0.1" @@ -5870,9 +5056,9 @@ form-data "^3.0.0" "@types/node@*", "@types/node@>=13.7.0": - version "20.3.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.3.2.tgz#fa6a90f2600e052a03c18b8cb3fd83dd4e599898" - integrity sha512-vOBLVQeCQfIcF/2Y7eKFTqrMnizK5lRNQ7ykML/5RuwVXVWxYkgwS7xbt4B6fKCUPgbSL5FSsjHQpaGQP/dQmw== + version "20.6.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.0.tgz#9d7daa855d33d4efec8aea88cd66db1c2f0ebe16" + integrity sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg== "@types/node@^13.7.0": version "13.13.52" @@ -5880,9 +5066,9 @@ integrity sha512-s3nugnZumCC//n4moGGe6tkNMyYEdaDBitVjwPxXmR5lnMG5dHePinH2EdxkG3Rh1ghFHHixAG4NJhpJW1rthQ== "@types/node@^14.0.10 || ^16.0.0", "@types/node@^14.14.20 || ^16.0.0", "@types/node@^16.7.13": - version "16.18.37" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.37.tgz#a1f8728e4dc30163deb41e9b7aba65d0c2d4eda1" - integrity sha512-ql+4dw4PlPFBP495k8JzUX/oMNRI2Ei4PrMHgj8oT4VhGlYUzF4EYr0qk2fW+XBVGIrq8Zzk13m4cvyXZuv4pA== + version "16.18.50" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.50.tgz#93003cf0251a2ecd26dad6dc757168d648519805" + integrity sha512-OiDU5xRgYTJ203v4cprTs0RwOCd5c5Zjv+K5P8KSqfiCsB1W3LcamTUMcnQarpq5kOYbhHfSOgIEJvdPyb5xyw== "@types/normalize-package-data@^2.4.0": version "2.4.1" @@ -5920,16 +5106,16 @@ integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== "@types/qrcode.react@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@types/qrcode.react/-/qrcode.react-1.0.2.tgz#f892432cc41b5dac52e3ca8873b717c8bfea6002" - integrity sha512-I9Oq5Cjlkgy3Tw7krCnCXLw2/zMhizkTere49OOcta23tkvH0xBTP0yInimTh0gstLRtb8Ki9NZVujE5UI6ffQ== + version "1.0.3" + resolved "https://registry.yarnpkg.com/@types/qrcode.react/-/qrcode.react-1.0.3.tgz#ce6852ebc1bbe4f43d1854eb19982cff30351025" + integrity sha512-gl7Ozf3BRQwfDUAU2xx7sWRBe/s7TqO0HAJukSQHbEVfQrFo5WKgZl0BHlN8u9W1DHXb4elgKRolHLZkgETXyA== dependencies: "@types/react" "*" "@types/qs@*", "@types/qs@^6.9.5": - version "6.9.7" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" - integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + version "6.9.8" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.8.tgz#f2a7de3c107b89b441e071d5472e6b726b4adf45" + integrity sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg== "@types/range-parser@*": version "1.2.4" @@ -5944,13 +5130,13 @@ "@types/react" "^17" "@types/react-dom@^18.0.10": - version "18.2.6" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.6.tgz#ad621fa71a8db29af7c31b41b2ea3d8a6f4144d1" - integrity sha512-2et4PDvg6PVCyS7fuTc4gPoksV58bW0RwSxWKcPRcHZf0PRUGq03TKcD/rUHe3azfV6/5/biUBJw+HhCQjaP0A== + version "18.2.7" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.7.tgz#67222a08c0a6ae0a0da33c3532348277c70abb63" + integrity sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA== dependencies: "@types/react" "*" -"@types/react-is@^18.2.0", "@types/react-is@^18.2.1": +"@types/react-is@^18.2.1": version "18.2.1" resolved "https://registry.yarnpkg.com/@types/react-is/-/react-is-18.2.1.tgz#61d01c2a6fc089a53520c0b66996d458fdc46863" integrity sha512-wyUkmaaSZEzFZivD8F2ftSyAfk6L+DfFliVj/mYdOXbVjRcS87fQJLTnhk6dRZPuJjI+9g6RZJO4PNCngUrmyw== @@ -5982,18 +5168,18 @@ "@types/react" "*" "@types/react@*", "@types/react@^18.0.26": - version "18.2.14" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.14.tgz#fa7a6fecf1ce35ca94e74874f70c56ce88f7a127" - integrity sha512-A0zjq+QN/O0Kpe30hA1GidzyFjatVvrpIvWLxD+xv67Vt91TWWgco9IvrJBkeyHm1trGaFS/FSGqPlhyeZRm0g== + version "18.2.21" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.21.tgz#774c37fd01b522d0b91aed04811b58e4e0514ed9" + integrity sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" csstype "^3.0.2" "@types/react@^17": - version "17.0.62" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.62.tgz#2efe8ddf8533500ec44b1334dd1a97caa2f860e3" - integrity sha512-eANCyz9DG8p/Vdhr0ZKST8JV12PhH2ACCDYlFw6DIO+D+ca+uP4jtEDEpVqXZrh/uZdXQGwk7whJa3ah5DtyLw== + version "17.0.65" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.65.tgz#95f6a2ab61145ffb69129d07982d047f9e0870cd" + integrity sha512-oxur785xZYHvnI7TRS61dXbkIhDPnGfsXKv0cNXR/0ml4SipRIFpSMzA7HMEfOywFwJ5AOnPrXYTEiTRUQeGlQ== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -6015,9 +5201,9 @@ integrity sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ== "@types/semver@^7.3.12", "@types/semver@^7.3.8": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" - integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== + version "7.5.1" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.1.tgz#0480eeb7221eb9bc398ad7432c9d7e14b1a5a367" + integrity sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg== "@types/send@*": version "0.17.1" @@ -6061,43 +5247,43 @@ integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== "@types/tapable@^1", "@types/tapable@^1.0.5": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.8.tgz#b94a4391c85666c7b73299fd3ad79d4faa435310" - integrity sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ== + version "1.0.9" + resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.9.tgz#1481a4236267dd2d0ca2a637adb90f0ccb3d69c4" + integrity sha512-fOHIwZua0sRltqWzODGUM6b4ffZrf/vzGUmNXdR+4DzuJP42PMbM5dLKcdzlYvv8bMJ3GALOzkk1q7cDm2zPyA== "@types/testing-library__jest-dom@^5.9.1": - version "5.14.6" - resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.6.tgz#4887f6e1af11215428ab02777873bcede98a53b0" - integrity sha512-FkHXCb+ikSoUP4Y4rOslzTdX5sqYwMxfefKh1GmZ8ce1GOkEHntSp6b5cGadmNfp5e4BMEWOMx+WSKd5/MqlDA== + version "5.14.9" + resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz#0fb1e6a0278d87b6737db55af5967570b67cb466" + integrity sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw== dependencies: "@types/jest" "*" "@types/topojson-client@^3.1.0": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@types/topojson-client/-/topojson-client-3.1.1.tgz#d1396b2e79f530ef69bb162523cddf94576bd5a9" - integrity sha512-E4/Z2Xg56kVLRzYWem/6uOKVcVNqqxEqlWM9qCG2tCV1BxuzvvXC02/ELoGJWgtKkQhfycBPlMFEuTFdA/YiTg== + version "3.1.2" + resolved "https://registry.yarnpkg.com/@types/topojson-client/-/topojson-client-3.1.2.tgz#57b02c68d8fa8797f0d2ad046736be5e6700337a" + integrity sha512-Lp6ZDxSQf9Tr4IcV/aJ72Zk1Fso7oPg1AbLKF4b6Jc5k05z+WK7nmmpfneKsnbj1NNUwj2SgydBZyJzc4O865w== dependencies: "@types/geojson" "*" "@types/topojson-specification" "*" "@types/topojson-specification@*": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@types/topojson-specification/-/topojson-specification-1.0.2.tgz#e20df2c5a611e31f51d606473dbaccc1d90461c8" - integrity sha512-SGc1NdX9g3UGDp6S+p+uyG+Z8CehS51sUJ9bejA25Xgn2kkAguILk6J9nxXK+0M/mbTBN7ypMA7+4HVLNMJ8ag== + version "1.0.3" + resolved "https://registry.yarnpkg.com/@types/topojson-specification/-/topojson-specification-1.0.3.tgz#40e7a1b754c244f1daf68c3334a88d22883ad40c" + integrity sha512-0rGL/Buelb+H2SVfmDRSDNxWgYQk4U/R18wrFc2DOfBKHaKOSz9bXbLQxAFY7j16e1E182bGwoSJdUhRq9fqBA== dependencies: "@types/geojson" "*" "@types/uglify-js@*": - version "3.17.1" - resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.17.1.tgz#e0ffcef756476410e5bce2cb01384ed878a195b5" - integrity sha512-GkewRA4i5oXacU/n4MA9+bLgt5/L3F1mKrYvFGm7r2ouLXhRKjuWwo9XHNnbx6WF3vlGW21S3fCvgqxvxXXc5g== + version "3.17.2" + resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.17.2.tgz#a2ba86fd524f6281a7655463338c546f845b29c3" + integrity sha512-9SjrHO54LINgC/6Ehr81NjAxAYvwEZqjUHLjJYvC4Nmr9jbLQCIZbWSvl4vXQkkmR1UAuaKDycau3O1kWGFyXQ== dependencies: source-map "^0.6.1" -"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" - integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== +"@types/unist@^2", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": + version "2.0.8" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.8.tgz#bb197b9639aa1a04cf464a617fe800cccd92ad5c" + integrity sha512-d0XxK3YTObnWVp6rZuev3c49+j4Lo8g4L1ZRm9z5L0xpoZycUPshHgczK5gsUMaZOstjVYYi09p5gYvUtfChYw== "@types/uuid@^8.3.4": version "8.3.4" @@ -6164,99 +5350,99 @@ "@types/yargs-parser" "*" "@types/zxcvbn@^4.4.1": - version "4.4.1" - resolved "https://registry.yarnpkg.com/@types/zxcvbn/-/zxcvbn-4.4.1.tgz#46e42cbdcee681b22181478feaf4af2bc4c1abd2" - integrity sha512-3NoqvZC2W5gAC5DZbTpCeJ251vGQmgcWIHQJGq2J240HY6ErQ9aWKkwfoKJlHLx+A83WPNTZ9+3cd2ILxbvr1w== + version "4.4.2" + resolved "https://registry.yarnpkg.com/@types/zxcvbn/-/zxcvbn-4.4.2.tgz#7b16c35330a15471cd7b9d3576503a40b6bd2416" + integrity sha512-T7SEL8b/eN7AEhHQ8oFt7c6Y+l3p8OpH7KwJIe+5oBOPLMMioPeMsUTB3huNgEnXhiittV8Ohdw21Jg8E/f70Q== "@typescript-eslint/eslint-plugin@^5.13.0", "@typescript-eslint/eslint-plugin@^5.7.0": - version "5.60.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.1.tgz#81382d6ecb92b8dda70e91f9035611cb2fecd1c3" - integrity sha512-KSWsVvsJsLJv3c4e73y/Bzt7OpqMCADUO846bHcuWYSYM19bldbAeDv7dYyV0jwkbMfJ2XdlzwjhXtuD7OY6bw== + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db" + integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag== dependencies: "@eslint-community/regexpp" "^4.4.0" - "@typescript-eslint/scope-manager" "5.60.1" - "@typescript-eslint/type-utils" "5.60.1" - "@typescript-eslint/utils" "5.60.1" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/type-utils" "5.62.0" + "@typescript-eslint/utils" "5.62.0" debug "^4.3.4" - grapheme-splitter "^1.0.4" + graphemer "^1.4.0" ignore "^5.2.0" natural-compare-lite "^1.4.0" semver "^7.3.7" tsutils "^3.21.0" "@typescript-eslint/experimental-utils@^5.3.0": - version "5.60.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.60.1.tgz#d783bb63b9183541019a945eda6a9d96b096d985" - integrity sha512-TXUdLxv2t8181nh5yLXl/Gr/zKj1ZofQ7m+ZdmG2+El0TYOHCvlZfc35D4nturemC3RUnf3KmLuFp3bVBjkG5w== + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz#14559bf73383a308026b427a4a6129bae2146741" + integrity sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw== dependencies: - "@typescript-eslint/utils" "5.60.1" + "@typescript-eslint/utils" "5.62.0" "@typescript-eslint/parser@^5.13.0", "@typescript-eslint/parser@^5.7.0": - version "5.60.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.60.1.tgz#0f2f58209c0862a73e3d5a56099abfdfa21d0fd3" - integrity sha512-pHWlc3alg2oSMGwsU/Is8hbm3XFbcrb6P5wIxcQW9NsYBfnrubl/GhVVD/Jm/t8HXhA2WncoIRfBtnCgRGV96Q== + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.62.0.tgz#1b63d082d849a2fcae8a569248fbe2ee1b8a56c7" + integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA== dependencies: - "@typescript-eslint/scope-manager" "5.60.1" - "@typescript-eslint/types" "5.60.1" - "@typescript-eslint/typescript-estree" "5.60.1" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.60.1": - version "5.60.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.60.1.tgz#35abdb47f500c68c08f2f2b4f22c7c79472854bb" - integrity sha512-Dn/LnN7fEoRD+KspEOV0xDMynEmR3iSHdgNsarlXNLGGtcUok8L4N71dxUgt3YvlO8si7E+BJ5Fe3wb5yUw7DQ== +"@typescript-eslint/scope-manager@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" + integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== dependencies: - "@typescript-eslint/types" "5.60.1" - "@typescript-eslint/visitor-keys" "5.60.1" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" -"@typescript-eslint/type-utils@5.60.1": - version "5.60.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.60.1.tgz#17770540e98d65ab4730c7aac618003f702893f4" - integrity sha512-vN6UztYqIu05nu7JqwQGzQKUJctzs3/Hg7E2Yx8rz9J+4LgtIDFWjjl1gm3pycH0P3mHAcEUBd23LVgfrsTR8A== +"@typescript-eslint/type-utils@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz#286f0389c41681376cdad96b309cedd17d70346a" + integrity sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew== dependencies: - "@typescript-eslint/typescript-estree" "5.60.1" - "@typescript-eslint/utils" "5.60.1" + "@typescript-eslint/typescript-estree" "5.62.0" + "@typescript-eslint/utils" "5.62.0" debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.60.1": - version "5.60.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.60.1.tgz#a17473910f6b8d388ea83c9d7051af89c4eb7561" - integrity sha512-zDcDx5fccU8BA0IDZc71bAtYIcG9PowaOwaD8rjYbqwK7dpe/UMQl3inJ4UtUK42nOCT41jTSCwg76E62JpMcg== +"@typescript-eslint/types@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" + integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== -"@typescript-eslint/typescript-estree@5.60.1": - version "5.60.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.1.tgz#8c71824b7165b64d5ebd7aa42968899525959834" - integrity sha512-hkX70J9+2M2ZT6fhti5Q2FoU9zb+GeZK2SLP1WZlvUDqdMbEKhexZODD1WodNRyO8eS+4nScvT0dts8IdaBzfw== +"@typescript-eslint/typescript-estree@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" + integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== dependencies: - "@typescript-eslint/types" "5.60.1" - "@typescript-eslint/visitor-keys" "5.60.1" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.60.1", "@typescript-eslint/utils@^5.10.0": - version "5.60.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.60.1.tgz#6861ebedbefba1ac85482d2bdef6f2ff1eb65b80" - integrity sha512-tiJ7FFdFQOWssFa3gqb94Ilexyw0JVxj6vBzaSpfN/8IhoKkDuSAenUKvsSHw2A/TMpJb26izIszTXaqygkvpQ== +"@typescript-eslint/utils@5.62.0", "@typescript-eslint/utils@^5.10.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" + integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@types/json-schema" "^7.0.9" "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.60.1" - "@typescript-eslint/types" "5.60.1" - "@typescript-eslint/typescript-estree" "5.60.1" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" eslint-scope "^5.1.1" semver "^7.3.7" -"@typescript-eslint/visitor-keys@5.60.1": - version "5.60.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.1.tgz#19a877358bf96318ec35d90bfe6bd1445cce9434" - integrity sha512-xEYIxKcultP6E/RMKqube11pGjXH1DCo60mQoWhVYyKfLkwbIVVjYxmOenNMxILx0TjCujPTjjnTIVzm09TXIw== +"@typescript-eslint/visitor-keys@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" + integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== dependencies: - "@typescript-eslint/types" "5.60.1" + "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" "@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": @@ -6572,10 +5758,10 @@ resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== -"@yarnpkg/parsers@^3.0.0-rc.18": - version "3.0.0-rc.47" - resolved "https://registry.yarnpkg.com/@yarnpkg/parsers/-/parsers-3.0.0-rc.47.tgz#2b67a2f5098cafcd0a1ce7f2e9174794d639046e" - integrity sha512-ri/QnMiMobEgRUBF1fPcxH1ICa9jsG8y4tDNRAuk6zPdCPkSAzACKaXjmDiAZFiwKxK4hTVj0E8nklgWFeTLng== +"@yarnpkg/parsers@3.0.0-rc.46": + version "3.0.0-rc.46" + resolved "https://registry.yarnpkg.com/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz#03f8363111efc0ea670e53b0282cd3ef62de4e01" + integrity sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q== dependencies: js-yaml "^3.10.0" tslib "^2.4.0" @@ -6587,7 +5773,7 @@ dependencies: argparse "^2.0.1" -JSONStream@^1.0.4: +JSONStream@^1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== @@ -6605,18 +5791,6 @@ abbrev@1, abbrev@^1.0.0: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -abbrev@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-2.0.0.tgz#cf59829b8b4f03f89dda2771cb7f3653828c89bf" - integrity sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ== - -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -6663,10 +5837,10 @@ acorn@^7.1.1, acorn@^7.4.0, acorn@^7.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.0.0, acorn@^8.2.4, acorn@^8.4.1, acorn@^8.7.1, acorn@^8.8.0, acorn@^8.8.2: - version "8.9.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.9.0.tgz#78a16e3b2bcc198c10822786fa6679e245db5b59" - integrity sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ== +acorn@^8.0.0, acorn@^8.2.4, acorn@^8.4.1, acorn@^8.7.1, acorn@^8.8.2, acorn@^8.9.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== add-stream@^1.0.0: version "1.0.0" @@ -6686,12 +5860,10 @@ agent-base@6, agent-base@^6.0.2: debug "4" agentkeepalive@^4.2.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.3.0.tgz#bb999ff07412653c1803b3ced35e50729830a255" - integrity sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg== + version "4.5.0" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.5.0.tgz#2673ad1389b3c418c5a20c5d7364f93ca04be923" + integrity sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew== dependencies: - debug "^4.1.0" - depd "^2.0.0" humanize-ms "^1.2.1" aggregate-error@^3.0.0: @@ -6875,7 +6047,7 @@ app-root-dir@^1.0.2: resolved "https://registry.yarnpkg.com/app-root-dir/-/app-root-dir-1.0.2.tgz#38187ec2dea7577fff033ffcb12172692ff6e118" integrity sha512-jlpIfsOoNoafl92Sz//64uQHGSyMrD2vYG5d8o2a4qGvyNCvXur7bzIsWtAC/6flI2RYAp3kv8rsfBtaLm7w0g== -"aproba@^1.0.3 || ^2.0.0", aproba@^2.0.0: +"aproba@^1.0.3 || ^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== @@ -6901,14 +6073,6 @@ are-we-there-yet@^3.0.0: delegates "^1.0.0" readable-stream "^3.6.0" -are-we-there-yet@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-4.0.0.tgz#3ff397dc14f08b52dd8b2a64d3cee154ab8760d2" - integrity sha512-nSXlV+u3vtVjRgihdTzbfWYzxPWGo424zPgQbHD0ZqIla3jqYAewDcvee0Ua2hjS5IfTAmjGlx1Jf0PKwjZDEw== - dependencies: - delegates "^1.0.0" - readable-stream "^4.1.0" - arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" @@ -6989,14 +6153,14 @@ array-ify@^1.0.0: integrity sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng== array-includes@^3.0.3, array-includes@^3.1.6: - version "3.1.6" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" - integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== + version "3.1.7" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.7.tgz#8cd2e01b26f7a3086cbc87271593fe921c62abda" + integrity sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - get-intrinsic "^1.1.3" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" is-string "^1.0.7" array-union@^1.0.1, array-union@^1.0.2: @@ -7021,58 +6185,82 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== +array.prototype.findlastindex@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz#b37598438f97b579166940814e2c0493a4f50207" + integrity sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA== + 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" + array.prototype.flat@^1.2.1, array.prototype.flat@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" - integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA== + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" + integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" array.prototype.flatmap@^1.2.1, array.prototype.flatmap@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183" - integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ== + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" + integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" array.prototype.map@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/array.prototype.map/-/array.prototype.map-1.0.5.tgz#6e43c2fee6c0fb5e4806da2dc92eb00970809e55" - integrity sha512-gfaKntvwqYIuC7mLLyv2wzZIJqrRhn5PZ9EfFejSx6a78sV7iDsGpG9P+3oUPtm1Rerqm6nrKS4FYuTIvWfo3g== + version "1.0.6" + resolved "https://registry.yarnpkg.com/array.prototype.map/-/array.prototype.map-1.0.6.tgz#6a3d23f7192b2066eb97666ccc34118cb8163950" + integrity sha512-nK1psgF2cXqP3wSyCSq0Hc7zwNq3sfljQqaG27r/7a7ooNUnn5nGq6yYWyks9jMO5EoFQ0ax80hSg6oXSRNXaw== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" es-array-method-boxes-properly "^1.0.0" is-string "^1.0.7" -array.prototype.reduce@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz#6b20b0daa9d9734dd6bc7ea66b5bbce395471eac" - integrity sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q== +array.prototype.reduce@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.6.tgz#63149931808c5fc1e1354814923d92d45f7d96d5" + integrity sha512-UW+Mz8LG/sPSU8jRDCjVr6J/ZKAGpHfwrZ6kWTG5qCxIEiXdVshqGnu5vEZA8S1y6X4aCSbQZ0/EEsfvEvBiSg== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" es-array-method-boxes-properly "^1.0.0" is-string "^1.0.7" array.prototype.tosorted@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz#ccf44738aa2b5ac56578ffda97c03fd3e23dd532" - integrity sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ== + version "1.1.2" + resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz#620eff7442503d66c799d95503f82b475745cefd" + integrity sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" - get-intrinsic "^1.1.3" + get-intrinsic "^1.2.1" + +arraybuffer.prototype.slice@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz#98bd561953e3e74bb34938e77647179dfe6e9f12" + integrity sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw== + 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" arrify@^1.0.0, arrify@^1.0.1: version "1.0.1" @@ -7095,12 +6283,12 @@ asn1.js@^5.2.0: safer-buffer "^2.1.0" assert@^1.1.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" - integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== + version "1.5.1" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.1.tgz#038ab248e4ff078e7bc2485ba6e6388466c78f76" + integrity sha512-zzw1uCAgLbsKwBfFc8CX78DDg+xZeBksSO3vwVIDDN5i94eOrPsSSyiVhmsSABFDM/OcpE2aagCat9dnWQLG1A== dependencies: - object-assign "^4.1.1" - util "0.10.3" + object.assign "^4.1.4" + util "^0.10.4" assign-symbols@^1.0.0: version "1.0.0" @@ -7139,6 +6327,13 @@ async@^3.2.3: resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== +asynciterator.prototype@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz#8c5df0514936cdd133604dfcc9d3fb93f09b2b62" + integrity sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg== + dependencies: + has-symbols "^1.0.3" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -7178,9 +6373,9 @@ available-typed-arrays@^1.0.5: integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== axe-core@^4.6.2: - version "4.7.2" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.2.tgz#040a7342b20765cb18bb50b628394c21bccc17a0" - integrity sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g== + version "4.8.1" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.8.1.tgz#6948854183ee7e7eae336b9877c5bafa027998ea" + integrity sha512-9l850jDDPnKq48nbad8SiEelCv4OrUWrKab/cPj0GScVg6cb6NbCCt/Ulk26QEq5jP9NnGr04Bit1BHyV6r5CQ== axios@^0.21.1, axios@^0.21.2: version "0.21.4" @@ -7190,9 +6385,9 @@ axios@^0.21.1, axios@^0.21.2: follow-redirects "^1.14.0" axios@^1.0.0, axios@^1.3.3: - version "1.4.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.4.0.tgz#38a7bf1224cd308de271146038b551d725f0be1f" - integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA== + version "1.5.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.5.0.tgz#f02e4af823e2e46a9768cfc74691fdd0517ea267" + integrity sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ== dependencies: follow-redirects "^1.15.0" form-data "^4.0.0" @@ -7205,6 +6400,11 @@ axobject-query@^3.1.1: dependencies: dequal "^2.0.3" +b4a@^1.6.4: + version "1.6.4" + resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.6.4.tgz#ef1c1422cae5ce6535ec191baeed7567443f36c9" + integrity sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw== + babel-jest@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.5.1.tgz#a1bf8d61928edfefd21da27eb86a695bfd691444" @@ -7219,15 +6419,15 @@ babel-jest@^27.5.1: graceful-fs "^4.2.9" slash "^3.0.0" -babel-jest@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.6.1.tgz#a7141ad1ed5ec50238f3cd36127636823111233a" - integrity sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A== +babel-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" + integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== dependencies: - "@jest/transform" "^29.6.1" + "@jest/transform" "^29.7.0" "@types/babel__core" "^7.1.14" babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^29.5.0" + babel-preset-jest "^29.6.3" chalk "^4.0.0" graceful-fs "^4.2.9" slash "^3.0.0" @@ -7291,10 +6491,10 @@ babel-plugin-jest-hoist@^27.5.1: "@types/babel__core" "^7.0.0" "@types/babel__traverse" "^7.0.6" -babel-plugin-jest-hoist@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz#a97db437936f441ec196990c9738d4b88538618a" - integrity sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w== +babel-plugin-jest-hoist@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" + integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== dependencies: "@babel/template" "^7.3.3" "@babel/types" "^7.3.3" @@ -7315,15 +6515,6 @@ babel-plugin-named-exports-order@^0.0.2: resolved "https://registry.yarnpkg.com/babel-plugin-named-exports-order/-/babel-plugin-named-exports-order-0.0.2.tgz#ae14909521cf9606094a2048239d69847540cb09" integrity sha512-OgOYHOLoRK+/mvXU9imKHlG6GkPLYrUCvFXG/CM93R/aNNO8pOOF4aS+S8CCHMDQoNSeiOYEZb/G6RwL95Jktw== -babel-plugin-polyfill-corejs2@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.3.tgz#75044d90ba5043a5fb559ac98496f62f3eb668fd" - integrity sha512-bM3gHc337Dta490gg+/AseNB9L4YLHxq1nGKZZSHbhXv4aTYU2MD2cjza1Ru4S6975YLTaL1K8uJf6ukJhhmtw== - dependencies: - "@babel/compat-data" "^7.17.7" - "@babel/helper-define-polyfill-provider" "^0.4.0" - semver "^6.1.1" - babel-plugin-polyfill-corejs2@^0.4.5: version "0.4.5" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz#8097b4cb4af5b64a1d11332b6fb72ef5e64a054c" @@ -7341,14 +6532,6 @@ babel-plugin-polyfill-corejs3@^0.1.0: "@babel/helper-define-polyfill-provider" "^0.1.5" core-js-compat "^3.8.1" -babel-plugin-polyfill-corejs3@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.1.tgz#39248263c38191f0d226f928d666e6db1b4b3a8a" - integrity sha512-ikFrZITKg1xH6pLND8zT14UPgjKHiGLqex7rGEZCH2EvhsneJaJPemmpQaIZV5AL03II+lXylw3UmddDK8RU5Q== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.4.0" - core-js-compat "^3.30.1" - babel-plugin-polyfill-corejs3@^0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.3.tgz#b4f719d0ad9bb8e0c23e3e630c0c8ec6dd7a1c52" @@ -7357,13 +6540,6 @@ babel-plugin-polyfill-corejs3@^0.8.3: "@babel/helper-define-polyfill-provider" "^0.4.2" core-js-compat "^3.31.0" -babel-plugin-polyfill-regenerator@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.0.tgz#e7344d88d9ef18a3c47ded99362ae4a757609380" - integrity sha512-hDJtKjMLVa7Z+LwnTCxoDLQj6wdc+B8dun7ayF2fYieI6OzfuvcLMB32ihJZ4UhCBwNYGl5bg/x/P9cMdnkc2g== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.4.0" - babel-plugin-polyfill-regenerator@^0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz#80d0f3e1098c080c8b5a65f41e9427af692dc326" @@ -7420,12 +6596,12 @@ babel-preset-jest@^27.5.1: babel-plugin-jest-hoist "^27.5.1" babel-preset-current-node-syntax "^1.0.0" -babel-preset-jest@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz#57bc8cc88097af7ff6a5ab59d1cd29d52a5916e2" - integrity sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg== +babel-preset-jest@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" + integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== dependencies: - babel-plugin-jest-hoist "^29.5.0" + babel-plugin-jest-hoist "^29.6.3" babel-preset-current-node-syntax "^1.0.0" bail@^1.0.0: @@ -7505,16 +6681,6 @@ big.js@^6.2.1: resolved "https://registry.yarnpkg.com/big.js/-/big.js-6.2.1.tgz#7205ce763efb17c2e41f26f121c420c6a7c2744f" integrity sha512-bCtHMwL9LeDIozFn+oNhhFoq+yQ3BNdnsLSASUxLciOb1vgvpHsIO1dsENiGMgbb4SkP5TrzWzRiLddn8ahVOQ== -bin-links@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-4.0.1.tgz#afeb0549e642f61ff889b58ea2f8dca78fb9d8d3" - integrity sha512-bmFEM39CyX336ZGGRsGPlc6jZHriIoHacOQcTt72MktIjpPhZoP4te2jOyUXF3BLILmJ8aNLncoPVeIIFlrDeA== - dependencies: - cmd-shim "^6.0.0" - npm-normalize-package-bin "^3.0.0" - read-cmd-shim "^4.0.0" - write-file-atomic "^5.0.0" - binary-extensions@^1.0.0: version "1.13.1" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" @@ -7736,17 +6902,7 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.21.3, browserslist@^4.21.4, browserslist@^4.21.5, browserslist@^4.21.9: - version "4.21.9" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.9.tgz#e11bdd3c313d7e2a9e87e8b4b0c7872b13897635" - integrity sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg== - dependencies: - caniuse-lite "^1.0.30001503" - electron-to-chromium "^1.4.431" - node-releases "^2.0.12" - update-browserslist-db "^1.0.11" - -browserslist@^4.21.10: +browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.21.10, browserslist@^4.21.4, browserslist@^4.21.9: version "4.21.10" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.10.tgz#dbbac576628c13d3b2231332cb2ec5a46e015bb0" integrity sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ== @@ -7804,14 +6960,6 @@ buffer@^5.5.0: base64-js "^1.3.1" ieee754 "^1.1.13" -buffer@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" - integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.2.1" - builtin-modules@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" @@ -7834,10 +6982,10 @@ builtins@^5.0.0: dependencies: semver "^7.0.0" -byte-size@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-7.0.0.tgz#36528cd1ca87d39bd9abd51f5715dc93b6ceb032" - integrity sha512-NNiBxKgxybMBtWdmvx7ZITJi4ZG+CYUgwOSZTfqB1qogkRHrhbQE/R2r5Fh94X+InN5MCYz6SvB/ejHMj/HbsQ== +byte-size@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-8.1.1.tgz#3424608c62d59de5bfda05d31e0313c6174842ae" + integrity sha512-tUkzZWK0M/qdoLEqikxBWe4kumyuwjl3HO6zHTr4yEI23EojPtLYXdG1+AQY7MN0cGyNDvEaJ8wiYQm6P2bPxg== bytes@3.0.0: version "3.0.0" @@ -7912,40 +7060,16 @@ cacache@^15.0.5: tar "^6.0.2" unique-filename "^1.1.1" -cacache@^16.1.0: - version "16.1.3" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-16.1.3.tgz#a02b9f34ecfaf9a78c9f4bc16fceb94d5d67a38e" - integrity sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ== - dependencies: - "@npmcli/fs" "^2.1.0" - "@npmcli/move-file" "^2.0.0" - chownr "^2.0.0" - fs-minipass "^2.1.0" - glob "^8.0.1" - infer-owner "^1.0.4" - lru-cache "^7.7.1" - minipass "^3.1.6" - minipass-collect "^1.0.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.4" - mkdirp "^1.0.4" - p-map "^4.0.0" - promise-inflight "^1.0.1" - rimraf "^3.0.2" - ssri "^9.0.0" - tar "^6.1.11" - unique-filename "^2.0.0" - -cacache@^17.0.0, cacache@^17.0.4: - version "17.1.3" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-17.1.3.tgz#c6ac23bec56516a7c0c52020fd48b4909d7c7044" - integrity sha512-jAdjGxmPxZh0IipMdR7fK/4sDSrHMLUV0+GvVUsjwyGNKHsh79kW/otg+GkbXwl6Uzvy9wsvHOX4nUoWldeZMg== +cacache@^17.0.0: + version "17.1.4" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-17.1.4.tgz#b3ff381580b47e85c6e64f801101508e26604b35" + integrity sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A== dependencies: "@npmcli/fs" "^3.1.0" fs-minipass "^3.0.0" glob "^10.2.2" lru-cache "^7.7.1" - minipass "^5.0.0" + minipass "^7.0.3" minipass-collect "^1.0.2" minipass-flush "^1.0.5" minipass-pipeline "^1.2.4" @@ -8042,15 +7166,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001503: - version "1.0.30001509" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001509.tgz#2b7ad5265392d6d2de25cd8776d1ab3899570d14" - integrity sha512-2uDDk+TRiTX5hMcUYT/7CSyzMZxjfGu0vAUjS2g0LSD8UoXOv0LtpH4LxGMemsiPq6LCVIUjNwVM0erkOkGCDA== - -caniuse-lite@^1.0.30001517: - version "1.0.30001527" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001527.tgz#813826554828245ccee776c850566dce12bdeaba" - integrity sha512-YkJi7RwPgWtXVSgK4lG9AHH57nSzvvOp9MesgXmw4Q7n0C3H04L0foHqfxcmSAm5AcWb8dW9AYj2tR7/5GnddQ== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001517: + version "1.0.30001534" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001534.tgz#f24a9b2a6d39630bac5c132b5dff89b39a12e7dd" + integrity sha512-vlPVrhsCS7XaSh2VvWluIQEzVhefrUQcEsQWSS5A5V+dM07uv1qHeQzAOTGIMy9i3e9bH15+muvI/UHojVgS/Q== capture-exit@^2.0.0: version "2.0.0" @@ -8082,7 +7201,7 @@ chalk@4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -8294,9 +7413,9 @@ cli-spinners@2.6.1: integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== cli-spinners@^2.5.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.0.tgz#5881d0ad96381e117bbe07ad91f2008fe6ffd8db" - integrity sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g== + version "2.9.1" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.1.tgz#9c0b9dad69a6d47cbb4333c14319b060ed395a35" + integrity sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ== cli-table3@^0.6.1: version "0.6.3" @@ -8383,14 +7502,12 @@ clsx@^1.0.4, clsx@^1.1.0, clsx@^1.1.1, clsx@^1.2.1: resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== -cmd-shim@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-5.0.0.tgz#8d0aaa1a6b0708630694c4dbde070ed94c707724" - integrity sha512-qkCtZ59BidfEwHltnJwkyVZn+XQojdAySM1D1gSeh11Z4pW1Kpolkyo53L5noc0nrxmIvyFwTmJRo4xs7FFLPw== - dependencies: - mkdirp-infer-owner "^2.0.0" +clsx@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.0.0.tgz#12658f3fd98fafe62075595a5c30e43d18f3d00b" + integrity sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q== -cmd-shim@^6.0.0: +cmd-shim@6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-6.0.1.tgz#a65878080548e1dca760b3aea1e21ed05194da9d" integrity sha512-S9iI9y0nKR4hwEQsVWpyxld/6kRfGepGfzff83FcaiEBpmvlbA2nnGe7Cylgrx2f/p1P5S5wpRm9oL8z1PbS3Q== @@ -8406,9 +7523,9 @@ collapse-white-space@^1.0.2: integrity sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ== collect-v8-coverage@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" - integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== + version "1.0.2" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" + integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== collection-visit@^1.0.0: version "1.0.0" @@ -8558,11 +7675,6 @@ commander@~9.4.0: resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.1.tgz#d1dd8f2ce6faf93147295c0df13c7c21141cfbdd" integrity sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw== -common-ancestor-path@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz#4f7d2d1394d91b7abdf51871c62f71eadb0182a7" - integrity sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w== - common-path-prefix@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" @@ -8631,14 +7743,6 @@ concat-stream@^2.0.0: readable-stream "^3.0.2" typedarray "^0.0.6" -config-chain@1.1.12: - version "1.1.12" - resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" - integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== - dependencies: - ini "^1.3.4" - proto-list "~1.2.1" - confusing-browser-globals@^1.0.10: version "1.0.11" resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" @@ -8676,87 +7780,78 @@ content-type@~1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== -conventional-changelog-angular@5.0.12: - version "5.0.12" - resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.12.tgz#c979b8b921cbfe26402eb3da5bbfda02d865a2b9" - integrity sha512-5GLsbnkR/7A89RyHLvvoExbiGbd9xKdKqDTrArnPbOqBqG/2wIosu0fHwpeIRI8Tl94MhVNBXcLJZl92ZQ5USw== +conventional-changelog-angular@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz#a9a9494c28b7165889144fd5b91573c4aa9ca541" + integrity sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg== dependencies: compare-func "^2.0.0" - q "^1.5.1" -conventional-changelog-core@4.2.4: - version "4.2.4" - resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz#e50d047e8ebacf63fac3dc67bf918177001e1e9f" - integrity sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg== +conventional-changelog-core@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-5.0.1.tgz#3c331b155d5b9850f47b4760aeddfc983a92ad49" + integrity sha512-Rvi5pH+LvgsqGwZPZ3Cq/tz4ty7mjijhr3qR4m9IBXNbxGGYgTVVO+duXzz9aArmHxFtwZ+LRkrNIMDQzgoY4A== dependencies: add-stream "^1.0.0" - conventional-changelog-writer "^5.0.0" - conventional-commits-parser "^3.2.0" - dateformat "^3.0.0" - get-pkg-repo "^4.0.0" - git-raw-commits "^2.0.8" + conventional-changelog-writer "^6.0.0" + conventional-commits-parser "^4.0.0" + dateformat "^3.0.3" + get-pkg-repo "^4.2.1" + git-raw-commits "^3.0.0" git-remote-origin-url "^2.0.0" - git-semver-tags "^4.1.1" - lodash "^4.17.15" - normalize-package-data "^3.0.0" - q "^1.5.1" + git-semver-tags "^5.0.0" + normalize-package-data "^3.0.3" read-pkg "^3.0.0" read-pkg-up "^3.0.0" - through2 "^4.0.0" -conventional-changelog-preset-loader@^2.3.4: - version "2.3.4" - resolved "https://registry.yarnpkg.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz#14a855abbffd59027fd602581f1f34d9862ea44c" - integrity sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g== +conventional-changelog-preset-loader@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-3.0.0.tgz#14975ef759d22515d6eabae6396c2ae721d4c105" + integrity sha512-qy9XbdSLmVnwnvzEisjxdDiLA4OmV3o8db+Zdg4WiFw14fP3B6XNz98X0swPPpkTd/pc1K7+adKgEDM1JCUMiA== -conventional-changelog-writer@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz#e0757072f045fe03d91da6343c843029e702f359" - integrity sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ== +conventional-changelog-writer@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-6.0.1.tgz#d8d3bb5e1f6230caed969dcc762b1c368a8f7b01" + integrity sha512-359t9aHorPw+U+nHzUXHS5ZnPBOizRxfQsWT5ZDHBfvfxQOAik+yfuhKXG66CN5LEWPpMNnIMHUTCKeYNprvHQ== dependencies: - conventional-commits-filter "^2.0.7" - dateformat "^3.0.0" + conventional-commits-filter "^3.0.0" + dateformat "^3.0.3" handlebars "^4.7.7" json-stringify-safe "^5.0.1" - lodash "^4.17.15" - meow "^8.0.0" - semver "^6.0.0" - split "^1.0.0" - through2 "^4.0.0" + meow "^8.1.2" + semver "^7.0.0" + split "^1.0.1" -conventional-commits-filter@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz#f8d9b4f182fce00c9af7139da49365b136c8a0b3" - integrity sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA== +conventional-commits-filter@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-3.0.0.tgz#bf1113266151dd64c49cd269e3eb7d71d7015ee2" + integrity sha512-1ymej8b5LouPx9Ox0Dw/qAO2dVdfpRFq28e5Y0jJEU8ZrLdy0vOSkkIInwmxErFGhg6SALro60ZrwYFVTUDo4Q== dependencies: lodash.ismatch "^4.4.0" - modify-values "^1.0.0" + modify-values "^1.0.1" -conventional-commits-parser@^3.2.0: - version "3.2.4" - resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz#a7d3b77758a202a9b2293d2112a8d8052c740972" - integrity sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q== +conventional-commits-parser@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-4.0.0.tgz#02ae1178a381304839bce7cea9da5f1b549ae505" + integrity sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg== dependencies: - JSONStream "^1.0.4" + JSONStream "^1.3.5" is-text-path "^1.0.1" - lodash "^4.17.15" - meow "^8.0.0" - split2 "^3.0.0" - through2 "^4.0.0" + meow "^8.1.2" + split2 "^3.2.2" -conventional-recommended-bump@6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz#cfa623285d1de554012f2ffde70d9c8a22231f55" - integrity sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw== +conventional-recommended-bump@7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/conventional-recommended-bump/-/conventional-recommended-bump-7.0.1.tgz#ec01f6c7f5d0e2491c2d89488b0d757393392424" + integrity sha512-Ft79FF4SlOFvX4PkwFDRnaNiIVX7YbmqGU0RwccUaiGvgp3S0a8ipR2/Qxk31vclDNM+GSdJOVs2KrsUCjblVA== dependencies: concat-stream "^2.0.0" - conventional-changelog-preset-loader "^2.3.4" - conventional-commits-filter "^2.0.7" - conventional-commits-parser "^3.2.0" - git-raw-commits "^2.0.8" - git-semver-tags "^4.1.1" - meow "^8.0.0" - q "^1.5.1" + conventional-changelog-preset-loader "^3.0.0" + conventional-commits-filter "^3.0.0" + conventional-commits-parser "^4.0.0" + git-raw-commits "^3.0.0" + git-semver-tags "^5.0.0" + meow "^8.1.2" convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.9.0" @@ -8807,46 +7902,28 @@ copy-webpack-plugin@^11.0.0: schema-utils "^4.0.0" serialize-javascript "^6.0.0" -core-js-compat@^3.30.1, core-js-compat@^3.30.2, core-js-compat@^3.8.1: - version "3.31.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.31.0.tgz#4030847c0766cc0e803dcdfb30055d7ef2064bf1" - integrity sha512-hM7YCu1cU6Opx7MXNu0NuumM0ezNeAeRKadixyiQELWY3vT3De9S4J5ZBMraWV2vZnrE1Cirl0GtFtDtMUXzPw== - dependencies: - browserslist "^4.21.5" - -core-js-compat@^3.31.0: - version "3.32.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.32.1.tgz#55f9a7d297c0761a8eb1d31b593e0f5b6ffae964" - integrity sha512-GSvKDv4wE0bPnQtjklV101juQ85g6H3rm5PDP20mqlS5j0kXF3pP97YvAu5hl+uFHqMictp3b2VxOHljWMAtuA== +core-js-compat@^3.31.0, core-js-compat@^3.8.1: + version "3.32.2" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.32.2.tgz#8047d1a8b3ac4e639f0d4f66d4431aa3b16e004c" + integrity sha512-+GjlguTDINOijtVRUxrQOv3kfu9rl+qPNdX2LTbJ/ZyVTuxK+ksVSAGX1nHstu4hrv1En/uPTtWgq2gI5wt4AQ== dependencies: browserslist "^4.21.10" core-js-pure@^3.23.3: - version "3.31.0" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.31.0.tgz#052fd9e82fbaaf86457f5db1fadcd06f15966ff2" - integrity sha512-/AnE9Y4OsJZicCzIe97JP5XoPKQJfTuEG43aEVLFJGOJpyqELod+pE6LEl63DfG1Mp8wX97LDaDpy1GmLEUxlg== + version "3.32.2" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.32.2.tgz#b7dbdac528625cf87eb0523b532eb61551b9a6d1" + integrity sha512-Y2rxThOuNywTjnX/PgA5vWM6CZ9QB9sz9oGeCixV8MqXZO70z/5SHzf9EeBrEBK0PN36DnEBBu9O/aGWzKuMZQ== core-js@^3.0.4, core-js@^3.6.5, core-js@^3.8.2: - version "3.31.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.31.0.tgz#4471dd33e366c79d8c0977ed2d940821719db344" - integrity sha512-NIp2TQSGfR6ba5aalZD+ZQ1fSxGhDo/s1w0nx3RYzf2pnJxt7YynxFlFScP6eV7+GZsKO95NSjGxyJsU3DZgeQ== + version "3.32.2" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.32.2.tgz#172fb5949ef468f93b4be7841af6ab1f21992db7" + integrity sha512-pxXSw1mYZPDGvTQqEc5vgIb83jGQKFGYWY76z4a7weZXUolw3G+OvpZqSRcfYOoOVUQJYEPsWeQK8pKEnUtWxQ== core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -cosmiconfig@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.0.tgz#ef9b44d773959cae63ddecd122de23853b60f8d3" - integrity sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA== - dependencies: - "@types/parse-json" "^4.0.0" - import-fresh "^3.2.1" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.10.0" - cosmiconfig@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" @@ -8869,6 +7946,16 @@ cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: path-type "^4.0.0" yaml "^1.10.0" +cosmiconfig@^8.2.0: + version "8.3.6" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" + integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== + dependencies: + import-fresh "^3.3.0" + js-yaml "^4.1.0" + parse-json "^5.2.0" + path-type "^4.0.0" + cosmjs-types@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/cosmjs-types/-/cosmjs-types-0.4.1.tgz#3b2a53ba60d33159dd075596ce8267cfa7027063" @@ -8941,6 +8028,19 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: safe-buffer "^5.0.1" sha.js "^2.4.8" +create-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" + integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== + 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" + create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" @@ -8983,15 +8083,10 @@ crypto-browserify@^3.11.0: randombytes "^2.0.0" randomfill "^1.0.3" -crypto-random-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" - integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== - css-declaration-sorter@^6.3.1: - version "6.4.0" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.4.0.tgz#630618adc21724484b3e9505bce812def44000ad" - integrity sha512-jDfsatwWMWN0MODAFuHszfjphEXfNw9JUAhmY4pLu3TyTU+ohUpsbVtbU+1MZn4a47D9kqh03i4eyOm+74+zew== + version "6.4.1" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz#28beac7c20bad7f1775be3a7129d7eae409a3a71" + integrity sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g== css-loader@^3.6.0: version "3.6.0" @@ -9466,7 +8561,7 @@ date-fns@^2.24.0, date-fns@^2.28.0: dependencies: "@babel/runtime" "^7.21.0" -dateformat@^3.0.0: +dateformat@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== @@ -9544,15 +8639,20 @@ dedent@0.7.0, dedent@^0.7.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== +dedent@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" + integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== + deep-equal@^2.0.5: - version "2.2.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.1.tgz#c72ab22f3a7d3503a4ca87dde976fe9978816739" - integrity sha512-lKdkdV6EOGoVn65XaOsPdH4rMxTZOnmFyuIkMjM1i5HHCbfjC97dawgTAy0deYNfuqUqW+Q5VrVaQYtUpSd6yQ== + version "2.2.2" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.2.tgz#9b2635da569a13ba8e1cc159c2f744071b115daa" + integrity sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA== dependencies: array-buffer-byte-length "^1.0.0" call-bind "^1.0.2" es-get-iterator "^1.1.3" - get-intrinsic "^1.2.0" + get-intrinsic "^1.2.1" is-arguments "^1.1.1" is-array-buffer "^3.0.2" is-date-object "^1.0.5" @@ -9573,7 +8673,7 @@ deep-extend@^0.6.0: resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== -deep-is@^0.1.3, deep-is@~0.1.3: +deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== @@ -9606,16 +8706,26 @@ defaults@^1.0.3: dependencies: clone "^1.0.2" +define-data-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.0.1.tgz#37589faaa735405b557fcb9537b46b575655c4cb" + integrity sha512-22M+6zEspQHx10bfFQl2ET39IvfuQ7+rZIH7+ard8fCC4hPmkOSy+8JhKxBRLaWUziJ0O63NTYT97LR8zUfPTw== + dependencies: + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + define-lazy-prop@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== define-properties@^1.1.2, define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" - integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== dependencies: + define-data-property "^1.0.1" has-property-descriptors "^1.0.0" object-keys "^1.1.1" @@ -9654,20 +8764,6 @@ del@^4.1.1: pify "^4.0.1" rimraf "^2.6.3" -del@^6.0.0: - version "6.1.1" - resolved "https://registry.yarnpkg.com/del/-/del-6.1.1.tgz#3b70314f1ec0aa325c6b14eb36b95786671edb7a" - integrity sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg== - dependencies: - globby "^11.0.1" - graceful-fs "^4.2.4" - is-glob "^4.0.1" - is-path-cwd "^2.2.0" - is-path-inside "^3.0.2" - p-map "^4.0.0" - rimraf "^3.0.2" - slash "^3.0.0" - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -9678,7 +8774,7 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== -depd@2.0.0, depd@^2.0.0: +depd@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== @@ -9688,7 +8784,7 @@ depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== -deprecation@^2.0.0, deprecation@^2.3.1: +deprecation@^2.0.0: version "2.3.1" resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== @@ -9728,10 +8824,10 @@ detect-libc@^1.0.3: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== -detect-libc@^2.0.0, detect-libc@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" - integrity sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w== +detect-libc@^2.0.0, detect-libc@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.2.tgz#8ccf2ba9315350e1241b88d0ac3b0e1fbd99605d" + integrity sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw== detect-newline@^3.0.0: version "3.1.0" @@ -9773,10 +8869,10 @@ diff-sequences@^28.1.1: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-28.1.1.tgz#9989dc731266dc2903457a70e996f3a041913ac6" integrity sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw== -diff-sequences@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.4.3.tgz#9314bc1fabe09267ffeca9cbafc457d8499a13f2" - integrity sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA== +diff-sequences@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" + integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== diff@5.0.0: version "5.0.0" @@ -9827,9 +8923,9 @@ dns-equal@^1.0.0: integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== dns-packet@^5.2.2: - version "5.6.0" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.0.tgz#2202c947845c7a63c23ece58f2f70ff6ab4c2f7d" - integrity sha512-rza3UH1LwdHh9qyPXp8lkwpjSNk/AMD3dPytUoRoqnypDUhY0xvbdmVhWOfxO68frEfV9BU8V12Ez7ZsHGZpCQ== + version "5.6.1" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.1.tgz#ae888ad425a9d1478a0674256ab866de1012cf2f" + integrity sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw== dependencies: "@leichtgewicht/ip-codec" "^2.0.1" @@ -9954,13 +9050,6 @@ dot-case@^3.0.4: no-case "^3.0.4" tslib "^2.0.3" -dot-prop@6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-6.0.1.tgz#fc26b3cf142b9e59b74dbd39ed66ce620c681083" - integrity sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA== - dependencies: - is-obj "^2.0.0" - dot-prop@^5.1.0: version "5.3.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" @@ -9980,6 +9069,11 @@ dotenv-expand@^5.1.0: resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA== +dotenv-expand@~10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-10.0.0.tgz#12605d00fb0af6d0a592e6558585784032e4ef37" + integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A== + dotenv-webpack@^7.0.3: version "7.1.1" resolved "https://registry.yarnpkg.com/dotenv-webpack/-/dotenv-webpack-7.1.1.tgz#ee8a699e1d736fd8eb9363fbc7054cfff1bd9dbf" @@ -9994,7 +9088,7 @@ dotenv-webpack@^8.0.1: dependencies: dotenv-defaults "^2.0.2" -dotenv@^16.0.3: +dotenv@^16.0.3, dotenv@~16.3.1: version "16.3.1" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e" integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ== @@ -10004,11 +9098,6 @@ dotenv@^8.0.0, dotenv@^8.2.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g== -dotenv@~10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" - integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== - duplexer@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" @@ -10041,15 +9130,10 @@ ejs@^3.1.7: dependencies: jake "^10.8.5" -electron-to-chromium@^1.4.431: - version "1.4.445" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.445.tgz#058d2c5f3a2981ab1a37440f5a5e42d15672aa6d" - integrity sha512-++DB+9VK8SBJwC+X1zlMfJ1tMA3F0ipi39GdEp+x3cV2TyBihqAgad8cNMWtLDEkbH39nlDQP7PfGrDr3Dr7HA== - electron-to-chromium@^1.4.477: - version "1.4.508" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.508.tgz#5641ff2f5ba11df4bd960fe6a2f9f70aa8b9af96" - integrity sha512-FFa8QKjQK/A5QuFr2167myhMesGrhlOBD+3cYNxO9/S4XzHEXesyTD/1/xF644gC8buFPz3ca6G1LOQD0tZrrg== + version "1.4.519" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.519.tgz#01b9bc3f1bb50c4971bdd1eeca6d9a73575bd581" + integrity sha512-kqs9oGYL4UFVkLKhqCTgBCYZv+wZ374yABDMqlDda9HvlkQxvSr7kgf4hfWVjMieDbX+1MwPHFBsOGCMIBaFKg== elliptic@^6.5.3, elliptic@^6.5.4: version "6.5.4" @@ -10134,7 +9218,15 @@ enhanced-resolve@^5.0.0, enhanced-resolve@^5.15.0, enhanced-resolve@^5.7.0: graceful-fs "^4.2.4" tapable "^2.2.0" -enquirer@^2.3.5, enquirer@~2.3.6: +enquirer@^2.3.5: + version "2.4.1" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" + integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== + dependencies: + ansi-colors "^4.1.1" + strip-ansi "^6.0.1" + +enquirer@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== @@ -10156,7 +9248,12 @@ env-paths@^2.2.0: resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== -envinfo@^7.7.3, envinfo@^7.7.4: +envinfo@7.8.1: + version "7.8.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" + integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== + +envinfo@^7.7.3: version "7.10.0" resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.10.0.tgz#55146e3909cc5fe63c22da63fb15b05aeac35b13" integrity sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw== @@ -10187,18 +9284,19 @@ error-stack-parser@^2.0.6: dependencies: stackframe "^1.3.4" -es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2: - version "1.21.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" - integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== +es-abstract@^1.22.1: + version "1.22.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.1.tgz#8b4e5fc5cefd7f1660f0f8e1a52900dfbc9d9ccc" + integrity sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw== dependencies: array-buffer-byte-length "^1.0.0" + arraybuffer.prototype.slice "^1.0.1" available-typed-arrays "^1.0.5" call-bind "^1.0.2" es-set-tostringtag "^2.0.1" es-to-primitive "^1.2.1" function.prototype.name "^1.1.5" - get-intrinsic "^1.2.0" + get-intrinsic "^1.2.1" get-symbol-description "^1.0.0" globalthis "^1.0.3" gopd "^1.0.1" @@ -10218,14 +9316,18 @@ es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2: object-inspect "^1.12.3" object-keys "^1.1.1" object.assign "^4.1.4" - regexp.prototype.flags "^1.4.3" + regexp.prototype.flags "^1.5.0" + safe-array-concat "^1.0.0" safe-regex-test "^1.0.0" string.prototype.trim "^1.2.7" string.prototype.trimend "^1.0.6" string.prototype.trimstart "^1.0.6" + 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.9" + which-typed-array "^1.1.10" es-array-method-boxes-properly@^1.0.0: version "1.0.0" @@ -10247,10 +9349,30 @@ es-get-iterator@^1.0.2, es-get-iterator@^1.1.3: isarray "^2.0.5" stop-iteration-iterator "^1.0.0" +es-iterator-helpers@^1.0.12: + version "1.0.14" + resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.14.tgz#19cd7903697d97e21198f3293b55e8985791c365" + integrity sha512-JgtVnwiuoRuzLvqelrvN3Xu7H9bu2ap/kQ2CrM62iidP8SKuD99rWU3CJy++s7IVL2qb/AjXPGR/E7i9ngd/Cw== + dependencies: + asynciterator.prototype "^1.0.0" + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-set-tostringtag "^2.0.1" + function-bind "^1.1.1" + get-intrinsic "^1.2.1" + globalthis "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + iterator.prototype "^1.1.0" + safe-array-concat "^1.0.0" + es-module-lexer@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.3.0.tgz#6be9c9e0b4543a60cd166ff6f8b4e9dae0b0c16f" - integrity sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA== + version "1.3.1" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.3.1.tgz#c1b0dd5ada807a3b3155315911f364dc4e909db1" + integrity sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q== es-set-tostringtag@^2.0.1: version "2.0.1" @@ -10349,14 +9471,13 @@ escape-string-regexp@^2.0.0: integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== escodegen@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" - integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== + version "2.1.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" + integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== dependencies: esprima "^4.0.1" estraverse "^5.2.0" esutils "^2.0.2" - optionator "^0.8.1" optionalDependencies: source-map "~0.6.1" @@ -10387,18 +9508,18 @@ eslint-config-airbnb@^19.0.2, eslint-config-airbnb@^19.0.4: object.entries "^1.1.5" eslint-config-prettier@^8.3.0, eslint-config-prettier@^8.5.0: - version "8.8.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz#bfda738d412adc917fd7b038857110efe98c9348" - integrity sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA== + version "8.10.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz#3a06a662130807e2502fc3ff8b4143d8a0658e11" + integrity sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg== eslint-import-resolver-node@^0.3.2, eslint-import-resolver-node@^0.3.7: - version "0.3.7" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz#83b375187d412324a1963d84fa664377a23eb4d7" - integrity sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA== + version "0.3.9" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" + integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== dependencies: debug "^3.2.7" - is-core-module "^2.11.0" - resolve "^1.22.1" + is-core-module "^2.13.0" + resolve "^1.22.4" eslint-import-resolver-root-import@^1.0.4: version "1.0.4" @@ -10408,7 +9529,7 @@ eslint-import-resolver-root-import@^1.0.4: eslint-import-resolver-node "^0.3.2" json5 "^2.1.0" -eslint-module-utils@^2.7.4: +eslint-module-utils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49" integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw== @@ -10416,25 +9537,27 @@ eslint-module-utils@^2.7.4: debug "^3.2.7" eslint-plugin-import@^2.25.4: - version "2.27.5" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz#876a6d03f52608a3e5bb439c2550588e51dd6c65" - integrity sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow== + version "2.28.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz#63b8b5b3c409bfc75ebaf8fb206b07ab435482c4" + integrity sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A== dependencies: array-includes "^3.1.6" + array.prototype.findlastindex "^1.2.2" array.prototype.flat "^1.3.1" array.prototype.flatmap "^1.3.1" debug "^3.2.7" doctrine "^2.1.0" eslint-import-resolver-node "^0.3.7" - eslint-module-utils "^2.7.4" + eslint-module-utils "^2.8.0" has "^1.0.3" - is-core-module "^2.11.0" + is-core-module "^2.13.0" is-glob "^4.0.3" minimatch "^3.1.2" + object.fromentries "^2.0.6" + object.groupby "^1.0.0" object.values "^1.1.6" - resolve "^1.22.1" - semver "^6.3.0" - tsconfig-paths "^3.14.1" + semver "^6.3.1" + tsconfig-paths "^3.14.2" eslint-plugin-jest@^26.1.1: version "26.9.0" @@ -10486,14 +9609,15 @@ eslint-plugin-react-hooks@^4.3.0: integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== eslint-plugin-react@^7.29.2: - version "7.32.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz#e71f21c7c265ebce01bcbc9d0955170c55571f10" - integrity sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg== + version "7.33.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz#69ee09443ffc583927eafe86ffebb470ee737608" + integrity sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw== dependencies: array-includes "^3.1.6" array.prototype.flatmap "^1.3.1" array.prototype.tosorted "^1.1.1" doctrine "^2.1.0" + es-iterator-helpers "^1.0.12" estraverse "^5.3.0" jsx-ast-utils "^2.4.1 || ^3.0.0" minimatch "^3.1.2" @@ -10503,7 +9627,7 @@ eslint-plugin-react@^7.29.2: object.values "^1.1.6" prop-types "^15.8.1" resolve "^2.0.0-next.4" - semver "^6.3.0" + semver "^6.3.1" string.prototype.matchall "^4.0.8" eslint-plugin-storybook@^0.5.12: @@ -10531,10 +9655,10 @@ eslint-scope@^4.0.3: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-scope@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b" - integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw== +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" @@ -10563,10 +9687,10 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" - integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== eslint@^7.18.0: version "7.32.0" @@ -10615,26 +9739,26 @@ eslint@^7.18.0: v8-compile-cache "^2.0.3" eslint@^8.10.0: - version "8.43.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.43.0.tgz#3e8c6066a57097adfd9d390b8fc93075f257a094" - integrity sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q== + version "8.49.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.49.0.tgz#09d80a89bdb4edee2efcf6964623af1054bf6d42" + integrity sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.4.0" - "@eslint/eslintrc" "^2.0.3" - "@eslint/js" "8.43.0" - "@humanwhocodes/config-array" "^0.11.10" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.2" + "@eslint/js" "8.49.0" + "@humanwhocodes/config-array" "^0.11.11" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" - ajv "^6.10.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.0" - eslint-visitor-keys "^3.4.1" - espree "^9.5.2" + 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" @@ -10644,7 +9768,6 @@ eslint@^8.10.0: globals "^13.19.0" graphemer "^1.4.0" ignore "^5.2.0" - import-fresh "^3.0.0" imurmurhash "^0.1.4" is-glob "^4.0.0" is-path-inside "^3.0.3" @@ -10654,9 +9777,8 @@ eslint@^8.10.0: lodash.merge "^4.6.2" minimatch "^3.1.2" natural-compare "^1.4.0" - optionator "^0.9.1" + optionator "^0.9.3" strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" text-table "^0.2.0" espree@^7.3.0, espree@^7.3.1: @@ -10668,12 +9790,12 @@ espree@^7.3.0, espree@^7.3.1: acorn-jsx "^5.3.1" eslint-visitor-keys "^1.3.0" -espree@^9.5.2: - version "9.5.2" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.2.tgz#e994e7dc33a082a7a82dceaf12883a829353215b" - integrity sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw== +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== dependencies: - acorn "^8.8.0" + acorn "^8.9.0" acorn-jsx "^5.3.2" eslint-visitor-keys "^3.4.1" @@ -10793,17 +9915,12 @@ event-emitter@^0.3.5: d "1" es5-ext "~0.10.14" -event-target-shim@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== - eventemitter3@^4.0.0, eventemitter3@^4.0.1, eventemitter3@^4.0.4: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== -events@^3.0.0, events@^3.2.0, events@^3.3.0: +events@^3.0.0, events@^3.2.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== @@ -10908,28 +10025,16 @@ expect@^28.1.3: jest-message-util "^28.1.3" jest-util "^28.1.3" -expect@^29.0.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.5.0.tgz#68c0509156cb2a0adb8865d413b137eeaae682f7" - integrity sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg== - dependencies: - "@jest/expect-utils" "^29.5.0" - jest-get-type "^29.4.3" - jest-matcher-utils "^29.5.0" - jest-message-util "^29.5.0" - jest-util "^29.5.0" - -expect@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.6.1.tgz#64dd1c8f75e2c0b209418f2b8d36a07921adfdf1" - integrity sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g== +expect@^29.0.0, expect@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" + integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== dependencies: - "@jest/expect-utils" "^29.6.1" - "@types/node" "*" - jest-get-type "^29.4.3" - jest-matcher-utils "^29.6.1" - jest-message-util "^29.6.1" - jest-util "^29.6.1" + "@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" exponential-backoff@^3.1.1: version "3.1.1" @@ -11038,6 +10143,11 @@ fast-equals@^5.0.0: resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-5.0.1.tgz#a4eefe3c5d1c0d021aeed0bc10ba5e0c12ee405d" integrity sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ== +fast-fifo@^1.1.0, fast-fifo@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" + integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== + fast-glob@3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" @@ -11061,7 +10171,7 @@ fast-glob@^2.2.6: merge2 "^1.2.3" micromatch "^3.1.10" -fast-glob@^3.2.11, fast-glob@^3.3.0: +fast-glob@^3.2.11, fast-glob@^3.2.9, fast-glob@^3.3.0: version "3.3.1" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== @@ -11072,17 +10182,6 @@ fast-glob@^3.2.11, fast-glob@^3.3.0: merge2 "^1.3.0" micromatch "^4.0.4" -fast-glob@^3.2.9: - version "3.2.12" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" - integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - fast-json-parse@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/fast-json-parse/-/fast-json-parse-1.0.3.tgz#43e5c61ee4efa9265633046b770fb682a7577c4d" @@ -11093,7 +10192,7 @@ fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-sta resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== @@ -11136,13 +10235,13 @@ favicons@7.0.0-beta.1: xml2js "^0.4.23" favicons@^7.0.2: - version "7.1.3" - resolved "https://registry.yarnpkg.com/favicons/-/favicons-7.1.3.tgz#e70800df0922415a544ab52c625012789f4e8035" - integrity sha512-G3lfvEroOij3k8JR+FH53EKQaloVz0PtxkDUmMcWRfeMFV1Mclh/6Wz7jHc4vodWOAwm6ISEpCgJHDU19Vm9pw== + version "7.1.4" + resolved "https://registry.yarnpkg.com/favicons/-/favicons-7.1.4.tgz#bc0ed1a8d752f94a36912294681925e272d25ff0" + integrity sha512-lnZpVgT7Fzz+DUjioKF1dMwLYlpqWCaB4gIksIfIKwtlhHO1Q7w23hERwHQjEsec+43iENwbTAPRDW3XvpLhbg== dependencies: escape-html "^1.0.3" - sharp "^0.32.0" - xml2js "^0.5.0" + sharp "^0.32.4" + xml2js "^0.6.1" faye-websocket@^0.11.3: version "0.11.4" @@ -11211,11 +10310,6 @@ file-uri-to-path@1.0.0: resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== -file-url@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/file-url/-/file-url-3.0.0.tgz#247a586a746ce9f7a8ed05560290968afc262a77" - integrity sha512-g872QGsHexznxkIAdK8UiZRe7SkE6kvylShU4Nsj8NvfvZag7S0QuQ4IgvPDkk75HxgjIVDwycFTDAgIiO4nDA== - filelist@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5" @@ -11331,11 +10425,12 @@ find-up@^6.3.0: path-exists "^5.0.0" flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + version "3.1.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.1.0.tgz#0e54ab4a1a60fe87e2946b6b00657f1c99e1af3f" + integrity sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew== dependencies: - flatted "^3.1.0" + flatted "^3.2.7" + keyv "^4.5.3" rimraf "^3.0.2" flat@^5.0.2: @@ -11343,7 +10438,7 @@ flat@^5.0.2: resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -flatted@^3.1.0: +flatted@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== @@ -11512,7 +10607,7 @@ fs-constants@^1.0.0: resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== -fs-extra@11.1.1, fs-extra@^11.1.0: +fs-extra@11.1.1, fs-extra@^11.1.0, fs-extra@^11.1.1: version "11.1.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.1.tgz#da69f7c39f3b002378b0954bb6ae7efdc0876e2d" integrity sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ== @@ -11521,26 +10616,26 @@ fs-extra@11.1.1, fs-extra@^11.1.0: jsonfile "^6.0.1" universalify "^2.0.0" -fs-extra@9.1.0, fs-extra@^9.0.0, fs-extra@^9.0.1, fs-extra@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" - integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== +fs-extra@^10.0.0, fs-extra@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== dependencies: - at-least-node "^1.0.0" graceful-fs "^4.2.0" jsonfile "^6.0.1" universalify "^2.0.0" -fs-extra@^10.0.0, fs-extra@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" - integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== +fs-extra@^9.0.0, fs-extra@^9.0.1: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== dependencies: + at-least-node "^1.0.0" graceful-fs "^4.2.0" jsonfile "^6.0.1" universalify "^2.0.0" -fs-minipass@^2.0.0, fs-minipass@^2.1.0: +fs-minipass@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== @@ -11548,11 +10643,11 @@ fs-minipass@^2.0.0, fs-minipass@^2.1.0: minipass "^3.0.0" fs-minipass@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-3.0.2.tgz#5b383858efa8c1eb8c33b39e994f7e8555b8b3a3" - integrity sha512-2GAfyfoaCDRrM6jaOS3UsBts8yJ55VioXdWcOL7dK9zdAuKT71+WBA4ifnNYqVjYv+4SsPxjK0JT4yIIn4cA/g== + version "3.0.3" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-3.0.3.tgz#79a85981c4dc120065e96f62086bf6f9dc26cc54" + integrity sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw== dependencies: - minipass "^5.0.0" + minipass "^7.0.3" fs-monkey@^1.0.4: version "1.0.4" @@ -11583,9 +10678,9 @@ fsevents@^1.2.7: nan "^2.12.1" fsevents@^2.1.2, fsevents@^2.3.2, fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== function-bind@^1.1.1: version "1.1.1" @@ -11593,21 +10688,21 @@ function-bind@^1.1.1: integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== function.prototype.name@^1.1.0, function.prototype.name@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" - integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + version "1.1.6" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" + integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - functions-have-names "^1.2.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + functions-have-names "^1.2.3" functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== -functions-have-names@^1.2.2, functions-have-names@^1.2.3: +functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== @@ -11641,20 +10736,6 @@ gauge@^4.0.3: strip-ansi "^6.0.1" wide-align "^1.1.5" -gauge@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-5.0.1.tgz#1efc801b8ff076b86ef3e9a7a280a975df572112" - integrity sha512-CmykPMJGuNan/3S4kZOpvvPYSNqSHANiWnh9XcMU2pSjtBfF0XzZ2p1bFAxTbnFxyBuPxQYHhzwaoOmUdqzvxQ== - dependencies: - aproba "^1.0.3 || ^2.0.0" - color-support "^1.1.3" - console-control-strings "^1.1.0" - has-unicode "^2.0.1" - signal-exit "^4.0.1" - string-width "^4.2.3" - strip-ansi "^6.0.1" - wide-align "^1.1.5" - gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -11665,7 +10746,7 @@ get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0: +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== @@ -11680,7 +10761,7 @@ get-package-type@^0.1.0: resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== -get-pkg-repo@^4.0.0: +get-pkg-repo@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz#75973e1c8050c73f48190c52047c4cee3acbf385" integrity sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA== @@ -11730,16 +10811,14 @@ get-value@^2.0.3, get-value@^2.0.6: resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== -git-raw-commits@^2.0.8: - version "2.0.11" - resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.11.tgz#bc3576638071d18655e1cc60d7f524920008d723" - integrity sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A== +git-raw-commits@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-3.0.0.tgz#5432f053a9744f67e8db03dbc48add81252cfdeb" + integrity sha512-b5OHmZ3vAgGrDn/X0kS+9qCfNKWe4K/jFnhwzVWWg0/k5eLa3060tZShrRg8Dja5kPc+YjS0Gc6y7cRr44Lpjw== dependencies: dargs "^7.0.0" - lodash "^4.17.15" - meow "^8.0.0" - split2 "^3.0.0" - through2 "^4.0.0" + meow "^8.1.2" + split2 "^3.2.2" git-remote-origin-url@^2.0.0: version "2.0.0" @@ -11749,13 +10828,13 @@ git-remote-origin-url@^2.0.0: gitconfiglocal "^1.0.0" pify "^2.3.0" -git-semver-tags@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/git-semver-tags/-/git-semver-tags-4.1.1.tgz#63191bcd809b0ec3e151ba4751c16c444e5b5780" - integrity sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA== +git-semver-tags@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/git-semver-tags/-/git-semver-tags-5.0.1.tgz#db748aa0e43d313bf38dcd68624d8443234e1c15" + integrity sha512-hIvOeZwRbQ+7YEUmCkHqo8FOLQZCEn18yevLHADlFPZY02KJGsu5FZt9YW/lybfK2uhWFI7Qg/07LekJiTv7iA== dependencies: - meow "^8.0.0" - semver "^6.0.0" + meow "^8.1.2" + semver "^7.0.0" git-up@^7.0.0: version "7.0.0" @@ -11853,15 +10932,15 @@ glob@7.2.0: path-is-absolute "^1.0.0" glob@^10.2.2: - version "10.3.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.1.tgz#9789cb1b994515bedb811a6deca735b5c37d2bf4" - integrity sha512-9BKYcEeIs7QwlCYs+Y3GBvqAMISufUS0i2ELd11zpZjxI5V9iyRj0HgzB5/cLf2NY4vcYBTYzJ7GIui7j/4DOw== + version "10.3.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.4.tgz#c85c9c7ab98669102b6defda76d35c5b1ef9766f" + integrity sha512-6LFElP3A+i/Q8XQKEvZjkEWEOTgAIALR9AO2rwT8bgPhDd1anmqDJDZ6lLddI4ehxxxR1S5RIqKe1uapMQfYaQ== dependencies: foreground-child "^3.1.0" jackspeak "^2.0.3" minimatch "^9.0.1" - minipass "^5.0.0 || ^6.0.2" - path-scurry "^1.10.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-scurry "^1.10.1" glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.3" @@ -11910,9 +10989,9 @@ globals@^11.1.0: integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globals@^13.19.0, globals@^13.6.0, globals@^13.9.0: - version "13.20.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" - integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== + version "13.21.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.21.0.tgz#163aae12f34ef502f5153cfbdd3600f36c63c571" + integrity sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg== dependencies: type-fest "^0.20.2" @@ -11923,7 +11002,7 @@ globalthis@^1.0.0, globalthis@^1.0.1, globalthis@^1.0.3: dependencies: define-properties "^1.1.3" -globby@11.1.0, globby@^11.0.1, globby@^11.0.2, globby@^11.1.0: +globby@11.1.0, globby@^11.0.2, globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -11978,21 +11057,11 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@4.2.10: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== - -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: +graceful-fs@4.2.11, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -grapheme-splitter@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" - integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== - graphemer@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" @@ -12003,13 +11072,13 @@ handle-thing@^2.0.0: resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== -handlebars@^4.7.7: - version "4.7.7" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" - integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== +handlebars@^4.7.7, handlebars@^4.7.8: + version "4.7.8" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" + integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== dependencies: minimist "^1.2.5" - neo-async "^2.6.0" + neo-async "^2.6.2" source-map "^0.6.1" wordwrap "^1.0.0" optionalDependencies: @@ -12265,14 +11334,7 @@ hosted-git-info@^4.0.0, hosted-git-info@^4.0.1: dependencies: lru-cache "^6.0.0" -hosted-git-info@^5.0.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-5.2.1.tgz#0ba1c97178ef91f3ab30842ae63d6a272341156f" - integrity sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw== - dependencies: - lru-cache "^7.5.1" - -hosted-git-info@^6.0.0, hosted-git-info@^6.1.1: +hosted-git-info@^6.0.0: version "6.1.1" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-6.1.1.tgz#629442c7889a69c05de604d52996b74fe6f26d58" integrity sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w== @@ -12378,7 +11440,7 @@ htmlparser2@^6.1.0: domutils "^2.5.2" entities "^2.0.0" -http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: +http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -12515,7 +11577,7 @@ icss-utils@^5.0.0, icss-utils@^5.1.0: resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== -ieee754@^1.1.13, ieee754@^1.1.4, ieee754@^1.2.1: +ieee754@^1.1.13, ieee754@^1.1.4: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -12559,7 +11621,7 @@ immediate@~3.0.5: resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== -import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: +import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -12567,7 +11629,7 @@ import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" -import-local@^3.0.2: +import-local@3.1.0, import-local@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== @@ -12610,64 +11672,38 @@ inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, i resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA== - inherits@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== -ini@^1.3.2, ini@^1.3.4, ini@~1.3.0: +ini@^1.3.2, ini@^1.3.8, ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -init-package-json@3.0.2, init-package-json@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-3.0.2.tgz#f5bc9bac93f2bdc005778bc2271be642fecfcd69" - integrity sha512-YhlQPEjNFqlGdzrBfDNRLhvoSgX7iQRgSxgsNknRQ9ITXFT7UMfVMWhBTOh2Y+25lRnGrv5Xz8yZwQ3ACR6T3A== +init-package-json@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-5.0.0.tgz#030cf0ea9c84cfc1b0dc2e898b45d171393e4b40" + integrity sha512-kBhlSheBfYmq3e0L1ii+VKe3zBTLL5lDCDWR+f9dLmEGSB3MqLlMlsolubSsyI88Bg6EA+BIMlomAnQ1SwgQBw== dependencies: - npm-package-arg "^9.0.1" - promzard "^0.3.0" - read "^1.0.7" - read-package-json "^5.0.0" + npm-package-arg "^10.0.0" + promzard "^1.0.0" + read "^2.0.0" + read-package-json "^6.0.0" semver "^7.3.5" validate-npm-package-license "^3.0.4" - validate-npm-package-name "^4.0.0" + validate-npm-package-name "^5.0.0" inline-style-parser@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== -inquirer@8.2.4: - version "8.2.4" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.4.tgz#ddbfe86ca2f67649a67daa6f1051c128f684f0b4" - integrity sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg== - dependencies: - ansi-escapes "^4.2.1" - chalk "^4.1.1" - cli-cursor "^3.1.0" - cli-width "^3.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.21" - mute-stream "0.0.8" - ora "^5.4.1" - run-async "^2.4.0" - rxjs "^7.5.5" - string-width "^4.1.0" - strip-ansi "^6.0.0" - through "^2.3.6" - wrap-ansi "^7.0.0" - inquirer@^8.2.4: - version "8.2.5" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.5.tgz#d8654a7542c35a9b9e069d27e2df4858784d54f8" - integrity sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ== + version "8.2.6" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.6.tgz#733b74888195d8d400a67ac332011b5fae5ea562" + integrity sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg== dependencies: ansi-escapes "^4.2.1" chalk "^4.1.1" @@ -12683,9 +11719,9 @@ inquirer@^8.2.4: string-width "^4.1.0" strip-ansi "^6.0.0" through "^2.3.6" - wrap-ansi "^7.0.0" + wrap-ansi "^6.0.1" -internal-slot@^1.0.3, internal-slot@^1.0.4, internal-slot@^1.0.5: +internal-slot@^1.0.4, internal-slot@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== @@ -12801,6 +11837,13 @@ is-arrayish@^0.3.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== +is-async-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" + integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== + dependencies: + has-tostringtag "^1.0.0" + is-bigint@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" @@ -12852,17 +11895,24 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-ci@2.0.0, is-ci@^2.0.0: +is-ci@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867" + integrity sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ== + dependencies: + ci-info "^3.2.0" + +is-ci@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== dependencies: ci-info "^2.0.0" -is-core-module@^2.11.0, is-core-module@^2.5.0, is-core-module@^2.8.1, is-core-module@^2.9.0: - version "2.12.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" - integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== +is-core-module@^2.13.0, is-core-module@^2.5.0, is-core-module@^2.8.1, is-core-module@^2.9.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== dependencies: has "^1.0.3" @@ -12945,6 +11995,13 @@ is-extglob@^2.1.0, is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== +is-finalizationregistry@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6" + integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== + dependencies: + call-bind "^1.0.2" + is-finite@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" @@ -12965,6 +12022,13 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== +is-generator-function@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + is-glob@^3.0.0, is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" @@ -13048,7 +12112,7 @@ is-object@^1.0.1: resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.2.tgz#a56552e1c665c9e950b4a025461da87e72f86fcf" integrity sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA== -is-path-cwd@^2.0.0, is-path-cwd@^2.2.0: +is-path-cwd@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== @@ -13067,7 +12131,7 @@ is-path-inside@^2.1.0: dependencies: path-is-inside "^1.0.2" -is-path-inside@^3.0.2, is-path-inside@^3.0.3: +is-path-inside@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== @@ -13122,9 +12186,9 @@ is-reference@1.2.1: "@types/estree" "*" is-reference@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-3.0.1.tgz#d400f4260f7e55733955e60d361d827eb4d3b831" - integrity sha512-baJJdQLiYaJdvFbJqXrcGv3WU3QCzBlUcI5QhbesIm6/xPsvmO+2CDoi/GMOFBQEQm+PXkwOPrp9KK5ozZsp2w== + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-3.0.2.tgz#154747a01f45cd962404ee89d43837af2cba247c" + integrity sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg== dependencies: "@types/estree" "*" @@ -13192,15 +12256,11 @@ is-text-path@^1.0.1: text-extensions "^1.0.0" is-typed-array@^1.1.10, is-typed-array@^1.1.9: - version "1.1.10" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" - integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + version "1.1.12" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" + integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" + which-typed-array "^1.1.11" is-typedarray@^1.0.0: version "1.0.0" @@ -13330,13 +12390,24 @@ istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: istanbul-lib-coverage "^3.2.0" semver "^6.3.0" +istanbul-lib-instrument@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz#7a8af094cbfff1d5bb280f62ce043695ae8dd5b8" + integrity sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw== + 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" + istanbul-lib-report@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" - integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== dependencies: istanbul-lib-coverage "^3.0.0" - make-dir "^3.0.0" + make-dir "^4.0.0" supports-color "^7.1.0" istanbul-lib-source-maps@^4.0.0: @@ -13349,9 +12420,9 @@ istanbul-lib-source-maps@^4.0.0: source-map "^0.6.1" istanbul-reports@^3.1.3, istanbul-reports@^3.1.4: - version "3.1.5" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" - integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== + version "3.1.6" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.6.tgz#2544bcab4768154281a2f0870471902704ccaa1a" + integrity sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" @@ -13369,10 +12440,20 @@ iterate-value@^1.0.2: es-get-iterator "^1.0.2" iterate-iterator "^1.0.1" +iterator.prototype@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.1.tgz#ab5b790e23ec00658f5974e032a2b05188bd3a5c" + integrity sha512-9E+nePc8C9cnQldmNl6bgpTY6zI4OPRZd97fhJ/iVZ1GifIUDVV5F6x1nEDqpe8KaMEZGT4xgrwKQDxXnjOIZQ== + dependencies: + define-properties "^1.2.0" + get-intrinsic "^1.2.1" + has-symbols "^1.0.3" + reflect.getprototypeof "^1.0.3" + jackspeak@^2.0.3: - version "2.2.1" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.2.1.tgz#655e8cf025d872c9c03d3eb63e8f0c024fef16a6" - integrity sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw== + version "2.3.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.3.tgz#95e4cbcc03b3eb357bf6bcce14a903fb3d1151e1" + integrity sha512-R2bUw+kVZFS/h1AZqBKrSgDmdmjApzgY0AlCPumopFiAlbUxE2gf+SCuBzQ0cP5hHmUmFYF5yw55T97Th5Kstg== dependencies: "@isaacs/cliui" "^8.0.2" optionalDependencies: @@ -13402,12 +12483,13 @@ jest-changed-files@^27.5.1: execa "^5.0.0" throat "^6.0.1" -jest-changed-files@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.5.0.tgz#e88786dca8bf2aa899ec4af7644e16d9dcf9b23e" - integrity sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag== +jest-changed-files@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" + integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== dependencies: execa "^5.0.0" + jest-util "^29.7.0" p-limit "^3.1.0" jest-circus@^27.5.1: @@ -13435,28 +12517,28 @@ jest-circus@^27.5.1: stack-utils "^2.0.3" throat "^6.0.1" -jest-circus@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.6.1.tgz#861dab37e71a89907d1c0fabc54a0019738ed824" - integrity sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ== +jest-circus@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" + integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== dependencies: - "@jest/environment" "^29.6.1" - "@jest/expect" "^29.6.1" - "@jest/test-result" "^29.6.1" - "@jest/types" "^29.6.1" + "@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 "^0.7.0" + dedent "^1.0.0" is-generator-fn "^2.0.0" - jest-each "^29.6.1" - jest-matcher-utils "^29.6.1" - jest-message-util "^29.6.1" - jest-runtime "^29.6.1" - jest-snapshot "^29.6.1" - jest-util "^29.6.1" + 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.6.1" + pretty-format "^29.7.0" pure-rand "^6.0.0" slash "^3.0.0" stack-utils "^2.0.3" @@ -13479,22 +12561,21 @@ jest-cli@^27.5.1: prompts "^2.0.1" yargs "^16.2.0" -jest-cli@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.6.1.tgz#99d9afa7449538221c71f358f0fdd3e9c6e89f72" - integrity sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing== +jest-cli@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" + integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== dependencies: - "@jest/core" "^29.6.1" - "@jest/test-result" "^29.6.1" - "@jest/types" "^29.6.1" + "@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" - graceful-fs "^4.2.9" import-local "^3.0.2" - jest-config "^29.6.1" - jest-util "^29.6.1" - jest-validate "^29.6.1" - prompts "^2.0.1" + jest-config "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" yargs "^17.3.1" jest-config@^27.5.1: @@ -13527,34 +12608,44 @@ jest-config@^27.5.1: slash "^3.0.0" strip-json-comments "^3.1.1" -jest-config@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.6.1.tgz#d785344509065d53a238224c6cdc0ed8e2f2f0dd" - integrity sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ== +jest-config@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" + integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== dependencies: "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^29.6.1" - "@jest/types" "^29.6.1" - babel-jest "^29.6.1" + "@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.6.1" - jest-environment-node "^29.6.1" - jest-get-type "^29.4.3" - jest-regex-util "^29.4.3" - jest-resolve "^29.6.1" - jest-runner "^29.6.1" - jest-util "^29.6.1" - jest-validate "^29.6.1" + 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.6.1" + pretty-format "^29.7.0" slash "^3.0.0" strip-json-comments "^3.1.1" +"jest-diff@>=29.4.3 < 30", jest-diff@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" + integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.6.3" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + jest-diff@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" @@ -13575,26 +12666,6 @@ jest-diff@^28.1.3: jest-get-type "^28.0.2" pretty-format "^28.1.3" -jest-diff@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.5.0.tgz#e0d83a58eb5451dcc1fa61b1c3ee4e8f5a290d63" - integrity sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw== - dependencies: - chalk "^4.0.0" - diff-sequences "^29.4.3" - jest-get-type "^29.4.3" - pretty-format "^29.5.0" - -jest-diff@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.6.1.tgz#13df6db0a89ee6ad93c747c75c85c70ba941e545" - integrity sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg== - dependencies: - chalk "^4.0.0" - diff-sequences "^29.4.3" - jest-get-type "^29.4.3" - pretty-format "^29.6.1" - jest-docblock@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.5.1.tgz#14092f364a42c6108d42c33c8cf30e058e25f6c0" @@ -13602,10 +12673,10 @@ jest-docblock@^27.5.1: dependencies: detect-newline "^3.0.0" -jest-docblock@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.4.3.tgz#90505aa89514a1c7dceeac1123df79e414636ea8" - integrity sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg== +jest-docblock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" + integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== dependencies: detect-newline "^3.0.0" @@ -13620,16 +12691,16 @@ jest-each@^27.5.1: jest-util "^27.5.1" pretty-format "^27.5.1" -jest-each@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.6.1.tgz#975058e5b8f55c6780beab8b6ab214921815c89c" - integrity sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ== +jest-each@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" + integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== dependencies: - "@jest/types" "^29.6.1" + "@jest/types" "^29.6.3" chalk "^4.0.0" - jest-get-type "^29.4.3" - jest-util "^29.6.1" - pretty-format "^29.6.1" + jest-get-type "^29.6.3" + jest-util "^29.7.0" + pretty-format "^29.7.0" jest-environment-jsdom@^27.5.1: version "27.5.1" @@ -13656,17 +12727,17 @@ jest-environment-node@^27.5.1: jest-mock "^27.5.1" jest-util "^27.5.1" -jest-environment-node@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.6.1.tgz#08a122dece39e58bc388da815a2166c58b4abec6" - integrity sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ== +jest-environment-node@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" + integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== dependencies: - "@jest/environment" "^29.6.1" - "@jest/fake-timers" "^29.6.1" - "@jest/types" "^29.6.1" + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" "@types/node" "*" - jest-mock "^29.6.1" - jest-util "^29.6.1" + jest-mock "^29.7.0" + jest-util "^29.7.0" jest-get-type@^27.5.1: version "27.5.1" @@ -13678,10 +12749,10 @@ jest-get-type@^28.0.2: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-28.0.2.tgz#34622e628e4fdcd793d46db8a242227901fcf203" integrity sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA== -jest-get-type@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.4.3.tgz#1ab7a5207c995161100b5187159ca82dd48b3dd5" - integrity sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg== +jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== jest-haste-map@^26.6.2: version "26.6.2" @@ -13724,20 +12795,20 @@ jest-haste-map@^27.5.1: optionalDependencies: fsevents "^2.3.2" -jest-haste-map@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.6.1.tgz#62655c7a1c1b349a3206441330fb2dbdb4b63803" - integrity sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig== +jest-haste-map@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" + integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== dependencies: - "@jest/types" "^29.6.1" + "@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.4.3" - jest-util "^29.6.1" - jest-worker "^29.6.1" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + jest-worker "^29.7.0" micromatch "^4.0.4" walker "^1.0.8" optionalDependencies: @@ -13774,13 +12845,13 @@ jest-leak-detector@^27.5.1: jest-get-type "^27.5.1" pretty-format "^27.5.1" -jest-leak-detector@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz#66a902c81318e66e694df7d096a95466cb962f8e" - integrity sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ== +jest-leak-detector@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" + integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== dependencies: - jest-get-type "^29.4.3" - pretty-format "^29.6.1" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" jest-matcher-utils@^27.0.0, jest-matcher-utils@^27.5.1: version "27.5.1" @@ -13802,25 +12873,15 @@ jest-matcher-utils@^28.1.3: jest-get-type "^28.0.2" pretty-format "^28.1.3" -jest-matcher-utils@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz#d957af7f8c0692c5453666705621ad4abc2c59c5" - integrity sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw== - dependencies: - chalk "^4.0.0" - jest-diff "^29.5.0" - jest-get-type "^29.4.3" - pretty-format "^29.5.0" - -jest-matcher-utils@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz#6c60075d84655d6300c5d5128f46531848160b53" - integrity sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA== +jest-matcher-utils@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" + integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== dependencies: chalk "^4.0.0" - jest-diff "^29.6.1" - jest-get-type "^29.4.3" - pretty-format "^29.6.1" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" jest-message-util@^27.5.1: version "27.5.1" @@ -13852,33 +12913,18 @@ jest-message-util@^28.1.3: slash "^3.0.0" stack-utils "^2.0.3" -jest-message-util@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.5.0.tgz#1f776cac3aca332ab8dd2e3b41625435085c900e" - integrity sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.5.0" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^29.5.0" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-message-util@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.6.1.tgz#d0b21d87f117e1b9e165e24f245befd2ff34ff8d" - integrity sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ== +jest-message-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" + integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== dependencies: "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.6.1" + "@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.6.1" + pretty-format "^29.7.0" slash "^3.0.0" stack-utils "^2.0.3" @@ -13890,14 +12936,14 @@ jest-mock@^27.0.6, jest-mock@^27.5.1: "@jest/types" "^27.5.1" "@types/node" "*" -jest-mock@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.6.1.tgz#049ee26aea8cbf54c764af649070910607316517" - integrity sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw== +jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== dependencies: - "@jest/types" "^29.6.1" + "@jest/types" "^29.6.3" "@types/node" "*" - jest-util "^29.6.1" + jest-util "^29.7.0" jest-pnp-resolver@^1.2.2: version "1.2.3" @@ -13914,10 +12960,10 @@ jest-regex-util@^27.5.1: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95" integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg== -jest-regex-util@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.4.3.tgz#a42616141e0cae052cfa32c169945d00c0aa0bb8" - integrity sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg== +jest-regex-util@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" + integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== jest-resolve-dependencies@^27.5.1: version "27.5.1" @@ -13928,13 +12974,13 @@ jest-resolve-dependencies@^27.5.1: jest-regex-util "^27.5.1" jest-snapshot "^27.5.1" -jest-resolve-dependencies@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz#b85b06670f987a62515bbf625d54a499e3d708f5" - integrity sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw== +jest-resolve-dependencies@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" + integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== dependencies: - jest-regex-util "^29.4.3" - jest-snapshot "^29.6.1" + jest-regex-util "^29.6.3" + jest-snapshot "^29.7.0" jest-resolve@^27.5.1: version "27.5.1" @@ -13952,17 +12998,17 @@ jest-resolve@^27.5.1: resolve.exports "^1.1.0" slash "^3.0.0" -jest-resolve@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.6.1.tgz#4c3324b993a85e300add2f8609f51b80ddea39ee" - integrity sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg== +jest-resolve@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" + integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== dependencies: chalk "^4.0.0" graceful-fs "^4.2.9" - jest-haste-map "^29.6.1" + jest-haste-map "^29.7.0" jest-pnp-resolver "^1.2.2" - jest-util "^29.6.1" - jest-validate "^29.6.1" + jest-util "^29.7.0" + jest-validate "^29.7.0" resolve "^1.20.0" resolve.exports "^2.0.0" slash "^3.0.0" @@ -13994,30 +13040,30 @@ jest-runner@^27.5.1: source-map-support "^0.5.6" throat "^6.0.1" -jest-runner@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.6.1.tgz#54557087e7972d345540d622ab5bfc3d8f34688c" - integrity sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ== +jest-runner@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" + integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== dependencies: - "@jest/console" "^29.6.1" - "@jest/environment" "^29.6.1" - "@jest/test-result" "^29.6.1" - "@jest/transform" "^29.6.1" - "@jest/types" "^29.6.1" + "@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.4.3" - jest-environment-node "^29.6.1" - jest-haste-map "^29.6.1" - jest-leak-detector "^29.6.1" - jest-message-util "^29.6.1" - jest-resolve "^29.6.1" - jest-runtime "^29.6.1" - jest-util "^29.6.1" - jest-watcher "^29.6.1" - jest-worker "^29.6.1" + 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" @@ -14049,31 +13095,31 @@ jest-runtime@^27.5.1: slash "^3.0.0" strip-bom "^4.0.0" -jest-runtime@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.6.1.tgz#8a0fc9274ef277f3d70ba19d238e64334958a0dc" - integrity sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ== - dependencies: - "@jest/environment" "^29.6.1" - "@jest/fake-timers" "^29.6.1" - "@jest/globals" "^29.6.1" - "@jest/source-map" "^29.6.0" - "@jest/test-result" "^29.6.1" - "@jest/transform" "^29.6.1" - "@jest/types" "^29.6.1" +jest-runtime@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" + integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== + 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.6.1" - jest-message-util "^29.6.1" - jest-mock "^29.6.1" - jest-regex-util "^29.4.3" - jest-resolve "^29.6.1" - jest-snapshot "^29.6.1" - jest-util "^29.6.1" + 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" @@ -14121,31 +13167,30 @@ jest-snapshot@^27.5.1: pretty-format "^27.5.1" semver "^7.3.2" -jest-snapshot@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.6.1.tgz#0d083cb7de716d5d5cdbe80d598ed2fbafac0239" - integrity sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A== +jest-snapshot@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" + integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== 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.6.1" - "@jest/transform" "^29.6.1" - "@jest/types" "^29.6.1" - "@types/prettier" "^2.1.5" + "@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.6.1" + expect "^29.7.0" graceful-fs "^4.2.9" - jest-diff "^29.6.1" - jest-get-type "^29.4.3" - jest-matcher-utils "^29.6.1" - jest-message-util "^29.6.1" - jest-util "^29.6.1" + 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.6.1" + pretty-format "^29.7.0" semver "^7.5.3" jest-util@^26.6.2: @@ -14184,34 +13229,10 @@ jest-util@^28.1.3: graceful-fs "^4.2.9" picomatch "^2.2.3" -jest-util@^29.0.0, jest-util@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.6.1.tgz#c9e29a87a6edbf1e39e6dee2b4689b8a146679cb" - integrity sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg== - dependencies: - "@jest/types" "^29.6.1" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - -jest-util@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.5.0.tgz#24a4d3d92fc39ce90425311b23c27a6e0ef16b8f" - integrity sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ== - dependencies: - "@jest/types" "^29.5.0" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - -jest-util@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.6.3.tgz#e15c3eac8716440d1ed076f09bc63ace1aebca63" - integrity sha512-QUjna/xSy4B32fzcKTSz1w7YYzgiHrjjJjevdRf61HYk998R5vVMMNmrHESYZVDS5DSWs+1srPLPKxXPkeSDOA== +jest-util@^29.0.0, jest-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" + integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== dependencies: "@jest/types" "^29.6.3" "@types/node" "*" @@ -14232,17 +13253,17 @@ jest-validate@^27.5.1: leven "^3.1.0" pretty-format "^27.5.1" -jest-validate@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.6.1.tgz#765e684af6e2c86dce950aebefbbcd4546d69f7b" - integrity sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA== +jest-validate@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== dependencies: - "@jest/types" "^29.6.1" + "@jest/types" "^29.6.3" camelcase "^6.2.0" chalk "^4.0.0" - jest-get-type "^29.4.3" + jest-get-type "^29.6.3" leven "^3.1.0" - pretty-format "^29.6.1" + pretty-format "^29.7.0" jest-watcher@^27.5.1: version "27.5.1" @@ -14257,18 +13278,18 @@ jest-watcher@^27.5.1: jest-util "^27.5.1" string-length "^4.0.1" -jest-watcher@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.6.1.tgz#7c0c43ddd52418af134c551c92c9ea31e5ec942e" - integrity sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA== +jest-watcher@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" + integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== dependencies: - "@jest/test-result" "^29.6.1" - "@jest/types" "^29.6.1" + "@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.6.1" + jest-util "^29.7.0" string-length "^4.0.1" jest-worker@^26.5.0, jest-worker@^26.6.2: @@ -14289,23 +13310,13 @@ jest-worker@^27.0.2, jest-worker@^27.4.5, jest-worker@^27.5.1: merge-stream "^2.0.0" supports-color "^8.0.0" -jest-worker@^29.4.3: - version "29.6.4" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.6.4.tgz#f34279f4afc33c872b470d4af21b281ac616abd3" - integrity sha512-6dpvFV4WjcWbDVGgHTWo/aupl8/LbBx2NSKfiwqf79xC/yeJjKHT1+StcKy/2KTmW16hE68ccKVOtXf+WZGz7Q== - dependencies: - "@types/node" "*" - jest-util "^29.6.3" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -jest-worker@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.6.1.tgz#64b015f0e985ef3a8ad049b61fe92b3db74a5319" - integrity sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA== +jest-worker@^29.4.3, jest-worker@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== dependencies: "@types/node" "*" - jest-util "^29.6.1" + jest-util "^29.7.0" merge-stream "^2.0.0" supports-color "^8.0.0" @@ -14319,14 +13330,14 @@ jest@^27.1.0: jest-cli "^27.5.1" jest@^29.5.0: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.6.1.tgz#74be1cb719c3abe439f2d94aeb18e6540a5b02ad" - integrity sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw== + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== dependencies: - "@jest/core" "^29.6.1" - "@jest/types" "^29.6.1" + "@jest/core" "^29.7.0" + "@jest/types" "^29.6.3" import-local "^3.0.2" - jest-cli "^29.6.1" + jest-cli "^29.7.0" js-sha3@^0.8.0: version "0.8.0" @@ -14401,6 +13412,11 @@ jsesc@~0.5.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -14431,11 +13447,6 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -json-stringify-nice@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz#2c937962b80181d3f317dd39aa323e14f5a60a67" - integrity sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw== - json-stringify-safe@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -14543,9 +13554,9 @@ jss@10.10.0, jss@^10.10.0: tiny-warning "^1.0.2" "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.3: - version "3.3.4" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.4.tgz#b896535fed5b867650acce5a9bd4135ffc7b3bf9" - integrity sha512-fX2TVdCViod6HwKEtSWGHs57oFhVfCMwieb9PuRDgjDPh5XeqJiHFFFJCHxU5cnTc3Bu/GRL+kPiFmw8XWOfKw== + version "3.3.5" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" + integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== dependencies: array-includes "^3.1.6" array.prototype.flat "^1.3.1" @@ -14557,15 +13568,12 @@ junk@^3.1.0: resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1" integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ== -just-diff-apply@^5.2.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/just-diff-apply/-/just-diff-apply-5.5.0.tgz#771c2ca9fa69f3d2b54e7c3f5c1dfcbcc47f9f0f" - integrity sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw== - -just-diff@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/just-diff/-/just-diff-6.0.2.tgz#03b65908543ac0521caf6d8eb85035f7d27ea285" - integrity sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA== +keyv@^4.5.3: + version "4.5.3" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.3.tgz#00873d2b046df737963157bd04f294ca818c9c25" + integrity sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug== + dependencies: + json-buffer "3.0.1" kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" @@ -14637,84 +13645,83 @@ lazy-universal-dotenv@^3.0.1: dotenv "^8.0.0" dotenv-expand "^5.1.0" -lerna@^6.6.2: - version "6.6.2" - resolved "https://registry.yarnpkg.com/lerna/-/lerna-6.6.2.tgz#ad921f913aca4e7307123a598768b6f15ca5804f" - integrity sha512-W4qrGhcdutkRdHEaDf9eqp7u4JvI+1TwFy5woX6OI8WPe4PYBdxuILAsvhp614fUG41rKSGDKlOh+AWzdSidTg== - dependencies: - "@lerna/child-process" "6.6.2" - "@lerna/create" "6.6.2" - "@lerna/legacy-package-management" "6.6.2" - "@npmcli/arborist" "6.2.3" - "@npmcli/run-script" "4.1.7" - "@nrwl/devkit" ">=15.5.2 < 16" +lerna@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/lerna/-/lerna-7.3.0.tgz#efecafbdce15694e2f6841256e073a3a2061053e" + integrity sha512-Dt8TH+J+c9+3MhTYcm5OxnNzXb87WG7GPNj3kidjYJjJY7KxIMDNU37qBTYRWA1h3wAeNKBplXVQYUPkGcYgkQ== + dependencies: + "@lerna/child-process" "7.3.0" + "@lerna/create" "7.3.0" + "@npmcli/run-script" "6.0.2" + "@nx/devkit" ">=16.5.1 < 17" "@octokit/plugin-enterprise-rest" "6.0.1" - "@octokit/rest" "19.0.3" - byte-size "7.0.0" + "@octokit/rest" "19.0.11" + byte-size "8.1.1" chalk "4.1.0" clone-deep "4.0.1" - cmd-shim "5.0.0" + cmd-shim "6.0.1" columnify "1.6.0" - config-chain "1.1.12" - conventional-changelog-angular "5.0.12" - conventional-changelog-core "4.2.4" - conventional-recommended-bump "6.1.0" - cosmiconfig "7.0.0" + conventional-changelog-angular "6.0.0" + conventional-changelog-core "5.0.1" + conventional-recommended-bump "7.0.1" + cosmiconfig "^8.2.0" dedent "0.7.0" - dot-prop "6.0.1" - envinfo "^7.7.4" + envinfo "7.8.1" execa "5.0.0" - fs-extra "9.1.0" + fs-extra "^11.1.1" get-port "5.1.1" get-stream "6.0.0" git-url-parse "13.1.0" glob-parent "5.1.2" globby "11.1.0" - graceful-fs "4.2.10" + graceful-fs "4.2.11" has-unicode "2.0.1" - import-local "^3.0.2" - init-package-json "3.0.2" + import-local "3.1.0" + ini "^1.3.8" + init-package-json "5.0.0" inquirer "^8.2.4" - is-ci "2.0.0" + is-ci "3.0.1" is-stream "2.0.0" - js-yaml "^4.1.0" - libnpmaccess "^6.0.3" - libnpmpublish "7.1.4" + jest-diff ">=29.4.3 < 30" + js-yaml "4.1.0" + libnpmaccess "7.0.2" + libnpmpublish "7.3.0" load-json-file "6.2.0" - make-dir "3.1.0" + lodash "^4.17.21" + make-dir "4.0.0" minimatch "3.0.5" multimatch "5.0.0" node-fetch "2.6.7" npm-package-arg "8.1.1" npm-packlist "5.1.1" - npm-registry-fetch "^14.0.3" + npm-registry-fetch "^14.0.5" npmlog "^6.0.2" - nx ">=15.5.2 < 16" + nx ">=16.5.1 < 17" p-map "4.0.0" p-map-series "2.1.0" p-pipe "3.1.0" p-queue "6.6.2" p-reduce "2.1.0" p-waterfall "2.1.1" - pacote "15.1.1" + pacote "^15.2.0" pify "5.0.0" - read-cmd-shim "3.0.0" - read-package-json "5.0.1" + read-cmd-shim "4.0.0" + read-package-json "6.0.4" resolve-from "5.0.0" rimraf "^4.4.1" semver "^7.3.8" signal-exit "3.0.7" slash "3.0.0" - ssri "9.0.1" + ssri "^9.0.1" strong-log-transformer "2.1.0" tar "6.1.11" temp-dir "1.0.0" - typescript "^3 || ^4" - upath "^2.0.1" - uuid "8.3.2" + typescript ">=3 < 6" + upath "2.0.1" + uuid "^9.0.0" validate-npm-package-license "3.0.4" - validate-npm-package-name "4.0.0" - write-file-atomic "4.0.1" + validate-npm-package-name "5.0.0" + write-file-atomic "5.0.1" write-pkg "4.0.0" yargs "16.2.0" yargs-parser "20.2.4" @@ -14732,28 +13739,18 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -libnpmaccess@^6.0.3: - version "6.0.4" - resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-6.0.4.tgz#2dd158bd8a071817e2207d3b201d37cf1ad6ae6b" - integrity sha512-qZ3wcfIyUoW0+qSFkMBovcTrSGJ3ZeyvpR7d5N9pEYv/kXs8sHP2wiqEIXBKLFrZlmM0kR0RJD7mtfLngtlLag== +libnpmaccess@7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-7.0.2.tgz#7f056c8c933dd9c8ba771fa6493556b53c5aac52" + integrity sha512-vHBVMw1JFMTgEk15zRsJuSAg7QtGGHpUSEfnbcRL1/gTBag9iEfJbyjpDmdJmwMhvpoLoNBtdAUCdGnaP32hhw== dependencies: - aproba "^2.0.0" - minipass "^3.1.1" - npm-package-arg "^9.0.1" - npm-registry-fetch "^13.0.0" + npm-package-arg "^10.1.0" + npm-registry-fetch "^14.0.3" -libnpmpublish@7.1.4: - version "7.1.4" - resolved "https://registry.yarnpkg.com/libnpmpublish/-/libnpmpublish-7.1.4.tgz#a0d138e00e52a0c71ffc82273acf0082fc2dfb36" - integrity sha512-mMntrhVwut5prP4rJ228eEbEyvIzLWhqFuY90j5QeXBCTT2pWSMno7Yo2S2qplPUr02zPurGH4heGLZ+wORczg== +libnpmpublish@7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/libnpmpublish/-/libnpmpublish-7.3.0.tgz#2ceb2b36866d75a6cd7b4aa748808169f4d17e37" + integrity sha512-fHUxw5VJhZCNSls0KLNEG0mCD2PN1i14gH5elGOgiVnU3VgTcRahagYP2LKI1m0tFCJ+XrAm0zVYyF5RCbXzcg== dependencies: ci-info "^3.6.1" normalize-package-data "^5.0.0" @@ -15021,9 +14018,9 @@ lru-cache@^7.4.4, lru-cache@^7.5.1, lru-cache@^7.7.1: integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== "lru-cache@^9.1.1 || ^10.0.0": - version "10.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.0.tgz#b9e2a6a72a129d81ab317202d93c7691df727e61" - integrity sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw== + version "10.0.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.1.tgz#0a3be479df549cca0e5d693ac402ff19537a6b7a" + integrity sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g== lru-queue@^0.1.0: version "0.1.0" @@ -15061,19 +14058,19 @@ magic-string@^0.27.0: dependencies: "@jridgewell/sourcemap-codec" "^1.4.13" -magic-string@^0.30.0: - version "0.30.0" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.0.tgz#fd58a4748c5c4547338a424e90fa5dd17f4de529" - integrity sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ== +magic-string@^0.30.2: + version "0.30.3" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.3.tgz#403755dfd9d6b398dfa40635d52e96c5ac095b85" + integrity sha512-B7xGbll2fG/VjP+SWg4sX3JynwIU0mjoTc6MPpKNuIvftk6u6vqhDnk1R80b8C2GBR6ywqy+1DcKBrevBg+bmw== dependencies: - "@jridgewell/sourcemap-codec" "^1.4.13" + "@jridgewell/sourcemap-codec" "^1.4.15" -make-dir@3.1.0, make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== +make-dir@4.0.0, make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== dependencies: - semver "^6.0.0" + semver "^7.5.3" make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" @@ -15083,33 +14080,18 @@ make-dir@^2.0.0, make-dir@^2.1.0: pify "^4.0.1" semver "^5.6.0" +make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + make-error@1.x, make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== -make-fetch-happen@^10.0.6: - version "10.2.1" - resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz#f5e3835c5e9817b617f2770870d9492d28678164" - integrity sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w== - dependencies: - agentkeepalive "^4.2.1" - cacache "^16.1.0" - http-cache-semantics "^4.1.0" - http-proxy-agent "^5.0.0" - https-proxy-agent "^5.0.0" - is-lambda "^1.0.1" - lru-cache "^7.7.1" - minipass "^3.1.6" - minipass-collect "^1.0.2" - minipass-fetch "^2.0.3" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.4" - negotiator "^0.6.3" - promise-retry "^2.0.1" - socks-proxy-agent "^7.0.0" - ssri "^9.0.0" - make-fetch-happen@^11.0.0, make-fetch-happen@^11.0.1, make-fetch-happen@^11.0.3, make-fetch-happen@^11.1.1: version "11.1.1" resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz#85ceb98079584a9523d4bf71d32996e7e208549f" @@ -15448,7 +14430,7 @@ meow@^3.1.0: redent "^1.0.0" trim-newlines "^1.0.0" -meow@^8.0.0: +meow@^8.1.2: version "8.1.2" resolved "https://registry.yarnpkg.com/meow/-/meow-8.1.2.tgz#bcbe45bda0ee1729d350c03cffc8395a36c4e897" integrity sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q== @@ -15912,13 +14894,6 @@ minimatch@^5.0.1, minimatch@^5.1.0: dependencies: brace-expansion "^2.0.1" -minimatch@^6.1.6: - version "6.2.0" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-6.2.0.tgz#2b70fd13294178c69c04dfc05aebdb97a4e79e42" - integrity sha512-sauLxniAmvnhhRjFwPNnJKaPFYyddAgbYdeUpHULtCT/GhzdCx/MDNy+Y40lBxTQUrMzDE8e0S43Z5uqfO0REg== - dependencies: - brace-expansion "^2.0.1" - minimatch@^8.0.2: version "8.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-8.0.4.tgz#847c1b25c014d4e9a7f68aaf63dedd668a626229" @@ -15927,9 +14902,9 @@ minimatch@^8.0.2: brace-expansion "^2.0.1" minimatch@^9.0.0, minimatch@^9.0.1: - version "9.0.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.2.tgz#397e387fff22f6795844d00badc903a3d5de7057" - integrity sha512-PZOT9g5v2ojiTL7r1xF6plNHLtOeTpSlDI007As2NlA2aYBMfVom17yqa6QzhmDP8QOhn7LjHTg7DFCVSSa6yg== + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== dependencies: brace-expansion "^2.0.1" @@ -15954,23 +14929,12 @@ minipass-collect@^1.0.2: dependencies: minipass "^3.0.0" -minipass-fetch@^2.0.3: - version "2.1.2" - resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-2.1.2.tgz#95560b50c472d81a3bc76f20ede80eaed76d8add" - integrity sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA== - dependencies: - minipass "^3.1.6" - minipass-sized "^1.0.3" - minizlib "^2.1.2" - optionalDependencies: - encoding "^0.1.13" - minipass-fetch@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-3.0.3.tgz#d9df70085609864331b533c960fd4ffaa78d15ce" - integrity sha512-n5ITsTkDqYkYJZjcRWzZt9qnZKCT7nKCosJhHoj7S7zD+BP4jVbWs+odsniw5TA3E0sLomhTKOKjF86wf11PuQ== + version "3.0.4" + resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-3.0.4.tgz#4d4d9b9f34053af6c6e597a64be8e66e42bf45b7" + integrity sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg== dependencies: - minipass "^5.0.0" + minipass "^7.0.3" minipass-sized "^1.0.3" minizlib "^2.1.2" optionalDependencies: @@ -16005,14 +14969,14 @@ minipass-sized@^1.0.3: dependencies: minipass "^3.0.0" -minipass@^3.0.0, minipass@^3.1.1, minipass@^3.1.6: +minipass@^3.0.0, minipass@^3.1.1: version "3.3.6" resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== dependencies: yallist "^4.0.0" -minipass@^4.0.0, minipass@^4.2.4: +minipass@^4.2.4: version "4.2.8" resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.8.tgz#f0010f64393ecfc1d1ccb5f582bcaf45f48e1a3a" integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ== @@ -16022,10 +14986,10 @@ minipass@^5.0.0: resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== -"minipass@^5.0.0 || ^6.0.2": - version "6.0.2" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-6.0.2.tgz#542844b6c4ce95b202c0995b0a471f1229de4c81" - integrity sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w== +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.3.tgz#05ea638da44e475037ed94d1c7efcc76a25e1974" + integrity sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg== minizlib@^2.1.1, minizlib@^2.1.2: version "2.1.2" @@ -16064,15 +15028,6 @@ mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== -mkdirp-infer-owner@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mkdirp-infer-owner/-/mkdirp-infer-owner-2.0.0.tgz#55d3b368e7d89065c38f32fd38e638f0ab61d316" - integrity sha512-sdqtiFt3lkOaYvTXSRIUjkIdPTcxgv5+fgqYE/5qgwdw12cOrAuzzgzvVExIkH/ul1oeHN3bCLOWSG3XOqbKKw== - dependencies: - chownr "^2.0.0" - infer-owner "^1.0.4" - mkdirp "^1.0.3" - mkdirp@^0.5.1, mkdirp@^0.5.3: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" @@ -16112,7 +15067,7 @@ mocha@^10.0.0: yargs-parser "20.2.4" yargs-unparser "2.0.0" -modify-values@^1.0.0: +modify-values@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== @@ -16180,15 +15135,20 @@ multimatch@5.0.0: arrify "^2.0.1" minimatch "^3.0.4" -mute-stream@0.0.8, mute-stream@~0.0.4: +mute-stream@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== +mute-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e" + integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA== + nan@^2.12.1: - version "2.17.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" - integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== + version "2.18.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.18.0.tgz#26a6faae7ffbeb293a39660e88a76b82e30b7554" + integrity sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w== nanoclone@^0.2.1: version "0.2.1" @@ -16242,7 +15202,7 @@ negotiator@0.6.3, negotiator@^0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1, neo-async@^2.6.2: +neo-async@^2.5.0, neo-async@^2.6.1, neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== @@ -16271,9 +15231,9 @@ no-case@^3.0.4: tslib "^2.0.3" node-abi@^3.3.0: - version "3.45.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.45.0.tgz#f568f163a3bfca5aacfce1fbeee1fa2cc98441f5" - integrity sha512-iwXuFrMAcFVi/ZoZiqq8BzAdsLw9kxDfTC0HMyjXfSL/6CSDAGD5UmR7azrAgWV1zKYq7dUUMj4owusBWKLsiQ== + version "3.47.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.47.0.tgz#6cbfa2916805ae25c2b7156ca640131632eb05e8" + integrity sha512-2s6B2CWZM//kPgwnuI0KrYwNjfdByE25zvAaEpq9IH4zcNsarH8Ihu/UuX6XMPEogDAxkuUFeZn60pXNHAqn3A== dependencies: semver "^7.3.5" @@ -16312,9 +15272,9 @@ node-fetch@2.6.7: whatwg-url "^5.0.0" node-fetch@^2.6.1, node-fetch@^2.6.7: - version "2.6.11" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.11.tgz#cde7fc71deef3131ef80a738919f999e6edfff25" - integrity sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w== + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" @@ -16324,9 +15284,9 @@ node-forge@^1: integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== node-gyp-build@^4.3.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" - integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== + version "4.6.1" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.1.tgz#24b6d075e5e391b8d5539d98c7fc5c210cac8a3e" + integrity sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ== node-gyp@^9.0.0, node-gyp@^9.3.1: version "9.4.0" @@ -16379,10 +15339,10 @@ node-libs-browser@^2.2.1: util "^0.11.0" vm-browserify "^1.0.1" -node-releases@^2.0.12: - version "2.0.12" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.12.tgz#35627cc224a23bfb06fb3380f2b3afaaa7eb1039" - integrity sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ== +node-machine-id@1.1.12: + version "1.1.12" + resolved "https://registry.yarnpkg.com/node-machine-id/-/node-machine-id-1.1.12.tgz#37904eee1e59b320bb9c5d6c0a59f3b469cb6267" + integrity sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ== node-releases@^2.0.13: version "2.0.13" @@ -16428,13 +15388,6 @@ nopt@^6.0.0: dependencies: abbrev "^1.0.0" -nopt@^7.0.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-7.2.0.tgz#067378c68116f602f552876194fd11f1292503d7" - integrity sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA== - dependencies: - abbrev "^2.0.0" - nopt@~1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" @@ -16452,7 +15405,7 @@ normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package- semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" -normalize-package-data@^3.0.0: +normalize-package-data@^3.0.0, normalize-package-data@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e" integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA== @@ -16462,16 +15415,6 @@ normalize-package-data@^3.0.0: semver "^7.3.4" validate-npm-package-license "^3.0.1" -normalize-package-data@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-4.0.1.tgz#b46b24e0616d06cadf9d5718b29b6d445a82a62c" - integrity sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg== - dependencies: - hosted-git-info "^5.0.0" - is-core-module "^2.8.1" - semver "^7.3.5" - validate-npm-package-license "^3.0.4" - normalize-package-data@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-5.0.0.tgz#abcb8d7e724c40d88462b84982f7cbf6859b4588" @@ -16527,9 +15470,9 @@ npm-bundled@^3.0.0: npm-normalize-package-bin "^3.0.0" npm-install-checks@^6.0.0: - version "6.1.1" - resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-6.1.1.tgz#b459b621634d06546664207fde16810815808db1" - integrity sha512-dH3GmQL4vsPtld59cOn8uY0iOqRmqKvV+DLGwNXV/Q7MDgD2QfOADWd/mFXcIE5LVhYYGjA3baz6W9JneqnuCw== + version "6.2.0" + resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-6.2.0.tgz#fae55b9967b03ac309695ec96629492d5cedf371" + integrity sha512-744wat5wAAHsxa4590mWO0tJ8PKxR8ORZsH9wGpQc3nWTzozMAgBN/XyqYw7mg3yqLM8dLwEnwSfKMmXAjF69g== dependencies: semver "^7.1.1" @@ -16538,12 +15481,7 @@ npm-normalize-package-bin@^1.0.1: resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== -npm-normalize-package-bin@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz#9447a1adaaf89d8ad0abe24c6c84ad614a675fff" - integrity sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ== - -npm-normalize-package-bin@^3.0.0, npm-normalize-package-bin@^3.0.1: +npm-normalize-package-bin@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz#25447e32a9a7de1f51362c61a559233b89947832" integrity sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ== @@ -16567,16 +15505,6 @@ npm-package-arg@^10.0.0, npm-package-arg@^10.1.0: semver "^7.3.5" validate-npm-package-name "^5.0.0" -npm-package-arg@^9.0.1: - version "9.1.2" - resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-9.1.2.tgz#fc8acecb00235f42270dda446f36926ddd9ac2bc" - integrity sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg== - dependencies: - hosted-git-info "^5.0.0" - proc-log "^2.0.1" - semver "^7.3.5" - validate-npm-package-name "^4.0.0" - npm-packlist@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-5.1.1.tgz#79bcaf22a26b6c30aa4dd66b976d69cc286800e0" @@ -16594,43 +15522,17 @@ npm-packlist@^7.0.0: dependencies: ignore-walk "^6.0.0" -npm-pick-manifest@^8.0.0, npm-pick-manifest@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-8.0.1.tgz#c6acd97d1ad4c5dbb80eac7b386b03ffeb289e5f" - integrity sha512-mRtvlBjTsJvfCCdmPtiu2bdlx8d/KXtF7yNXNWe7G0Z36qWA9Ny5zXsI2PfBZEv7SXgoxTmNaTzGSbbzDZChoA== +npm-pick-manifest@^8.0.0: + version "8.0.2" + resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-8.0.2.tgz#2159778d9c7360420c925c1a2287b5a884c713aa" + integrity sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg== dependencies: npm-install-checks "^6.0.0" npm-normalize-package-bin "^3.0.0" npm-package-arg "^10.0.0" semver "^7.3.5" -npm-registry-fetch@14.0.3: - version "14.0.3" - resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-14.0.3.tgz#8545e321c2b36d2c6fe6e009e77e9f0e527f547b" - integrity sha512-YaeRbVNpnWvsGOjX2wk5s85XJ7l1qQBGAp724h8e2CZFFhMSuw9enom7K1mWVUtvXO1uUSFIAPofQK0pPN0ZcA== - dependencies: - make-fetch-happen "^11.0.0" - minipass "^4.0.0" - minipass-fetch "^3.0.0" - minipass-json-stream "^1.0.1" - minizlib "^2.1.2" - npm-package-arg "^10.0.0" - proc-log "^3.0.0" - -npm-registry-fetch@^13.0.0: - version "13.3.1" - resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-13.3.1.tgz#bb078b5fa6c52774116ae501ba1af2a33166af7e" - integrity sha512-eukJPi++DKRTjSBRcDZSDDsGqRK3ehbxfFUcgaRd0Yp6kRwOwh2WVn0r+8rMB4nnuzvAk6rQVzl6K5CkYOmnvw== - dependencies: - make-fetch-happen "^10.0.6" - minipass "^3.1.6" - minipass-fetch "^2.0.3" - minipass-json-stream "^1.0.1" - minizlib "^2.1.2" - npm-package-arg "^9.0.1" - proc-log "^2.0.0" - -npm-registry-fetch@^14.0.0, npm-registry-fetch@^14.0.3: +npm-registry-fetch@^14.0.0, npm-registry-fetch@^14.0.3, npm-registry-fetch@^14.0.5: version "14.0.5" resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-14.0.5.tgz#fe7169957ba4986a4853a650278ee02e568d115d" integrity sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA== @@ -16672,16 +15574,6 @@ npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -npmlog@6.0.2, npmlog@^6.0.0, npmlog@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830" - integrity sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg== - dependencies: - are-we-there-yet "^3.0.0" - console-control-strings "^1.1.0" - gauge "^4.0.3" - set-blocking "^2.0.0" - npmlog@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" @@ -16692,14 +15584,14 @@ npmlog@^5.0.1: gauge "^3.0.0" set-blocking "^2.0.0" -npmlog@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-7.0.1.tgz#7372151a01ccb095c47d8bf1d0771a4ff1f53ac8" - integrity sha512-uJ0YFk/mCQpLBt+bxN88AKd+gyqZvZDbtiNxk6Waqcj2aPRyfVx8ITawkyQynxUagInjdYT1+qj4NfA5KJJUxg== +npmlog@^6.0.0, npmlog@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830" + integrity sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg== dependencies: - are-we-there-yet "^4.0.0" + are-we-there-yet "^3.0.0" console-control-strings "^1.1.0" - gauge "^5.0.0" + gauge "^4.0.3" set-blocking "^2.0.0" nth-check@^2.0.1: @@ -16715,27 +15607,27 @@ num2fraction@^1.2.2: integrity sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg== nwsapi@^2.2.0: - version "2.2.5" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.5.tgz#a52744c61b3889dd44b0a158687add39b8d935e2" - integrity sha512-6xpotnECFy/og7tKSBVmUNft7J3jyXAka4XvG6AUhFWRz+Q/Ljus7znJAA3bxColfQLdS+XsjoodtJfCgeTEFQ== + version "2.2.7" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.7.tgz#738e0707d3128cb750dddcfe90e4610482df0f30" + integrity sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ== -nx@15.9.4, "nx@>=15.5.2 < 16": - version "15.9.4" - resolved "https://registry.yarnpkg.com/nx/-/nx-15.9.4.tgz#1075bc33fe8ee6c6546c21ec6ffcfd2e000946c6" - integrity sha512-P1G4t59UvE/lkHyruLeSOB5ZuNyh01IwU0tTUOi8f9s/NbP7+OQ8MYVwDV74JHTr6mQgjlS+n+4Eox8tVm9itA== +nx@16.8.1, "nx@>=16.5.1 < 17": + version "16.8.1" + resolved "https://registry.yarnpkg.com/nx/-/nx-16.8.1.tgz#b3b084da5f880c638debbefbf33eeccb96633595" + integrity sha512-K5KrwNdPz0eEe6SY5wrnhZcigjfIJkttPrIJRXNBQTE50NGcOfz1TjMXPdTWBxBCCua5PAealO3OrE8jpv+QnQ== dependencies: - "@nrwl/cli" "15.9.4" - "@nrwl/tao" "15.9.4" + "@nrwl/tao" "16.8.1" "@parcel/watcher" "2.0.4" "@yarnpkg/lockfile" "^1.1.0" - "@yarnpkg/parsers" "^3.0.0-rc.18" + "@yarnpkg/parsers" "3.0.0-rc.46" "@zkochan/js-yaml" "0.0.6" axios "^1.0.0" chalk "^4.1.0" cli-cursor "3.1.0" cli-spinners "2.6.1" cliui "^7.0.2" - dotenv "~10.0.0" + dotenv "~16.3.1" + dotenv-expand "~10.0.0" enquirer "~2.3.6" fast-glob "3.2.7" figures "3.2.0" @@ -16747,9 +15639,10 @@ nx@15.9.4, "nx@>=15.5.2 < 16": jsonc-parser "3.2.0" lines-and-columns "~2.0.3" minimatch "3.0.5" + node-machine-id "1.1.12" npm-run-path "^4.0.1" open "^8.4.0" - semver "7.3.4" + semver "7.5.3" string-width "^4.2.3" strong-log-transformer "^2.1.0" tar-stream "~2.2.0" @@ -16760,15 +15653,16 @@ nx@15.9.4, "nx@>=15.5.2 < 16": yargs "^17.6.2" yargs-parser "21.1.1" optionalDependencies: - "@nrwl/nx-darwin-arm64" "15.9.4" - "@nrwl/nx-darwin-x64" "15.9.4" - "@nrwl/nx-linux-arm-gnueabihf" "15.9.4" - "@nrwl/nx-linux-arm64-gnu" "15.9.4" - "@nrwl/nx-linux-arm64-musl" "15.9.4" - "@nrwl/nx-linux-x64-gnu" "15.9.4" - "@nrwl/nx-linux-x64-musl" "15.9.4" - "@nrwl/nx-win32-arm64-msvc" "15.9.4" - "@nrwl/nx-win32-x64-msvc" "15.9.4" + "@nx/nx-darwin-arm64" "16.8.1" + "@nx/nx-darwin-x64" "16.8.1" + "@nx/nx-freebsd-x64" "16.8.1" + "@nx/nx-linux-arm-gnueabihf" "16.8.1" + "@nx/nx-linux-arm64-gnu" "16.8.1" + "@nx/nx-linux-arm64-musl" "16.8.1" + "@nx/nx-linux-x64-gnu" "16.8.1" + "@nx/nx-linux-x64-musl" "16.8.1" + "@nx/nx-win32-arm64-msvc" "16.8.1" + "@nx/nx-win32-x64-msvc" "16.8.1" object-assign@^4.0.1, object-assign@^4.1.1: version "4.1.1" @@ -16820,41 +15714,51 @@ object.assign@^4.1.2, object.assign@^4.1.4: object-keys "^1.1.1" object.entries@^1.1.0, object.entries@^1.1.5, object.entries@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.6.tgz#9737d0e5b8291edd340a3e3264bb8a3b00d5fa23" - integrity sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w== + version "1.1.7" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.7.tgz#2b47760e2a2e3a752f39dd874655c61a7f03c131" + integrity sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" "object.fromentries@^2.0.0 || ^1.0.0", object.fromentries@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.6.tgz#cdb04da08c539cffa912dcd368b886e0904bfa73" - integrity sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg== + version "2.0.7" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616" + integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.2: - version "2.1.6" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz#5e5c384dd209fa4efffead39e3a0512770ccc312" - integrity sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ== + version "2.1.7" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.7.tgz#7a466a356cd7da4ba8b9e94ff6d35c3eeab5d56a" + integrity sha512-PrJz0C2xJ58FNn11XV2lr4Jt5Gzl94qpy9Lu0JlfEj14z88sqbSBJCBEzdlNUCzY2gburhbrwOZ5BHCmuNUy0g== dependencies: - array.prototype.reduce "^1.0.5" + array.prototype.reduce "^1.0.6" call-bind "^1.0.2" define-properties "^1.2.0" - es-abstract "^1.21.2" + es-abstract "^1.22.1" safe-array-concat "^1.0.0" +object.groupby@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.1.tgz#d41d9f3c8d6c778d9cbac86b4ee9f5af103152ee" + integrity sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + object.hasown@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.2.tgz#f919e21fad4eb38a57bc6345b3afd496515c3f92" - integrity sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw== + version "1.1.3" + resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.3.tgz#6a5f2897bb4d3668b8e79364f98ccf971bda55ae" + integrity sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA== dependencies: - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" object.pick@^1.3.0: version "1.3.0" @@ -16864,13 +15768,13 @@ object.pick@^1.3.0: isobject "^3.0.1" object.values@^1.1.0, object.values@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" - integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== + version "1.1.7" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a" + integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" objectorarray@^1.0.5: version "1.0.5" @@ -16925,19 +15829,7 @@ open@^8.0.0, open@^8.0.9, open@^8.4.0: is-docker "^2.1.1" is-wsl "^2.2.0" -optionator@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - -optionator@^0.9.1: +optionator@^0.9.1, optionator@^0.9.3: version "0.9.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== @@ -17147,31 +16039,7 @@ p-waterfall@2.1.1: dependencies: p-reduce "^2.0.0" -pacote@15.1.1: - version "15.1.1" - resolved "https://registry.yarnpkg.com/pacote/-/pacote-15.1.1.tgz#94d8c6e0605e04d427610b3aacb0357073978348" - integrity sha512-eeqEe77QrA6auZxNHIp+1TzHQ0HBKf5V6c8zcaYZ134EJe1lCi+fjXATkNiEEfbG+e50nu02GLvUtmZcGOYabQ== - dependencies: - "@npmcli/git" "^4.0.0" - "@npmcli/installed-package-contents" "^2.0.1" - "@npmcli/promise-spawn" "^6.0.1" - "@npmcli/run-script" "^6.0.0" - cacache "^17.0.0" - fs-minipass "^3.0.0" - minipass "^4.0.0" - npm-package-arg "^10.0.0" - npm-packlist "^7.0.0" - npm-pick-manifest "^8.0.0" - npm-registry-fetch "^14.0.0" - proc-log "^3.0.0" - promise-retry "^2.0.1" - read-package-json "^6.0.0" - read-package-json-fast "^3.0.0" - sigstore "^1.0.0" - ssri "^10.0.0" - tar "^6.1.11" - -pacote@^15.0.0, pacote@^15.0.8: +pacote@^15.2.0: version "15.2.0" resolved "https://registry.yarnpkg.com/pacote/-/pacote-15.2.0.tgz#0f0dfcc3e60c7b39121b2ac612bf8596e95344d3" integrity sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA== @@ -17247,15 +16115,6 @@ parse-author@^2.0.0: dependencies: author-regex "^1.0.0" -parse-conflict-json@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/parse-conflict-json/-/parse-conflict-json-3.0.1.tgz#67dc55312781e62aa2ddb91452c7606d1969960c" - integrity sha512-01TvEktc68vwbJOtWZluyWeVGWjP+bZwXtPDMQVbBKzbJ/vZBif0L69KH1+cHv1SZ6e0FKLvjyHe8mqsIqYOmw== - dependencies: - json-parse-even-better-errors "^3.0.0" - just-diff "^6.0.0" - just-diff-apply "^5.2.0" - parse-entities@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" @@ -17406,13 +16265,13 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-scurry@^1.10.0, path-scurry@^1.6.1: - version "1.10.0" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.0.tgz#0ffbd4c1f7de9600f98a1405507d9f9acb438ab3" - integrity sha512-tZFEaRQbMLjwrsmidsGJ6wDMv0iazJWk6SfIKnY4Xru8auXgmJkOBa5DUbYFcFD2Rzk2+KDlIiF0GVXNCbgC7g== +path-scurry@^1.10.1, path-scurry@^1.6.1: + version "1.10.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698" + integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ== dependencies: lru-cache "^9.1.1 || ^10.0.0" - minipass "^5.0.0 || ^6.0.2" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-to-regexp@0.1.7: version "0.1.7" @@ -17480,7 +16339,7 @@ pidtree@^0.3.0: resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a" integrity sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA== -pify@5.0.0, pify@^5.0.0: +pify@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f" integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA== @@ -18006,7 +16865,7 @@ postcss-reduce-transforms@^6.0.0: dependencies: postcss-value-parser "^4.2.0" -postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: +postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: version "6.0.13" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz#d05d8d76b1e8e173257ef9d60b706a8e5e99bf1b" integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ== @@ -18062,16 +16921,7 @@ postcss@^7.0.14, postcss@^7.0.26, postcss@^7.0.32, postcss@^7.0.36, postcss@^7.0 picocolors "^0.2.1" source-map "^0.6.1" -postcss@^8.2.15, postcss@^8.3.5, postcss@^8.4.21: - version "8.4.24" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.24.tgz#f714dba9b2284be3cc07dbd2fc57ee4dc972d2df" - integrity sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg== - dependencies: - nanoid "^3.3.6" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -postcss@^8.4.24: +postcss@^8.2.15, postcss@^8.3.5, postcss@^8.4.21, postcss@^8.4.24: version "8.4.29" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.29.tgz#33bc121cf3b3688d4ddef50be869b2a54185a1dd" integrity sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw== @@ -18103,11 +16953,6 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== - prettier-linter-helpers@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" @@ -18121,14 +16966,14 @@ prettier-linter-helpers@^1.0.0: integrity sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w== prettier@^2.8.7: - version "2.8.7" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.7.tgz#bb79fc8729308549d28fe3a98fce73d2c0656450" - integrity sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw== + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== pretty-bytes@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-6.1.0.tgz#1d1cc9aae1939012c74180b679da6684616bf804" - integrity sha512-Rk753HI8f4uivXi4ZCIYdhmG1V+WKzvRMg/X+M42a6t7D07RcmopXJMDNk6N++7Bl75URRGsb40ruvg7Hcp2wQ== + version "6.1.1" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-6.1.1.tgz#38cd6bb46f47afbf667c202cfc754bffd2016a3b" + integrity sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ== pretty-error@^2.1.1: version "2.1.2" @@ -18146,15 +16991,6 @@ pretty-error@^4.0.0: lodash "^4.17.20" renderkid "^3.0.0" -pretty-format@29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.4.3.tgz#25500ada21a53c9e8423205cf0337056b201244c" - integrity sha512-cvpcHTc42lcsvOOAzd3XuNWTcvk1Jmnzqeu+WsOuiPmxUJTnkbAcFNsRKvEpBEUFVUgy/GTZLulZDcDEi+CIlA== - dependencies: - "@jest/schemas" "^29.4.3" - ansi-styles "^5.0.0" - react-is "^18.0.0" - pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" @@ -18174,21 +17010,12 @@ pretty-format@^28.1.3: ansi-styles "^5.0.0" react-is "^18.0.0" -pretty-format@^29.0.0, pretty-format@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.5.0.tgz#283134e74f70e2e3e7229336de0e4fce94ccde5a" - integrity sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw== - dependencies: - "@jest/schemas" "^29.4.3" - ansi-styles "^5.0.0" - react-is "^18.0.0" - -pretty-format@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.6.1.tgz#ec838c288850b7c4f9090b867c2d4f4edbfb0f3e" - integrity sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog== +pretty-format@^29.0.0, pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== dependencies: - "@jest/schemas" "^29.6.0" + "@jest/schemas" "^29.6.3" ansi-styles "^5.0.0" react-is "^18.0.0" @@ -18197,11 +17024,6 @@ pretty-hrtime@^1.0.3: resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" integrity sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A== -proc-log@^2.0.0, proc-log@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-2.0.1.tgz#8f3f69a1f608de27878f91f5c688b225391cb685" - integrity sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw== - proc-log@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-3.0.0.tgz#fb05ef83ccd64fd7b20bbe9c8c1070fc08338dd8" @@ -18222,16 +17044,6 @@ progress@^2.0.0: resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -promise-all-reject-late@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz#f8ebf13483e5ca91ad809ccc2fcf25f26f8643c2" - integrity sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw== - -promise-call-limit@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/promise-call-limit/-/promise-call-limit-1.0.2.tgz#f64b8dd9ef7693c9c7613e7dfe8d6d24de3031ea" - integrity sha512-1vTUnfI2hzui8AEIixbdAJlFY4LFDXqQswy/2eOlThAscXCY4It8FdVuI0fMJGAB2aWGbdQf/gv0skKYXmdrHA== - promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" @@ -18246,25 +17058,25 @@ promise-retry@^2.0.1: retry "^0.12.0" promise.allsettled@^1.0.0: - version "1.0.6" - resolved "https://registry.yarnpkg.com/promise.allsettled/-/promise.allsettled-1.0.6.tgz#8dc8ba8edf429feb60f8e81335b920e109c94b6e" - integrity sha512-22wJUOD3zswWFqgwjNHa1965LvqTX87WPu/lreY2KSd7SVcERfuZ4GfUaOnJNnvtoIv2yXT/W00YIGMetXtFXg== + version "1.0.7" + resolved "https://registry.yarnpkg.com/promise.allsettled/-/promise.allsettled-1.0.7.tgz#b9dd51e9cffe496243f5271515652c468865f2d8" + integrity sha512-hezvKvQQmsFkOdrZfYxUxkyxl8mgFQeT259Ajj9PXdbg9VzBCWrItOev72JyWxkCD5VSSqAeHmlN3tWx4DlmsA== dependencies: array.prototype.map "^1.0.5" call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - get-intrinsic "^1.1.3" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" iterate-value "^1.0.2" promise.prototype.finally@^3.1.0: - version "3.1.4" - resolved "https://registry.yarnpkg.com/promise.prototype.finally/-/promise.prototype.finally-3.1.4.tgz#4e756a154e4db27fae24c6b18703495c31da3927" - integrity sha512-nNc3YbgMfLzqtqvO/q5DP6RR0SiHI9pUPGzyDf1q+usTwCN2kjvAnJkBb7bHe3o+fFSBPpsGMoYtaSi+LTNqng== + version "3.1.5" + resolved "https://registry.yarnpkg.com/promise.prototype.finally/-/promise.prototype.finally-3.1.5.tgz#94ba0a29f925e6da0709faddf85163cd8ed892c2" + integrity sha512-4TQ3Dk8yyUZGyU+UXInKdkQ2b6xtiBXAIScGAtGnXVmJtG1uOrxRgbF1ggIu72uzoWFzUfT3nUKa1SuMm9NBdg== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" prompts@^2.0.1, prompts@^2.4.0: version "2.4.2" @@ -18274,12 +17086,12 @@ prompts@^2.0.1, prompts@^2.4.0: kleur "^3.0.3" sisteransi "^1.0.5" -promzard@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz#26a5d6ee8c7dee4cb12208305acfb93ba382a9ee" - integrity sha512-JZeYqd7UAcHCwI+sTOeUDYkvEU+1bQ7iE0UT1MgB/tERkAPkesW46MrpIySzODi+owTjZtiF8Ay5j9m60KmMBw== +promzard@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/promzard/-/promzard-1.0.0.tgz#3246f8e6c9895a77c0549cefb65828ac0f6c006b" + integrity sha512-KQVDEubSUHGSt5xLakaToDFrSoZhStB8dXLzk2xvwR67gJktrHFvpR63oZgHyK19WKbHFLXJqCPXdVR3aBP8Ig== dependencies: - read "1" + read "^2.0.0" prop-types@^15.0.0, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" @@ -18303,19 +17115,14 @@ property-information@^5.0.0, property-information@^5.3.0: xtend "^4.0.0" property-information@^6.0.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.2.0.tgz#b74f522c31c097b5149e3c3cb8d7f3defd986a1d" - integrity sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg== - -proto-list@~1.2.1: - version "1.2.4" - resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" - integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA== + version "6.3.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.3.0.tgz#ba4a06ec6b4e1e90577df9931286953cdf4282c3" + integrity sha512-gVNZ74nqhRMiIUYWGQdosYetaKc83x8oT41a0LlV3AAFCAZwCpg4vmGkq8t34+cUhp3cnM4XDiU/7xlgK7HGrg== protobufjs@^6.8.8, protobufjs@~6.11.2, protobufjs@~6.11.3: - version "6.11.3" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.3.tgz#637a527205a35caa4f3e2a9a4a13ddffe0e7af74" - integrity sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg== + version "6.11.4" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.4.tgz#29a412c38bf70d89e537b6d02d904a6f448173aa" + integrity sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" @@ -18431,14 +17238,9 @@ punycode@^2.1.0, punycode@^2.1.1: integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== pure-rand@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.2.tgz#a9c2ddcae9b68d736a8163036f088a2781c8b306" - integrity sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ== - -q@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw== + version "6.0.3" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.3.tgz#3c9e6b53c09e52ac3cedffc85ab7c1c7094b38cb" + integrity sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w== qr.js@0.0.0: version "0.0.0" @@ -18461,7 +17263,7 @@ qs@6.11.0: dependencies: side-channel "^1.0.4" -qs@^6.10.0, qs@^6.11.0: +qs@^6.10.0, qs@^6.11.2: version "6.11.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== @@ -18483,6 +17285,11 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +queue-tick@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/queue-tick/-/queue-tick-1.0.1.tgz#f6f07ac82c1fd60f82e098b417a80e52f1f4c142" + integrity sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag== + quick-lru@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" @@ -18609,9 +17416,9 @@ react-google-charts@^3.0.15: react-load-script "^0.0.6" react-hook-form@^7.14.2: - version "7.45.1" - resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.45.1.tgz#e352c7f4dbc7540f0756abbb4dcfd1122fecc9bb" - integrity sha512-6dWoFJwycbuFfw/iKMcl+RdAOAOHDiF11KWYhNDRN/OkUt+Di5qsZHwA0OwsVnu9y135gkHpTw9DJA+WzCeR9w== + version "7.46.1" + resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.46.1.tgz#39347dbff19d980cb41087ac32a57abdc6045bb3" + integrity sha512-0GfI31LRTBd5tqbXMGXT1Rdsv3rnvy0FjEk8Gn9/4tp6+s77T7DPZuGEpBRXOauL+NhyGT5iaXzdIM2R6F/E+w== react-identicons@^1.2.5: version "1.2.5" @@ -18701,19 +17508,19 @@ react-resize-detector@^8.0.4: lodash "^4.17.21" react-router-dom@6, react-router-dom@^6.7.0: - version "6.14.0" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.14.0.tgz#7ce6c3f73549e4d40216ba150253d3bf30812b33" - integrity sha512-YEwlApKwzMMMbGbhh+Q7MsloTldcwMgHxUY/1g0uA62+B1hZo2jsybCWIDCL8zvIDB1FA0pBKY9chHbZHt+2dQ== + version "6.15.0" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.15.0.tgz#6da7db61e56797266fbbef0d5e324d6ac443ee40" + integrity sha512-aR42t0fs7brintwBGAv2+mGlCtgtFQeOzK0BM1/OiqEzRejOZtpMZepvgkscpMUnKb8YO84G7s3LsHnnDNonbQ== dependencies: - "@remix-run/router" "1.7.0" - react-router "6.14.0" + "@remix-run/router" "1.8.0" + react-router "6.15.0" -react-router@6.14.0: - version "6.14.0" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.14.0.tgz#1c3e8e922d934d43a253fd862c72c82167c0a7f1" - integrity sha512-OD+vkrcGbvlwkspUFDgMzsu1RXwdjNh83YgG/28lBnDzgslhCgxIqoExLlxsfTpIygp7fc+Hd3esloNwzkm2xA== +react-router@6.15.0: + version "6.15.0" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.15.0.tgz#bf2cb5a4a7ed57f074d4ea88db0d95033f39cac8" + integrity sha512-NIytlzvzLwJkCQj2HLefmeakxxWHWAP+02EGqWEZy+DgfHHKQMUoBBjUQLOtFInBMhWtb3hiUy6MfFgwLjXhqg== dependencies: - "@remix-run/router" "1.7.0" + "@remix-run/router" "1.8.0" react-simple-maps@^2.3.0: version "2.3.0" @@ -18726,17 +17533,17 @@ react-simple-maps@^2.3.0: topojson-client "^3.1.0" react-smooth@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/react-smooth/-/react-smooth-2.0.3.tgz#2845fa8f22914f2e4445856d5688fb8a7d72f3ae" - integrity sha512-yl4y3XiMorss7ayF5QnBiSprig0+qFHui8uh7Hgg46QX5O+aRMRKlfGGNGLHno35JkQSvSYY8eCWkBfHfrSHfg== + version "2.0.4" + resolved "https://registry.yarnpkg.com/react-smooth/-/react-smooth-2.0.4.tgz#95187126265970a1490e2aea5690365203ee555f" + integrity sha512-OkFsrrMBTvQUwEJthE1KXSOj79z57yvEWeFefeXPib+RmQEI9B1Ub1PgzlzzUyBOvl/TjXt5nF2hmD4NsgAh8A== dependencies: fast-equals "^5.0.0" react-transition-group "2.9.0" react-tooltip@*: - version "5.16.1" - resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-5.16.1.tgz#dafb42170c50d93eaa06e26581ba8e6f7ceb2c48" - integrity sha512-z3IKJppX4llW8wQLQB3o5qUutVul79HVXI+Ncjf/5FMHbniCYPnxS1oCLpOhOEG9lV2QZRrQe9+l/pLEPOrrXA== + version "5.21.3" + resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-5.21.3.tgz#131d578c7ea69f96c65dbd09f071880c34b4f83d" + integrity sha512-z3Q+Uka4D6uYxfsssPqfx1W8vw7NIHyC2ZMq+NJkWg4EpUD3w7Fwz/o+dezyUQMCHL7nO/2sFbtWIrkyxktq2Q== dependencies: "@floating-ui/dom" "^1.0.0" classnames "^2.3.0" @@ -18776,25 +17583,12 @@ react@^18.2.0: dependencies: loose-envify "^1.1.0" -read-cmd-shim@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-3.0.0.tgz#62b8c638225c61e6cc607f8f4b779f3b8238f155" - integrity sha512-KQDVjGqhZk92PPNRj9ZEXEuqg8bUobSKRw+q0YQ3TKI5xkce7bUJobL4Z/OtiEbAAv70yEpYIXp4iQ9L8oPVog== - -read-cmd-shim@^4.0.0: +read-cmd-shim@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz#640a08b473a49043e394ae0c7a34dd822c73b9bb" integrity sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q== -read-package-json-fast@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz#323ca529630da82cb34b36cc0b996693c98c2b83" - integrity sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ== - dependencies: - json-parse-even-better-errors "^2.3.0" - npm-normalize-package-bin "^1.0.1" - -read-package-json-fast@^3.0.0, read-package-json-fast@^3.0.2: +read-package-json-fast@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz#394908a9725dc7a5f14e70c8e7556dff1d2b1049" integrity sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw== @@ -18802,27 +17596,7 @@ read-package-json-fast@^3.0.0, read-package-json-fast@^3.0.2: json-parse-even-better-errors "^3.0.0" npm-normalize-package-bin "^3.0.0" -read-package-json@5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-5.0.1.tgz#1ed685d95ce258954596b13e2e0e76c7d0ab4c26" - integrity sha512-MALHuNgYWdGW3gKzuNMuYtcSSZbGQm94fAp16xt8VsYTLBjUSc55bLMKe6gzpWue0Tfi6CBgwCSdDAqutGDhMg== - dependencies: - glob "^8.0.1" - json-parse-even-better-errors "^2.3.1" - normalize-package-data "^4.0.0" - npm-normalize-package-bin "^1.0.1" - -read-package-json@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-5.0.2.tgz#b8779ccfd169f523b67208a89cc912e3f663f3fa" - integrity sha512-BSzugrt4kQ/Z0krro8zhTwV1Kd79ue25IhNN/VtHFy1mG/6Tluyi+msc0UpwaoQzxSHa28mntAjIZY6kEgfR9Q== - dependencies: - glob "^8.0.1" - json-parse-even-better-errors "^2.3.1" - normalize-package-data "^4.0.0" - npm-normalize-package-bin "^2.0.0" - -read-package-json@^6.0.0: +read-package-json@6.0.4, read-package-json@^6.0.0: version "6.0.4" resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-6.0.4.tgz#90318824ec456c287437ea79595f4c2854708836" integrity sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw== @@ -18885,12 +17659,12 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -read@1, read@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" - integrity sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ== +read@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/read/-/read-2.1.0.tgz#69409372c54fe3381092bc363a00650b6ac37218" + integrity sha512-bvxi1QLJHcaywCAEsAk4DG3nVoqiY2Csps3qzWalhj5hFqRn1d/OixkFXtLO1PrgHUcAP0FNaSY/5GYNfENFFQ== dependencies: - mute-stream "~0.0.4" + mute-stream "~1.0.0" "readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.8" @@ -18914,16 +17688,6 @@ readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stre string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^4.1.0: - version "4.4.1" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.4.1.tgz#fa0f0878c3bc0c12b6a82e4e58c5dc160e1faaa2" - integrity sha512-llAHX9QC25bz5RPIoTeJxPaA/hgryaldValRhVZ2fK9bzbmFiscpz8fw6iBTvJfAk1w4FC1KXQme/nO7fbKyKg== - dependencies: - abort-controller "^3.0.0" - buffer "^6.0.3" - events "^3.3.0" - process "^0.11.10" - readdirp@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" @@ -18953,9 +17717,9 @@ recharts-scale@^0.4.4: decimal.js-light "^2.4.1" recharts@^2.1.13: - version "2.7.2" - resolved "https://registry.yarnpkg.com/recharts/-/recharts-2.7.2.tgz#6d813681910ad33a4bbf3bdd06c6f64f20b39319" - integrity sha512-HMKRBkGoOXHW+7JcRa6+MukPSifNtJlqbc+JreGVNA407VLE/vOP+8n3YYjprDVVIF9E2ZgwWnL3D7K/LUFzBg== + version "2.8.0" + resolved "https://registry.yarnpkg.com/recharts/-/recharts-2.8.0.tgz#90c95136e2cb6930224c94a51adce607701284fc" + integrity sha512-nciXqQDh3aW8abhwUlA4EBOBusRHLNiKHfpRZiG/yjups1x+auHb2zWPuEcTn/IMiN47vVMMuF8Sr+vcQJtsmw== dependencies: classnames "^2.2.5" eventemitter3 "^4.0.1" @@ -19005,6 +17769,18 @@ reduce-css-calc@^2.1.8: css-unit-converter "^1.1.1" postcss-value-parser "^3.3.0" +reflect.getprototypeof@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz#aaccbf41aca3821b87bb71d9dcbc7ad0ba50a3f3" + integrity sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + globalthis "^1.0.3" + which-builtin-type "^1.1.3" + regenerate-unicode-properties@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" @@ -19017,17 +17793,15 @@ regenerate@^1.4.2: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== -regenerator-runtime@^0.13.11, regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.7: +regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.7: version "0.13.11" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== -regenerator-transform@^0.15.1: - version "0.15.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56" - integrity sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg== - dependencies: - "@babel/runtime" "^7.8.4" +regenerator-runtime@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" + integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== regenerator-transform@^0.15.2: version "0.15.2" @@ -19044,14 +17818,14 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexp.prototype.flags@^1.4.3, regexp.prototype.flags@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb" - integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA== +regexp.prototype.flags@^1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e" + integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg== dependencies: call-bind "^1.0.2" define-properties "^1.2.0" - functions-have-names "^1.2.3" + set-function-name "^2.0.0" regexpp@^3.1.0: version "3.2.0" @@ -19297,12 +18071,12 @@ resolve.exports@^2.0.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== -resolve@^1.10.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.3.2, resolve@^1.9.0: - version "1.22.2" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" - integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== +resolve@^1.10.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.22.4, resolve@^1.3.2, resolve@^1.9.0: + version "1.22.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" + integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== dependencies: - is-core-module "^2.11.0" + is-core-module "^2.13.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -19385,13 +18159,13 @@ rollup-plugin-base64@^1.0.1: "@rollup/pluginutils" "^3.1.0" rollup-plugin-dts@^5.0.0, rollup-plugin-dts@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-dts/-/rollup-plugin-dts-5.3.0.tgz#80a95988002f188e376f6db3b7e2f53679168957" - integrity sha512-8FXp0ZkyZj1iU5klkIJYLjIq/YZSwBoERu33QBDxm/1yw5UU4txrEtcmMkrq+ZiKu3Q4qvPCNqc3ovX6rjqzbQ== + version "5.3.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-dts/-/rollup-plugin-dts-5.3.1.tgz#c2841269a3a5cb986b7791b0328e6a178eba108f" + integrity sha512-gusMi+Z4gY/JaEQeXnB0RUdU82h1kF0WYzCWgVmV4p3hWXqelaKuCvcJawfeg+EKn2T1Ie+YWF2OiN1/L8bTVg== dependencies: - magic-string "^0.30.0" + magic-string "^0.30.2" optionalDependencies: - "@babel/code-frame" "^7.18.6" + "@babel/code-frame" "^7.22.5" rollup-plugin-inject@^3.0.0: version "3.0.2" @@ -19422,9 +18196,9 @@ rollup-pluginutils@^2.8.1: estree-walker "^0.6.1" rollup@^3.17.2, rollup@^3.2.1, rollup@^3.9.1: - version "3.25.3" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.25.3.tgz#f9a8986f0f244bcfde2208da91ba46b8fd252551" - integrity sha512-ZT279hx8gszBj9uy5FfhoG4bZx8c+0A1sbqtr7Q3KNWIizpTdDEPZbV2xcbvHsnFp4MavCQYZyzApJ+virB8Yw== + version "3.29.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.1.tgz#ba53a179d46ac3cd79e162dca6ab70d93cd26f78" + integrity sha512-c+ebvQz0VIH4KhhCpDsI+Bik0eT8ZFEVZEYw0cGMVqIP8zc+gnwl7iXCamTw7vzv2MeuZFZfdx5JJIq+ehzDlg== optionalDependencies: fsevents "~2.3.2" @@ -19467,12 +18241,12 @@ sade@^1.7.3: mri "^1.1.0" safe-array-concat@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060" - integrity sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ== + version "1.0.1" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.1.tgz#91686a63ce3adbea14d61b14c99572a8ff84754c" + integrity sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q== dependencies: call-bind "^1.0.2" - get-intrinsic "^1.2.0" + get-intrinsic "^1.2.1" has-symbols "^1.0.3" isarray "^2.0.5" @@ -19605,48 +18379,29 @@ selfsigned@^2.1.1: node-forge "^1" "semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@7.3.4: - version "7.3.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" - integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== - dependencies: - lru-cache "^6.0.0" - -semver@7.3.8: - version "7.3.8" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" - integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== - dependencies: - lru-cache "^6.0.0" + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@7.x, semver@^7.0.0, semver@^7.1.1, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.0: +semver@7.5.3: version "7.5.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.5.3: +semver@7.x, semver@^7.0.0, semver@^7.1.1, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" +semver@^6.0.0, semver@^6.1.2, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + semver@~7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" @@ -19738,6 +18493,14 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== +set-function-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.0.tgz#e59e53e7fa23f9c2da1c0999fa202d5ed09c4756" + integrity sha512-WmS8UHojv5s1eSoRSmzO5zzgDq8PE1/X/ij0k+9fMYmINCc6+j+SF3Om8YyucKn2yjnK4ItNZOoQycNnHsZJTw== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" @@ -19792,18 +18555,18 @@ sharp@^0.29.1: tar-fs "^2.1.1" tunnel-agent "^0.6.0" -sharp@^0.32.0: - version "0.32.1" - resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.32.1.tgz#41aa0d0b2048b2e0ee453d9fcb14ec1f408390fe" - integrity sha512-kQTFtj7ldpUqSe8kDxoGLZc1rnMFU0AO2pqbX6pLy3b7Oj8ivJIdoKNwxHVQG2HN6XpHPJqCSM2nsma2gOXvOg== +sharp@^0.32.4: + version "0.32.5" + resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.32.5.tgz#9ddc78ead6446094f51e50355a2d4ec6e7220cd4" + integrity sha512-0dap3iysgDkNaPOaOL4X/0akdu0ma62GcdC2NBQ+93eqpePdDdr2/LM0sFdDSMmN7yS+odyZtPsb7tx/cYBKnQ== dependencies: color "^4.2.3" - detect-libc "^2.0.1" + detect-libc "^2.0.2" node-addon-api "^6.1.0" prebuild-install "^7.1.1" - semver "^7.5.0" + semver "^7.5.4" simple-get "^4.0.1" - tar-fs "^2.1.1" + tar-fs "^3.0.4" tunnel-agent "^0.6.0" shebang-command@^1.2.0: @@ -19845,9 +18608,9 @@ shiki@^0.10.1: vscode-textmate "5.2.0" shiki@^0.14.1: - version "0.14.3" - resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.14.3.tgz#d1a93c463942bdafb9866d74d619a4347d0bbf64" - integrity sha512-U3S/a+b0KS+UkTyMjoNojvTgrBHjgp7L6ovhFVZsXmBGnVdQ4K4U9oK0z63w538S91ATngv1vXigHCSWOwnr+g== + version "0.14.4" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.14.4.tgz#2454969b466a5f75067d0f2fa0d7426d32881b20" + integrity sha512-IXCRip2IQzKwxArNNq1S+On4KPML3Yyn8Zzs/xRgcgOWIr8ntIK3IKzjFPfjy/7kt9ZMjc+FItfqHRBg8b6tNQ== dependencies: ansi-sequence-parser "^1.1.0" jsonc-parser "^3.2.0" @@ -19869,19 +18632,20 @@ signal-exit@3.0.7, signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, s integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== signal-exit@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.0.2.tgz#ff55bb1d9ff2114c13b400688fa544ac63c36967" - integrity sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q== + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== -sigstore@^1.0.0, sigstore@^1.3.0, sigstore@^1.4.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/sigstore/-/sigstore-1.6.0.tgz#887a4007c6ee83f3ef3fd844be1a0840e849c301" - integrity sha512-QODKff/qW/TXOZI6V/Clqu74xnInAS6it05mufj4/fSewexLtfEntgLZZcBtUK44CDQyUE5TUXYy1ARYzlfG9g== +sigstore@^1.3.0, sigstore@^1.4.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/sigstore/-/sigstore-1.9.0.tgz#1e7ad8933aa99b75c6898ddd0eeebc3eb0d59875" + integrity sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A== dependencies: - "@sigstore/protobuf-specs" "^0.1.0" - "@sigstore/tuf" "^1.0.0" + "@sigstore/bundle" "^1.1.0" + "@sigstore/protobuf-specs" "^0.2.0" + "@sigstore/sign" "^1.0.0" + "@sigstore/tuf" "^1.0.3" make-fetch-happen "^11.0.1" - tuf-js "^1.1.3" simple-concat@^1.0.0: version "1.0.1" @@ -20153,14 +18917,14 @@ split-string@^3.0.1, split-string@^3.0.2: dependencies: extend-shallow "^3.0.0" -split2@^3.0.0: +split2@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f" integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg== dependencies: readable-stream "^3.0.0" -split@^1.0.0: +split@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== @@ -20172,19 +18936,12 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== -ssri@9.0.1, ssri@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-9.0.1.tgz#544d4c357a8d7b71a19700074b6883fcb4eae057" - integrity sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q== - dependencies: - minipass "^3.1.1" - ssri@^10.0.0, ssri@^10.0.1: - version "10.0.4" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.4.tgz#5a20af378be586df139ddb2dfb3bf992cf0daba6" - integrity sha512-12+IR2CB2C28MMAw0Ncqwj5QbTcs0nGIhgJzYWzDkb21vWmfNI83KS4f3Ci6GI98WreIfG7o9UXp3C0qbpA8nQ== + version "10.0.5" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.5.tgz#e49efcd6e36385196cb515d3a2ad6c3f0265ef8c" + integrity sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A== dependencies: - minipass "^5.0.0" + minipass "^7.0.3" ssri@^6.0.1: version "6.0.2" @@ -20200,6 +18957,13 @@ ssri@^8.0.1: dependencies: minipass "^3.1.1" +ssri@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-9.0.1.tgz#544d4c357a8d7b71a19700074b6883fcb4eae057" + integrity sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q== + dependencies: + minipass "^3.1.1" + stable@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" @@ -20284,6 +19048,14 @@ stream-shift@^1.0.0: resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== +streamx@^2.15.0: + version "2.15.1" + resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.15.1.tgz#396ad286d8bc3eeef8f5cea3f029e81237c024c6" + integrity sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA== + dependencies: + fast-fifo "^1.1.0" + queue-tick "^1.0.1" + string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -20323,63 +19095,64 @@ string-width@^5.0.1, string-width@^5.1.2: strip-ansi "^7.0.1" "string.prototype.matchall@^4.0.0 || ^3.0.1", string.prototype.matchall@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz#3bf85722021816dcd1bf38bb714915887ca79fd3" - integrity sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg== + version "4.0.10" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz#a1553eb532221d4180c51581d6072cd65d1ee100" + integrity sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - get-intrinsic "^1.1.3" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" has-symbols "^1.0.3" - internal-slot "^1.0.3" - regexp.prototype.flags "^1.4.3" + internal-slot "^1.0.5" + regexp.prototype.flags "^1.5.0" + set-function-name "^2.0.0" side-channel "^1.0.4" string.prototype.padend@^3.0.0: - version "3.1.4" - resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.4.tgz#2c43bb3a89eb54b6750de5942c123d6c98dd65b6" - integrity sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw== + version "3.1.5" + resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.5.tgz#311ef3a4e3c557dd999cdf88fbdde223f2ac0f95" + integrity sha512-DOB27b/2UTTD+4myKUFh+/fXWcu/UDyASIXfg+7VzoCNNGOfWvoyU/x5pvVHr++ztyt/oSYI1BcWBBG/hmlNjA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" string.prototype.padstart@^3.0.0: - version "3.1.4" - resolved "https://registry.yarnpkg.com/string.prototype.padstart/-/string.prototype.padstart-3.1.4.tgz#4842d58a09df2addac23cf0b325ce9f087978e90" - integrity sha512-XqOHj8horGsF+zwxraBvMTkBFM28sS/jHBJajh17JtJKA92qazidiQbLosV4UA18azvLOVKYo/E3g3T9Y5826w== + version "3.1.5" + resolved "https://registry.yarnpkg.com/string.prototype.padstart/-/string.prototype.padstart-3.1.5.tgz#ce435e145e4d68b701d1db51cb546ba100177d98" + integrity sha512-R57IsE3JIfModQWrVXYZ8ZHWMBNDpIoniDwhYCR1nx+iHwDkjjk26a8xM9BYgf7SAXJO7sdNPng5J+0ccr5LFQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" string.prototype.trim@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" - integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== + version "1.2.8" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz#f9ac6f8af4bd55ddfa8895e6aea92a96395393bd" + integrity sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" string.prototype.trimend@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" - integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== + version "1.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz#1bb3afc5008661d73e2dc015cd4853732d6c471e" + integrity sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" string.prototype.trimstart@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" - integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== + version "1.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz#d4cdb44b83a4737ffbac2d406e405d43d0184298" + integrity sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" @@ -20513,9 +19286,9 @@ style-to-object@0.3.0, style-to-object@^0.3.0: inline-style-parser "0.1.1" style-to-object@^0.4.0, style-to-object@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.4.1.tgz#53cf856f7cf7f172d72939d9679556469ba5de37" - integrity sha512-HFpbb5gr2ypci7Qw+IOhnP2zOU7e77b+rzM+wTzXzfi1PrtBCX0E7Pk4wL4iTLnhzZ+JgEGAhX81ebTg/aYjQw== + version "0.4.2" + resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.4.2.tgz#a8247057111dea8bd3b8a1a66d2d0c9cf9218a54" + integrity sha512-1JGpfPB3lo42ZX8cuPrheZbfQ6kqPPnPHlKMyeRYtfKD+0jG+QsXgXN57O/dvJlzlB2elI6dGmrPnl5VPQFPaA== dependencies: inline-style-parser "0.1.1" @@ -20665,6 +19438,15 @@ tar-fs@^2.0.0, tar-fs@^2.1.1: pump "^3.0.0" tar-stream "^2.1.4" +tar-fs@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.0.4.tgz#a21dc60a2d5d9f55e0089ccd78124f1d3771dbbf" + integrity sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w== + dependencies: + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^3.1.5" + tar-stream@^2.1.4, tar-stream@~2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" @@ -20676,6 +19458,15 @@ tar-stream@^2.1.4, tar-stream@~2.2.0: inherits "^2.0.3" readable-stream "^3.1.1" +tar-stream@^3.1.5: + version "3.1.6" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-3.1.6.tgz#6520607b55a06f4a2e2e04db360ba7d338cc5bab" + integrity sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg== + dependencies: + b4a "^1.6.4" + fast-fifo "^1.2.0" + streamx "^2.15.0" + tar@6.1.11: version "6.1.11" resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" @@ -20689,9 +19480,9 @@ tar@6.1.11: yallist "^4.0.0" tar@^6.0.2, tar@^6.1.11, tar@^6.1.2: - version "6.1.15" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.15.tgz#c9738b0b98845a3b344d334b8fa3041aaba53a69" - integrity sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A== + version "6.2.0" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.0.tgz#b14ce49a79cb1cd23bc9b016302dea5474493f73" + integrity sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ== dependencies: chownr "^2.0.0" fs-minipass "^2.0.0" @@ -20714,10 +19505,10 @@ telejson@^6.0.8: lodash "^4.17.21" memoizerific "^1.11.3" -telejson@^7.0.3: - version "7.1.0" - resolved "https://registry.yarnpkg.com/telejson/-/telejson-7.1.0.tgz#1ef7a0dd57eeb52cde933126f61bcc296c170f52" - integrity sha512-jFJO4P5gPebZAERPkJsqMAQ0IMA1Hi0AoSfxpnUaV6j6R2SZqlpkbS20U6dEUtA3RUYt2Ak/mTlkQzHH9Rv/hA== +telejson@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/telejson/-/telejson-7.2.0.tgz#3994f6c9a8f8d7f2dba9be2c7c5bbb447e876f32" + integrity sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ== dependencies: memoizerific "^1.11.3" @@ -20726,22 +19517,6 @@ temp-dir@1.0.0: resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" integrity sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ== -temp-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" - integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg== - -tempy@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/tempy/-/tempy-1.0.0.tgz#4f192b3ee3328a2684d0e3fc5c491425395aab65" - integrity sha512-eLXG5B1G0mRPHmgH2WydPl5v4jH35qEn3y/rA/aahKhIa91Pn119SsU7n7v/433gtT9ONzC8ISvNHIh2JSTm0w== - dependencies: - del "^6.0.0" - is-stream "^2.0.0" - temp-dir "^2.0.0" - type-fest "^0.16.0" - unique-string "^2.0.0" - terminal-link@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" @@ -20801,9 +19576,9 @@ terser@^4.1.2, terser@^4.6.3: source-map-support "~0.5.12" terser@^5.10.0, terser@^5.15.1, terser@^5.16.8, terser@^5.3.4: - version "5.18.2" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.18.2.tgz#ff3072a0faf21ffd38f99acc9a0ddf7b5f07b948" - integrity sha512-Ah19JS86ypbJzTzvUCX7KOsEIhDaRONungA4aYBjEP3JZRf4ocuDzTg4QWZnPn9DEMiMYGJPiSOy7aykoCc70w== + version "5.19.4" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.19.4.tgz#941426fa482bf9b40a0308ab2b3cd0cf7c775ebd" + integrity sha512-6p1DjHeuluwxDXcuT9VR8p64klWJKo1ILiy19s6C9+0Bh2+NWTX6nD9EPppiER4ICkHDVB1RkVpin/YW2nQn/g== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.8.2" @@ -20863,7 +19638,7 @@ through2@^2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" -through2@^4.0.0, through2@^4.0.2: +through2@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/through2/-/through2-4.0.2.tgz#a7ce3ac2a7a8b0b966c80e7c49f0484c3b239764" integrity sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw== @@ -20900,6 +19675,11 @@ tiny-case@^1.0.3: resolved "https://registry.yarnpkg.com/tiny-case/-/tiny-case-1.0.3.tgz#d980d66bc72b5d5a9ca86fb7c9ffdb9c898ddd03" integrity sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q== +tiny-invariant@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" + integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== + tiny-warning@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" @@ -21012,11 +19792,6 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== -treeverse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/treeverse/-/treeverse-3.0.0.tgz#dd82de9eb602115c6ebd77a574aae67003cb48c8" - integrity sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ== - trim-lines@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338" @@ -21160,7 +19935,7 @@ tsconfig-paths-webpack-plugin@^4.1.0: enhanced-resolve "^5.7.0" tsconfig-paths "^4.1.2" -tsconfig-paths@^3.14.1, tsconfig-paths@^3.5.0, tsconfig-paths@^3.9.0: +tsconfig-paths@^3.14.2, tsconfig-paths@^3.5.0, tsconfig-paths@^3.9.0: version "3.14.2" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g== @@ -21190,9 +19965,9 @@ tslib@^1.8.1, tslib@^1.9.3: integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0, "tslib@^2.4.1 || ^1.9.3": - version "2.6.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.0.tgz#b295854684dbda164e181d259a22cd779dcd7bc3" - integrity sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA== + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== tsutils@^3.21.0: version "3.21.0" @@ -21206,7 +19981,7 @@ tty-browserify@0.0.0: resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" integrity sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw== -tuf-js@^1.1.3: +tuf-js@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/tuf-js/-/tuf-js-1.1.7.tgz#21b7ae92a9373015be77dfe0cb282a80ec3bbe43" integrity sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg== @@ -21239,23 +20014,11 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== - dependencies: - prelude-ls "~1.1.2" - type-detect@4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -type-fest@^0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.16.0.tgz#3240b891a78b0deae910dbeb86553e552a148860" - integrity sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg== - type-fest@^0.18.0: version "0.18.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" @@ -21309,6 +20072,36 @@ type@^2.7.2: resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== +typed-array-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" + integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + is-typed-array "^1.1.10" + +typed-array-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" + integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" + integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== + 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" + typed-array-length@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" @@ -21351,7 +20144,12 @@ typedoc@^0.24.8: minimatch "^9.0.0" shiki "^0.14.1" -"typescript@^3 || ^4", typescript@^4.6.2, typescript@^4.8.4: +"typescript@>=3 < 6": + version "5.2.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" + integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== + +typescript@^4.6.2, typescript@^4.8.4: version "4.9.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== @@ -21454,13 +20252,6 @@ unique-filename@^1.1.1: dependencies: unique-slug "^2.0.0" -unique-filename@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-2.0.1.tgz#e785f8675a9a7589e0ac77e0b5c34d2eaeac6da2" - integrity sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A== - dependencies: - unique-slug "^3.0.0" - unique-filename@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-3.0.0.tgz#48ba7a5a16849f5080d26c760c86cf5cf05770ea" @@ -21475,13 +20266,6 @@ unique-slug@^2.0.0: dependencies: imurmurhash "^0.1.4" -unique-slug@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-3.0.0.tgz#6d347cf57c8a7a7a6044aabd0e2d74e4d76dc7c9" - integrity sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w== - dependencies: - imurmurhash "^0.1.4" - unique-slug@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-4.0.0.tgz#6bae6bb16be91351badd24cdce741f892a6532e3" @@ -21489,13 +20273,6 @@ unique-slug@^4.0.0: dependencies: imurmurhash "^0.1.4" -unique-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" - integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== - dependencies: - crypto-random-string "^2.0.0" - unist-builder@2.0.3, unist-builder@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-2.0.3.tgz#77648711b5d86af0942f334397a33c5e91516436" @@ -21647,7 +20424,7 @@ untildify@^2.0.0: dependencies: os-homedir "^1.0.0" -upath@2.0.1, upath@^2.0.1: +upath@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/upath/-/upath-2.0.1.tgz#50c73dea68d6f6b990f51d279ce6081665d61a8b" integrity sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w== @@ -21695,12 +20472,12 @@ url-parse@^1.5.3: requires-port "^1.0.0" url@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.1.tgz#26f90f615427eca1b9f4d6a28288c147e2302a32" - integrity sha512-rWS3H04/+mzzJkv0eZ7vEDGiQbgquI1fGfOad6zKvgYQi1SzMmhl7c/DdRGxhaWrVH6z0qWITo8rpnxK/RfEhA== + version "0.11.2" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.2.tgz#02f250a6e0d992b781828cd456d44f49bf2e19dd" + integrity sha512-7yIgNnrST44S7PJ5+jXbdIupfU1nWUdQJBFBeJRclPXiWgCvrSq5Frw8lr/i//n5sqDfzoKmBymMS81l4U/7cg== dependencies: punycode "^1.4.1" - qs "^6.11.0" + qs "^6.11.2" use-clipboard-copy@^0.2.0: version "0.2.0" @@ -21727,12 +20504,12 @@ util.promisify@1.0.0: define-properties "^1.1.2" object.getownpropertydescriptors "^2.0.3" -util@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ== +util@^0.10.4: + version "0.10.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" + integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== dependencies: - inherits "2.0.1" + inherits "2.0.3" util@^0.11.0: version "0.11.1" @@ -21756,11 +20533,6 @@ uuid-browser@^3.1.0: resolved "https://registry.yarnpkg.com/uuid-browser/-/uuid-browser-3.1.0.tgz#0f05a40aef74f9e5951e20efbf44b11871e56410" integrity sha512-dsNgbLaTrd6l3MMxTtouOCFw4CBFc/3a+GgYA2YyrJvyQ1u6q4pcu3ktLoUZ/VN/Aw9WsauazbgsgdfVWgAKQg== -uuid@8.3.2, uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - uuid@^3.3.2: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" @@ -21771,6 +20543,16 @@ uuid@^7.0.3: resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +uuid@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + uvu@^0.5.0: version "0.5.6" resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.6.tgz#2754ca20bcb0bb59b64e9985e84d2e81058502df" @@ -21786,11 +20568,16 @@ v8-compile-cache-lib@^3.0.1: resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== -v8-compile-cache@2.3.0, v8-compile-cache@^2.0.3: +v8-compile-cache@2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== +v8-compile-cache@^2.0.3: + version "2.4.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz#cdada8bec61e15865f05d097c5f4fd30e94dc128" + integrity sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw== + v8-to-istanbul@^8.1.0: version "8.1.1" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed" @@ -21817,10 +20604,10 @@ validate-npm-package-license@3.0.4, validate-npm-package-license@^3.0.1, validat spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -validate-npm-package-name@4.0.0, validate-npm-package-name@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz#fe8f1c50ac20afdb86f177da85b3600f0ac0d747" - integrity sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q== +validate-npm-package-name@5.0.0, validate-npm-package-name@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz#f16afd48318e6f90a1ec101377fa0384cfc8c713" + integrity sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ== dependencies: builtins "^5.0.0" @@ -21831,13 +20618,6 @@ validate-npm-package-name@^3.0.0: dependencies: builtins "^1.0.3" -validate-npm-package-name@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz#f16afd48318e6f90a1ec101377fa0384cfc8c713" - integrity sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ== - dependencies: - builtins "^5.0.0" - vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -21950,11 +20730,6 @@ w3c-xmlserializer@^2.0.0: dependencies: xml-name-validator "^3.0.0" -walk-up-path@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/walk-up-path/-/walk-up-path-1.0.0.tgz#d4745e893dd5fd0dbb58dd0a4c6a33d9c9fec53e" - integrity sha512-hwj/qMDUEjCU5h0xr90KGCf0tg0/LgJbmOWgrWKYlcJZM7XvquvUJZ0G/HMGr7F7OQMOUuPHWP9JpriinkAlkg== - walker@^1.0.7, walker@^1.0.8, walker@~1.0.5: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" @@ -22192,9 +20967,9 @@ webpack-virtual-modules@^0.4.1: integrity sha512-5tyDlKLqPfMqjT3Q9TAqf2YqjwmnUleZwzJi1A5qXnlBCdj2AtOJ6wAWdglTIDOPgOiOrXeBeFcsQ8+aGQ6QbA== webpack@4: - version "4.46.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542" - integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q== + version "4.47.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.47.0.tgz#8b8a02152d7076aeb03b61b47dad2eeed9810ebc" + integrity sha512-td7fYwgLSrky3fI1EuU5cneU4+pbH6GgOfuKNS1tNPcfdGinGELAqsb/BP4nnvZyKSG2i/xFGU7+n2PvZA8HJQ== dependencies: "@webassemblyjs/ast" "1.9.0" "@webassemblyjs/helper-module-context" "1.9.0" @@ -22220,37 +20995,7 @@ webpack@4: watchpack "^1.7.4" webpack-sources "^1.4.1" -"webpack@>=4.43.0 <6.0.0", webpack@^5.75.0, webpack@^5.9.0: - version "5.88.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.88.1.tgz#21eba01e81bd5edff1968aea726e2fbfd557d3f8" - integrity sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ== - dependencies: - "@types/eslint-scope" "^3.7.3" - "@types/estree" "^1.0.0" - "@webassemblyjs/ast" "^1.11.5" - "@webassemblyjs/wasm-edit" "^1.11.5" - "@webassemblyjs/wasm-parser" "^1.11.5" - acorn "^8.7.1" - acorn-import-assertions "^1.9.0" - browserslist "^4.14.5" - chrome-trace-event "^1.0.2" - enhanced-resolve "^5.15.0" - es-module-lexer "^1.2.1" - eslint-scope "5.1.1" - events "^3.2.0" - glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" - json-parse-even-better-errors "^2.3.1" - loader-runner "^4.2.0" - mime-types "^2.1.27" - neo-async "^2.6.2" - schema-utils "^3.2.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.3.7" - watchpack "^2.4.0" - webpack-sources "^3.2.3" - -webpack@^5.88.2: +"webpack@>=4.43.0 <6.0.0", webpack@^5.75.0, webpack@^5.88.2, webpack@^5.9.0: version "5.88.2" resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.88.2.tgz#f62b4b842f1c6ff580f3fcb2ed4f0b579f4c210e" integrity sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ== @@ -22334,6 +21079,24 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" +which-builtin-type@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.3.tgz#b1b8443707cc58b6e9bf98d32110ff0c2cbd029b" + integrity sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw== + dependencies: + function.prototype.name "^1.1.5" + has-tostringtag "^1.0.0" + is-async-function "^2.0.0" + is-date-object "^1.0.5" + is-finalizationregistry "^1.0.2" + is-generator-function "^1.0.10" + is-regex "^1.1.4" + is-weakref "^1.0.2" + isarray "^2.0.5" + which-boxed-primitive "^1.0.2" + which-collection "^1.0.1" + which-typed-array "^1.1.9" + which-collection@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906" @@ -22344,17 +21107,16 @@ which-collection@^1.0.1: is-weakmap "^2.0.1" is-weakset "^2.0.1" -which-typed-array@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" - integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== +which-typed-array@^1.1.10, which-typed-array@^1.1.11, which-typed-array@^1.1.9: + version "1.1.11" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a" + integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew== dependencies: available-typed-arrays "^1.0.5" call-bind "^1.0.2" for-each "^0.3.3" gopd "^1.0.1" has-tostringtag "^1.0.0" - is-typed-array "^1.1.10" which@^1.2.9: version "1.3.1" @@ -22396,11 +21158,6 @@ wildcard@^2.0.0: resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== -word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - wordwrap@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" @@ -22434,6 +21191,15 @@ workerpool@6.2.1: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^6.0.1: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -22448,13 +21214,13 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -write-file-atomic@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.1.tgz#9faa33a964c1c85ff6f849b80b42a88c2c537c8f" - integrity sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ== +write-file-atomic@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-5.0.1.tgz#68df4717c55c6fa4281a7860b4c2ba0a6d2b11e7" + integrity sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw== dependencies: imurmurhash "^0.1.4" - signal-exit "^3.0.7" + signal-exit "^4.0.1" write-file-atomic@^2.4.2: version "2.4.3" @@ -22483,14 +21249,6 @@ write-file-atomic@^4.0.2: imurmurhash "^0.1.4" signal-exit "^3.0.7" -write-file-atomic@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-5.0.1.tgz#68df4717c55c6fa4281a7860b4c2ba0a6d2b11e7" - integrity sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw== - dependencies: - imurmurhash "^0.1.4" - signal-exit "^4.0.1" - write-json-file@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-3.2.0.tgz#65bbdc9ecd8a1458e15952770ccbadfcff5fe62a" @@ -22518,9 +21276,9 @@ ws@^7, ws@^7.4.6: integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== ws@^8.13.0, ws@^8.2.3: - version "8.13.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" - integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== + version "8.14.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.1.tgz#4b9586b4f70f9e6534c7bb1d3dc0baa8b8cf01e0" + integrity sha512-4OOseMUq8AzRBI/7SLMUwO+FEDnguetSk7KMb1sHwvF2w2Wv5Hoj0nlifx8vtGsftE/jWHojPy8sMMzYLJ2G/A== ws@~8.11.0: version "8.11.0" @@ -22547,10 +21305,10 @@ xml2js@^0.4.23: sax ">=0.6.0" xmlbuilder "~11.0.0" -xml2js@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" - integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== +xml2js@^0.6.1: + version "0.6.2" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" + integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== dependencies: sax ">=0.6.0" xmlbuilder "~11.0.0" @@ -22613,9 +21371,9 @@ yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== yaml@^2.0.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b" - integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ== + version "2.3.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.2.tgz#f522db4313c671a0ca963a75670f1c12ea909144" + integrity sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg== yargs-parser@20.2.4: version "20.2.4"