diff --git a/.drone.yml b/.drone.yml
index df3e313fc7..d66e3de853 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -53,10 +53,10 @@ steps:
- cp /usr/local/bin/mina cli/bin/
- name: build
- image: rust:1.80-bullseye
+ image: rust:1.83-bullseye
commands:
- apt-get update && apt-get install -y libssl-dev libjemalloc-dev jq protobuf-compiler
- - rustup update 1.80 && rustup default 1.80
+ - rustup update 1.83 && rustup default 1.83
- rustup component add rustfmt
# just to be sure it builds without errors
- cargo build
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index b3b835dfd8..2e728f7d8f 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -43,6 +43,81 @@ jobs:
cd ledger
cargo test --release -- -Z unstable-options --report-time
+ ledger-32x9-tests:
+ runs-on: ubuntu-20.04
+ steps:
+ - name: Git checkout
+ uses: actions/checkout@v4
+ - name: Setup build dependencies
+ run: |
+ sudo apt update
+ sudo apt install -y protobuf-compiler
+ - name: Setup Rust
+ run: |
+ # Nightly to be able to use `--report-time` below
+ rustup install nightly
+ rustup override set nightly
+ - name: Download circuits files
+ run: |
+ git clone --depth 1 https://github.com/openmina/circuit-blobs.git
+ ln -s -b $PWD/circuit-blobs/* ledger/
+ - name: Enable 32x9 fields implementation
+ run: |
+ cargo install sd
+ sd '^mina-curves.*$' '' ./Cargo.toml
+ sd '^ark-ff = \{ version .*$' '' ./Cargo.toml
+ sd -F '# UNCOMMENTED_IN_CI ' '' ./Cargo.toml
+ cat ./Cargo.toml
+ - name: Build ledger tests
+ run: |
+ cd ledger
+ cargo build --release --tests
+ - name: Run ledger tests
+ run: |
+ cd ledger
+ cargo test --release -- -Z unstable-options --report-time
+
+ vrf-tests:
+ runs-on: ubuntu-20.04
+ steps:
+ - name: Git checkout
+ uses: actions/checkout@v4
+ - name: Setup build dependencies
+ run: |
+ sudo apt update
+ sudo apt install -y protobuf-compiler
+ - name: Setup Rust
+ run: |
+ # Nightly to be able to use `--report-time` below
+ rustup install nightly
+ rustup override set nightly
+ - name: Build vrf tests
+ run: |
+ cd vrf
+ cargo build --release --tests
+ - name: Run vrf tests
+ run: |
+ cd vrf
+ cargo test --release -- -Z unstable-options --report-time
+
+ tx-fuzzer-check:
+ runs-on: ubuntu-20.04
+ steps:
+ - name: Git checkout
+ uses: actions/checkout@v4
+ - name: Setup build dependencies
+ run: |
+ sudo apt update
+ sudo apt install -y protobuf-compiler
+ - name: Setup Rust
+ run: |
+ rustup install nightly
+ rustup override set nightly
+ - name: Check for compilation errors in transaction fuzzer
+ run: |
+ cd tools/fuzzing
+ cargo check
+
p2p-tests:
runs-on: ubuntu-20.04
steps:
@@ -56,7 +131,7 @@ jobs:
- name: Setup Rust
run: |
- rustup default 1.80
+ rustup default 1.83
rustup component add rustfmt
- name: Setup Rust Cache
@@ -82,7 +157,7 @@ jobs:
- name: Setup Rust
run: |
- rustup default 1.80
+ rustup default 1.83
rustup component add rustfmt
- name: Setup Rust Cache
@@ -142,7 +217,7 @@ jobs:
- name: Setup Rust
run: |
- rustup default 1.80
+ rustup default 1.83
rustup component add rustfmt
- name: Setup Rust Cache
@@ -178,7 +253,7 @@ jobs:
- name: Setup Rust
run: |
- rustup default 1.80
+ rustup default 1.83
rustup component add rustfmt
- name: Setup Rust Cache
@@ -259,15 +334,15 @@ jobs:
# TODO: query cluster for actual addresses, or specify then on deployment
env:
PEERS: |
- /ip4/135.181.217.23/tcp/31881/p2p/12D3KooWS4TMSjrAS4Cj31PgjZ9KgeHh5goLP65M5GSriF28d7Jx
- /ip4/135.181.217.23/tcp/30386/p2p/12D3KooWK92cYz26JqBE9vM9s9Jd9pJKcNxLd7VVRupU7YG5NupU
- /ip4/135.181.217.23/tcp/32272/p2p/12D3KooWSU1DYZYVA7wAYLvLsH6yVS8oV1sMJUcC7VtUxCgtsWkJ
- /ip4/135.181.217.23/tcp/32218/p2p/12D3KooWM5m9QqHpDkPJi54GPP6rGFpzo7E274husrModPSLQ7tn
- /ip4/135.181.217.23/tcp/30798/p2p/12D3KooWCk2QSmQH2XbtpDXiSPUq6wb2LB2JaExHRXkJggmEfN4J
- /ip4/135.181.217.23/tcp/31631/p2p/12D3KooWQ1642Dzm57Kr8tmTwS9NRFaJPy4ysaQ2ne3ZYwQn5qCk
- /ip4/135.181.217.23/tcp/30196/p2p/12D3KooWHK67syE2LeTz5EnNqCe5ZFf9SoZRFN4AdHVZsL31WkMn
- /ip4/135.181.217.23/tcp/30790/p2p/12D3KooWDwxrG5u12FzXAFyK7vd8aHnEQf4dwoboBJ72FUS179xK
- /ip4/135.181.217.23/tcp/30070/p2p/12D3KooWEowA3VakSddUjZuBTK3HJhNM7sRqwWDbqtPtwymAMCcy
+ /dns4/primary-tcp-proxy.hz.minaprotocol.network/tcp/40101/p2p/12D3KooWNGY3guz8pYHrVEqs8se4MSnnmpgguyQYDazMbVCyrMnS
+ /dns4/primary-tcp-proxy.hz.minaprotocol.network/tcp/40102/p2p/12D3KooWSqZ4qtysb8Du4yVpcc5SYc3gsRuNqgMomggw6hekATWg
+ /dns4/primary-tcp-proxy.hz.minaprotocol.network/tcp/40103/p2p/12D3KooWSHiGavQpamDPEc6rPaqT4PoS1Lr9aDfrfg5dKM2V6x3H
+ /dns4/primary-tcp-proxy.hz.minaprotocol.network/tcp/40104/p2p/12D3KooWA3yPrTaLXsggVSCG4mr7c33YNdz5DSs87LszRUVt9vLT
+ /dns4/primary-tcp-proxy.hz.minaprotocol.network/tcp/40105/p2p/12D3KooWCLcUWCdU4VstETztxE3feQyS57dVDdzBhmkj5tiCaha8
+ /dns4/primary-tcp-proxy.hz.minaprotocol.network/tcp/40106/p2p/12D3KooWNZWqEoCuhMrc9tTMxtEsfxmeFhjh2agUcmzJFNKxQnNA
+ /dns4/primary-tcp-proxy.hz.minaprotocol.network/tcp/40107/p2p/12D3KooWAMSP94SM3icSeAXeBmPUuZ5JvwrZ5w87fpRHVeJkdboe
+ /dns4/primary-tcp-proxy.hz.minaprotocol.network/tcp/40108/p2p/12D3KooWL5gPf5CrARVPhBi6KsDHmB1gsJKZ4vWrcLweWyMjpB5e
+ /dns4/primary-tcp-proxy.hz.minaprotocol.network/tcp/40109/p2p/12D3KooWT1nNJLGE8jWcshPSq3FmSXmmNn2MzfmvJcWYZ1HrtHnZ
outputs:
peers: ${{ steps.peers.outputs.peers }}
steps:
@@ -296,7 +371,7 @@ jobs:
# TODO: remove when replayer supports identify
KEEP_CONNECTION_WITH_UNKNOWN_STREAM: true
OPENMINA_SCENARIO_SEEDS: ${{ needs.k8s-peers.outputs.peers }}
- REPLAYER_MULTIADDR: "/dns4/1.k8.openmina.com/tcp/31968/p2p/12D3KooWPayQEdprqY2m3biReUUybA5LoULpJE7YWu6wetEKKELv"
+ REPLAYER_MULTIADDR: "/dns4/primary-tcp-proxy.hz.minaprotocol.network/tcp/40110/p2p/12D3KooWPayQEdprqY2m3biReUUybA5LoULpJE7YWu6wetEKKELv"
BPF_ALIAS: /coda/0.0.1/29936104443aaf264a7f0192ac64b1c7173198c1ed404c1bcff5e562e05eb7f6-0.0.0.0
strategy:
matrix:
@@ -333,7 +408,7 @@ jobs:
with:
pattern: tests*
merge-multiple: true
-
+
- name: Download tests
uses: actions/download-artifact@v4
with:
@@ -399,7 +474,7 @@ jobs:
env:
PEERS_LIST: ${{ needs.k8s-peers.outputs.peers }}
PEER_LIST_FILE: peer-list.txt
- WORK_DIR: data
+ OPENMINA_HOME: data
BPF_ALIAS: /coda/0.0.1/29936104443aaf264a7f0192ac64b1c7173198c1ed404c1bcff5e562e05eb7f6-0.0.0.0
services:
@@ -444,7 +519,7 @@ jobs:
env:
OPENMINA_COMMAND: openmina
NO_PEER_DISCOVERY: "true"
- OUT_PATH: ${{ env.WORK_DIR }}/logs/bootstrap_output
+ OUT_PATH: ${{ env.OPENMINA_HOME }}/logs/bootstrap_output
RECORD: state-with-input-actions
run: |
mkdir -p $OUT_PATH
@@ -459,14 +534,14 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: bootstrap-logs
- path: ${{ env.WORK_DIR }}/logs/*
+ path: ${{ env.OPENMINA_HOME }}/logs/*
if: ${{ failure() }}
- name: Upload record
uses: actions/upload-artifact@v4
with:
name: bootstrap-record
- path: ${{ env.WORK_DIR }}/recorder/*
+ path: ${{ env.OPENMINA_HOME }}/recorder/*
if: ${{ failure() }}
- name: Archive network debugger database
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 39bda33630..a45a0d70d4 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -17,7 +17,7 @@ jobs:
sudo apt install -y protobuf-compiler
- uses: actions-rs/toolchain@v1
with:
- toolchain: 1.81
+ toolchain: 1.83
components: rustfmt, clippy
default: true
- uses: actions-rs/cargo@v1
diff --git a/.gitignore b/.gitignore
index 053699847a..a8e606eb62 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
/target
/node/testing/res/
+.DS_Store
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8cb675141a..6ff4a9cf2d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+## [0.12.0] - 2024-12-04
+
+### Fixed
+
+- Properly handle time in cases in which the system goes to sleep.
+- Various corner cases in block proof production.
+- Improved ledgers sync during bootstrap (be smarter about which peers to query).
+- **P2P**: More efficient memory usage when managing the p2p state.
+- **P2P**: Lower outgoing traffic by being more conservative about what is broadcasted to each peer.
+- **P2P**: Better handling of disconnections.
+- **VRF**: Correctly handle cases in which the delegator table is empty.
+- **Webnode**: Peer connection handling improvements.
+
+### Changed
+
+- **Webnode**: Reduced startup time by loading prover indexes in parallel to the bootstrap process.
+- **Webnode**: Faster field operations (faster hashing and proving).
+- Improved hashing performance by caching and reusing common prefixes.
+- Added more pre-validation checks for blocks received from the network.
+
+### Added
+
+- **Webnode**: Transaction propagation
+- **P2P**: Support for specifying the external ip to be advertised.
+
## [0.11.0] - 2024-10-31
### Added
@@ -305,24 +330,25 @@ First public release.
- Alpha version of the node which can connect and syncup to the berkeleynet network, and keep applying new blocks to maintain consensus state and ledger up to date.
- Web-based frontend for the node.
-[Unreleased]: https://github.com/openmina/openmina/compare/v0.11.0...develop
-[0.11.0]: https://github.com/openmina/openmina/releases/tag/v0.10.3...v0.11.0
-[0.10.3]: https://github.com/openmina/openmina/releases/tag/v0.10.0...v0.10.3
-[0.10.0]: https://github.com/openmina/openmina/releases/tag/v0.9.0...v0.10.0
-[0.9.0]: https://github.com/openmina/openmina/releases/tag/v0.8.14...v0.9.0
-[0.8.14]: https://github.com/openmina/openmina/releases/tag/v0.8.13...v0.8.14
-[0.8.13]: https://github.com/openmina/openmina/releases/tag/v0.8.3...v0.8.13
-[0.8.3]: https://github.com/openmina/openmina/releases/tag/v0.8.2...v0.8.3
-[0.8.2]: https://github.com/openmina/openmina/releases/tag/v0.8.1...v0.8.2
-[0.8.1]: https://github.com/openmina/openmina/releases/tag/v0.8.0...v0.8.1
-[0.8.0]: https://github.com/openmina/openmina/releases/tag/v0.7.0...v0.8.0
-[0.7.0]: https://github.com/openmina/openmina/releases/tag/v0.6.0...v0.7.0
-[0.6.0]: https://github.com/openmina/openmina/releases/tag/v0.5.1...v0.6.0
-[0.5.1]: https://github.com/openmina/openmina/releases/tag/v0.5.0...v0.5.1
-[0.5.0]: https://github.com/openmina/openmina/releases/tag/v0.4.0...v0.5.0
-[0.4.0]: https://github.com/openmina/openmina/releases/tag/v0.3.0...v0.4.0
-[0.3.1]: https://github.com/openmina/openmina/releases/tag/v0.3.0...v0.3.1
-[0.3.0]: https://github.com/openmina/openmina/releases/tag/v0.2.0...v0.3.0
-[0.2.0]: https://github.com/openmina/openmina/releases/tag/v0.1.0...v0.2.0
-[0.1.0]: https://github.com/openmina/openmina/releases/tag/v0.0.1...v0.1.0
+[Unreleased]: https://github.com/openmina/openmina/compare/v0.12.0...develop
+[0.12.0]: https://github.com/openmina/openmina/compare/v0.11.0...v0.12.0
+[0.11.0]: https://github.com/openmina/openmina/compare/v0.10.3...v0.11.0
+[0.10.3]: https://github.com/openmina/openmina/compare/v0.10.0...v0.10.3
+[0.10.0]: https://github.com/openmina/openmina/compare/v0.9.0...v0.10.0
+[0.9.0]: https://github.com/openmina/openmina/compare/v0.8.14...v0.9.0
+[0.8.14]: https://github.com/openmina/openmina/compare/v0.8.13...v0.8.14
+[0.8.13]: https://github.com/openmina/openmina/compare/v0.8.3...v0.8.13
+[0.8.3]: https://github.com/openmina/openmina/compare/v0.8.2...v0.8.3
+[0.8.2]: https://github.com/openmina/openmina/compare/v0.8.1...v0.8.2
+[0.8.1]: https://github.com/openmina/openmina/compare/v0.8.0...v0.8.1
+[0.8.0]: https://github.com/openmina/openmina/compare/v0.7.0...v0.8.0
+[0.7.0]: https://github.com/openmina/openmina/compare/v0.6.0...v0.7.0
+[0.6.0]: https://github.com/openmina/openmina/compare/v0.5.1...v0.6.0
+[0.5.1]: https://github.com/openmina/openmina/compare/v0.5.0...v0.5.1
+[0.5.0]: https://github.com/openmina/openmina/compare/v0.4.0...v0.5.0
+[0.4.0]: https://github.com/openmina/openmina/compare/v0.3.0...v0.4.0
+[0.3.1]: https://github.com/openmina/openmina/compare/v0.3.0...v0.3.1
+[0.3.0]: https://github.com/openmina/openmina/compare/v0.2.0...v0.3.0
+[0.2.0]: https://github.com/openmina/openmina/compare/v0.1.0...v0.2.0
+[0.1.0]: https://github.com/openmina/openmina/compare/v0.0.1...v0.1.0
[0.0.1]: https://github.com/openmina/openmina/releases/tag/v0.0.1
diff --git a/Cargo.lock b/Cargo.lock
index 7350cf9a1f..a8bb229c4d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -242,7 +242,7 @@ dependencies = [
[[package]]
name = "ark-ec"
version = "0.3.0"
-source = "git+https://github.com/openmina/algebra?rev=33a1de2#33a1de22d36af53bd9169475195d9a6ea809bd5b"
+source = "git+https://github.com/openmina/algebra?rev=d0343f5#d0343f56c517675d2c340d066727d470ce22d552"
dependencies = [
"ark-ff",
"ark-serialize 0.3.0",
@@ -256,7 +256,7 @@ dependencies = [
[[package]]
name = "ark-ff"
version = "0.3.0"
-source = "git+https://github.com/openmina/algebra?rev=33a1de2#33a1de22d36af53bd9169475195d9a6ea809bd5b"
+source = "git+https://github.com/openmina/algebra?rev=d0343f5#d0343f56c517675d2c340d066727d470ce22d552"
dependencies = [
"ark-ff-asm",
"ark-ff-macros",
@@ -274,7 +274,7 @@ dependencies = [
[[package]]
name = "ark-ff-asm"
version = "0.3.0"
-source = "git+https://github.com/openmina/algebra?rev=33a1de2#33a1de22d36af53bd9169475195d9a6ea809bd5b"
+source = "git+https://github.com/openmina/algebra?rev=d0343f5#d0343f56c517675d2c340d066727d470ce22d552"
dependencies = [
"quote",
"syn 1.0.109",
@@ -283,7 +283,7 @@ dependencies = [
[[package]]
name = "ark-ff-macros"
version = "0.3.0"
-source = "git+https://github.com/openmina/algebra?rev=33a1de2#33a1de22d36af53bd9169475195d9a6ea809bd5b"
+source = "git+https://github.com/openmina/algebra?rev=d0343f5#d0343f56c517675d2c340d066727d470ce22d552"
dependencies = [
"num-bigint",
"num-traits",
@@ -294,7 +294,7 @@ dependencies = [
[[package]]
name = "ark-poly"
version = "0.3.0"
-source = "git+https://github.com/openmina/algebra?rev=33a1de2#33a1de22d36af53bd9169475195d9a6ea809bd5b"
+source = "git+https://github.com/openmina/algebra?rev=d0343f5#d0343f56c517675d2c340d066727d470ce22d552"
dependencies = [
"ark-ff",
"ark-serialize 0.3.0",
@@ -307,7 +307,7 @@ dependencies = [
[[package]]
name = "ark-serialize"
version = "0.3.0"
-source = "git+https://github.com/openmina/algebra?rev=33a1de2#33a1de22d36af53bd9169475195d9a6ea809bd5b"
+source = "git+https://github.com/openmina/algebra?rev=d0343f5#d0343f56c517675d2c340d066727d470ce22d552"
dependencies = [
"ark-serialize-derive",
"ark-std 0.3.0",
@@ -328,7 +328,7 @@ dependencies = [
[[package]]
name = "ark-serialize-derive"
version = "0.3.0"
-source = "git+https://github.com/openmina/algebra?rev=33a1de2#33a1de22d36af53bd9169475195d9a6ea809bd5b"
+source = "git+https://github.com/openmina/algebra?rev=d0343f5#d0343f56c517675d2c340d066727d470ce22d552"
dependencies = [
"proc-macro2",
"quote",
@@ -535,7 +535,7 @@ version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d9a9bf8b79a749ee0b911b91b671cc2b6c670bdbc7e3dfd537576ddc94bb2a2"
dependencies = [
- "http",
+ "http 0.2.9",
"log",
"url",
]
@@ -571,18 +571,19 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "axum"
-version = "0.6.20"
+version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf"
+checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf"
dependencies = [
"async-trait",
"axum-core",
- "bitflags 1.3.2",
"bytes",
"futures-util",
- "http",
- "http-body",
- "hyper",
+ "http 1.1.0",
+ "http-body 1.0.1",
+ "http-body-util",
+ "hyper 1.5.0",
+ "hyper-util",
"itoa",
"matchit",
"memchr",
@@ -594,28 +595,33 @@ dependencies = [
"serde_json",
"serde_path_to_error",
"serde_urlencoded",
- "sync_wrapper",
+ "sync_wrapper 1.0.1",
"tokio",
"tower",
"tower-layer",
"tower-service",
+ "tracing",
]
[[package]]
name = "axum-core"
-version = "0.3.4"
+version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c"
+checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199"
dependencies = [
"async-trait",
"bytes",
"futures-util",
- "http",
- "http-body",
+ "http 1.1.0",
+ "http-body 1.0.1",
+ "http-body-util",
"mime",
+ "pin-project-lite",
"rustversion",
+ "sync_wrapper 1.0.1",
"tower-layer",
"tower-service",
+ "tracing",
]
[[package]]
@@ -1036,7 +1042,7 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]]
name = "cli"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"anyhow",
"bytes",
@@ -2387,7 +2393,7 @@ dependencies = [
[[package]]
name = "groupmap"
version = "0.1.0"
-source = "git+https://github.com/openmina/proof-systems?rev=2fdb5a7#2fdb5a75c61e2ac1db452bd813aa12fd9fb77527"
+source = "git+https://github.com/openmina/proof-systems?rev=c478b19#c478b197ddb7fcefee87c4cfdc097a217a855086"
dependencies = [
"ark-ec",
"ark-ff",
@@ -2405,7 +2411,7 @@ dependencies = [
"futures-core",
"futures-sink",
"futures-util",
- "http",
+ "http 0.2.9",
"indexmap 2.0.2",
"slab",
"tokio",
@@ -2415,7 +2421,7 @@ dependencies = [
[[package]]
name = "hash-tool"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"bs58 0.5.0",
"hex",
@@ -2474,7 +2480,7 @@ dependencies = [
"base64 0.21.7",
"bytes",
"headers-core",
- "http",
+ "http 0.2.9",
"httpdate",
"mime",
"sha1",
@@ -2486,7 +2492,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
dependencies = [
- "http",
+ "http 0.2.9",
]
[[package]]
@@ -2606,6 +2612,17 @@ dependencies = [
"itoa",
]
+[[package]]
+name = "http"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
[[package]]
name = "http-body"
version = "0.4.5"
@@ -2613,15 +2630,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
dependencies = [
"bytes",
- "http",
+ "http 0.2.9",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "http-body"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
+dependencies = [
+ "bytes",
+ "http 1.1.0",
+]
+
+[[package]]
+name = "http-body-util"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f"
+dependencies = [
+ "bytes",
+ "futures-util",
+ "http 1.1.0",
+ "http-body 1.0.1",
"pin-project-lite",
]
[[package]]
name = "http-range-header"
-version = "0.3.1"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f"
+checksum = "08a397c49fec283e3d6211adbe480be95aae5f304cfb923e9970e08956d5168a"
[[package]]
name = "httparse"
@@ -2652,8 +2692,8 @@ dependencies = [
"futures-core",
"futures-util",
"h2",
- "http",
- "http-body",
+ "http 0.2.9",
+ "http-body 0.4.5",
"httparse",
"httpdate",
"itoa",
@@ -2665,6 +2705,25 @@ dependencies = [
"want",
]
+[[package]]
+name = "hyper"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-util",
+ "http 1.1.0",
+ "http-body 1.0.1",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "smallvec",
+ "tokio",
+]
+
[[package]]
name = "hyper-tls"
version = "0.5.0"
@@ -2672,12 +2731,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
dependencies = [
"bytes",
- "hyper",
+ "hyper 0.14.27",
"native-tls",
"tokio",
"tokio-native-tls",
]
+[[package]]
+name = "hyper-util"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9"
+dependencies = [
+ "bytes",
+ "futures-util",
+ "http 1.1.0",
+ "http-body 1.0.1",
+ "hyper 1.5.0",
+ "pin-project-lite",
+ "tokio",
+]
+
[[package]]
name = "iana-time-zone"
version = "0.1.58"
@@ -2756,8 +2830,8 @@ dependencies = [
"attohttpc",
"bytes",
"futures",
- "http",
- "hyper",
+ "http 0.2.9",
+ "hyper 0.14.27",
"log",
"rand",
"tokio",
@@ -2828,7 +2902,7 @@ dependencies = [
[[package]]
name = "internal-tracing"
version = "0.1.0"
-source = "git+https://github.com/openmina/proof-systems?rev=2fdb5a7#2fdb5a75c61e2ac1db452bd813aa12fd9fb77527"
+source = "git+https://github.com/openmina/proof-systems?rev=c478b19#c478b197ddb7fcefee87c4cfdc097a217a855086"
[[package]]
name = "io-lifetimes"
@@ -2991,7 +3065,7 @@ dependencies = [
[[package]]
name = "kimchi"
version = "0.1.0"
-source = "git+https://github.com/openmina/proof-systems?rev=2fdb5a7#2fdb5a75c61e2ac1db452bd813aa12fd9fb77527"
+source = "git+https://github.com/openmina/proof-systems?rev=c478b19#c478b197ddb7fcefee87c4cfdc097a217a855086"
dependencies = [
"ark-ec",
"ark-ff",
@@ -3041,7 +3115,7 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
[[package]]
name = "ledger-tool"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"anyhow",
"mina-curves",
@@ -3367,7 +3441,7 @@ dependencies = [
[[package]]
name = "libp2p-rpc-behaviour"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"libp2p",
"log",
@@ -3655,7 +3729,7 @@ dependencies = [
[[package]]
name = "mina-curves"
version = "0.1.0"
-source = "git+https://github.com/openmina/proof-systems?rev=2fdb5a7#2fdb5a75c61e2ac1db452bd813aa12fd9fb77527"
+source = "git+https://github.com/openmina/proof-systems?rev=c478b19#c478b197ddb7fcefee87c4cfdc097a217a855086"
dependencies = [
"ark-ec",
"ark-ff",
@@ -3664,7 +3738,7 @@ dependencies = [
[[package]]
name = "mina-hasher"
version = "0.1.0"
-source = "git+https://github.com/openmina/proof-systems?rev=2fdb5a7#2fdb5a75c61e2ac1db452bd813aa12fd9fb77527"
+source = "git+https://github.com/openmina/proof-systems?rev=c478b19#c478b197ddb7fcefee87c4cfdc097a217a855086"
dependencies = [
"ark-ff",
"bitvec",
@@ -3693,11 +3767,11 @@ dependencies = [
"lazy_static",
"mina-curves",
"mina-hasher",
- "mina-poseidon",
"mina-signer",
"num-bigint",
"o1-utils",
"openmina-macros",
+ "poseidon",
"rsexp",
"rsexp-derive",
"serde",
@@ -3717,7 +3791,7 @@ dependencies = [
[[package]]
name = "mina-poseidon"
version = "0.1.0"
-source = "git+https://github.com/openmina/proof-systems?rev=2fdb5a7#2fdb5a75c61e2ac1db452bd813aa12fd9fb77527"
+source = "git+https://github.com/openmina/proof-systems?rev=c478b19#c478b197ddb7fcefee87c4cfdc097a217a855086"
dependencies = [
"ark-ec",
"ark-ff",
@@ -3734,7 +3808,7 @@ dependencies = [
[[package]]
name = "mina-signer"
version = "0.1.0"
-source = "git+https://github.com/openmina/proof-systems?rev=2fdb5a7#2fdb5a75c61e2ac1db452bd813aa12fd9fb77527"
+source = "git+https://github.com/openmina/proof-systems?rev=c478b19#c478b197ddb7fcefee87c4cfdc097a217a855086"
dependencies = [
"ark-ec",
"ark-ff",
@@ -3752,7 +3826,7 @@ dependencies = [
[[package]]
name = "mina-transport"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"blake2",
"hex",
@@ -3763,7 +3837,7 @@ dependencies = [
[[package]]
name = "mina-tree"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"anyhow",
"ark-ec",
@@ -3781,7 +3855,6 @@ dependencies = [
"getrandom",
"hex",
"itertools 0.10.5",
- "js-sys",
"juniper",
"kimchi",
"lazy_static",
@@ -3798,6 +3871,7 @@ dependencies = [
"openmina-core",
"openmina-macros",
"poly-commitment",
+ "poseidon",
"postcard",
"rand",
"rand_pcg",
@@ -3857,7 +3931,7 @@ dependencies = [
"bytes",
"encoding_rs",
"futures-util",
- "http",
+ "http 0.2.9",
"httparse",
"log",
"memchr",
@@ -4103,7 +4177,7 @@ dependencies = [
[[package]]
name = "node"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"anyhow",
"ark-ff",
@@ -4119,6 +4193,7 @@ dependencies = [
"openmina-core",
"openmina-node-account",
"p2p",
+ "poseidon",
"postcard",
"rand",
"redux",
@@ -4352,7 +4427,7 @@ dependencies = [
[[package]]
name = "o1-utils"
version = "0.1.0"
-source = "git+https://github.com/openmina/proof-systems?rev=2fdb5a7#2fdb5a75c61e2ac1db452bd813aa12fd9fb77527"
+source = "git+https://github.com/openmina/proof-systems?rev=c478b19#c478b197ddb7fcefee87c4cfdc097a217a855086"
dependencies = [
"ark-ec",
"ark-ff",
@@ -4461,7 +4536,7 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "openmina-bootstrap-sandbox"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"base64 0.21.7",
"binprot",
@@ -4486,12 +4561,17 @@ dependencies = [
[[package]]
name = "openmina-core"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
+ "argon2",
"ark-ff",
+ "base64 0.22.0",
"binprot",
"binprot_derive",
+ "bs58 0.4.0",
+ "crypto_secretbox",
"hex",
+ "js-sys",
"lazy_static",
"md5",
"mina-hasher",
@@ -4500,22 +4580,25 @@ dependencies = [
"once_cell",
"openmina-fuzzer",
"openmina-macros",
+ "poseidon",
"redux",
"serde",
"serde_json",
"sha2 0.10.8",
"slab",
+ "thiserror",
"time",
"tokio",
"tracing",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm_thread",
+ "web-sys",
]
[[package]]
name = "openmina-fuzzer"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"lazy_static",
"rand",
@@ -4526,7 +4609,7 @@ dependencies = [
[[package]]
name = "openmina-gossipsub-sandbox"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"bs58 0.5.0",
"env_logger",
@@ -4540,7 +4623,7 @@ dependencies = [
[[package]]
name = "openmina-macros"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"anyhow",
"openmina-core",
@@ -4553,13 +4636,10 @@ dependencies = [
[[package]]
name = "openmina-node-account"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"anyhow",
- "argon2",
- "base64 0.22.0",
"bs58 0.4.0",
- "crypto_secretbox",
"hex",
"lazy_static",
"mina-hasher",
@@ -4574,7 +4654,7 @@ dependencies = [
[[package]]
name = "openmina-node-common"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"ark-ff",
"gloo-timers",
@@ -4605,7 +4685,7 @@ dependencies = [
[[package]]
name = "openmina-node-invariants"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"documented",
"lazy_static",
@@ -4619,7 +4699,7 @@ dependencies = [
[[package]]
name = "openmina-node-native"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"anyhow",
"bs58 0.4.0",
@@ -4656,10 +4736,12 @@ dependencies = [
[[package]]
name = "openmina-node-testing"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"anyhow",
"axum",
+ "base64 0.22.0",
+ "bs58 0.4.0",
"clap 4.5.20",
"console",
"ctrlc",
@@ -4700,12 +4782,13 @@ dependencies = [
[[package]]
name = "openmina-node-web"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"anyhow",
"bytes",
"console_error_panic_hook",
"derive_more",
+ "gloo-utils",
"jsonpath-rust",
"libp2p-identity",
"mina-p2p-messages",
@@ -4726,7 +4809,7 @@ dependencies = [
[[package]]
name = "openmina-producer-dashboard"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"bincode",
"clap 4.5.20",
@@ -4818,10 +4901,11 @@ dependencies = [
[[package]]
name = "p2p"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"aes-gcm 0.10.3",
"anyhow",
+ "base64 0.22.0",
"binprot",
"binprot_derive",
"bitflags 2.4.1",
@@ -4841,7 +4925,6 @@ dependencies = [
"gloo-utils",
"hex",
"hkdf",
- "hyper",
"js-sys",
"libc",
"libp2p-identity",
@@ -4883,7 +4966,7 @@ dependencies = [
[[package]]
name = "p2p-testing"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"derive_more",
"futures",
@@ -5203,7 +5286,7 @@ dependencies = [
[[package]]
name = "poly-commitment"
version = "0.1.0"
-source = "git+https://github.com/openmina/proof-systems?rev=2fdb5a7#2fdb5a75c61e2ac1db452bd813aa12fd9fb77527"
+source = "git+https://github.com/openmina/proof-systems?rev=c478b19#c478b197ddb7fcefee87c4cfdc097a217a855086"
dependencies = [
"ark-ec",
"ark-ff",
@@ -5277,6 +5360,15 @@ version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265"
+[[package]]
+name = "poseidon"
+version = "0.12.0"
+dependencies = [
+ "ark-ff",
+ "mina-curves",
+ "once_cell",
+]
+
[[package]]
name = "postcard"
version = "1.0.10"
@@ -5686,7 +5778,7 @@ dependencies = [
[[package]]
name = "redux"
version = "0.1.0"
-source = "git+https://github.com/openmina/redux-rs.git?rev=bf0726e5#bf0726e596a456f2204c5138528ac7a64695e3b4"
+source = "git+https://github.com/openmina/redux-rs.git?rev=ab14890c#ab14890c68fa478ccfec9d499a76d25f20759619"
dependencies = [
"enum_dispatch",
"linkme",
@@ -5741,7 +5833,7 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "replay_dynamic_effects"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"node",
"openmina-node-invariants",
@@ -5760,9 +5852,9 @@ dependencies = [
"futures-core",
"futures-util",
"h2",
- "http",
- "http-body",
- "hyper",
+ "http 0.2.9",
+ "http-body 0.4.5",
+ "hyper 0.14.27",
"hyper-tls",
"ipnet",
"js-sys",
@@ -5776,7 +5868,7 @@ dependencies = [
"serde",
"serde_json",
"serde_urlencoded",
- "sync_wrapper",
+ "sync_wrapper 0.1.2",
"system-configuration",
"tokio",
"tokio-native-tls",
@@ -6124,7 +6216,7 @@ checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]]
name = "salsa-simple"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"generic-array",
"hex",
@@ -6532,7 +6624,7 @@ dependencies = [
[[package]]
name = "snark"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"ark-ec",
"ark-ff",
@@ -6552,6 +6644,7 @@ dependencies = [
"once_cell",
"openmina-core",
"poly-commitment",
+ "poseidon",
"rand",
"rayon",
"redux",
@@ -6993,6 +7086,12 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
+[[package]]
+name = "sync_wrapper"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
+
[[package]]
name = "synstructure"
version = "0.12.6"
@@ -7290,27 +7389,34 @@ dependencies = [
[[package]]
name = "tower-http"
-version = "0.4.4"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140"
+checksum = "8437150ab6bbc8c5f0f519e3d5ed4aa883a83dd4cdd3d1b21f9482936046cb97"
dependencies = [
"bitflags 2.4.1",
"bytes",
- "futures-core",
"futures-util",
- "http",
- "http-body",
+ "http 1.1.0",
+ "http-body 1.0.1",
+ "http-body-util",
"http-range-header",
+ "httpdate",
+ "mime",
+ "mime_guess",
+ "percent-encoding",
"pin-project-lite",
+ "tokio",
+ "tokio-util",
"tower-layer",
"tower-service",
+ "tracing",
]
[[package]]
name = "tower-layer"
-version = "0.3.2"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
+checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
[[package]]
name = "tower-service"
@@ -7418,7 +7524,7 @@ dependencies = [
[[package]]
name = "transaction_fuzzer"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"ark-ec",
"ark-ff",
@@ -7441,6 +7547,7 @@ dependencies = [
"object 0.36.5",
"once_cell",
"openmina-core",
+ "poseidon",
"rand",
"ring_buffer",
"rsprocmaps",
@@ -7512,7 +7619,7 @@ dependencies = [
"byteorder",
"bytes",
"data-encoding",
- "http",
+ "http 0.2.9",
"httparse",
"log",
"rand",
@@ -7551,7 +7658,7 @@ dependencies = [
[[package]]
name = "turshi"
version = "0.1.0"
-source = "git+https://github.com/openmina/proof-systems?rev=2fdb5a7#2fdb5a75c61e2ac1db452bd813aa12fd9fb77527"
+source = "git+https://github.com/openmina/proof-systems?rev=c478b19#c478b197ddb7fcefee87c4cfdc097a217a855086"
dependencies = [
"ark-ff",
"hex",
@@ -7785,7 +7892,7 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "vrf"
-version = "0.11.0"
+version = "0.12.0"
dependencies = [
"anyhow",
"ark-ec",
@@ -7802,6 +7909,7 @@ dependencies = [
"num",
"o1-utils",
"openmina-node-account",
+ "poseidon",
"rand",
"redux",
"serde",
@@ -7844,8 +7952,8 @@ dependencies = [
"futures-channel",
"futures-util",
"headers",
- "http",
- "hyper",
+ "http 0.2.9",
+ "hyper 0.14.27",
"log",
"mime",
"mime_guess",
diff --git a/Cargo.toml b/Cargo.toml
index 763bd8b627..7c6b6a2118 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -20,6 +20,7 @@ members = [
"mina-p2p-messages",
"ledger",
+ "poseidon",
"tools/transport",
"tools/bootstrap-sandbox",
@@ -35,20 +36,29 @@ members = [
resolver = "2"
+[workspace.lints.clippy]
+#unwrap_used = "warn"
+arithmetic_side_effects = "warn"
+indexing_slicing = "warn"
+
[workspace.dependencies]
mina-p2p-messages = { path = "mina-p2p-messages" }
+poseidon = { path = "poseidon" }
ledger = { path = "ledger", package = "mina-tree" }
-mina-hasher = { git = "https://github.com/openmina/proof-systems", rev = "2fdb5a7" }
-mina-signer = { git = "https://github.com/openmina/proof-systems", rev = "2fdb5a7" }
-mina-curves = { git = "https://github.com/openmina/proof-systems", rev = "2fdb5a7" }
-o1-utils = { git = "https://github.com/openmina/proof-systems", rev = "2fdb5a7" }
-kimchi = { git = "https://github.com/openmina/proof-systems", rev = "2fdb5a7" }
-mina-poseidon = {git = "https://github.com/openmina/proof-systems", rev = "2fdb5a7"}
-poly-commitment = {git = "https://github.com/openmina/proof-systems", rev = "2fdb5a7"}
+
+mina-hasher = { git = "https://github.com/openmina/proof-systems", rev = "c478b19" }
+mina-signer = { git = "https://github.com/openmina/proof-systems", rev = "c478b19" }
+mina-curves = { git = "https://github.com/openmina/proof-systems", rev = "c478b19" }
+# UNCOMMENTED_IN_CI mina-curves = { git = "https://github.com/openmina/proof-systems", rev = "c478b19", features = [ "32x9" ] }
+o1-utils = { git = "https://github.com/openmina/proof-systems", rev = "c478b19" }
+kimchi = { git = "https://github.com/openmina/proof-systems", rev = "c478b19" }
+mina-poseidon = {git = "https://github.com/openmina/proof-systems", rev = "c478b19" }
+poly-commitment = {git = "https://github.com/openmina/proof-systems", rev = "c478b19" }
+
libp2p = { git = "https://github.com/openmina/rust-libp2p", rev = "5c44c7d9", default-features = false }
vrf = { path = "vrf" }
openmina-node-account = { path = "node/account" }
-redux = { git = "https://github.com/openmina/redux-rs.git", rev = "bf0726e5", features = ["serde"] }
+redux = { git = "https://github.com/openmina/redux-rs.git", rev = "ab14890c", features = ["serde"] }
serde = "1.0.190"
serde_json = "1.0.107"
serde_with = { version = "3.7.0", features = ["hex"] }
@@ -56,6 +66,9 @@ linkme = "0.3.22"
static_assertions = "1.1.0"
juniper = { version = "0.16" }
+ark-ff = { version = "0.3.0", features = [ "parallel", "asm", "std" ] }
+# UNCOMMENTED_IN_CI ark-ff = { version = "0.3.0", features = [ "parallel", "asm", "std", "32x9" ] }
+
[profile.fuzz]
inherits = "release"
@@ -69,10 +82,10 @@ incremental = false
codegen-units = 1
[patch.crates-io]
-ark-ff = { git = "https://github.com/openmina/algebra", rev = "33a1de2" } # branch: fix-openmina
-ark-ec = { git = "https://github.com/openmina/algebra", rev = "33a1de2" } # branch: fix-openmina
-ark-poly = { git = "https://github.com/openmina/algebra", rev = "33a1de2" } # branch: fix-openmina
-ark-serialize = { git = "https://github.com/openmina/algebra", rev = "33a1de2" } # branch: fix-openmina
+ark-ff = { git = "https://github.com/openmina/algebra", rev = "d0343f5" } # branch: fix-openmina-webnode
+ark-ec = { git = "https://github.com/openmina/algebra", rev = "d0343f5" } # branch: fix-openmina-webnode
+ark-poly = { git = "https://github.com/openmina/algebra", rev = "d0343f5" } # branch: fix-openmina-webnode
+ark-serialize = { git = "https://github.com/openmina/algebra", rev = "d0343f5" } # branch: fix-openmina-webnode
[profile.test.package."*"]
opt-level = 3
diff --git a/Dockerfile b/Dockerfile
index 441ca69069..fb375a0697 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,6 @@
FROM rust:buster AS build
RUN apt-get update && apt-get install -y protobuf-compiler && apt-get clean
-RUN rustup default 1.80 && rustup component add rustfmt
+RUN rustup default 1.83 && rustup component add rustfmt
WORKDIR /openmina
COPY . .
RUN cargo build --release --package=cli --bin=openmina
diff --git a/README.md b/README.md
index 6972671913..0dcc46dfbd 100644
--- a/README.md
+++ b/README.md
@@ -1,264 +1,91 @@
-# The Open Mina Node
+
+
+
+
+
+
-## With the Rust-based Open Mina node, you can produce, validate and apply blocks
+![Beta][beta-badge] [![release-badge]][release-link] [![Changelog][changelog-badge]][changelog] [![Apache licensed]][Apache link]
-[](https://github.com/openmina/openmina/actions/workflows/daily.yaml) [![Changelog][changelog-badge]][changelog] [![release-badge]][release-link] [![Apache licensed]][Apache link]
+_The **Open Mina Node** is a fast and secure implementation of the Mina protocol in **Rust**._
+_Currently in **public beta**, join our [Discord community](https://discord.com/channels/484437221055922177/1290662938734231552) to help test future releases._
-## Run the Block Producer
+
-Once you have completed the [pre-requisites](./docs/docker-installation.md) for your operating system, follow these steps:
+---
-### Setup Option 1: Download Docker Compose Files from the Release
+## Getting Started
-1. **Download the Docker Compose files:**
+### Building from Source
- - Go to the [Releases page](https://github.com/openmina/openmina/releases) of this repository.
- - Download the latest `openmina-vX.Y.Z-docker-compose.zip` (or `.tar.gz`) file corresponding to the release version (available since v0.8.0).
+- [Rust Node](/docs/building-from-source-guide.md#how-to-build-and-launch-a-node-from-source) and [Dashboards](./docs/building-from-source-guide.md#how-to-launch-the-ui)
-2. **Extract the files:**
+### Run Node on Devnet via Docker
- - Unzip or untar the downloaded file:
- ```bash
- unzip openmina-vX.Y.Z-docker-compose.zip
- ```
- or
- ```bash
- tar -xzvf openmina-vX.Y.Z-docker-compose.tar.gz
- ```
- - Replace `vX.Y.Z` with the actual release version you downloaded.
+- [Non-Block Producing Node](/docs/alpha-testing-guide.md) Connect to peers and sync a node on the devnet; no devnet stake needed.
+- [Block Producing Node](/docs/block-producer-guide.md) Produce blocks on the devnet; sufficient devnet stake needed.
+- [Local Block Production Demo](/docs/local-demo-guide.md) Produce blocks on a custom local chain without devnet stake.
-3. **Navigate to the extracted directory:**
- ```bash
- cd openmina-vX.Y.Z-docker-compose
- ```
+
-### Setup Option 2: Clone the Repository
+---
-1. **Clone this repository:**
+## Release Process
- ```bash
- git clone https://github.com/openmina/openmina.git
- ```
+**This project is in beta**. We maintain a monthly release cycle, providing [updates every month](https://github.com/openmina/openmina/releases).
-2. **Navigate to the repository:**
- ```bash
- cd openmina
- ```
-### Launch
-**Run the following command to start the demo:**
+## Core Features
-```bash
-docker compose -f docker-compose.local.producers.yml up --pull always --force-recreate
-```
-
-And finally:
-
-**Open your browser and visit [http://localhost:8070](http://localhost:8070)**
-
-You should see the following screen:
-
-
-
-## Description
-
-The Open Mina Node is a Mina node written completely in Rust and capable of verifying blocks of transactions, producing blocks and generating SNARKs.
-
-In the design of the Open Mina node, we are utilizing much of the same logic as in the Mina Web Node. The key difference is that unlike the Web Node, which is an in-browser node with limited resources, the Open Mina node is able to perform resource-intensive tasks such as SNARK proof generation.
-
-## Overview of the Node’s current functionalities
-
-| Current functionalities | In Development | Future Plans |
-| ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------- | --------------------------------------------------- |
-| ☑ **Produce and prove blocks** (with and without transactions). | ☐ Receiving and broadcasting transactions from/into the transaction pool. | ☐ Direct transfer of MINA funds using Webnode |
-| ☑ **Produce SNARK proofs** for transactions. | ☐ A block replayer that uses data from the archive nodes | ☐ O1JS support for Webnode. |
-| ☑ **Connect to the network** and sync up to the best tip block | | |
-| ☑ **Validate and apply new blocks** and transactions to update consensus and ledger state. | | |
-| ☑ **Broadcast messages**: blocks, SNARK pool | | |
-
-Please note that receiving and broadcasting transactions from/into the transaction pool is already possible, but is still an early alpha version and needs more work.
-
-## Updates to the Front End
-
-We've added two new pages to the node's front end:
-
-### Mempool
-
-
-
-Shows a list of the transactions from the pool and a side panel detail.
-
-### Benchmarks
-
-
-
-The benchmarks page helps us to send transactions. The transactions are signed in the front end by the Mina signer.
-Every user can send transactions and they can see in the mempool whether the transactions were sent by their node.
-
-## Launch the block producer demo
-
-Run the Open Mina block producer node by following this [guide](https://github.com/openmina/openmina/blob/main/docs/producer-demo.md).
-
-## How to launch the node (with Docker compose):
-
-From the directory containing the Docker Compose files (either the root of the cloned repository or the directory where the released Docker Compose files were extracted):
-
-```
-docker compose up --pull always
-```
-
-Then visit http://localhost:8070 in your browser.
-
-
-
-By default, `docker compose up` will use the latest node and frontend images available (tagged with `latest`), but specific versions can be selected by using the `OPENMINA_TAG` and `OPENMINA_FRONTEND_TAG` variables.
-
-## How to launch the node (without Docker compose):
-
-This installation guide has been tested on Debian and Ubuntu and should work on most distributions of Linux.
-
-**Pre-requisites:**
-
-Ubuntu or Debian-based Linux distribution with the following packages installed:
-
-- `curl`
-- `git`
-- `libssl-dev`
-- `pkg-config`
-- `protobuf-compiler`
-- `build-essential`
-
-Example (debian-based):
-
-```sh
-# Either using "sudo" or as the "root" user
-sudo apt install curl git libssl-dev pkg-config protobuf-compiler build-essential
-```
-
-Example (macOS):
-
-If you have not yet installed homebrew:
-
-```sh
-/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
-```
-
-```sh
-brew install curl git openssl pkg-config protobuf gcc make
-```
-
-**Steps (for Debian-based Linux distros and macOS):**
-
-Open up the command line and enter the following:
-
-And then:
-
-```sh
-# Install rustup and set the default Rust toolchain to 1.80 (newer versions work too)
-curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.80
-# Setup the current shell with rustup
-source "$HOME/.cargo/env"
-# Clone the openmina repository
-git clone https://github.com/openmina/openmina.git
-cd openmina/
-# Build and run the node
-cargo run --release -p cli node
-```
-
-## How to launch the UI:
-
-## Prerequisites
-
-### 1. Node.js v20.11.1
-
-#### MacOS
-
-```bash
-/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
-brew install node@20.11.1
-```
-
-#### Linux
-
-```bash
-curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
-source ~/.bashrc
-nvm install 20.11.1
-```
-
-#### Windows
-
-Download [Node.js v20.11.1](https://nodejs.org/) from the official website, open the installer and follow the prompts to complete the installation.
-
-### 2. Angular CLI v16.2.0
-
-```bash
-npm install -g @angular/cli@16.2.0
-```
-
-### 3. Installation
-
-Open a terminal and navigate to this project's root directory
-
-```bash
-cd PROJECT_LOCATION/openmina/frontend
-```
-
-Install the dependencies
-
-```bash
-npm install
-```
-
-## Run the application
-
-```bash
-npm start
-```
+- **Mina Network**: Connect to peers, sync up, broadcast messages
+- **Block Production**: Produces, validates, and applies blocks according to Mina's consensus.
+- **SNARK Generation**: Produce SNARK proofs for transactions
+- **Debugging**: A block replayer that uses data from the archive nodes
## Repository Structure
-- [core/](core) - Provides basic types needed to be shared across different
- components of the node.
+- [core/](core) - Provides basic types needed to be shared across different components of the node.
- [ledger/](ledger) - Mina ledger implementation in Rust.
- [snark/](snark) - Snark/Proof verification.
- [p2p/](p2p) - P2p implementation for OpenMina node.
- [node/](node) - Combines all the business logic of the node.
- - [native/](node/native) - OS specific pieces of the node, which is
- used to run the node natively (Linux/Mac/Windows).
+ - [native/](node/native) - OS specific pieces of the node, which is used to run the node natively (Linux/Mac/Windows).
- [testing/](node/testing) - Testing framework for OpenMina node.
- [cli/](cli) - OpenMina cli.
- [frontend/](frontend) - OpenMina frontend.
-[Details regarding architecture](ARCHITECTURE.md)
-
## The Open Mina Documentation
+### What is Open Mina?
+
- [Why we are developing Open Mina](docs/why-openmina.md)
-- What is Open Mina?
- - [Openmina Node](#the-open-mina-node)
- - [The Mina Web Node](https://github.com/openmina/webnode/blob/main/README.md)
-- Core components
- - [P2P communication](https://github.com/openmina/openmina/blob/documentation/docs/p2p_service.md)
- - [GossipSub](https://github.com/openmina/mina-wiki/blob/3ea9041e52fb2e606918f6c60bd3a32b8652f016/p2p/mina-gossip.md)
- - [Scan state](docs/scan-state.md)
- - [SNARKs](docs/snark-work.md)
-- Developer tools
- - [Debugger](https://github.com/openmina/mina-network-debugger/blob/main/README.md)
- - [Front End](https://github.com/openmina/mina-frontend/blob/main/README.md)
- - [Dashboard](https://github.com/openmina/mina-frontend/blob/main/docs/MetricsTracing.md#Dashboard)
-- [Testing](docs/testing/testing.md)
-- How to run
- - [Launch Openmina node](#how-to-launch-without-docker-compose)
- - [Launch Node with UI](#how-to-launch-with-docker-compose)
- - [Debugger](https://github.com/openmina/mina-network-debugger?tab=readme-ov-file#Preparing-for-build)
- - [Web Node](https://github.com/openmina/webnode/blob/main/README.md#try-out-the-mina-web-node)
-- External links
- - [Medium](https://medium.com/openmina)
- - [Twitter](https://twitter.com/viable_systems)
+
+### Core components
+
+- [P2P communication](https://github.com/openmina/openmina/blob/documentation/docs/p2p_service.md)
+ - [GossipSub](https://github.com/openmina/mina-wiki/blob/3ea9041e52fb2e606918f6c60bd3a32b8652f016/p2p/mina-gossip.md)
+- [Scan state](docs/scan-state.md)
+- [SNARKs](docs/snark-work.md)
+
+### Developer tools
+
+- [Front End](./docs/building-from-source-guide.md#how-to-launch-the-ui)
+
+### Testing Framework for Mina
+
+- [Full Testing Documentation](docs/testing/testing.md)
+
+### How to run
+
+- [Non-Block Producing Node](./docs/alpha-testing-guide.md)
+- [Block Producing Node](./docs/block-producer-guide.md)
+- [Local Block Production Demo](./docs/local-demo-guide.md)
[changelog]: ./CHANGELOG.md
+[beta-badge]: https://img.shields.io/badge/status-beta-yellow
[changelog-badge]: https://img.shields.io/badge/changelog-Changelog-%23E05735
[release-badge]: https://img.shields.io/github/v/release/openmina/openmina
[release-link]: https://github.com/openmina/openmina/releases/latest
diff --git a/cli/Cargo.toml b/cli/Cargo.toml
index 4583f8783e..9acf6026fc 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "cli"
-version = "0.11.0"
+version = "0.12.0"
edition = "2021"
license = "Apache-2.0"
diff --git a/cli/replay_dynamic_effects/Cargo.toml b/cli/replay_dynamic_effects/Cargo.toml
index 99df2ad7df..2f9d41f8e3 100644
--- a/cli/replay_dynamic_effects/Cargo.toml
+++ b/cli/replay_dynamic_effects/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "replay_dynamic_effects"
-version = "0.11.0"
+version = "0.12.0"
edition = "2021"
license = "Apache-2.0"
diff --git a/cli/replay_dynamic_effects/src/lib.rs b/cli/replay_dynamic_effects/src/lib.rs
index 29b7bcc3b4..f788b95c75 100644
--- a/cli/replay_dynamic_effects/src/lib.rs
+++ b/cli/replay_dynamic_effects/src/lib.rs
@@ -1,5 +1,5 @@
use ::node::{ActionWithMeta, Store};
-use openmina_node_invariants::{InvariantResult, Invariants};
+use openmina_node_invariants::{InvariantIgnoreReason, InvariantResult, Invariants};
use openmina_node_native::NodeService;
pub mod ret {
@@ -33,6 +33,8 @@ extern "C" fn replay_dynamic_effects(
) -> u8 {
for (invariant, res) in Invariants::check_all(store, action) {
match res {
+ InvariantResult::Ignored(InvariantIgnoreReason::GlobalInvariantNotInTestingCluster) => {
+ }
InvariantResult::Violation(violation) => {
eprintln!(
"Invariant({}) violated! violation: {violation}",
diff --git a/cli/src/commands/node/mod.rs b/cli/src/commands/node/mod.rs
index fde5d76d9a..1f837271ce 100644
--- a/cli/src/commands/node/mod.rs
+++ b/cli/src/commands/node/mod.rs
@@ -169,9 +169,9 @@ impl Node {
// warning, this overrides `OPENMINA_P2P_SEC_KEY`
if let (Some(key_file), Some(password)) = (&self.libp2p_keypair, &self.libp2p_password) {
- match AccountSecretKey::from_encrypted_file(key_file, password) {
+ match SecretKey::from_encrypted_file(key_file, password) {
Ok(sk) => {
- node_builder.p2p_sec_key(SecretKey::from_bytes(sk.to_bytes()));
+ node_builder.p2p_sec_key(sk.clone());
node::core::info!(
node::core::log::system_time();
summary = "read sercret key from file",
@@ -226,10 +226,12 @@ impl Node {
if let Some(producer_key_path) = self.producer_key {
let password = &self.producer_key_password;
- node::core::info!(node::core::log::system_time(); summary = "loading provers index");
- let provers = BlockProver::make(Some(block_verifier_index), Some(work_verifier_index));
- node::core::info!(node::core::log::system_time(); summary = "loaded provers index");
- node_builder.block_producer_from_file(provers, producer_key_path, password)?;
+ openmina_core::thread::spawn(|| {
+ node::core::info!(node::core::log::system_time(); summary = "loading provers index");
+ BlockProver::make(Some(block_verifier_index), Some(work_verifier_index));
+ node::core::info!(node::core::log::system_time(); summary = "loaded provers index");
+ });
+ node_builder.block_producer_from_file(producer_key_path, password, None)?;
if let Some(pub_key) = self.coinbase_receiver {
node_builder
diff --git a/clippy.toml b/clippy.toml
new file mode 100644
index 0000000000..c592911cd6
--- /dev/null
+++ b/clippy.toml
@@ -0,0 +1 @@
+allow-unwrap-in-tests=true
\ No newline at end of file
diff --git a/core/Cargo.toml b/core/Cargo.toml
index acc29c0767..7d1af1ad45 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "openmina-core"
-version = "0.11.0"
+version = "0.12.0"
edition = "2021"
license = "Apache-2.0"
@@ -8,6 +8,7 @@ license = "Apache-2.0"
lazy_static = "1.4.0"
once_cell = "1"
serde = { version = "1.0.147", features = ["rc"] }
+serde_json = "1.0"
slab = { version = "0.4.7", features = ["serde"] }
tracing = { version = "0.1", features = ["std"] }
sha2 = "0.10.6"
@@ -20,11 +21,17 @@ md5 = "0.7.0"
multihash = { version = "0.18.1", features = ["blake2b"] }
openmina-macros = { path = "../macros" }
openmina-fuzzer = { path = "../fuzzer", optional = true }
+argon2 = { version = "0.5.3", features = ["std"] }
+crypto_secretbox = { version = "0.1.1", features = ["std"] }
+base64 = "0.22"
+bs58 = "0.4.0"
+thiserror = "1.0.37"
mina-hasher = { workspace = true }
mina-p2p-messages = { workspace = true }
+poseidon = { workspace = true }
hex = "0.4.3"
-ark-ff = { version = "0.3.0", features = [ "parallel", "asm", "std" ] }
+ark-ff = { workspace = true }
[target.'cfg(not(target_family = "wasm"))'.dependencies]
redux = { workspace = true, features=["serializable_callbacks"] }
@@ -33,6 +40,8 @@ redux = { workspace = true, features=["serializable_callbacks"] }
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4"
wasm_thread = { version = "0.3", features = [ "es_modules" ] }
+js-sys = "0.3"
+web-sys = { version = "0.3", features = ["Window", "Response"] }
[dev-dependencies]
serde_json = { version = "1" }
diff --git a/core/src/consensus.rs b/core/src/consensus.rs
index 5429dbf07d..bd149eba74 100644
--- a/core/src/consensus.rs
+++ b/core/src/consensus.rs
@@ -7,7 +7,7 @@ use time::{macros::format_description, OffsetDateTime};
use crate::constants::constraint_constants;
pub use crate::constants::{
- checkpoint_window_size_in_slots, grace_period_end, slots_per_window, CHECKPOINTS_PER_YEAR,
+ checkpoint_window_size_in_slots, slots_per_window, CHECKPOINTS_PER_YEAR,
};
// TODO get constants from elsewhere
@@ -39,21 +39,21 @@ pub fn is_short_range_fork(a: &MinaConsensusState, b: &MinaConsensusState) -> bo
if s1.epoch_count.as_u32() == s2.epoch_count.as_u32() + 1
&& s2_epoch_slot >= slots_per_epoch * 2 / 3
{
- crate::log::debug!(crate::log::system_time(); kind = "is_short_range_fork", msg = format!("s2 is 1 epoch behind and not in seed update range: {} vs {}", s1.staking_epoch_data.lock_checkpoint, s2.next_epoch_data.lock_checkpoint));
+ crate::log::trace!(crate::log::system_time(); kind = "is_short_range_fork", msg = format!("s2 is 1 epoch behind and not in seed update range: {} vs {}", s1.staking_epoch_data.lock_checkpoint, s2.next_epoch_data.lock_checkpoint));
// S1 is one epoch ahead of S2 and S2 is not in the seed update range
s1.staking_epoch_data.lock_checkpoint == s2.next_epoch_data.lock_checkpoint
} else {
- crate::log::debug!(crate::log::system_time(); kind = "is_short_range_fork", msg = format!("chains are from different epochs"));
+ crate::log::trace!(crate::log::system_time(); kind = "is_short_range_fork", msg = format!("chains are from different epochs"));
false
}
};
- crate::log::debug!(crate::log::system_time(); kind = "is_short_range_fork", msg = format!("epoch count: {} vs {}", a.epoch_count.as_u32(), b.epoch_count.as_u32()));
+ crate::log::trace!(crate::log::system_time(); kind = "is_short_range_fork", msg = format!("epoch count: {} vs {}", a.epoch_count.as_u32(), b.epoch_count.as_u32()));
if a.epoch_count == b.epoch_count {
let a_prev_lock_checkpoint = &a.staking_epoch_data.lock_checkpoint;
let b_prev_lock_checkpoint = &b.staking_epoch_data.lock_checkpoint;
// Simple case: blocks have same previous epoch, so compare previous epochs' lock_checkpoints
- crate::log::debug!(crate::log::system_time(); kind = "is_short_range_fork", msg = format!("checkpoints: {} vs {}", a_prev_lock_checkpoint, b_prev_lock_checkpoint));
+ crate::log::trace!(crate::log::system_time(); kind = "is_short_range_fork", msg = format!("checkpoints: {} vs {}", a_prev_lock_checkpoint, b_prev_lock_checkpoint));
a_prev_lock_checkpoint == b_prev_lock_checkpoint
} else {
// Check for previous epoch case using both orientations
@@ -75,7 +75,9 @@ pub fn relative_min_window_density(b1: &MinaConsensusState, b2: &MinaConsensusSt
let projected_window = {
// Compute shift count
- let shift_count = (max_slot - global_slot(b1) - 1).clamp(0, SUB_WINDOWS_PER_WINDOW);
+ let shift_count = max_slot
+ .saturating_sub(global_slot(b1) + 1)
+ .min(SUB_WINDOWS_PER_WINDOW);
// Initialize projected window
let mut projected_window = b1
diff --git a/core/src/constants.rs b/core/src/constants.rs
index 7d99d64772..070adfbddc 100644
--- a/core/src/constants.rs
+++ b/core/src/constants.rs
@@ -107,19 +107,6 @@ pub fn checkpoint_window_size_in_slots() -> u32 {
size_in_slots as u32
}
-pub fn grace_period_end(constants: &v2::MinaBaseProtocolConstantsCheckedValueStableV1) -> u32 {
- let slots = {
- const NUM_DAYS: u64 = 3;
- let n_days_ms = days_to_ms(NUM_DAYS);
- let n_days = n_days_ms / constraint_constants().block_window_duration_ms;
- (n_days as u32).min(constants.slots_per_epoch.as_u32())
- };
- match constraint_constants().fork.as_ref() {
- None => slots,
- Some(fork) => slots + fork.global_slot_since_genesis,
- }
-}
-
pub const DEFAULT_GENESIS_TIMESTAMP_MILLISECONDS: u64 = 1707157200000;
pub const PROTOCOL_TRANSACTION_VERSION: u8 = 3;
diff --git a/core/src/distributed_pool.rs b/core/src/distributed_pool.rs
new file mode 100644
index 0000000000..7346caa20a
--- /dev/null
+++ b/core/src/distributed_pool.rs
@@ -0,0 +1,219 @@
+use std::cmp::Ord;
+use std::collections::BTreeMap;
+use std::ops::RangeBounds;
+
+use crate::bug_condition;
+
+#[derive(Clone)]
+pub struct DistributedPool {
+ counter: u64,
+ list: BTreeMap,
+ by_key: BTreeMap,
+}
+
+impl Default for DistributedPool {
+ fn default() -> Self {
+ Self {
+ counter: 0,
+ list: Default::default(),
+ by_key: Default::default(),
+ }
+ }
+}
+
+impl DistributedPool
+where
+ State: AsRef,
+ Key: Ord + Clone,
+{
+ pub fn is_empty(&self) -> bool {
+ self.list.is_empty()
+ }
+
+ pub fn len(&self) -> usize {
+ self.list.len()
+ }
+
+ pub fn contains(&self, key: &Key) -> bool {
+ self.by_key
+ .get(key)
+ .map_or(false, |i| self.list.contains_key(i))
+ }
+
+ pub fn get(&self, key: &Key) -> Option<&State> {
+ self.by_key.get(key).and_then(|i| self.list.get(i))
+ }
+
+ fn get_mut(&mut self, key: &Key) -> Option<&mut State> {
+ self.by_key.get(key).and_then(|i| self.list.get_mut(i))
+ }
+
+ pub fn range(&self, range: R) -> impl '_ + DoubleEndedIterator-
+ where
+ R: RangeBounds
,
+ {
+ self.list.range(range).map(|(k, v)| (*k, v))
+ }
+
+ pub fn last_index(&self) -> u64 {
+ self.list.last_key_value().map_or(0, |(k, _)| *k)
+ }
+
+ pub fn insert(&mut self, state: State) {
+ let key = state.as_ref().clone();
+ self.list.insert(self.counter, state);
+ self.by_key.insert(key, self.counter);
+ self.counter = self.counter.saturating_add(1);
+ }
+
+ pub fn update(&mut self, key: &Key, f: F) -> Option
+ where
+ F: FnOnce(&mut State) -> R,
+ {
+ let mut state = self.remove(key)?;
+ let res = f(&mut state);
+ self.insert(state);
+ Some(res)
+ }
+
+ /// Don't use if the change needs to be synced with other peers.
+ pub fn silent_update(&mut self, key: &Key, f: F) -> Option
+ where
+ F: FnOnce(&mut State) -> R,
+ {
+ self.get_mut(key).map(f)
+ }
+
+ pub fn remove(&mut self, key: &Key) -> Option {
+ let index = self.by_key.remove(key)?;
+ self.list.remove(&index)
+ }
+
+ pub fn retain(&mut self, mut f: F)
+ where
+ F: FnMut(&Key, &State) -> bool,
+ {
+ self.retain_and_update(|key, state| f(key, state))
+ }
+
+ pub fn retain_and_update(&mut self, mut f: F)
+ where
+ F: FnMut(&Key, &mut State) -> bool,
+ {
+ let list = &mut self.list;
+ self.by_key.retain(|key, index| {
+ let Some(v) = list.get_mut(index) else {
+ bug_condition!("Pool: key found in the index, but the item not found");
+ return false;
+ };
+ if f(key, v) {
+ return true;
+ }
+ list.remove(index);
+ false
+ });
+ }
+
+ pub fn states(&self) -> impl Iterator- {
+ self.list.values()
+ }
+}
+
+impl
DistributedPool
+where
+ State: AsRef,
+ Key: Ord + Clone,
+{
+ pub fn next_messages_to_send(
+ &self,
+ (index, limit): (u64, u8),
+ extract_message: F,
+ ) -> (Vec, u64, u64)
+ where
+ F: Fn(&State) -> Option,
+ {
+ if limit == 0 {
+ let index = index.saturating_sub(1);
+ return (vec![], index, index);
+ }
+
+ self.range(index..)
+ .try_fold(
+ (vec![], None),
+ |(mut list, mut first_index), (index, job)| {
+ if let Some(data) = extract_message(job) {
+ let first_index = *first_index.get_or_insert(index);
+ list.push(data);
+ if list.len() >= limit as usize {
+ return Err((list, first_index, index));
+ }
+ }
+
+ Ok((list, first_index))
+ },
+ )
+ // Loop iterated on whole list.
+ .map(|(list, first_index)| (list, first_index.unwrap_or(index), self.last_index()))
+ // Loop preemptively ended.
+ .unwrap_or_else(|v| v)
+ }
+}
+
+mod ser {
+ use super::*;
+ use serde::ser::SerializeStruct;
+ use serde::{Deserialize, Serialize};
+
+ #[derive(Deserialize)]
+ struct Pool {
+ counter: u64,
+ list: BTreeMap,
+ }
+
+ impl Serialize for super::DistributedPool
+ where
+ State: Serialize,
+ Key: Ord,
+ {
+ fn serialize(&self, serializer: S) -> Result
+ where
+ S: serde::Serializer,
+ {
+ let mut s = serializer.serialize_struct("Pool", 2)?;
+ s.serialize_field("counter", &self.counter)?;
+ s.serialize_field("list", &self.list)?;
+ s.end()
+ }
+ }
+ impl<'de, State, Key> Deserialize<'de> for super::DistributedPool
+ where
+ State: Deserialize<'de> + AsRef,
+ Key: Ord + Clone,
+ {
+ fn deserialize(deserializer: D) -> Result
+ where
+ D: serde::Deserializer<'de>,
+ {
+ let v = Pool::::deserialize(deserializer)?;
+ let by_key = v
+ .list
+ .iter()
+ .map(|(k, v)| (v.as_ref().clone(), *k))
+ .collect();
+ Ok(Self {
+ counter: v.counter,
+ list: v.list,
+ by_key,
+ })
+ }
+ }
+}
+
+impl std::fmt::Debug for DistributedPool {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("Pool")
+ .field("counter", &self.counter)
+ .field("len", &self.list.len())
+ .finish()
+ }
+}
diff --git a/core/src/encrypted_key.rs b/core/src/encrypted_key.rs
new file mode 100644
index 0000000000..1d5b894b79
--- /dev/null
+++ b/core/src/encrypted_key.rs
@@ -0,0 +1,154 @@
+use std::fs;
+use std::path::Path;
+
+use argon2::{password_hash::SaltString, Argon2, PasswordHasher};
+use base64::Engine;
+use crypto_secretbox::aead::{Aead, OsRng};
+use crypto_secretbox::{AeadCore, KeyInit, XSalsa20Poly1305};
+use serde::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize, Debug)]
+struct Base58String(String);
+
+impl Base58String {
+ pub fn new(raw: &[u8], version: u8) -> Self {
+ Base58String(bs58::encode(raw).with_check_version(version).into_string())
+ }
+
+ pub fn try_decode(&self, version: u8) -> Result, EncryptionError> {
+ let decoded = bs58::decode(&self.0).with_check(Some(version)).into_vec()?;
+ Ok(decoded[1..].to_vec())
+ }
+}
+
+#[derive(Debug, thiserror::Error)]
+pub enum EncryptionError {
+ #[error(transparent)]
+ SecretBox(#[from] crypto_secretbox::aead::Error),
+ #[error(transparent)]
+ ArgonError(#[from] argon2::Error),
+ #[error(transparent)]
+ PasswordHash(#[from] argon2::password_hash::Error),
+ #[error(transparent)]
+ Base58DecodeError(#[from] bs58::decode::Error),
+ #[error(transparent)]
+ CipherKeyInvalidLength(#[from] crypto_secretbox::cipher::InvalidLength),
+ #[error("Password hash missing after hash_password")]
+ HashMissing,
+ #[error(transparent)]
+ Io(#[from] std::io::Error),
+ #[error(transparent)]
+ SerdeJson(#[from] serde_json::Error),
+ #[error("Other: {0}")]
+ Other(String),
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct EncryptedSecretKeyFile {
+ box_primitive: String,
+ pw_primitive: String,
+ nonce: Base58String,
+ pwsalt: Base58String,
+ pwdiff: (u32, u32),
+ ciphertext: Base58String,
+}
+
+impl EncryptedSecretKeyFile {
+ pub fn new(path: impl AsRef) -> Result {
+ let file = fs::File::open(path)?;
+ Ok(serde_json::from_reader(file)?)
+ }
+}
+
+fn setup_argon(pwdiff: (u32, u32)) -> Result, EncryptionError> {
+ let params = argon2::Params::new(
+ pwdiff.0 / 1024,
+ pwdiff.1,
+ argon2::Params::DEFAULT_P_COST,
+ None,
+ )?;
+
+ Ok(Argon2::new(
+ argon2::Algorithm::Argon2i,
+ Default::default(),
+ params,
+ ))
+}
+
+pub trait EncryptedSecretKey {
+ const ENCRYPTION_DATA_VERSION_BYTE: u8 = 2;
+ const SECRET_KEY_PREFIX_BYTE: u8 = 1;
+
+ // Based on the ocaml implementation
+ const BOX_PRIMITIVE: &'static str = "xsalsa20poly1305";
+ const PW_PRIMITIVE: &'static str = "argon2i";
+ // Note: Only used for enryption, for decryption use the pwdiff from the file
+ const PW_DIFF: (u32, u32) = (134217728, 6);
+
+ fn try_decrypt(
+ encrypted: &EncryptedSecretKeyFile,
+ password: &str,
+ ) -> Result, EncryptionError> {
+ // prepare inputs to cipher
+ let password = password.as_bytes();
+ let pwsalt = encrypted
+ .pwsalt
+ .try_decode(Self::ENCRYPTION_DATA_VERSION_BYTE)?;
+ let nonce = encrypted
+ .nonce
+ .try_decode(Self::ENCRYPTION_DATA_VERSION_BYTE)?;
+ let ciphertext = encrypted
+ .ciphertext
+ .try_decode(Self::ENCRYPTION_DATA_VERSION_BYTE)?;
+
+ // The argon crate's SaltString can only be built from base64 string, ocaml node encodes the salt in base58
+ // So we decoded it from base58 first, then convert to base64 and lastly to SaltString
+ let pwsalt_encoded = base64::engine::general_purpose::STANDARD_NO_PAD.encode(pwsalt);
+ let salt = SaltString::from_b64(&pwsalt_encoded)?;
+
+ let argon2 = setup_argon(encrypted.pwdiff)?;
+ let password_hash = argon2
+ .hash_password(password, &salt)?
+ .hash
+ .ok_or(EncryptionError::HashMissing)?;
+ let password_bytes = password_hash.as_bytes();
+
+ // decrypt cipher
+ let cipher = XSalsa20Poly1305::new_from_slice(password_bytes)?;
+ let decrypted = cipher.decrypt(nonce.as_slice().into(), ciphertext.as_ref())?;
+
+ // strip the prefix and create keypair
+ Ok(decrypted)
+ }
+ fn try_encrypt(key: &[u8], password: &str) -> Result {
+ let argon2 = setup_argon(Self::PW_DIFF)?;
+
+ // add the prefix byt to the key
+ let mut key_prefixed = vec![Self::SECRET_KEY_PREFIX_BYTE];
+ key_prefixed.extend(key);
+
+ let salt = SaltString::generate(&mut OsRng);
+ let password_hash = argon2
+ .hash_password(password.as_bytes(), &salt)?
+ .hash
+ .ok_or(EncryptionError::HashMissing)?;
+
+ let nonce = XSalsa20Poly1305::generate_nonce(&mut OsRng);
+ let cipher = XSalsa20Poly1305::new_from_slice(password_hash.as_bytes())?;
+
+ let ciphertext = cipher.encrypt(&nonce, key_prefixed.as_slice())?;
+
+ // Same reason as in decrypt, we ned to decode the SaltString from base64 then encode it to base58 bellow
+ let mut salt_bytes = [0; 32];
+ let salt_portion = salt.decode_b64(&mut salt_bytes)?;
+
+ Ok(EncryptedSecretKeyFile {
+ box_primitive: Self::BOX_PRIMITIVE.to_string(),
+ pw_primitive: Self::PW_PRIMITIVE.to_string(),
+ nonce: Base58String::new(&nonce, Self::ENCRYPTION_DATA_VERSION_BYTE),
+ pwsalt: Base58String::new(salt_portion, Self::ENCRYPTION_DATA_VERSION_BYTE),
+ pwdiff: (argon2.params().m_cost() * 1024, argon2.params().t_cost()),
+ ciphertext: Base58String::new(&ciphertext, Self::ENCRYPTION_DATA_VERSION_BYTE),
+ })
+ }
+}
diff --git a/core/src/http.rs b/core/src/http.rs
new file mode 100644
index 0000000000..830776cfb4
--- /dev/null
+++ b/core/src/http.rs
@@ -0,0 +1,49 @@
+#[cfg(target_family = "wasm")]
+mod http {
+ use crate::thread;
+ use wasm_bindgen::prelude::*;
+
+ fn to_io_err(err: JsValue) -> std::io::Error {
+ std::io::Error::new(std::io::ErrorKind::Other, format!("{err:?}"))
+ }
+
+ async fn _get_bytes(url: String) -> std::io::Result> {
+ use wasm_bindgen_futures::JsFuture;
+ use web_sys::Response;
+
+ // let window = js_sys::global().dyn_into::().unwrap();
+ let window = web_sys::window().unwrap();
+
+ let resp_value = JsFuture::from(window.fetch_with_str(&url))
+ .await
+ .map_err(to_io_err)?;
+
+ assert!(resp_value.is_instance_of::());
+ let resp: Response = resp_value.dyn_into().unwrap();
+ let js = JsFuture::from(resp.array_buffer().map_err(to_io_err)?)
+ .await
+ .map_err(to_io_err)?;
+ Ok(js_sys::Uint8Array::new(&js).to_vec())
+ }
+
+ pub async fn get_bytes(url: &str) -> std::io::Result> {
+ let url = url.to_owned();
+ if thread::is_web_worker_thread() {
+ thread::run_async_fn_in_main_thread(move || _get_bytes(url)).await.expect("failed to run task in the main thread! Maybe main thread crashed or not initialized?")
+ } else {
+ _get_bytes(url).await
+ }
+ }
+
+ pub fn get_bytes_blocking(url: &str) -> std::io::Result> {
+ let url = url.to_owned();
+ if thread::is_web_worker_thread() {
+ thread::run_async_fn_in_main_thread_blocking(move || _get_bytes(url)).expect("failed to run task in the main thread! Maybe main thread crashed or not initialized?")
+ } else {
+ panic!("can't do blocking requests from main browser thread");
+ }
+ }
+}
+
+#[cfg(target_family = "wasm")]
+pub use http::{get_bytes, get_bytes_blocking};
diff --git a/core/src/invariants.rs b/core/src/invariants.rs
index 3ab2861eee..727a11bc63 100644
--- a/core/src/invariants.rs
+++ b/core/src/invariants.rs
@@ -1,7 +1,22 @@
use std::any::Any;
pub trait InvariantService: redux::Service {
+ type ClusterInvariantsState<'a>: 'a + std::ops::DerefMut
+ where
+ Self: 'a;
+
+ fn node_id(&self) -> usize {
+ 0
+ }
+
fn invariants_state(&mut self) -> &mut InvariantsState;
+
+ fn cluster_invariants_state<'a>(&'a mut self) -> Option>
+ where
+ Self: 'a,
+ {
+ None
+ }
}
#[derive(Default)]
diff --git a/core/src/lib.rs b/core/src/lib.rs
index 6301073699..42755a1cab 100644
--- a/core/src/lib.rs
+++ b/core/src/lib.rs
@@ -1,7 +1,12 @@
+pub mod distributed_pool;
pub mod invariants;
pub mod log;
pub mod requests;
+// TODO(binier): refactor
+#[cfg(target_family = "wasm")]
+pub mod http;
+
pub mod channels;
pub mod thread;
@@ -23,6 +28,9 @@ pub use network::NetworkConfig;
mod chain_id;
pub use chain_id::*;
+pub mod encrypted_key;
+pub use encrypted_key::*;
+
mod work_dir {
use once_cell::sync::OnceCell;
use std::path::PathBuf;
diff --git a/core/src/log.rs b/core/src/log.rs
index b1883e5f06..34a9182a5d 100644
--- a/core/src/log.rs
+++ b/core/src/log.rs
@@ -168,7 +168,7 @@ macro_rules! bug_condition {
.unwrap_or(false) {
panic!($($arg)*)
} else {
- $crate::log::inner::error!($($arg)*)
+ $crate::log::inner::error!("BUG CONDITION: {}", format!($($arg)*))
}
}};
}
diff --git a/core/src/network.rs b/core/src/network.rs
index 6b84f4cbe4..53d670e0de 100644
--- a/core/src/network.rs
+++ b/core/src/network.rs
@@ -1,4 +1,8 @@
use once_cell::sync::OnceCell;
+use poseidon::hash::{
+ legacy,
+ params::{CODA_SIGNATURE, MAINNET_ZKAPP_BODY, MINA_SIGNATURE_MAINNET, TESTNET_ZKAPP_BODY},
+};
use crate::constants::ConstraintConstants;
@@ -16,8 +20,9 @@ pub enum NetworkId {
pub struct NetworkConfig {
pub name: &'static str,
pub network_id: NetworkId,
- pub signature_prefix: &'static str,
- pub account_update_hash_param: &'static str,
+ pub signature_prefix: &'static poseidon::hash::LazyParam,
+ pub legacy_signature_prefix: &'static poseidon::hash::LazyParam,
+ pub account_update_hash_param: &'static poseidon::hash::LazyParam,
pub constraint_system_digests: &'static [[u8; 16]; 3],
pub default_peers: Vec<&'static str>,
pub circuits_config: &'static CircuitsConfig,
@@ -76,8 +81,9 @@ impl NetworkConfig {
Self {
name: mainnet::NAME,
network_id: mainnet::NETWORK_ID,
- signature_prefix: mainnet::SIGNATURE_PREFIX,
- account_update_hash_param: mainnet::ACCOUNT_UPDATE_HASH_PARAM,
+ signature_prefix: &MINA_SIGNATURE_MAINNET,
+ legacy_signature_prefix: &legacy::params::MINA_SIGNATURE_MAINNET,
+ account_update_hash_param: &MAINNET_ZKAPP_BODY,
constraint_system_digests: &mainnet::CONSTRAINT_SYSTEM_DIGESTS,
default_peers: mainnet::default_peers(),
circuits_config: &mainnet::CIRCUITS_CONFIG,
@@ -89,8 +95,9 @@ impl NetworkConfig {
Self {
name: devnet::NAME,
network_id: devnet::NETWORK_ID,
- signature_prefix: devnet::SIGNATURE_PREFIX,
- account_update_hash_param: devnet::ACCOUNT_UPDATE_HASH_PARAM,
+ signature_prefix: &CODA_SIGNATURE,
+ legacy_signature_prefix: &legacy::params::CODA_SIGNATURE,
+ account_update_hash_param: &TESTNET_ZKAPP_BODY,
constraint_system_digests: &devnet::CONSTRAINT_SYSTEM_DIGESTS,
default_peers: devnet::default_peers(),
circuits_config: &devnet::CIRCUITS_CONFIG,
diff --git a/core/src/snark/snark_cmp.rs b/core/src/snark/snark_cmp.rs
index 20e9147b0b..b354e817a9 100644
--- a/core/src/snark/snark_cmp.rs
+++ b/core/src/snark/snark_cmp.rs
@@ -11,13 +11,13 @@ pub struct SnarkCmp<'a> {
pub prover: &'a NonZeroCurvePoint,
}
-impl<'a> SnarkCmp<'a> {
+impl SnarkCmp<'_> {
pub fn tie_breaker_hash(&self) -> [u8; 32] {
super::tie_breaker_hash(&self.job_id, self.prover)
}
}
-impl<'a> Ord for SnarkCmp<'a> {
+impl Ord for SnarkCmp<'_> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.job_id
.cmp(&other.job_id)
@@ -26,7 +26,7 @@ impl<'a> Ord for SnarkCmp<'a> {
}
}
-impl<'a> PartialOrd for SnarkCmp<'a> {
+impl PartialOrd for SnarkCmp<'_> {
fn partial_cmp(&self, other: &Self) -> Option {
Some(self.cmp(other))
}
diff --git a/core/src/thread.rs b/core/src/thread.rs
index daabd4fc67..7752288db6 100644
--- a/core/src/thread.rs
+++ b/core/src/thread.rs
@@ -73,6 +73,24 @@ mod main_thread {
}));
rx.await.ok()
}
+
+ pub fn run_async_fn_in_main_thread_blocking(f: F) -> Option
+ where
+ T: 'static + Send,
+ FU: Future,
+ F: 'static + Send + FnOnce() -> FU,
+ {
+ let sender = MAIN_THREAD_TASK_SENDER
+ .get()
+ .expect("main thread not initialized");
+ let (tx, rx) = oneshot::channel();
+ let _ = sender.send(Box::pin(async move {
+ wasm_bindgen_futures::spawn_local(async move {
+ let _ = tx.send(f().await);
+ })
+ }));
+ rx.blocking_recv().ok()
+ }
}
#[cfg(target_family = "wasm")]
pub use main_thread::*;
diff --git a/core/src/transaction/mod.rs b/core/src/transaction/mod.rs
index 6378f1a6b8..4a4a9e5938 100644
--- a/core/src/transaction/mod.rs
+++ b/core/src/transaction/mod.rs
@@ -1,4 +1,7 @@
mod transaction_info;
pub use transaction_info::TransactionInfo;
+mod transaction_with_hash;
+pub use transaction_with_hash::*;
+
pub use mina_p2p_messages::v2::{MinaBaseUserCommandStableV2 as Transaction, TransactionHash};
diff --git a/core/src/transaction/transaction_with_hash.rs b/core/src/transaction/transaction_with_hash.rs
new file mode 100644
index 0000000000..e62cf6ae04
--- /dev/null
+++ b/core/src/transaction/transaction_with_hash.rs
@@ -0,0 +1,30 @@
+use serde::{Deserialize, Serialize};
+
+use super::{Transaction, TransactionHash};
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct TransactionWithHash = Transaction> {
+ hash: TransactionHash,
+ body: T,
+}
+
+impl> TransactionWithHash {
+ pub fn try_new(body: T) -> std::io::Result {
+ Ok(Self {
+ hash: body.as_ref().hash()?,
+ body,
+ })
+ }
+
+ pub fn hash(&self) -> &TransactionHash {
+ &self.hash
+ }
+
+ pub fn body(&self) -> &Transaction {
+ self.body.as_ref()
+ }
+
+ pub fn into_body(self) -> T {
+ self.body
+ }
+}
diff --git a/docker-compose.block-producer.yml b/docker-compose.block-producer.yml
index 352606c559..a738413167 100644
--- a/docker-compose.block-producer.yml
+++ b/docker-compose.block-producer.yml
@@ -2,16 +2,17 @@ services:
openmina-node:
image: openmina/openmina:${OPENMINA_TAG:-latest}
entrypoint: >
- sh -c "openmina node --producer-key /root/.openmina/producer-key $${COINBASE_RECEIVER:+--coinbase-receiver $$COINBASE_RECEIVER} $${OPENMINA_LIBP2P_EXTERNAL_IP:+--libp2p-external-ip $$OPENMINA_LIBP2P_EXTERNAL_IP}"
+ sh -c "openmina node --producer-key /root/.openmina/producer-key $${COINBASE_RECEIVER:+--coinbase-receiver $$COINBASE_RECEIVER} $${OPENMINA_LIBP2P_EXTERNAL_IP:+--libp2p-external-ip $$OPENMINA_LIBP2P_EXTERNAL_IP} $${OPENMINA_LIBP2P_PORT:+--libp2p-port $$OPENMINA_LIBP2P_PORT}"
ports:
- "3000:3000"
- - "8302:8302"
+ - "${OPENMINA_LIBP2P_PORT:-8302}:${OPENMINA_LIBP2P_PORT:-8302}"
volumes:
- ./openmina-workdir:/root/.openmina:rw
environment:
MINA_PRIVKEY_PASS: "${MINA_PRIVKEY_PASS:-}"
COINBASE_RECEIVER: "${COINBASE_RECEIVER:-}"
OPENMINA_LIBP2P_EXTERNAL_IP: "${OPENMINA_LIBP2P_EXTERNAL_IP}"
+ OPENMINA_LIBP2P_PORT: "${OPENMINA_LIBP2P_PORT}"
frontend:
image: openmina/frontend:${OPENMINA_FRONTEND_TAG:-latest}
diff --git a/docker-compose.local.producers.yml b/docker-compose.local.producers.yml
index 588aee6825..fd57492317 100644
--- a/docker-compose.local.producers.yml
+++ b/docker-compose.local.producers.yml
@@ -1,7 +1,7 @@
services:
local-producer-cluster:
container_name: local-producer-cluster
- image: openmina/openmina:0.11.0
+ image: openmina/openmina:0.12.0
environment:
- RUST_BACKTRACE=1
entrypoint: ["openmina-node-testing", "scenarios-generate", "--name", "simulation-small-forever-real-time"]
@@ -12,7 +12,7 @@ services:
frontend:
container_name: frontend
- image: openmina/frontend:0.11.0
+ image: openmina/frontend:0.12.0
environment:
OPENMINA_FRONTEND_ENVIRONMENT: block-producers
ports:
diff --git a/docker-compose.yml b/docker-compose.yml
index 32ba5ea634..b313c0245c 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -2,14 +2,15 @@ services:
openmina-node:
image: openmina/openmina:${OPENMINA_TAG:-latest}
entrypoint: >
- sh -c "openmina node $${OPENMINA_LIBP2P_EXTERNAL_IP:+--libp2p-external-ip $$OPENMINA_LIBP2P_EXTERNAL_IP}"
+ sh -c "openmina node $${OPENMINA_LIBP2P_EXTERNAL_IP:+--libp2p-external-ip $$OPENMINA_LIBP2P_EXTERNAL_IP} $${OPENMINA_LIBP2P_PORT:+--libp2p-port $$OPENMINA_LIBP2P_PORT}"
volumes:
- ./openmina-workdir:/root/.openmina:rw
ports:
- "3000:3000"
- - "8302:8302"
+ - "${OPENMINA_LIBP2P_PORT:-8302}:${OPENMINA_LIBP2P_PORT:-8302}"
environment:
OPENMINA_LIBP2P_EXTERNAL_IP: "${OPENMINA_LIBP2P_EXTERNAL_IP}"
+ OPENMINA_LIBP2P_PORT: "${OPENMINA_LIBP2P_PORT}"
frontend:
image: openmina/frontend:${OPENMINA_FRONTEND_TAG:-latest}
diff --git a/docker/producer-dashboard/Dockerfile b/docker/producer-dashboard/Dockerfile
index e9970ff97e..c6ae4a58f0 100644
--- a/docker/producer-dashboard/Dockerfile
+++ b/docker/producer-dashboard/Dockerfile
@@ -1,4 +1,4 @@
-FROM rust:1.80 AS app-builder
+FROM rust:1.83 AS app-builder
WORKDIR /usr/src/openmina-producer-dashboard
@@ -77,10 +77,10 @@ RUN eval $(opam config env) && make build_all_sigs
FROM ubuntu:latest
RUN apt-get update && apt-get install -y libpq5 libjemalloc2
-
+
COPY --from=app-builder /usr/local/cargo/bin/openmina-producer-dashboard /usr/local/bin/openmina-producer-dashboard
COPY --from=mina-builder /go/mina/src/app/libp2p_helper/result/bin/libp2p_helper /usr/local/bin/coda-libp2p_helper
COPY --from=mina-builder /go/mina/_build/default/src/app/cli/src/mina_testnet_signatures.exe /usr/local/bin/mina
# TODO: replace
-ENTRYPOINT [ "openmina-producer-dashboard" ]
\ No newline at end of file
+ENTRYPOINT [ "openmina-producer-dashboard" ]
diff --git a/docs/alpha-testing-guide.md b/docs/alpha-testing-guide.md
index 76c182248d..adaf7a9b9f 100644
--- a/docs/alpha-testing-guide.md
+++ b/docs/alpha-testing-guide.md
@@ -1,4 +1,4 @@
-# Test Alpha Rust Node on Devnet
+# Run Non-Block Producing Node on Devnet
This guide will walk you through running the **Alpha Rust Node** on Devnet using Docker. Follow these steps to set up the node and [Provide Feedback](#4-provide-feedback) on this Alpha release.
@@ -22,6 +22,12 @@ Ensure you have **Docker** installed:
cd openmina-vX.Y.Z-docker-compose
```
+ Additional optional parameters:
+
+ `OPENMINA_LIBP2P_EXTERNAL_IP` Sets your node’s external IP address to help other nodes find it.
+
+ `OPENMINA_LIBP2P_PORT` Sets the port for Libp2p communication.
+
3. **Start the Node on Devnet and Save Logs**:
Start the node and save the logs for later analysis:
diff --git a/docs/assets/NodeUI.png b/docs/assets/NodeUI.png
new file mode 100644
index 0000000000..1c8024777f
Binary files /dev/null and b/docs/assets/NodeUI.png differ
diff --git a/docs/assets/OpenMinaGH_Dark.svg b/docs/assets/OpenMinaGH_Dark.svg
new file mode 100644
index 0000000000..18d979943b
--- /dev/null
+++ b/docs/assets/OpenMinaGH_Dark.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/docs/assets/OpenMinaGH_Light.svg b/docs/assets/OpenMinaGH_Light.svg
new file mode 100644
index 0000000000..197a1e2a13
--- /dev/null
+++ b/docs/assets/OpenMinaGH_Light.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/docs/block-producer-guide.md b/docs/block-producer-guide.md
index 515c8bb793..166c34faac 100644
--- a/docs/block-producer-guide.md
+++ b/docs/block-producer-guide.md
@@ -1,4 +1,4 @@
-# Rust Node Block Production Testing on Devnet
+# Run Block Producing Node on Devnet
This guide is intended for setting up block producer nodes on **Mina Devnet** only.
Do not use this guide for Mina Mainnet until necessary security audits are complete.
@@ -43,6 +43,12 @@ Ensure Docker and Docker Compose are installed on your system - [Docker Installa
docker compose -f docker-compose.block-producer.yml up -d --pull always
```
+ Optional parameters:
+
+ `OPENMINA_LIBP2P_EXTERNAL_IP` Sets your node’s external IP address to help other nodes find it.
+
+ `OPENMINA_LIBP2P_PORT` Sets the port for Libp2p communication.
+
4. **Go to Dashboard**
Visit [http://localhost:8070](http://localhost:8070) to [monitor sync](http://localhost:8070/dashboard) and [block production](http://localhost:8070/block-production).
diff --git a/docs/building-from-source-guide.md b/docs/building-from-source-guide.md
new file mode 100644
index 0000000000..dd749d8417
--- /dev/null
+++ b/docs/building-from-source-guide.md
@@ -0,0 +1,102 @@
+# How to build and launch a node from source
+
+This installation guide has been tested on Debian and Ubuntu and should work on most distributions of Linux.
+
+## Prerequisites
+
+Ubuntu or Debian-based Linux distribution with the following packages installed:
+
+- `curl`
+- `git`
+- `libssl-dev`
+- `pkg-config`
+- `protobuf-compiler`
+- `build-essential`
+
+Example (debian-based):
+
+```sh
+# Either using "sudo" or as the "root" user
+sudo apt install curl git libssl-dev pkg-config protobuf-compiler build-essential
+```
+
+Example (macOS):
+
+If you have not yet installed homebrew:
+
+```sh
+/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
+```
+
+```sh
+brew install curl git openssl pkg-config protobuf gcc make
+```
+
+## Steps (for Debian-based Linux distros and macOS):
+
+Open up the command line and enter the following:
+
+And then:
+
+```sh
+# Install rustup and set the default Rust toolchain to 1.80 (newer versions work too)
+curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.80
+# Setup the current shell with rustup
+source "$HOME/.cargo/env"
+# Clone the openmina repository
+git clone https://github.com/openmina/openmina.git
+cd openmina/
+# Build and run the node
+cargo run --release -p cli node
+```
+
+# How to launch the UI:
+
+## Prerequisites
+
+### 1. Node.js v20.11.1
+
+#### MacOS
+
+```bash
+/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
+brew install node@20.11.1
+```
+
+#### Linux
+
+```bash
+curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
+source ~/.bashrc
+nvm install 20.11.1
+```
+
+#### Windows
+
+Download [Node.js v20.11.1](https://nodejs.org/) from the official website, open the installer and follow the prompts to complete the installation.
+
+### 2. Angular CLI v16.2.0
+
+```bash
+npm install -g @angular/cli@16.2.0
+```
+
+### 3. Installation
+
+Open a terminal and navigate to this project's root directory
+
+```bash
+cd PROJECT_LOCATION/openmina/frontend
+```
+
+Install the dependencies
+
+```bash
+npm install
+```
+
+## Run the application
+
+```bash
+npm start
+```
diff --git a/docs/local-demo-guide.md b/docs/local-demo-guide.md
new file mode 100644
index 0000000000..487c0646b9
--- /dev/null
+++ b/docs/local-demo-guide.md
@@ -0,0 +1,56 @@
+# Run Block Producers on local network
+
+Once you have completed the [pre-requisites](./docs/docker-installation.md) for your operating system, follow these steps:
+
+## Setup Option 1: Download Docker Compose Files from the Release
+
+1. **Download the Docker Compose files:**
+
+ - Go to the [Releases page](https://github.com/openmina/openmina/releases) of this repository.
+ - Download the latest `openmina-vX.Y.Z-docker-compose.zip` (or `.tar.gz`) file corresponding to the release version (available since v0.8.0).
+
+2. **Extract the files:**
+
+ - Unzip or untar the downloaded file:
+ ```bash
+ unzip openmina-vX.Y.Z-docker-compose.zip
+ ```
+ or
+ ```bash
+ tar -xzvf openmina-vX.Y.Z-docker-compose.tar.gz
+ ```
+ - Replace `vX.Y.Z` with the actual release version you downloaded.
+
+3. **Navigate to the extracted directory:**
+ ```bash
+ cd openmina-vX.Y.Z-docker-compose
+ ```
+
+## Setup Option 2: Clone the Repository
+
+1. **Clone this repository:**
+
+ ```bash
+ git clone https://github.com/openmina/openmina.git
+ ```
+
+2. **Navigate to the repository:**
+ ```bash
+ cd openmina
+ ```
+
+## Launch
+
+**Run the following command to start the demo:**
+
+```bash
+docker compose -f docker-compose.local.producers.yml up --pull always --force-recreate
+```
+
+And finally:
+
+**Open your browser and visit [http://localhost:8070](http://localhost:8070)**
+
+You should see the following screen:
+
+
diff --git a/frontend/.gitignore b/frontend/.gitignore
index e10321af5a..bf0f3a86c7 100644
--- a/frontend/.gitignore
+++ b/frontend/.gitignore
@@ -44,3 +44,11 @@ Thumbs.db
# Open Mina
/src/assets/webnode/pkg
/src/assets/webnode/circuit-blobs
+
+# Sentry Config File
+.sentryclirc
+
+# Firebase
+.firebase
+*-debug.log
+.runtimeconfig.json
diff --git a/frontend/Dockerfile b/frontend/Dockerfile
index e993ee8550..ad489347c7 100644
--- a/frontend/Dockerfile
+++ b/frontend/Dockerfile
@@ -9,13 +9,14 @@ RUN npm prune --production
RUN echo "---------- USING APACHE ----------"
+
FROM httpd:2.4
RUN apt-get update && \
apt-get install -y curl && \
rm -rf /var/lib/apt/lists/*
-COPY --from=BUILD_IMAGE /app/dist/frontend /usr/local/apache2/htdocs/
+COPY --from=BUILD_IMAGE /app/dist/frontend/browser /usr/local/apache2/htdocs/
COPY --from=BUILD_IMAGE /app/httpd.conf /usr/local/apache2/conf/httpd.conf
COPY docker/startup.sh /usr/local/bin/startup.sh
@@ -23,4 +24,4 @@ RUN chmod +x /usr/local/bin/startup.sh
ENTRYPOINT ["/usr/local/bin/startup.sh"]
-CMD ["httpd-foreground"]
\ No newline at end of file
+CMD ["httpd-foreground"]
diff --git a/frontend/README.md b/frontend/README.md
index ded497ce4c..7bff8ff863 100644
--- a/frontend/README.md
+++ b/frontend/README.md
@@ -4,13 +4,13 @@ This is a simple Angular application that will help you to see the behaviour of
## Prerequisites
-### 1. Node.js v20.11.1
+### 1. Node.js v23.1.0
#### MacOS
```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
-brew install node@20.11.1
+brew install node@23.1.0
```
#### Linux
@@ -18,17 +18,17 @@ brew install node@20.11.1
```bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
source ~/.bashrc
-nvm install 20.11.1
+nvm install 23.1.0
```
#### Windows
-Download [Node.js v20.11.1](https://nodejs.org/) from the official website, open the installer and follow the prompts to complete the installation.
+Download [Node.js v23.1.0](https://nodejs.org/) from the official website, open the installer and follow the prompts to complete the installation.
-### 2. Angular CLI v16.2.0
+### 2. Angular CLI v17.3.0
```bash
-npm install -g @angular/cli@16.2.0
+npm install -g @angular/cli@17.3.0
```
### 3. Installation
diff --git a/frontend/angular.json b/frontend/angular.json
index 2fc3226724..d5c75245ff 100644
--- a/frontend/angular.json
+++ b/frontend/angular.json
@@ -34,7 +34,7 @@
"customWebpackConfig": {
"path": "./webpack.config.js"
},
- "outputPath": "dist/frontend",
+ "outputPath": "dist/frontend/browser",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": [
@@ -46,6 +46,7 @@
"assets": [
"src/assets"
],
+ "sourceMap": true,
"styles": [
"src/styles.scss"
],
@@ -134,7 +135,6 @@
],
"inlineStyleLanguage": "scss",
"assets": [
- "src/favicon.ico",
"src/assets"
],
"styles": [
@@ -142,6 +142,93 @@
],
"scripts": []
}
+ },
+ "server": {
+ "builder": "@angular-devkit/build-angular:server",
+ "options": {
+ "outputPath": "dist/frontend/server",
+ "main": "server.ts",
+ "tsConfig": "tsconfig.server.json",
+ "stylePreprocessorOptions": {
+ "includePaths": [
+ "src/assets",
+ "src/assets/styles",
+ "src/assets/styles/utilities",
+ "src/assets/images"
+ ]
+ },
+ "inlineStyleLanguage": "scss"
+ },
+ "configurations": {
+ "production": {
+ "outputHashing": "media",
+ "fileReplacements": [
+ {
+ "replace": "src/environments/environment.ts",
+ "with": "src/environments/environment.prod.ts"
+ }
+ ]
+ },
+ "development": {
+ "buildOptimizer": false,
+ "optimization": false,
+ "sourceMap": true,
+ "extractLicenses": false,
+ "vendorChunk": true
+ },
+ "local": {
+ "outputHashing": "media",
+ "fileReplacements": [
+ {
+ "replace": "src/environments/environment.ts",
+ "with": "src/environments/environment.local.ts"
+ }
+ ]
+ },
+ "producer": {
+ "outputHashing": "media",
+ "fileReplacements": [
+ {
+ "replace": "src/environments/environment.ts",
+ "with": "src/environments/environment.producer.ts"
+ }
+ ]
+ }
+ },
+ "defaultConfiguration": "production"
+ },
+ "serve-ssr": {
+ "builder": "@angular-devkit/build-angular:ssr-dev-server",
+ "configurations": {
+ "development": {
+ "browserTarget": "frontend:build:development",
+ "serverTarget": "frontend:server:development"
+ },
+ "production": {
+ "browserTarget": "frontend:build:production",
+ "serverTarget": "frontend:server:production"
+ }
+ },
+ "defaultConfiguration": "development"
+ },
+ "prerender": {
+ "builder": "@angular-devkit/build-angular:prerender",
+ "options": {
+ "routes": [
+ "/"
+ ]
+ },
+ "configurations": {
+ "production": {
+ "browserTarget": "frontend:build:production",
+ "serverTarget": "frontend:server:production"
+ },
+ "development": {
+ "browserTarget": "frontend:build:development",
+ "serverTarget": "frontend:server:development"
+ }
+ },
+ "defaultConfiguration": "production"
}
}
}
diff --git a/frontend/cypress/e2e/dashboard/ledgers.cy.ts b/frontend/cypress/e2e/dashboard/ledgers.cy.ts
index 21c8b8c663..22ecbdd6bd 100644
--- a/frontend/cypress/e2e/dashboard/ledgers.cy.ts
+++ b/frontend/cypress/e2e/dashboard/ledgers.cy.ts
@@ -88,7 +88,7 @@ describe('DASHBOARD LEDGERS', () => {
cy.get('mina-dashboard-ledger > div:first-child > div.h-minus-xl > .group:nth-child(3) div.primary')
.then((el: any) => {
let progress;
- progress = state.rpcStats.rootLedger?.fetched / state.rpcStats.rootLedger?.estimation * 100 || 0;
+ progress = state.rpcStats.snarkedRootLedger?.fetched / state.rpcStats.snarkedRootLedger?.estimation * 100 || 0;
progress = Math.round(progress);
if (state.nodes[0].ledgers.rootSnarked.state === 'success') {
diff --git a/frontend/docker/startup.sh b/frontend/docker/startup.sh
index 7f167362f2..3ce73c91a2 100644
--- a/frontend/docker/startup.sh
+++ b/frontend/docker/startup.sh
@@ -27,6 +27,8 @@ download_circuit_files() {
CIRCUITS_VERSION="3.0.1devnet"
DEVNET_CIRCUIT_FILES=(
+ "block_verifier_index.postcard"
+ "transaction_verifier_index.postcard"
"step-step-proving-key-blockchain-snark-step-0-55f640777b6486a6fd3fdbc3fcffcc60_gates.json"
"step-step-proving-key-blockchain-snark-step-0-55f640777b6486a6fd3fdbc3fcffcc60_internal_vars.bin"
"step-step-proving-key-blockchain-snark-step-0-55f640777b6486a6fd3fdbc3fcffcc60_rows_rev.bin"
@@ -77,15 +79,15 @@ download_wasm_files() {
echo "Error: OPENMINA_WASM_VERSION is not set. Exiting."
exit 1
fi
-
+
WASM_URL="$OPENMINA_BASE_URL/openmina/releases/download/$OPENMINA_WASM_VERSION/openmina-$OPENMINA_WASM_VERSION-webnode-wasm.tar.gz"
TARGET_DIR="/usr/local/apache2/htdocs/assets/webnode/pkg"
-
+
mkdir -p "$TARGET_DIR"
echo "Downloading WASM files from $WASM_URL..."
curl -s -L --retry 3 --retry-delay 5 -o "/tmp/openmina-$OPENMINA_WASM_VERSION-webnode-wasm.tar.gz" "$WASM_URL"
-
+
if [[ $? -ne 0 ]]; then
echo "Failed to download the WASM file after 3 attempts, exiting."
exit 1
@@ -93,19 +95,95 @@ download_wasm_files() {
echo "WASM file downloaded successfully. Extracting to $TARGET_DIR..."
tar -xzf "/tmp/openmina-$OPENMINA_WASM_VERSION-webnode-wasm.tar.gz" -C "$TARGET_DIR"
-
+
# Check if the extraction was successful
if [[ $? -ne 0 ]]; then
echo "Failed to extract the WASM file, exiting."
exit 1
else
echo "WASM files extracted successfully to $TARGET_DIR"
+
+ # Inject caching logic into openmina_node_web.js
+ OPENMINA_JS="$TARGET_DIR/openmina_node_web.js"
+ INDEX_HTML="/usr/local/apache2/htdocs/index.html"
+ inject_caching_logic "$OPENMINA_JS" "$INDEX_HTML"
fi
fi
rm "/tmp/openmina-$OPENMINA_WASM_VERSION-webnode-wasm.tar.gz"
}
+get_short_sha1() {
+ local file="$1"
+ if [ -z "$file" ]; then
+ echo "Usage: get_short_sha1 filename" >&2
+ return 1
+ fi
+ if [ ! -f "$file" ]; then
+ echo "Error: File not found: $file" >&2
+ return 1
+ fi
+
+ if command -v sha1sum >/dev/null 2>&1; then
+ sha1sum "$file" | awk '{ print substr($1,1,8) }'
+ elif command -v openssl >/dev/null 2>&1; then
+ openssl sha1 "$file" | awk '{ print substr($2,1,8) }'
+ else
+ echo "Error: Neither sha1sum nor openssl is available for hashing." >&2
+ return 1
+ fi
+}
+
+inject_caching_logic() {
+ local js_file="$1"
+ local index_html="$2"
+
+ # Check if JavaScript file exists
+ if [ ! -f "$js_file" ]; then
+ echo "Warning: $js_file not found. Caching logic not injected."
+ return 0
+ fi
+
+ echo "Injecting caching logic into $js_file"
+
+ # Define target files
+ local js_target_file="${TARGET_DIR}/openmina_node_web.js"
+ local wasm_target_file="${TARGET_DIR}/openmina_node_web_bg.wasm"
+
+ # Generate checksum hashes
+ local js_file_hash
+ js_file_hash=$(get_short_sha1 "$js_target_file") || { echo "Failed to get hash for $js_target_file"; return 1; }
+
+ local wasm_file_hash
+ wasm_file_hash=$(get_short_sha1 "$wasm_target_file") || { echo "Failed to get hash for $wasm_target_file"; return 1; }
+
+ # Check if hashed files already exist to prevent multiple injections
+ local js_new_file="${TARGET_DIR}/openmina_node_web.${js_file_hash}.js"
+ local wasm_new_file="${TARGET_DIR}/openmina_node_web_bg.${wasm_file_hash}.wasm"
+
+ if [[ -f "$js_new_file" ]] && [[ -f "$wasm_new_file" ]]; then
+ echo "Hashed files already exist. Skipping caching logic injection."
+ return 0
+ fi
+
+ # Replace openmina_node_web_bg.wasm with openmina_node_web_bg..wasm in JS file
+ sed -i "s/openmina_node_web_bg\.wasm/openmina_node_web_bg.${wasm_file_hash}.wasm/g" "$js_file" || { echo "Failed to update wasm filename in $js_file"; return 1; }
+
+ # Add cache headers to fetch calls in JS file
+ sed -i 's/module_or_path = fetch(module_or_path);/module_or_path = fetch(module_or_path, { cache: "force-cache", headers: { "Cache-Control": "max-age=31536000, immutable" } });/' "$js_file" || { echo "Failed to inject cache headers into $js_file"; return 1; }
+
+ # Rename wasm file with hash
+ mv "$wasm_target_file" "$wasm_new_file" || { echo "Failed to rename $wasm_target_file to $wasm_new_file"; return 1; }
+
+ # Rename JS file with hash
+ mv "$js_target_file" "$js_new_file" || { echo "Failed to rename $js_target_file to $js_new_file"; return 1; }
+
+ # Replace JS filename in index.html
+ sed -i "s/openmina_node_web\.js/openmina_node_web.${js_file_hash}.js/g" "$index_html" || { echo "Failed to update JS filename in $index_html"; return 1; }
+
+ echo "Successfully injected caching logic into $js_file"
+}
+
if [ -n "$OPENMINA_FRONTEND_ENVIRONMENT" ]; then
echo "Using environment: $OPENMINA_FRONTEND_ENVIRONMENT"
cp -f /usr/local/apache2/htdocs/assets/environments/"$OPENMINA_FRONTEND_ENVIRONMENT".js \
diff --git a/frontend/firebase.json b/frontend/firebase.json
new file mode 100644
index 0000000000..314966c493
--- /dev/null
+++ b/frontend/firebase.json
@@ -0,0 +1,58 @@
+{
+ "hosting": {
+ "public": "dist/frontend/browser",
+ "ignore": [
+ "firebase.json",
+ "**/.*",
+ "**/node_modules/**"
+ ],
+ "rewrites": [
+ {
+ "source": "**",
+ "destination": "/index.html"
+ }
+ ],
+ "headers": [
+ {
+ "source": "/service-worker.js",
+ "headers": [
+ {
+ "key": "Cache-Control",
+ "value": "no-cache"
+ }
+ ]
+ },
+ {
+ "source": "/**",
+ "headers": [
+ {
+ "key": "Cross-Origin-Opener-Policy",
+ "value": "same-origin"
+ },
+ {
+ "key": "Cross-Origin-Embedder-Policy",
+ "value": "require-corp"
+ }
+ ]
+ },
+ {
+ "source": "**/*.@(js|wasm|html)",
+ "headers": [
+ {
+ "key": "Cache-Control",
+ "value": "no-cache, no-store, must-revalidate"
+ }
+ ]
+ },
+ {
+ "source": "/",
+ "headers": [
+ {
+ "key": "Cache-Control",
+ "value": "no-cache, no-store, must-revalidate"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/frontend/httpd.conf b/frontend/httpd.conf
index f82a328e46..c333bb343c 100644
--- a/frontend/httpd.conf
+++ b/frontend/httpd.conf
@@ -1,68 +1,8 @@
-#
-# This is the main Apache HTTP server configuration file. It contains the
-# configuration directives that give the server its instructions.
-# See for detailed information.
-# In particular, see
-#
-# for a discussion of each configuration directive.
-#
-# Do NOT simply read the instructions in here without understanding
-# what they do. They're here only as hints or reminders. If you are unsure
-# consult the online docs. You have been warned.
-#
-# Configuration and logfile names: If the filenames you specify for many
-# of the server's control files begin with "/" (or "drive:/" for Win32), the
-# server will use that explicit path. If the filenames do *not* begin
-# with "/", the value of ServerRoot is prepended -- so "logs/access_log"
-# with ServerRoot set to "/usr/local/apache2" will be interpreted by the
-# server as "/usr/local/apache2/logs/access_log", whereas "/logs/access_log"
-# will be interpreted as '/logs/access_log'.
-#
-# ServerRoot: The top of the directory tree under which the server's
-# configuration, error, and log files are kept.
-#
-# Do not add a slash at the end of the directory path. If you point
-# ServerRoot at a non-local disk, be sure to specify a local disk on the
-# Mutex directive, if file-based mutexes are used. If you wish to share the
-# same ServerRoot for multiple httpd daemons, you will need to change at
-# least PidFile.
-#
ServerRoot "/usr/local/apache2"
-#
-# Mutex: Allows you to set the mutex mechanism and mutex file directory
-# for individual mutexes, or change the global defaults
-#
-# Uncomment and change the directory if mutexes are file-based and the default
-# mutex file directory is not on a local disk or is not appropriate for some
-# other reason.
-#
-# Mutex default:logs
-
-#
-# Listen: Allows you to bind Apache to specific IP addresses and/or
-# ports, instead of the default. See also the
-# directive.
-#
-# Change this to Listen on specific IP addresses as shown below to
-# prevent Apache from glomming onto all bound IP addresses.
-#
-#Listen 12.34.56.78:80
Listen 80
-#
-# Dynamic Shared Object (DSO) Support
-#
-# To be able to use the functionality of a module which was built as a DSO you
-# have to place corresponding `LoadModule' lines at this location so the
-# directives contained in it are actually available _before_ they are used.
-# Statically compiled modules (those listed by `httpd -l') do not need
-# to be loaded here.
-#
-# Example:
-# LoadModule foo_module modules/mod_foo.so
-#
LoadModule mpm_event_module modules/mod_mpm_event.so
#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
#LoadModule mpm_worker_module modules/mod_mpm_worker.so
@@ -83,55 +23,18 @@ LoadModule authz_core_module modules/mod_authz_core.so
#LoadModule authnz_fcgi_module modules/mod_authnz_fcgi.so
LoadModule access_compat_module modules/mod_access_compat.so
LoadModule auth_basic_module modules/mod_auth_basic.so
-#LoadModule auth_form_module modules/mod_auth_form.so
-#LoadModule auth_digest_module modules/mod_auth_digest.so
-#LoadModule allowmethods_module modules/mod_allowmethods.so
-#LoadModule isapi_module modules/mod_isapi.so
-#LoadModule file_cache_module modules/mod_file_cache.so
-#LoadModule cache_module modules/mod_cache.so
-#LoadModule cache_disk_module modules/mod_cache_disk.so
-#LoadModule cache_socache_module modules/mod_cache_socache.so
-#LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
-#LoadModule socache_dbm_module modules/mod_socache_dbm.so
-#LoadModule socache_memcache_module modules/mod_socache_memcache.so
-#LoadModule socache_redis_module modules/mod_socache_redis.so
-#LoadModule watchdog_module modules/mod_watchdog.so
-#LoadModule macro_module modules/mod_macro.so
-#LoadModule dbd_module modules/mod_dbd.so
-#LoadModule bucketeer_module modules/mod_bucketeer.so
-#LoadModule dumpio_module modules/mod_dumpio.so
-#LoadModule echo_module modules/mod_echo.so
-#LoadModule example_hooks_module modules/mod_example_hooks.so
-#LoadModule case_filter_module modules/mod_case_filter.so
-#LoadModule case_filter_in_module modules/mod_case_filter_in.so
-#LoadModule example_ipc_module modules/mod_example_ipc.so
-#LoadModule buffer_module modules/mod_buffer.so
-#LoadModule data_module modules/mod_data.so
-#LoadModule ratelimit_module modules/mod_ratelimit.so
LoadModule reqtimeout_module modules/mod_reqtimeout.so
#LoadModule ext_filter_module modules/mod_ext_filter.so
#LoadModule request_module modules/mod_request.so
#LoadModule include_module modules/mod_include.so
LoadModule filter_module modules/mod_filter.so
-#LoadModule reflector_module modules/mod_reflector.so
-#LoadModule substitute_module modules/mod_substitute.so
-#LoadModule sed_module modules/mod_sed.so
-#LoadModule charset_lite_module modules/mod_charset_lite.so
-#LoadModule deflate_module modules/mod_deflate.so
-#LoadModule xml2enc_module modules/mod_xml2enc.so
-#LoadModule proxy_html_module modules/mod_proxy_html.so
-#LoadModule brotli_module modules/mod_brotli.so
LoadModule mime_module modules/mod_mime.so
#LoadModule ldap_module modules/mod_ldap.so
LoadModule log_config_module modules/mod_log_config.so
-#LoadModule log_debug_module modules/mod_log_debug.so
-#LoadModule log_forensic_module modules/mod_log_forensic.so
-#LoadModule logio_module modules/mod_logio.so
-#LoadModule lua_module modules/mod_lua.so
LoadModule env_module modules/mod_env.so
#LoadModule mime_magic_module modules/mod_mime_magic.so
#LoadModule cern_meta_module modules/mod_cern_meta.so
-#LoadModule expires_module modules/mod_expires.so
+LoadModule expires_module modules/mod_expires.so
LoadModule headers_module modules/mod_headers.so
#LoadModule ident_module modules/mod_ident.so
#LoadModule usertrack_module modules/mod_usertrack.so
@@ -148,29 +51,7 @@ LoadModule proxy_http_module modules/mod_proxy_http.so
#LoadModule proxy_uwsgi_module modules/mod_proxy_uwsgi.so
#LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
-#LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
-#LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
-#LoadModule proxy_express_module modules/mod_proxy_express.so
-#LoadModule proxy_hcheck_module modules/mod_proxy_hcheck.so
-#LoadModule session_module modules/mod_session.so
-#LoadModule session_cookie_module modules/mod_session_cookie.so
-#LoadModule session_crypto_module modules/mod_session_crypto.so
-#LoadModule session_dbd_module modules/mod_session_dbd.so
-#LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
-#LoadModule slotmem_plain_module modules/mod_slotmem_plain.so
LoadModule ssl_module modules/mod_ssl.so
-#LoadModule optional_hook_export_module modules/mod_optional_hook_export.so
-#LoadModule optional_hook_import_module modules/mod_optional_hook_import.so
-#LoadModule optional_fn_import_module modules/mod_optional_fn_import.so
-#LoadModule optional_fn_export_module modules/mod_optional_fn_export.so
-#LoadModule dialup_module modules/mod_dialup.so
-#LoadModule http2_module modules/mod_http2.so
-#LoadModule proxy_http2_module modules/mod_proxy_http2.so
-#LoadModule md_module modules/mod_md.so
-#LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
-#LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
-#LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so
-#LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so
LoadModule unixd_module modules/mod_unixd.so
#LoadModule heartbeat_module modules/mod_heartbeat.so
#LoadModule heartmonitor_module modules/mod_heartmonitor.so
@@ -186,10 +67,6 @@ LoadModule autoindex_module modules/mod_autoindex.so
#LoadModule cgi_module modules/mod_cgi.so
-#LoadModule dav_fs_module modules/mod_dav_fs.so
-#LoadModule dav_lock_module modules/mod_dav_lock.so
-#LoadModule vhost_alias_module modules/mod_vhost_alias.so
-#LoadModule negotiation_module modules/mod_negotiation.so
LoadModule dir_module modules/mod_dir.so
#LoadModule imagemap_module modules/mod_imagemap.so
#LoadModule actions_module modules/mod_actions.so
@@ -198,23 +75,6 @@ LoadModule dir_module modules/mod_dir.so
LoadModule alias_module modules/mod_alias.so
LoadModule rewrite_module modules/mod_rewrite.so
-
- RewriteEngine On
-
- # Exclude /openmina-node from the general rewrite rules
- RewriteCond %{REQUEST_URI} ^/openmina-node/ [NC,OR]
- RewriteCond %{REQUEST_URI} ^/mina/webrtc/signal [NC]
- RewriteRule ^ - [L]
-
- # If an existing asset or directory is requested go to it as it is
- RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
- RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
- RewriteRule ^ - [L]
-
- # If the requested resource doesn't exist, use index.html
- RewriteRule ^ /index.html
-
-
SSLProxyEngine On
@@ -228,121 +88,70 @@ SSLProxyEngine On
-#
-# If you wish httpd to run as a different user or group, you must run
-# httpd as root initially and it will switch.
-#
-# User/Group: The name (or #number) of the user/group to run httpd as.
-# It is usually good practice to create a dedicated user and group for
-# running httpd, as with most system services.
-#
+
User www-data
Group www-data
-# 'Main' server configuration
-#
-# The directives in this section set up the values used by the 'main'
-# server, which responds to any requests that aren't handled by a
-# definition. These values also provide defaults for
-# any containers you may define later in the file.
-#
-# All of these directives may appear inside containers,
-# in which case these default settings will be overridden for the
-# virtual host being defined.
-#
-
-#
-# ServerAdmin: Your address, where problems with the server should be
-# e-mailed. This address appears on some server-generated pages, such
-# as error documents. e.g. admin@your-domain.com
-#
+# send issue emails to
ServerAdmin you@example.com
-#
-# ServerName gives the name and port that the server uses to identify itself.
-# This can often be determined automatically, but we recommend you specify
-# it explicitly to prevent problems during startup.
-#
-# If your host doesn't have a registered DNS name, enter its IP address here.
-#
-#ServerName www.example.com:80
-
-#
# Deny access to the entirety of your server's filesystem. You must
# explicitly permit access to web content directories in other
# blocks below.
-#
AllowOverride none
Require all denied
-#
-# Note that from this point forward you must specifically allow
-# particular features to be enabled - so if something's not working as
-# you might expect, make sure that you have specifically enabled it
-# below.
-#
-
-#
-# DocumentRoot: The directory out of which you will serve your
-# documents. By default, all requests are taken from this directory, but
-# symbolic links and aliases may be used to point to other locations.
-#
DocumentRoot "/usr/local/apache2/htdocs"
- #
- # Possible values for the Options directive are "None", "All",
- # or any combination of:
- # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
- #
- # Note that "MultiViews" must be named *explicitly* --- "Options All"
- # doesn't give it to you.
- #
- # The Options directive is both complicated and important. Please see
- # http://httpd.apache.org/docs/2.4/mod/core.html#options
- # for more information.
- #
Options Indexes FollowSymLinks
-
- #
- # AllowOverride controls what directives may be placed in .htaccess files.
- # It can be "All", "None", or any combination of the keywords:
- # AllowOverride FileInfo AuthConfig Limit
- #
- AllowOverride None
-
- #
- # Controls who can get stuff from this server.
- #
+ AllowOverride All
Require all granted
+ DirectoryIndex index.html
+ DirectorySlash On
-#
-# DirectoryIndex: sets the file that Apache will serve if a directory
-# is requested.
-#
DirectoryIndex index.html
-#
+
+
+
+ RewriteEngine On
+
+ # Exclude specific paths from rewriting if needed
+ RewriteCond %{REQUEST_URI} ^/openmina-node/ [NC,OR]
+ RewriteCond %{REQUEST_URI} ^/mina/webrtc/signal [NC]
+ RewriteRule ^ - [L]
+
+ # Serve correct MIME type for hashed JS files
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteRule ^(.+)\.([0-9a-f]+)\.js$ $1.js [L]
+
+ # Your existing Angular routing rules
+ RewriteRule ^index\.html$ - [L]
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteCond %{REQUEST_FILENAME} !-d
+ RewriteRule . /index.html [L]
+
+
+ AddType application/javascript .js
+
# The following lines prevent .htaccess and .htpasswd files from being
# viewed by Web clients.
-#
Require all denied
-#
# ErrorLog: The location of the error log file.
# If you do not specify an ErrorLog directive within a
# container, error messages relating to that virtual host will be
# logged here. If you *do* define an error logfile for a
# container, that host's errors will be logged there and not here.
-#
ErrorLog /proc/self/fd/2
#
@@ -387,32 +196,6 @@ LogLevel warn
- #
- # Redirect: Allows you to tell clients about documents that used to
- # exist in your server's namespace, but do not anymore. The client
- # will make a new request for the document at its new location.
- # Example:
- # Redirect permanent /foo http://www.example.com/bar
-
- #
- # Alias: Maps web paths into filesystem paths and is used to
- # access content that does not live under the DocumentRoot.
- # Example:
- # Alias /webpath /full/filesystem/path
- #
- # If you include a trailing / on /webpath then the server will
- # require it to be present in the URL. You will also likely
- # need to provide a section to allow access to
- # the filesystem path.
-
- #
- # ScriptAlias: This controls which directories contain server scripts.
- # ScriptAliases are essentially the same as Aliases, except that
- # documents in the target directory are treated as applications and
- # run by the server when requested rather than as documents sent to the
- # client. The same rules about trailing "/" apply to ScriptAlias
- # directives as to Alias.
- #
ScriptAlias /cgi-bin/ "/usr/local/apache2/cgi-bin/"
@@ -425,10 +208,8 @@ LogLevel warn
#Scriptsock cgisock
-#
# "/usr/local/apache2/cgi-bin" should be changed to whatever your ScriptAliased
# CGI directory exists, if you have that configured.
-#
AllowOverride None
Options None
@@ -436,137 +217,48 @@ LogLevel warn
- #
# Avoid passing HTTP_PROXY environment to CGI's on this or any proxied
# backend servers which have lingering "httpoxy" defects.
# 'Proxy' request header is undefined by the IETF, not listed by IANA
- #
RequestHeader unset Proxy early
- #
# TypesConfig points to the file containing the list of mappings from
# filename extension to MIME-type.
- #
TypesConfig conf/mime.types
- #
- # AddType allows you to add to or override the MIME configuration
- # file specified in TypesConfig for specific file types.
- #
- #AddType application/x-gzip .tgz
- #
- # AddEncoding allows you to have certain browsers uncompress
- # information on the fly. Note: Not all browsers support this.
- #
- #AddEncoding x-compress .Z
- #AddEncoding x-gzip .gz .tgz
- #
- # If the AddEncoding directives above are commented-out, then you
- # probably should define those extensions to indicate media types:
- #
- AddType application/x-compress .Z
- AddType application/x-gzip .gz .tgz
-
- #
- # AddHandler allows you to map certain file extensions to "handlers":
- # actions unrelated to filetype. These can be either built into the server
- # or added with the Action directive (see below)
- #
- # To use CGI scripts outside of ScriptAliased directories:
- # (You will also need to add "ExecCGI" to the "Options" directive.)
- #
- #AddHandler cgi-script .cgi
-
- # For type maps (negotiated resources):
- #AddHandler type-map var
-
- #
- # Filters allow you to process content before it is sent to the client.
- #
- # To parse .shtml files for server-side includes (SSI):
- # (You will also need to add "Includes" to the "Options" directive.)
- #
- #AddType text/html .shtml
- #AddOutputFilter INCLUDES .shtml
+ AddType application/javascript .js
-#
-# The mod_mime_magic module allows the server to use various hints from the
-# contents of the file itself to determine its type. The MIMEMagicFile
-# directive tells the module where the hint definitions are located.
-#
-#MIMEMagicFile conf/magic
+# Specific handling for webnode JS files
+
+ # Force JavaScript MIME type
+ ForceType application/javascript
-#
-# Customizable error responses come in three flavors:
-# 1) plain text 2) local redirects 3) external redirects
-#
-# Some examples:
-#ErrorDocument 500 "The server made a boo boo."
-#ErrorDocument 404 /missing.html
-#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
-#ErrorDocument 402 http://www.example.com/subscription_info.html
-#
+ # Ensure these files are not rewritten
+ RewriteEngine Off
-#
-# MaxRanges: Maximum number of Ranges in a request before
-# returning the entire resource, or one of the special
-# values 'default', 'none' or 'unlimited'.
-# Default setting is to accept 200 Ranges.
-#MaxRanges unlimited
+ # Debug headers
+ Header set X-Content-Debug "%{CONTENT_TYPE}e"
+ Header set X-Handler-Debug "%{HANDLER}e"
-#
-# EnableMMAP and EnableSendfile: On systems that support it,
-# memory-mapping or the sendfile syscall may be used to deliver
-# files. This usually improves server performance, but must
-# be turned off when serving from networked-mounted
-# filesystems or if support for these functions is otherwise
-# broken on your system.
-# Defaults: EnableMMAP On, EnableSendfile Off
-#
-#EnableMMAP off
-#EnableSendfile on
-
-# Supplemental configuration
-#
-# The configuration files in the conf/extra/ directory can be
-# included to add extra features or to modify the default configuration of
-# the server, or you may simply copy their contents here and change as
-# necessary.
-
-# Server-pool management (MPM specific)
-#Include conf/extra/httpd-mpm.conf
-
-# Multi-language error messages
-#Include conf/extra/httpd-multilang-errordoc.conf
-
-# Fancy directory listings
-#Include conf/extra/httpd-autoindex.conf
+ # Ensure proper CORS headers
+ Header set Access-Control-Allow-Origin "*"
+ Header set Access-Control-Allow-Methods "GET, OPTIONS"
+
-# Language settings
-#Include conf/extra/httpd-languages.conf
-
-# User home directories
-#Include conf/extra/httpd-userdir.conf
-
-# Real-time info on requests and configuration
-#Include conf/extra/httpd-info.conf
-
-# Virtual hosts
-#Include conf/extra/httpd-vhosts.conf
-
-# Local access to the Apache HTTP Server Manual
-#Include conf/extra/httpd-manual.conf
-
-# Distributed authoring and versioning (WebDAV)
-#Include conf/extra/httpd-dav.conf
+# Map all SPA-looking routes to our single page app index file
+
+ FallbackResource /index.html
+
-# Various default settings
-#Include conf/extra/httpd-default.conf
+# Requests for files should return a real 404 and not fallback to the index.html page, though
+
+ FallbackResource disabled
+ ErrorDocument 404 "File not found"
+
-# Configure mod_proxy_html to understand HTML4/XHTML1
Include conf/extra/proxy-html.conf
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index a1ee521509..f7e1bb1481 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -1,36 +1,44 @@
{
"name": "frontend",
- "version": "0.8.20",
+ "version": "1.0.50",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "frontend",
- "version": "0.8.20",
+ "version": "1.0.50",
"dependencies": {
"@angular/animations": "^17.3.12",
"@angular/cdk": "^17.3.10",
"@angular/common": "^17.3.12",
"@angular/compiler": "^17.3.12",
"@angular/core": "^17.3.12",
+ "@angular/fire": "^17.1.0",
"@angular/forms": "^17.3.12",
"@angular/material": "^17.3.10",
"@angular/platform-browser": "^17.3.12",
"@angular/platform-browser-dynamic": "^17.3.12",
+ "@angular/platform-server": "^17.3.12",
"@angular/router": "^17.3.12",
+ "@angular/ssr": "^17.3.10",
"@ledgerhq/hw-transport-webhid": "^6.29.4",
"@ngneat/until-destroy": "^10.0.0",
"@ngrx/effects": "^17.2.0",
"@ngrx/router-store": "^17.2.0",
"@ngrx/store": "^17.2.0",
- "@openmina/shared": "^0.102.0",
+ "@nguniversal/express-engine": "^7.0.2",
+ "@openmina/shared": "^0.117.0",
"@sentry/angular": "^8.35.0",
+ "@sentry/cli": "^2.38.2",
"@sentry/tracing": "^7.114.0",
"base-x": "^5.0.0",
"bs58check": "^4.0.0",
"buffer": "^6.0.3",
"d3": "^7.8.4",
"eigen": "^0.2.2",
+ "express": "^4.18.2",
+ "firebase": "^11.0.1",
+ "jszip": "^3.10.1",
"mathjs": "^12.3.0",
"mina-signer": "^3.0.7",
"ngx-json-viewer": "^3.2.1",
@@ -46,9 +54,11 @@
"@angular/compiler-cli": "^17.3.12",
"@ngrx/store-devtools": "^17.2.0",
"@types/d3": "^7.4.0",
+ "@types/express": "^4.17.17",
"@types/jasmine": "~4.3.0",
- "@types/node": "^20.4.8",
+ "@types/node": "^18.19.64",
"@types/w3c-web-hid": "^1.0.6",
+ "browser-sync": "^3.0.0",
"cypress": "^13.3.2",
"cypress-real-events": "^1.10.0",
"jasmine-core": "~4.6.0",
@@ -557,7 +567,6 @@
"version": "17.3.10",
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.10.tgz",
"integrity": "sha512-czdl54yxU5DOAGy/uUPNjJruoBDTgwi/V+eOgLNybYhgrc+TsY0f7uJ11yEk/pz5sCov7xIiS7RdRv96waS7vg==",
- "dev": true,
"dependencies": {
"ajv": "8.12.0",
"ajv-formats": "2.1.1",
@@ -583,14 +592,12 @@
"node_modules/@angular-devkit/core/node_modules/jsonc-parser": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz",
- "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==",
- "dev": true
+ "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA=="
},
"node_modules/@angular-devkit/core/node_modules/picomatch": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.1.tgz",
"integrity": "sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==",
- "dev": true,
"engines": {
"node": ">=12"
},
@@ -602,7 +609,6 @@
"version": "17.3.10",
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.10.tgz",
"integrity": "sha512-FHcNa1ktYRd0SKExCsNJpR75RffsyuPIV8kvBXzXnLHmXMqvl25G2te3yYJ9yYqy9OLy/58HZznZTxWRyUdHOg==",
- "dev": true,
"dependencies": {
"@angular-devkit/core": "17.3.10",
"jsonc-parser": "3.2.1",
@@ -619,8 +625,7 @@
"node_modules/@angular-devkit/schematics/node_modules/jsonc-parser": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz",
- "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==",
- "dev": true
+ "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA=="
},
"node_modules/@angular/animations": {
"version": "17.3.12",
@@ -899,668 +904,1024 @@
"zone.js": "~0.14.0"
}
},
- "node_modules/@angular/forms": {
- "version": "17.3.12",
- "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-17.3.12.tgz",
- "integrity": "sha512-tV6r12Q3yEUlXwpVko4E+XscunTIpPkLbaiDn/MTL3Vxi2LZnsLgHyd/i38HaHN+e/H3B0a1ToSOhV5wf3ay4Q==",
+ "node_modules/@angular/fire": {
+ "version": "17.1.0",
+ "resolved": "https://registry.npmjs.org/@angular/fire/-/fire-17.1.0.tgz",
+ "integrity": "sha512-G/hktuErkAoqLc21BsLL+4LPXP8xV+Wu2vl0rqLgx7hr3DinAV+xJ1EsXJpdF8WexLQdtjEyr3ATgAao50Ykxw==",
+ "license": "MIT",
+ "dependencies": {
+ "@angular-devkit/schematics": "^17.0.0",
+ "@schematics/angular": "^17.0.0",
+ "firebase": "^10.12.0",
+ "fs-extra": "^8.0.1",
+ "fuzzy": "^0.1.3",
+ "inquirer": "^8.1.1",
+ "inquirer-autocomplete-prompt": "^1.0.1",
+ "jsonc-parser": "^3.0.0",
+ "node-fetch": "^2.6.1",
+ "open": "^8.0.0",
+ "ora": "^5.3.0",
+ "rxfire": "^6.0.5",
+ "semver": "^7.1.3",
+ "triple-beam": "^1.3.0",
+ "tslib": "^2.3.0",
+ "winston": "^3.0.0"
+ },
+ "peerDependencies": {
+ "@angular/common": "^17.0.0",
+ "@angular/core": "^17.0.0",
+ "@angular/platform-browser": "^17.0.0",
+ "@angular/platform-browser-dynamic": "^17.0.0",
+ "firebase-tools": "^13.0.0",
+ "rxjs": "~7.8.0"
+ },
+ "peerDependenciesMeta": {
+ "firebase-tools": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@angular/fire/node_modules/@firebase/analytics": {
+ "version": "0.10.8",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.8.tgz",
+ "integrity": "sha512-CVnHcS4iRJPqtIDc411+UmFldk0ShSK3OB+D0bKD8Ck5Vro6dbK5+APZpkuWpbfdL359DIQUnAaMLE+zs/PVyA==",
+ "license": "Apache-2.0",
"dependencies": {
- "tslib": "^2.3.0"
+ "@firebase/component": "0.6.9",
+ "@firebase/installations": "0.6.9",
+ "@firebase/logger": "0.4.2",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0"
},
- "engines": {
- "node": "^18.13.0 || >=20.9.0"
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@angular/fire/node_modules/@firebase/analytics-compat": {
+ "version": "0.2.14",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.14.tgz",
+ "integrity": "sha512-unRVY6SvRqfNFIAA/kwl4vK+lvQAL2HVcgu9zTrUtTyYDmtIt/lOuHJynBMYEgLnKm39YKBDhtqdapP2e++ASw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/analytics": "0.10.8",
+ "@firebase/analytics-types": "0.8.2",
+ "@firebase/component": "0.6.9",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0"
},
"peerDependencies": {
- "@angular/common": "17.3.12",
- "@angular/core": "17.3.12",
- "@angular/platform-browser": "17.3.12",
- "rxjs": "^6.5.3 || ^7.4.0"
+ "@firebase/app-compat": "0.x"
}
},
- "node_modules/@angular/material": {
- "version": "17.3.10",
- "resolved": "https://registry.npmjs.org/@angular/material/-/material-17.3.10.tgz",
- "integrity": "sha512-hHMQES0tQPH5JW33W+mpBPuM8ybsloDTqFPuRV8cboDjosAWfJhzAKF3ozICpNlUrs62La/2Wu/756GcQrxebg==",
+ "node_modules/@angular/fire/node_modules/@firebase/app": {
+ "version": "0.10.13",
+ "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.13.tgz",
+ "integrity": "sha512-OZiDAEK/lDB6xy/XzYAyJJkaDqmQ+BCtOEPLqFvxWKUz5JbBmej7IiiRHdtiIOD/twW7O5AxVsfaaGA/V1bNsA==",
+ "license": "Apache-2.0",
"dependencies": {
- "@material/animation": "15.0.0-canary.7f224ddd4.0",
- "@material/auto-init": "15.0.0-canary.7f224ddd4.0",
- "@material/banner": "15.0.0-canary.7f224ddd4.0",
- "@material/base": "15.0.0-canary.7f224ddd4.0",
- "@material/button": "15.0.0-canary.7f224ddd4.0",
- "@material/card": "15.0.0-canary.7f224ddd4.0",
- "@material/checkbox": "15.0.0-canary.7f224ddd4.0",
- "@material/chips": "15.0.0-canary.7f224ddd4.0",
- "@material/circular-progress": "15.0.0-canary.7f224ddd4.0",
- "@material/data-table": "15.0.0-canary.7f224ddd4.0",
- "@material/density": "15.0.0-canary.7f224ddd4.0",
- "@material/dialog": "15.0.0-canary.7f224ddd4.0",
- "@material/dom": "15.0.0-canary.7f224ddd4.0",
- "@material/drawer": "15.0.0-canary.7f224ddd4.0",
- "@material/elevation": "15.0.0-canary.7f224ddd4.0",
- "@material/fab": "15.0.0-canary.7f224ddd4.0",
- "@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
- "@material/floating-label": "15.0.0-canary.7f224ddd4.0",
- "@material/form-field": "15.0.0-canary.7f224ddd4.0",
- "@material/icon-button": "15.0.0-canary.7f224ddd4.0",
- "@material/image-list": "15.0.0-canary.7f224ddd4.0",
- "@material/layout-grid": "15.0.0-canary.7f224ddd4.0",
- "@material/line-ripple": "15.0.0-canary.7f224ddd4.0",
- "@material/linear-progress": "15.0.0-canary.7f224ddd4.0",
- "@material/list": "15.0.0-canary.7f224ddd4.0",
- "@material/menu": "15.0.0-canary.7f224ddd4.0",
- "@material/menu-surface": "15.0.0-canary.7f224ddd4.0",
- "@material/notched-outline": "15.0.0-canary.7f224ddd4.0",
- "@material/radio": "15.0.0-canary.7f224ddd4.0",
- "@material/ripple": "15.0.0-canary.7f224ddd4.0",
- "@material/rtl": "15.0.0-canary.7f224ddd4.0",
- "@material/segmented-button": "15.0.0-canary.7f224ddd4.0",
- "@material/select": "15.0.0-canary.7f224ddd4.0",
- "@material/shape": "15.0.0-canary.7f224ddd4.0",
- "@material/slider": "15.0.0-canary.7f224ddd4.0",
- "@material/snackbar": "15.0.0-canary.7f224ddd4.0",
- "@material/switch": "15.0.0-canary.7f224ddd4.0",
- "@material/tab": "15.0.0-canary.7f224ddd4.0",
- "@material/tab-bar": "15.0.0-canary.7f224ddd4.0",
- "@material/tab-indicator": "15.0.0-canary.7f224ddd4.0",
- "@material/tab-scroller": "15.0.0-canary.7f224ddd4.0",
- "@material/textfield": "15.0.0-canary.7f224ddd4.0",
- "@material/theme": "15.0.0-canary.7f224ddd4.0",
- "@material/tooltip": "15.0.0-canary.7f224ddd4.0",
- "@material/top-app-bar": "15.0.0-canary.7f224ddd4.0",
- "@material/touch-target": "15.0.0-canary.7f224ddd4.0",
- "@material/typography": "15.0.0-canary.7f224ddd4.0",
- "tslib": "^2.3.0"
+ "@firebase/component": "0.6.9",
+ "@firebase/logger": "0.4.2",
+ "@firebase/util": "1.10.0",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@angular/fire/node_modules/@firebase/app-check": {
+ "version": "0.8.8",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.8.tgz",
+ "integrity": "sha512-O49RGF1xj7k6BuhxGpHmqOW5hqBIAEbt2q6POW0lIywx7emYtzPDeQI+ryQpC4zbKX646SoVZ711TN1DBLNSOQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.9",
+ "@firebase/logger": "0.4.2",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0"
},
"peerDependencies": {
- "@angular/animations": "^17.0.0 || ^18.0.0",
- "@angular/cdk": "17.3.10",
- "@angular/common": "^17.0.0 || ^18.0.0",
- "@angular/core": "^17.0.0 || ^18.0.0",
- "@angular/forms": "^17.0.0 || ^18.0.0",
- "@angular/platform-browser": "^17.0.0 || ^18.0.0",
- "rxjs": "^6.5.3 || ^7.4.0"
+ "@firebase/app": "0.x"
}
},
- "node_modules/@angular/platform-browser": {
- "version": "17.3.12",
- "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-17.3.12.tgz",
- "integrity": "sha512-DYY04ptWh/ulMHzd+y52WCE8QnEYGeIiW3hEIFjCN8z0kbIdFdUtEB0IK5vjNL3ejyhUmphcpeT5PYf3YXtqWQ==",
+ "node_modules/@angular/fire/node_modules/@firebase/app-check-compat": {
+ "version": "0.3.15",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.15.tgz",
+ "integrity": "sha512-zFIvIFFNqDXpOT2huorz9cwf56VT3oJYRFjSFYdSbGYEJYEaXjLJbfC79lx/zjx4Fh+yuN8pry3TtvwaevrGbg==",
+ "license": "Apache-2.0",
"dependencies": {
- "tslib": "^2.3.0"
+ "@firebase/app-check": "0.8.8",
+ "@firebase/app-check-types": "0.5.2",
+ "@firebase/component": "0.6.9",
+ "@firebase/logger": "0.4.2",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0"
},
- "engines": {
- "node": "^18.13.0 || >=20.9.0"
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@angular/fire/node_modules/@firebase/app-compat": {
+ "version": "0.2.43",
+ "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.43.tgz",
+ "integrity": "sha512-HM96ZyIblXjAC7TzE8wIk2QhHlSvksYkQ4Ukh1GmEenzkucSNUmUX4QvoKrqeWsLEQ8hdcojABeCV8ybVyZmeg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app": "0.10.13",
+ "@firebase/component": "0.6.9",
+ "@firebase/logger": "0.4.2",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@angular/fire/node_modules/@firebase/auth": {
+ "version": "1.7.9",
+ "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.7.9.tgz",
+ "integrity": "sha512-yLD5095kVgDw965jepMyUrIgDklD6qH/BZNHeKOgvu7pchOKNjVM+zQoOVYJIKWMWOWBq8IRNVU6NXzBbozaJg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.9",
+ "@firebase/logger": "0.4.2",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0",
+ "undici": "6.19.7"
},
"peerDependencies": {
- "@angular/animations": "17.3.12",
- "@angular/common": "17.3.12",
- "@angular/core": "17.3.12"
+ "@firebase/app": "0.x",
+ "@react-native-async-storage/async-storage": "^1.18.1"
},
"peerDependenciesMeta": {
- "@angular/animations": {
+ "@react-native-async-storage/async-storage": {
"optional": true
}
}
},
- "node_modules/@angular/platform-browser-dynamic": {
- "version": "17.3.12",
- "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-17.3.12.tgz",
- "integrity": "sha512-DQwV7B2x/DRLRDSisngZRdLqHdYbbrqZv2Hmu4ZbnNYaWPC8qvzgE/0CvY+UkDat3nCcsfwsMnlDeB6TL7/IaA==",
+ "node_modules/@angular/fire/node_modules/@firebase/auth-compat": {
+ "version": "0.5.14",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.14.tgz",
+ "integrity": "sha512-2eczCSqBl1KUPJacZlFpQayvpilg3dxXLy9cSMTKtQMTQSmondUtPI47P3ikH3bQAXhzKLOE+qVxJ3/IRtu9pw==",
+ "license": "Apache-2.0",
"dependencies": {
- "tslib": "^2.3.0"
- },
- "engines": {
- "node": "^18.13.0 || >=20.9.0"
+ "@firebase/auth": "1.7.9",
+ "@firebase/auth-types": "0.12.2",
+ "@firebase/component": "0.6.9",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0",
+ "undici": "6.19.7"
},
"peerDependencies": {
- "@angular/common": "17.3.12",
- "@angular/compiler": "17.3.12",
- "@angular/core": "17.3.12",
- "@angular/platform-browser": "17.3.12"
+ "@firebase/app-compat": "0.x"
}
},
- "node_modules/@angular/router": {
- "version": "17.3.12",
- "resolved": "https://registry.npmjs.org/@angular/router/-/router-17.3.12.tgz",
- "integrity": "sha512-dg7PHBSW9fmPKTVzwvHEeHZPZdpnUqW/U7kj8D29HTP9ur8zZnx9QcnbplwPeYb8yYa62JMnZSEel2X4PxdYBg==",
+ "node_modules/@angular/fire/node_modules/@firebase/component": {
+ "version": "0.6.9",
+ "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.9.tgz",
+ "integrity": "sha512-gm8EUEJE/fEac86AvHn8Z/QW8BvR56TBw3hMW0O838J/1mThYQXAIQBgUv75EqlCZfdawpWLrKt1uXvp9ciK3Q==",
+ "license": "Apache-2.0",
"dependencies": {
- "tslib": "^2.3.0"
- },
- "engines": {
- "node": "^18.13.0 || >=20.9.0"
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@angular/fire/node_modules/@firebase/data-connect": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.1.0.tgz",
+ "integrity": "sha512-vSe5s8dY13ilhLnfY0eYRmQsdTbH7PUFZtBbqU6JVX/j8Qp9A6G5gG6//ulbX9/1JFOF1IWNOne9c8S/DOCJaQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/auth-interop-types": "0.2.3",
+ "@firebase/component": "0.6.9",
+ "@firebase/logger": "0.4.2",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0"
},
"peerDependencies": {
- "@angular/common": "17.3.12",
- "@angular/core": "17.3.12",
- "@angular/platform-browser": "17.3.12",
- "rxjs": "^6.5.3 || ^7.4.0"
+ "@firebase/app": "0.x"
}
},
- "node_modules/@babel/code-frame": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.9.tgz",
- "integrity": "sha512-z88xeGxnzehn2sqZ8UdGQEvYErF1odv2CftxInpSYJt6uHuPe9YjahKZITGs3l5LeI9d2ROG+obuDAoSlqbNfQ==",
- "dev": true,
+ "node_modules/@angular/fire/node_modules/@firebase/database": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.8.tgz",
+ "integrity": "sha512-dzXALZeBI1U5TXt6619cv0+tgEhJiwlUtQ55WNZY7vGAjv7Q1QioV969iYwt1AQQ0ovHnEW0YW9TiBfefLvErg==",
+ "license": "Apache-2.0",
"dependencies": {
- "@babel/highlight": "^7.25.9",
- "picocolors": "^1.0.0"
- },
- "engines": {
- "node": ">=6.9.0"
+ "@firebase/app-check-interop-types": "0.3.2",
+ "@firebase/auth-interop-types": "0.2.3",
+ "@firebase/component": "0.6.9",
+ "@firebase/logger": "0.4.2",
+ "@firebase/util": "1.10.0",
+ "faye-websocket": "0.11.4",
+ "tslib": "^2.1.0"
}
},
- "node_modules/@babel/compat-data": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.9.tgz",
- "integrity": "sha512-yD+hEuJ/+wAJ4Ox2/rpNv5HIuPG82x3ZlQvYVn8iYCprdxzE7P1udpGF1jyjQVBU4dgznN+k2h103vxZ7NdPyw==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
+ "node_modules/@angular/fire/node_modules/@firebase/database-compat": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.8.tgz",
+ "integrity": "sha512-OpeWZoPE3sGIRPBKYnW9wLad25RaWbGyk7fFQe4xnJQKRzlynWeFBSRRAoLE2Old01WXwskUiucNqUUVlFsceg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.9",
+ "@firebase/database": "1.0.8",
+ "@firebase/database-types": "1.0.5",
+ "@firebase/logger": "0.4.2",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0"
}
},
- "node_modules/@babel/core": {
- "version": "7.22.9",
- "dev": true,
- "license": "MIT",
+ "node_modules/@angular/fire/node_modules/@firebase/database-types": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.5.tgz",
+ "integrity": "sha512-fTlqCNwFYyq/C6W7AJ5OCuq5CeZuBEsEwptnVxlNPkWCo5cTTyukzAHRSO/jaQcItz33FfYrrFk1SJofcu2AaQ==",
+ "license": "Apache-2.0",
"dependencies": {
- "@ampproject/remapping": "^2.2.0",
- "@babel/code-frame": "^7.22.5",
- "@babel/generator": "^7.22.9",
- "@babel/helper-compilation-targets": "^7.22.9",
- "@babel/helper-module-transforms": "^7.22.9",
- "@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",
- "convert-source-map": "^1.7.0",
- "debug": "^4.1.0",
- "gensync": "^1.0.0-beta.2",
- "json5": "^2.2.2",
- "semver": "^6.3.1"
+ "@firebase/app-types": "0.9.2",
+ "@firebase/util": "1.10.0"
+ }
+ },
+ "node_modules/@angular/fire/node_modules/@firebase/firestore": {
+ "version": "4.7.3",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.3.tgz",
+ "integrity": "sha512-NwVU+JPZ/3bhvNSJMCSzfcBZZg8SUGyzZ2T0EW3/bkUeefCyzMISSt/TTIfEHc8cdyXGlMqfGe3/62u9s74UEg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.9",
+ "@firebase/logger": "0.4.2",
+ "@firebase/util": "1.10.0",
+ "@firebase/webchannel-wrapper": "1.0.1",
+ "@grpc/grpc-js": "~1.9.0",
+ "@grpc/proto-loader": "^0.7.8",
+ "tslib": "^2.1.0",
+ "undici": "6.19.7"
},
"engines": {
- "node": ">=6.9.0"
+ "node": ">=10.10.0"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/babel"
- }
- },
- "node_modules/@babel/core/node_modules/semver": {
- "version": "6.3.1",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
+ "peerDependencies": {
+ "@firebase/app": "0.x"
}
},
- "node_modules/@babel/generator": {
- "version": "7.22.9",
- "dev": true,
- "license": "MIT",
+ "node_modules/@angular/fire/node_modules/@firebase/firestore-compat": {
+ "version": "0.3.38",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.38.tgz",
+ "integrity": "sha512-GoS0bIMMkjpLni6StSwRJarpu2+S5m346Na7gr9YZ/BZ/W3/8iHGNr9PxC+f0rNZXqS4fGRn88pICjrZEgbkqQ==",
+ "license": "Apache-2.0",
"dependencies": {
- "@babel/types": "^7.22.5",
- "@jridgewell/gen-mapping": "^0.3.2",
- "@jridgewell/trace-mapping": "^0.3.17",
- "jsesc": "^2.5.1"
+ "@firebase/component": "0.6.9",
+ "@firebase/firestore": "4.7.3",
+ "@firebase/firestore-types": "3.0.2",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0"
},
- "engines": {
- "node": ">=6.9.0"
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
}
},
- "node_modules/@babel/helper-annotate-as-pure": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
- "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
- "dev": true,
+ "node_modules/@angular/fire/node_modules/@firebase/functions": {
+ "version": "0.11.8",
+ "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.11.8.tgz",
+ "integrity": "sha512-Lo2rTPDn96naFIlSZKVd1yvRRqqqwiJk7cf9TZhUerwnPKgBzXy+aHE22ry+6EjCaQusUoNai6mU6p+G8QZT1g==",
+ "license": "Apache-2.0",
"dependencies": {
- "@babel/types": "^7.22.5"
+ "@firebase/app-check-interop-types": "0.3.2",
+ "@firebase/auth-interop-types": "0.2.3",
+ "@firebase/component": "0.6.9",
+ "@firebase/messaging-interop-types": "0.2.2",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0",
+ "undici": "6.19.7"
},
- "engines": {
- "node": ">=6.9.0"
+ "peerDependencies": {
+ "@firebase/app": "0.x"
}
},
- "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.9.tgz",
- "integrity": "sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g==",
- "dev": true,
+ "node_modules/@angular/fire/node_modules/@firebase/functions-compat": {
+ "version": "0.3.14",
+ "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.14.tgz",
+ "integrity": "sha512-dZ0PKOKQFnOlMfcim39XzaXonSuPPAVuzpqA4ONTIdyaJK/OnBaIEVs/+BH4faa1a2tLeR+Jy15PKqDRQoNIJw==",
+ "license": "Apache-2.0",
"dependencies": {
- "@babel/traverse": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "@firebase/component": "0.6.9",
+ "@firebase/functions": "0.11.8",
+ "@firebase/functions-types": "0.6.2",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0"
},
- "engines": {
- "node": ">=6.9.0"
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
}
},
- "node_modules/@babel/helper-compilation-targets": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz",
- "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==",
- "dev": true,
+ "node_modules/@angular/fire/node_modules/@firebase/installations": {
+ "version": "0.6.9",
+ "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.9.tgz",
+ "integrity": "sha512-hlT7AwCiKghOX3XizLxXOsTFiFCQnp/oj86zp1UxwDGmyzsyoxtX+UIZyVyH/oBF5+XtblFG9KZzZQ/h+dpy+Q==",
+ "license": "Apache-2.0",
"dependencies": {
- "@babel/compat-data": "^7.25.9",
- "@babel/helper-validator-option": "^7.25.9",
- "browserslist": "^4.24.0",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.1"
+ "@firebase/component": "0.6.9",
+ "@firebase/util": "1.10.0",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
},
- "engines": {
- "node": ">=6.9.0"
+ "peerDependencies": {
+ "@firebase/app": "0.x"
}
},
- "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
- "version": "6.3.1",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
+ "node_modules/@angular/fire/node_modules/@firebase/installations-compat": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.9.tgz",
+ "integrity": "sha512-2lfdc6kPXR7WaL4FCQSQUhXcPbI7ol3wF+vkgtU25r77OxPf8F/VmswQ7sgIkBBWtymn5ZF20TIKtnOj9rjb6w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.9",
+ "@firebase/installations": "0.6.9",
+ "@firebase/installations-types": "0.5.2",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
}
},
- "node_modules/@babel/helper-create-class-features-plugin": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz",
- "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==",
- "dev": true,
+ "node_modules/@angular/fire/node_modules/@firebase/logger": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz",
+ "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==",
+ "license": "Apache-2.0",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.25.9",
- "@babel/helper-member-expression-to-functions": "^7.25.9",
- "@babel/helper-optimise-call-expression": "^7.25.9",
- "@babel/helper-replace-supers": "^7.25.9",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
- "@babel/traverse": "^7.25.9",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@angular/fire/node_modules/@firebase/messaging": {
+ "version": "0.12.12",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.12.tgz",
+ "integrity": "sha512-6q0pbzYBJhZEtUoQx7hnPhZvAbuMNuBXKQXOx2YlWhSrlv9N1m0ZzlNpBbu/ItTzrwNKTibdYzUyaaxdWLg+4w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.9",
+ "@firebase/installations": "0.6.9",
+ "@firebase/messaging-interop-types": "0.2.2",
+ "@firebase/util": "1.10.0",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0"
+ "@firebase/app": "0.x"
}
},
- "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-annotate-as-pure": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz",
- "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==",
- "dev": true,
+ "node_modules/@angular/fire/node_modules/@firebase/messaging-compat": {
+ "version": "0.2.12",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.12.tgz",
+ "integrity": "sha512-pKsiUVZrbmRgdImYqhBNZlkKJbqjlPkVdQRZGRbkTyX4OSGKR0F/oJeCt1a8jEg5UnBp4fdVwSWSp4DuCovvEQ==",
+ "license": "Apache-2.0",
"dependencies": {
- "@babel/types": "^7.25.9"
+ "@firebase/component": "0.6.9",
+ "@firebase/messaging": "0.12.12",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0"
},
- "engines": {
- "node": ">=6.9.0"
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
}
},
- "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "bin": {
- "semver": "bin/semver.js"
+ "node_modules/@angular/fire/node_modules/@firebase/performance": {
+ "version": "0.6.9",
+ "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.9.tgz",
+ "integrity": "sha512-PnVaak5sqfz5ivhua+HserxTJHtCar/7zM0flCX6NkzBNzJzyzlH4Hs94h2Il0LQB99roBqoE5QT1JqWqcLJHQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.9",
+ "@firebase/installations": "0.6.9",
+ "@firebase/logger": "0.4.2",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
}
},
- "node_modules/@babel/helper-create-regexp-features-plugin": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.9.tgz",
- "integrity": "sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw==",
- "dev": true,
+ "node_modules/@angular/fire/node_modules/@firebase/performance-compat": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.9.tgz",
+ "integrity": "sha512-dNl95IUnpsu3fAfYBZDCVhXNkASE0uo4HYaEPd2/PKscfTvsgqFAOxfAXzBEDOnynDWiaGUnb5M1O00JQ+3FXA==",
+ "license": "Apache-2.0",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.25.9",
- "regexpu-core": "^6.1.1",
- "semver": "^6.3.1"
+ "@firebase/component": "0.6.9",
+ "@firebase/logger": "0.4.2",
+ "@firebase/performance": "0.6.9",
+ "@firebase/performance-types": "0.2.2",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0"
},
- "engines": {
- "node": ">=6.9.0"
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@angular/fire/node_modules/@firebase/remote-config": {
+ "version": "0.4.9",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.9.tgz",
+ "integrity": "sha512-EO1NLCWSPMHdDSRGwZ73kxEEcTopAxX1naqLJFNApp4hO8WfKfmEpmjxmP5TrrnypjIf2tUkYaKsfbEA7+AMmA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.9",
+ "@firebase/installations": "0.6.9",
+ "@firebase/logger": "0.4.2",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0"
+ "@firebase/app": "0.x"
}
},
- "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/@babel/helper-annotate-as-pure": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz",
- "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==",
- "dev": true,
+ "node_modules/@angular/fire/node_modules/@firebase/remote-config-compat": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.9.tgz",
+ "integrity": "sha512-AxzGpWfWFYejH2twxfdOJt5Cfh/ATHONegTd/a0p5flEzsD5JsxXgfkFToop+mypEL3gNwawxrxlZddmDoNxyA==",
+ "license": "Apache-2.0",
"dependencies": {
- "@babel/types": "^7.25.9"
+ "@firebase/component": "0.6.9",
+ "@firebase/logger": "0.4.2",
+ "@firebase/remote-config": "0.4.9",
+ "@firebase/remote-config-types": "0.3.2",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0"
},
- "engines": {
- "node": ">=6.9.0"
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
}
},
- "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "bin": {
- "semver": "bin/semver.js"
+ "node_modules/@angular/fire/node_modules/@firebase/storage": {
+ "version": "0.13.2",
+ "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.2.tgz",
+ "integrity": "sha512-fxuJnHshbhVwuJ4FuISLu+/76Aby2sh+44ztjF2ppoe0TELIDxPW6/r1KGlWYt//AD0IodDYYA8ZTN89q8YqUw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.9",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0",
+ "undici": "6.19.7"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
}
},
- "node_modules/@babel/helper-define-polyfill-provider": {
- "version": "0.6.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz",
- "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==",
- "dev": true,
+ "node_modules/@angular/fire/node_modules/@firebase/storage-compat": {
+ "version": "0.3.12",
+ "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.12.tgz",
+ "integrity": "sha512-hA4VWKyGU5bWOll+uwzzhEMMYGu9PlKQc1w4DWxB3aIErWYzonrZjF0icqNQZbwKNIdh8SHjZlFeB2w6OSsjfg==",
+ "license": "Apache-2.0",
"dependencies": {
- "@babel/helper-compilation-targets": "^7.22.6",
- "@babel/helper-plugin-utils": "^7.22.5",
- "debug": "^4.1.1",
- "lodash.debounce": "^4.0.8",
- "resolve": "^1.14.2"
+ "@firebase/component": "0.6.9",
+ "@firebase/storage": "0.13.2",
+ "@firebase/storage-types": "0.8.2",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0"
},
"peerDependencies": {
- "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ "@firebase/app-compat": "0.x"
}
},
- "node_modules/@babel/helper-environment-visitor": {
- "version": "7.22.20",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
+ "node_modules/@angular/fire/node_modules/@firebase/util": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.0.tgz",
+ "integrity": "sha512-xKtx4A668icQqoANRxyDLBLz51TAbDP9KRfpbKGxiCAW346d0BeJe5vN6/hKxxmWwnZ0mautyv39JxviwwQMOQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.1.0"
}
},
- "node_modules/@babel/helper-member-expression-to-functions": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz",
- "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==",
- "dev": true,
+ "node_modules/@angular/fire/node_modules/@firebase/webchannel-wrapper": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.1.tgz",
+ "integrity": "sha512-jmEnr/pk0yVkA7mIlHNnxCi+wWzOFUg0WyIotgkKAb2u1J7fAeDBcVNSTjTihbAYNusCLQdW5s9IJ5qwnEufcQ==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@angular/fire/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==",
+ "license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "color-convert": "^2.0.1"
},
"engines": {
- "node": ">=6.9.0"
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/@babel/helper-module-imports": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz",
- "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==",
- "dev": true,
+ "node_modules/@angular/fire/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
},
"engines": {
- "node": ">=6.9.0"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
}
},
- "node_modules/@babel/helper-module-transforms": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.9.tgz",
- "integrity": "sha512-TvLZY/F3+GvdRYFZFyxMvnsKi+4oJdgZzU3BoGN9Uc2d9C6zfNwJcKKhjqLAhK8i46mv93jsO74fDh3ih6rpHA==",
- "dev": true,
+ "node_modules/@angular/fire/node_modules/cli-width": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
+ "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@angular/fire/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==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-module-imports": "^7.25.9",
- "@babel/helper-simple-access": "^7.25.9",
- "@babel/helper-validator-identifier": "^7.25.9",
- "@babel/traverse": "^7.25.9"
+ "color-name": "~1.1.4"
},
"engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
+ "node": ">=7.0.0"
}
},
- "node_modules/@babel/helper-optimise-call-expression": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz",
- "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==",
- "dev": true,
+ "node_modules/@angular/fire/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==",
+ "license": "MIT"
+ },
+ "node_modules/@angular/fire/node_modules/firebase": {
+ "version": "10.14.1",
+ "resolved": "https://registry.npmjs.org/firebase/-/firebase-10.14.1.tgz",
+ "integrity": "sha512-0KZxU+Ela9rUCULqFsUUOYYkjh7OM1EWdIfG6///MtXd0t2/uUIf0iNV5i0KariMhRQ5jve/OY985nrAXFaZeQ==",
+ "license": "Apache-2.0",
"dependencies": {
- "@babel/types": "^7.25.9"
- },
+ "@firebase/analytics": "0.10.8",
+ "@firebase/analytics-compat": "0.2.14",
+ "@firebase/app": "0.10.13",
+ "@firebase/app-check": "0.8.8",
+ "@firebase/app-check-compat": "0.3.15",
+ "@firebase/app-compat": "0.2.43",
+ "@firebase/app-types": "0.9.2",
+ "@firebase/auth": "1.7.9",
+ "@firebase/auth-compat": "0.5.14",
+ "@firebase/data-connect": "0.1.0",
+ "@firebase/database": "1.0.8",
+ "@firebase/database-compat": "1.0.8",
+ "@firebase/firestore": "4.7.3",
+ "@firebase/firestore-compat": "0.3.38",
+ "@firebase/functions": "0.11.8",
+ "@firebase/functions-compat": "0.3.14",
+ "@firebase/installations": "0.6.9",
+ "@firebase/installations-compat": "0.2.9",
+ "@firebase/messaging": "0.12.12",
+ "@firebase/messaging-compat": "0.2.12",
+ "@firebase/performance": "0.6.9",
+ "@firebase/performance-compat": "0.2.9",
+ "@firebase/remote-config": "0.4.9",
+ "@firebase/remote-config-compat": "0.2.9",
+ "@firebase/storage": "0.13.2",
+ "@firebase/storage-compat": "0.3.12",
+ "@firebase/util": "1.10.0",
+ "@firebase/vertexai-preview": "0.0.4"
+ }
+ },
+ "node_modules/@angular/fire/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==",
+ "license": "MIT",
"engines": {
- "node": ">=6.9.0"
+ "node": ">=8"
}
},
- "node_modules/@babel/helper-plugin-utils": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz",
- "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==",
- "dev": true,
+ "node_modules/@angular/fire/node_modules/inquirer": {
+ "version": "8.2.6",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz",
+ "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==",
+ "license": "MIT",
+ "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": "^6.0.1"
+ },
"engines": {
- "node": ">=6.9.0"
+ "node": ">=12.0.0"
}
},
- "node_modules/@babel/helper-remap-async-to-generator": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz",
- "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==",
- "dev": true,
+ "node_modules/@angular/fire/node_modules/inquirer-autocomplete-prompt": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/inquirer-autocomplete-prompt/-/inquirer-autocomplete-prompt-1.4.0.tgz",
+ "integrity": "sha512-qHgHyJmbULt4hI+kCmwX92MnSxDs/Yhdt4wPA30qnoa01OF6uTXV8yvH4hKXgdaTNmkZ9D01MHjqKYEuJN+ONw==",
+ "license": "ISC",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.25.9",
- "@babel/helper-wrap-function": "^7.25.9",
- "@babel/traverse": "^7.25.9"
+ "ansi-escapes": "^4.3.1",
+ "chalk": "^4.0.0",
+ "figures": "^3.2.0",
+ "run-async": "^2.4.0",
+ "rxjs": "^6.6.2"
},
"engines": {
- "node": ">=6.9.0"
+ "node": ">=10"
},
"peerDependencies": {
- "@babel/core": "^7.0.0"
+ "inquirer": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
- "node_modules/@babel/helper-remap-async-to-generator/node_modules/@babel/helper-annotate-as-pure": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz",
- "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==",
- "dev": true,
+ "node_modules/@angular/fire/node_modules/inquirer-autocomplete-prompt/node_modules/rxjs": {
+ "version": "6.6.7",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
+ "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
+ "license": "Apache-2.0",
"dependencies": {
- "@babel/types": "^7.25.9"
+ "tslib": "^1.9.0"
},
"engines": {
- "node": ">=6.9.0"
+ "npm": ">=2.0.0"
}
},
- "node_modules/@babel/helper-replace-supers": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.9.tgz",
- "integrity": "sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-member-expression-to-functions": "^7.25.9",
- "@babel/helper-optimise-call-expression": "^7.25.9",
- "@babel/traverse": "^7.25.9"
- },
+ "node_modules/@angular/fire/node_modules/inquirer-autocomplete-prompt/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "license": "0BSD"
+ },
+ "node_modules/@angular/fire/node_modules/mute-stream": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
+ "license": "ISC"
+ },
+ "node_modules/@angular/fire/node_modules/run-async": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+ "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
+ "license": "MIT",
"engines": {
- "node": ">=6.9.0"
- },
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/@angular/fire/node_modules/rxfire": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/rxfire/-/rxfire-6.0.5.tgz",
+ "integrity": "sha512-ycBsANGbya3GNtOBKzZVATLEV+0S9gUrlTfwnN15TCXtgG8OgIMAuv2k9+kMeVaevp/DRp1KT+vYf6Wkop6gvw==",
+ "license": "Apache-2.0",
"peerDependencies": {
- "@babel/core": "^7.0.0"
+ "firebase": "^9.0.0 || ^10.0.0",
+ "rxjs": "^6.0.0 || ^7.0.0"
}
},
- "node_modules/@babel/helper-simple-access": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz",
- "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==",
- "dev": true,
+ "node_modules/@angular/fire/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==",
+ "license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "has-flag": "^4.0.0"
},
"engines": {
- "node": ">=6.9.0"
+ "node": ">=8"
}
},
- "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz",
- "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==",
- "dev": true,
- "dependencies": {
- "@babel/traverse": "^7.25.9",
- "@babel/types": "^7.25.9"
- },
+ "node_modules/@angular/fire/node_modules/undici": {
+ "version": "6.19.7",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-6.19.7.tgz",
+ "integrity": "sha512-HR3W/bMGPSr90i8AAp2C4DM3wChFdJPLrWYpIS++LxS8K+W535qftjt+4MyjNYHeWabMj1nvtmLIi7l++iq91A==",
+ "license": "MIT",
"engines": {
- "node": ">=6.9.0"
+ "node": ">=18.17"
}
},
- "node_modules/@babel/helper-split-export-declaration": {
- "version": "7.22.6",
- "dev": true,
+ "node_modules/@angular/fire/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.22.5"
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
},
"engines": {
- "node": ">=6.9.0"
+ "node": ">=8"
}
},
- "node_modules/@babel/helper-string-parser": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
- "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
- "dev": true,
+ "node_modules/@angular/forms": {
+ "version": "17.3.12",
+ "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-17.3.12.tgz",
+ "integrity": "sha512-tV6r12Q3yEUlXwpVko4E+XscunTIpPkLbaiDn/MTL3Vxi2LZnsLgHyd/i38HaHN+e/H3B0a1ToSOhV5wf3ay4Q==",
+ "dependencies": {
+ "tslib": "^2.3.0"
+ },
"engines": {
- "node": ">=6.9.0"
+ "node": "^18.13.0 || >=20.9.0"
+ },
+ "peerDependencies": {
+ "@angular/common": "17.3.12",
+ "@angular/core": "17.3.12",
+ "@angular/platform-browser": "17.3.12",
+ "rxjs": "^6.5.3 || ^7.4.0"
}
},
- "node_modules/@babel/helper-validator-identifier": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
- "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
+ "node_modules/@angular/material": {
+ "version": "17.3.10",
+ "resolved": "https://registry.npmjs.org/@angular/material/-/material-17.3.10.tgz",
+ "integrity": "sha512-hHMQES0tQPH5JW33W+mpBPuM8ybsloDTqFPuRV8cboDjosAWfJhzAKF3ozICpNlUrs62La/2Wu/756GcQrxebg==",
+ "dependencies": {
+ "@material/animation": "15.0.0-canary.7f224ddd4.0",
+ "@material/auto-init": "15.0.0-canary.7f224ddd4.0",
+ "@material/banner": "15.0.0-canary.7f224ddd4.0",
+ "@material/base": "15.0.0-canary.7f224ddd4.0",
+ "@material/button": "15.0.0-canary.7f224ddd4.0",
+ "@material/card": "15.0.0-canary.7f224ddd4.0",
+ "@material/checkbox": "15.0.0-canary.7f224ddd4.0",
+ "@material/chips": "15.0.0-canary.7f224ddd4.0",
+ "@material/circular-progress": "15.0.0-canary.7f224ddd4.0",
+ "@material/data-table": "15.0.0-canary.7f224ddd4.0",
+ "@material/density": "15.0.0-canary.7f224ddd4.0",
+ "@material/dialog": "15.0.0-canary.7f224ddd4.0",
+ "@material/dom": "15.0.0-canary.7f224ddd4.0",
+ "@material/drawer": "15.0.0-canary.7f224ddd4.0",
+ "@material/elevation": "15.0.0-canary.7f224ddd4.0",
+ "@material/fab": "15.0.0-canary.7f224ddd4.0",
+ "@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
+ "@material/floating-label": "15.0.0-canary.7f224ddd4.0",
+ "@material/form-field": "15.0.0-canary.7f224ddd4.0",
+ "@material/icon-button": "15.0.0-canary.7f224ddd4.0",
+ "@material/image-list": "15.0.0-canary.7f224ddd4.0",
+ "@material/layout-grid": "15.0.0-canary.7f224ddd4.0",
+ "@material/line-ripple": "15.0.0-canary.7f224ddd4.0",
+ "@material/linear-progress": "15.0.0-canary.7f224ddd4.0",
+ "@material/list": "15.0.0-canary.7f224ddd4.0",
+ "@material/menu": "15.0.0-canary.7f224ddd4.0",
+ "@material/menu-surface": "15.0.0-canary.7f224ddd4.0",
+ "@material/notched-outline": "15.0.0-canary.7f224ddd4.0",
+ "@material/radio": "15.0.0-canary.7f224ddd4.0",
+ "@material/ripple": "15.0.0-canary.7f224ddd4.0",
+ "@material/rtl": "15.0.0-canary.7f224ddd4.0",
+ "@material/segmented-button": "15.0.0-canary.7f224ddd4.0",
+ "@material/select": "15.0.0-canary.7f224ddd4.0",
+ "@material/shape": "15.0.0-canary.7f224ddd4.0",
+ "@material/slider": "15.0.0-canary.7f224ddd4.0",
+ "@material/snackbar": "15.0.0-canary.7f224ddd4.0",
+ "@material/switch": "15.0.0-canary.7f224ddd4.0",
+ "@material/tab": "15.0.0-canary.7f224ddd4.0",
+ "@material/tab-bar": "15.0.0-canary.7f224ddd4.0",
+ "@material/tab-indicator": "15.0.0-canary.7f224ddd4.0",
+ "@material/tab-scroller": "15.0.0-canary.7f224ddd4.0",
+ "@material/textfield": "15.0.0-canary.7f224ddd4.0",
+ "@material/theme": "15.0.0-canary.7f224ddd4.0",
+ "@material/tooltip": "15.0.0-canary.7f224ddd4.0",
+ "@material/top-app-bar": "15.0.0-canary.7f224ddd4.0",
+ "@material/touch-target": "15.0.0-canary.7f224ddd4.0",
+ "@material/typography": "15.0.0-canary.7f224ddd4.0",
+ "tslib": "^2.3.0"
+ },
+ "peerDependencies": {
+ "@angular/animations": "^17.0.0 || ^18.0.0",
+ "@angular/cdk": "17.3.10",
+ "@angular/common": "^17.0.0 || ^18.0.0",
+ "@angular/core": "^17.0.0 || ^18.0.0",
+ "@angular/forms": "^17.0.0 || ^18.0.0",
+ "@angular/platform-browser": "^17.0.0 || ^18.0.0",
+ "rxjs": "^6.5.3 || ^7.4.0"
}
},
- "node_modules/@babel/helper-validator-option": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz",
- "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==",
- "dev": true,
+ "node_modules/@angular/platform-browser": {
+ "version": "17.3.12",
+ "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-17.3.12.tgz",
+ "integrity": "sha512-DYY04ptWh/ulMHzd+y52WCE8QnEYGeIiW3hEIFjCN8z0kbIdFdUtEB0IK5vjNL3ejyhUmphcpeT5PYf3YXtqWQ==",
+ "dependencies": {
+ "tslib": "^2.3.0"
+ },
"engines": {
- "node": ">=6.9.0"
+ "node": "^18.13.0 || >=20.9.0"
+ },
+ "peerDependencies": {
+ "@angular/animations": "17.3.12",
+ "@angular/common": "17.3.12",
+ "@angular/core": "17.3.12"
+ },
+ "peerDependenciesMeta": {
+ "@angular/animations": {
+ "optional": true
+ }
}
},
- "node_modules/@babel/helper-wrap-function": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz",
- "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==",
- "dev": true,
+ "node_modules/@angular/platform-browser-dynamic": {
+ "version": "17.3.12",
+ "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-17.3.12.tgz",
+ "integrity": "sha512-DQwV7B2x/DRLRDSisngZRdLqHdYbbrqZv2Hmu4ZbnNYaWPC8qvzgE/0CvY+UkDat3nCcsfwsMnlDeB6TL7/IaA==",
"dependencies": {
- "@babel/template": "^7.25.9",
- "@babel/traverse": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "tslib": "^2.3.0"
},
"engines": {
- "node": ">=6.9.0"
+ "node": "^18.13.0 || >=20.9.0"
+ },
+ "peerDependencies": {
+ "@angular/common": "17.3.12",
+ "@angular/compiler": "17.3.12",
+ "@angular/core": "17.3.12",
+ "@angular/platform-browser": "17.3.12"
}
},
- "node_modules/@babel/helper-wrap-function/node_modules/@babel/template": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
- "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
- "dev": true,
+ "node_modules/@angular/platform-server": {
+ "version": "17.3.12",
+ "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-17.3.12.tgz",
+ "integrity": "sha512-P3xBzyeT2w/iiGsqGUNuLRYdqs2e+5nRnVYU9tc/TjhYDAgwEgq946U7Nie1xq5Ts/8b7bhxcK9maPKWG237Kw==",
+ "license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.25.9",
- "@babel/parser": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "tslib": "^2.3.0",
+ "xhr2": "^0.2.0"
},
"engines": {
- "node": ">=6.9.0"
+ "node": "^18.13.0 || >=20.9.0"
+ },
+ "peerDependencies": {
+ "@angular/animations": "17.3.12",
+ "@angular/common": "17.3.12",
+ "@angular/compiler": "17.3.12",
+ "@angular/core": "17.3.12",
+ "@angular/platform-browser": "17.3.12"
}
},
- "node_modules/@babel/helpers": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.9.tgz",
- "integrity": "sha512-oKWp3+usOJSzDZOucZUAMayhPz/xVjzymyDzUN8dk0Wd3RWMlGLXi07UCQ/CgQVb8LvXx3XBajJH4XGgkt7H7g==",
- "dev": true,
+ "node_modules/@angular/router": {
+ "version": "17.3.12",
+ "resolved": "https://registry.npmjs.org/@angular/router/-/router-17.3.12.tgz",
+ "integrity": "sha512-dg7PHBSW9fmPKTVzwvHEeHZPZdpnUqW/U7kj8D29HTP9ur8zZnx9QcnbplwPeYb8yYa62JMnZSEel2X4PxdYBg==",
"dependencies": {
- "@babel/template": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "tslib": "^2.3.0"
},
"engines": {
- "node": ">=6.9.0"
+ "node": "^18.13.0 || >=20.9.0"
+ },
+ "peerDependencies": {
+ "@angular/common": "17.3.12",
+ "@angular/core": "17.3.12",
+ "@angular/platform-browser": "17.3.12",
+ "rxjs": "^6.5.3 || ^7.4.0"
}
},
- "node_modules/@babel/helpers/node_modules/@babel/template": {
+ "node_modules/@angular/ssr": {
+ "version": "17.3.11",
+ "resolved": "https://registry.npmjs.org/@angular/ssr/-/ssr-17.3.11.tgz",
+ "integrity": "sha512-8AslXZnj5bu0fJrSSoZf202HXptc+vS8hSvEIobK1+UpEVmtrk3StiBxYTdbN4Pe76r7RGRmBt40fHe+88AZoA==",
+ "license": "MIT",
+ "dependencies": {
+ "critters": "0.0.22",
+ "tslib": "^2.3.0"
+ },
+ "peerDependencies": {
+ "@angular/common": "^17.0.0",
+ "@angular/core": "^17.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
- "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.9.tgz",
+ "integrity": "sha512-z88xeGxnzehn2sqZ8UdGQEvYErF1odv2CftxInpSYJt6uHuPe9YjahKZITGs3l5LeI9d2ROG+obuDAoSlqbNfQ==",
"dev": true,
"dependencies": {
- "@babel/code-frame": "^7.25.9",
- "@babel/parser": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "@babel/highlight": "^7.25.9",
+ "picocolors": "^1.0.0"
},
"engines": {
"node": ">=6.9.0"
}
},
- "node_modules/@babel/highlight": {
+ "node_modules/@babel/compat-data": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz",
- "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.9.tgz",
+ "integrity": "sha512-yD+hEuJ/+wAJ4Ox2/rpNv5HIuPG82x3ZlQvYVn8iYCprdxzE7P1udpGF1jyjQVBU4dgznN+k2h103vxZ7NdPyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.22.9",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-validator-identifier": "^7.25.9",
- "chalk": "^2.4.2",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.0.0"
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.22.5",
+ "@babel/generator": "^7.22.9",
+ "@babel/helper-compilation-targets": "^7.22.9",
+ "@babel/helper-module-transforms": "^7.22.9",
+ "@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",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.2",
+ "semver": "^6.3.1"
},
"engines": {
"node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
}
},
- "node_modules/@babel/parser": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.9.tgz",
- "integrity": "sha512-aI3jjAAO1fh7vY/pBGsn1i9LDbRP43+asrRlkPuTXW5yHXtd1NgTEMudbBoDDxrf1daEEfPJqR+JBMakzrR4Dg==",
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.1",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.22.9",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/types": "^7.25.9"
+ "@babel/types": "^7.22.5",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "@jridgewell/trace-mapping": "^0.3.17",
+ "jsesc": "^2.5.1"
},
- "bin": {
- "parser": "bin/babel-parser.js"
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
+ "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.22.5"
},
"engines": {
- "node": ">=6.0.0"
+ "node": ">=6.9.0"
}
},
- "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
+ "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz",
- "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.9.tgz",
+ "integrity": "sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
+ "node_modules/@babel/helper-compilation-targets": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz",
- "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz",
+ "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
- "@babel/plugin-transform-optional-chaining": "^7.25.9"
+ "@babel/compat-data": "^7.25.9",
+ "@babel/helper-validator-option": "^7.25.9",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
},
"engines": {
"node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.13.0"
}
},
- "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": {
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.1",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-create-class-features-plugin": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz",
- "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz",
+ "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/traverse": "^7.25.9"
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-member-expression-to-functions": "^7.25.9",
+ "@babel/helper-optimise-call-expression": "^7.25.9",
+ "@babel/helper-replace-supers": "^7.25.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
+ "@babel/traverse": "^7.25.9",
+ "semver": "^6.3.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1569,451 +1930,402 @@
"@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/plugin-proposal-private-property-in-object": {
- "version": "7.21.0-placeholder-for-preset-env.2",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz",
- "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==",
+ "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz",
+ "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==",
"dev": true,
+ "dependencies": {
+ "@babel/types": "^7.25.9"
+ },
"engines": {
"node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-async-generators": {
- "version": "7.8.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
- "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "bin": {
+ "semver": "bin/semver.js"
}
},
- "node_modules/@babel/plugin-syntax-class-properties": {
- "version": "7.12.13",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
- "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "node_modules/@babel/helper-create-regexp-features-plugin": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.9.tgz",
+ "integrity": "sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.12.13"
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "regexpu-core": "^6.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/plugin-syntax-class-static-block": {
- "version": "7.14.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
- "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
+ "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz",
+ "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-dynamic-import": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
- "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
+ "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-define-polyfill-provider": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz",
+ "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
+ "@babel/helper-compilation-targets": "^7.22.6",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "debug": "^4.1.1",
+ "lodash.debounce": "^4.0.8",
+ "resolve": "^1.14.2"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
}
},
- "node_modules/@babel/plugin-syntax-export-namespace-from": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
- "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
+ "node_modules/@babel/helper-environment-visitor": {
+ "version": "7.22.20",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-member-expression-to-functions": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz",
+ "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "engines": {
+ "node": ">=6.9.0"
}
},
- "node_modules/@babel/plugin-syntax-import-assertions": {
+ "node_modules/@babel/helper-module-imports": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.9.tgz",
- "integrity": "sha512-4GHX5uzr5QMOOuzV0an9MFju4hKlm0OyePl/lHhcsTVae5t/IKVHnb8W67Vr6FuLlk5lPqLB7n7O+K5R46emYg==",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz",
+ "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-import-attributes": {
+ "node_modules/@babel/helper-module-transforms": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.9.tgz",
- "integrity": "sha512-u3EN9ub8LyYvgTnrgp8gboElouayiwPdnM7x5tcnW3iSt09/lQYPwMNK40I9IUxo7QOZhAsPHCmmuO7EPdruqg==",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.9.tgz",
+ "integrity": "sha512-TvLZY/F3+GvdRYFZFyxMvnsKi+4oJdgZzU3BoGN9Uc2d9C6zfNwJcKKhjqLAhK8i46mv93jsO74fDh3ih6rpHA==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-module-imports": "^7.25.9",
+ "@babel/helper-simple-access": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/plugin-syntax-import-meta": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
- "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+ "node_modules/@babel/helper-optimise-call-expression": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz",
+ "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
+ "@babel/types": "^7.25.9"
},
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "engines": {
+ "node": ">=6.9.0"
}
},
- "node_modules/@babel/plugin-syntax-json-strings": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
- "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz",
+ "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==",
"dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "engines": {
+ "node": ">=6.9.0"
}
},
- "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
- "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "node_modules/@babel/helper-remap-async-to-generator": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz",
+ "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-wrap-function": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
},
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
- "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
+ "engines": {
+ "node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/plugin-syntax-numeric-separator": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
- "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "node_modules/@babel/helper-remap-async-to-generator/node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz",
+ "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
+ "@babel/types": "^7.25.9"
},
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "engines": {
+ "node": ">=6.9.0"
}
},
- "node_modules/@babel/plugin-syntax-object-rest-spread": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
- "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "node_modules/@babel/helper-replace-supers": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.9.tgz",
+ "integrity": "sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
+ "@babel/helper-member-expression-to-functions": "^7.25.9",
+ "@babel/helper-optimise-call-expression": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
},
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-optional-catch-binding": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
- "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
+ "engines": {
+ "node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/plugin-syntax-optional-chaining": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
- "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "node_modules/@babel/helper-simple-access": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz",
+ "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "engines": {
+ "node": ">=6.9.0"
}
},
- "node_modules/@babel/plugin-syntax-private-property-in-object": {
- "version": "7.14.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
- "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+ "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz",
+ "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-top-level-await": {
- "version": "7.14.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
- "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "node_modules/@babel/helper-split-export-declaration": {
+ "version": "7.22.6",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-unicode-sets-regex": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz",
- "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==",
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
+ "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
"dev": true,
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.18.6",
- "@babel/helper-plugin-utils": "^7.18.6"
- },
"engines": {
"node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/plugin-transform-arrow-functions": {
+ "node_modules/@babel/helper-validator-identifier": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz",
- "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
+ "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
"dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
- },
"engines": {
"node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-async-generator-functions": {
- "version": "7.23.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.9.tgz",
- "integrity": "sha512-8Q3veQEDGe14dTYuwagbRtwxQDnytyg1JFu4/HwEMETeofocrB0U0ejBJIXoeG/t2oXZ8kzCyI0ZZfbT80VFNQ==",
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz",
+ "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==",
"dev": true,
- "dependencies": {
- "@babel/helper-environment-visitor": "^7.22.20",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-remap-async-to-generator": "^7.22.20",
- "@babel/plugin-syntax-async-generators": "^7.8.4"
- },
"engines": {
"node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-async-to-generator": {
- "version": "7.23.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz",
- "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==",
+ "node_modules/@babel/helper-wrap-function": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz",
+ "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==",
"dev": true,
"dependencies": {
- "@babel/helper-module-imports": "^7.22.15",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-remap-async-to-generator": "^7.22.20"
+ "@babel/template": "^7.25.9",
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-block-scoped-functions": {
+ "node_modules/@babel/helper-wrap-function/node_modules/@babel/template": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.9.tgz",
- "integrity": "sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
+ "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/code-frame": "^7.25.9",
+ "@babel/parser": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-block-scoping": {
+ "node_modules/@babel/helpers": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz",
- "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.9.tgz",
+ "integrity": "sha512-oKWp3+usOJSzDZOucZUAMayhPz/xVjzymyDzUN8dk0Wd3RWMlGLXi07UCQ/CgQVb8LvXx3XBajJH4XGgkt7H7g==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/template": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-class-properties": {
+ "node_modules/@babel/helpers/node_modules/@babel/template": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz",
- "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
+ "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
"dev": true,
"dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/code-frame": "^7.25.9",
+ "@babel/parser": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-class-static-block": {
+ "node_modules/@babel/highlight": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.9.tgz",
- "integrity": "sha512-UIf+72C7YJ+PJ685/PpATbCz00XqiFEzHX5iysRwfvNT0Ko+FaXSvRgLytFSp8xUItrG9pFM/KoBBZDrY/cYyg==",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz",
+ "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==",
"dev": true,
"dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.0.0"
},
"engines": {
"node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.12.0"
}
},
- "node_modules/@babel/plugin-transform-classes": {
+ "node_modules/@babel/parser": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz",
- "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.25.9",
- "@babel/helper-compilation-targets": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/helper-replace-supers": "^7.25.9",
- "@babel/traverse": "^7.25.9",
- "globals": "^11.1.0"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-annotate-as-pure": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz",
- "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.9.tgz",
+ "integrity": "sha512-aI3jjAAO1fh7vY/pBGsn1i9LDbRP43+asrRlkPuTXW5yHXtd1NgTEMudbBoDDxrf1daEEfPJqR+JBMakzrR4Dg==",
"dev": true,
"dependencies": {
"@babel/types": "^7.25.9"
},
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
"engines": {
- "node": ">=6.9.0"
+ "node": ">=6.0.0"
}
},
- "node_modules/@babel/plugin-transform-computed-properties": {
+ "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz",
- "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz",
+ "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/template": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/plugin-transform-computed-properties/node_modules/@babel/template": {
+ "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
- "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz",
+ "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==",
"dev": true,
"dependencies": {
- "@babel/code-frame": "^7.25.9",
- "@babel/parser": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
+ "@babel/plugin-transform-optional-chaining": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.13.0"
}
},
- "node_modules/@babel/plugin-transform-destructuring": {
+ "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz",
- "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz",
+ "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/plugin-transform-dotall-regex": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz",
- "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==",
+ "node_modules/@babel/plugin-proposal-private-property-in-object": {
+ "version": "7.21.0-placeholder-for-preset-env.2",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz",
+ "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==",
"dev": true,
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
- },
"engines": {
"node": ">=6.9.0"
},
@@ -2021,44 +2333,37 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-duplicate-keys": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz",
- "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==",
+ "node_modules/@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
+ "@babel/helper-plugin-utils": "^7.8.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-dynamic-import": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz",
- "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==",
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
+ "@babel/helper-plugin-utils": "^7.12.13"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-exponentiation-operator": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.9.tgz",
- "integrity": "sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA==",
+ "node_modules/@babel/plugin-syntax-class-static-block": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
+ "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
"dev": true,
"dependencies": {
- "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.14.5"
},
"engines": {
"node": ">=6.9.0"
@@ -2067,46 +2372,37 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-export-namespace-from": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz",
- "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==",
+ "node_modules/@babel/plugin-syntax-dynamic-import": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
+ "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
+ "@babel/helper-plugin-utils": "^7.8.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-for-of": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz",
- "integrity": "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==",
+ "node_modules/@babel/plugin-syntax-export-namespace-from": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
+ "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
+ "@babel/helper-plugin-utils": "^7.8.3"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-function-name": {
+ "node_modules/@babel/plugin-syntax-import-assertions": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz",
- "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.9.tgz",
+ "integrity": "sha512-4GHX5uzr5QMOOuzV0an9MFju4hKlm0OyePl/lHhcsTVae5t/IKVHnb8W67Vr6FuLlk5lPqLB7n7O+K5R46emYg==",
"dev": true,
"dependencies": {
- "@babel/helper-compilation-targets": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/traverse": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -2115,10 +2411,10 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-json-strings": {
+ "node_modules/@babel/plugin-syntax-import-attributes": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz",
- "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.9.tgz",
+ "integrity": "sha512-u3EN9ub8LyYvgTnrgp8gboElouayiwPdnM7x5tcnW3iSt09/lQYPwMNK40I9IUxo7QOZhAsPHCmmuO7EPdruqg==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.25.9"
@@ -2130,141 +2426,124 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-literals": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz",
- "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==",
+ "node_modules/@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
+ "@babel/helper-plugin-utils": "^7.10.4"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-logical-assignment-operators": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz",
- "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==",
+ "node_modules/@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
+ "@babel/helper-plugin-utils": "^7.8.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-member-expression-literals": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz",
- "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==",
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
+ "@babel/helper-plugin-utils": "^7.10.4"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-modules-amd": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz",
- "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==",
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
"dev": true,
"dependencies": {
- "@babel/helper-module-transforms": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
+ "@babel/helper-plugin-utils": "^7.8.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-modules-commonjs": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz",
- "integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==",
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
"dev": true,
"dependencies": {
- "@babel/helper-module-transforms": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/helper-simple-access": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
+ "@babel/helper-plugin-utils": "^7.10.4"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-modules-systemjs": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz",
- "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==",
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
"dev": true,
"dependencies": {
- "@babel/helper-module-transforms": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/helper-validator-identifier": "^7.25.9",
- "@babel/traverse": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
+ "@babel/helper-plugin-utils": "^7.8.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-modules-umd": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz",
- "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==",
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
"dev": true,
"dependencies": {
- "@babel/helper-module-transforms": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
+ "@babel/helper-plugin-utils": "^7.8.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz",
- "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==",
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
"dev": true,
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-private-property-in-object": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
+ "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0"
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-new-target": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz",
- "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==",
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.14.5"
},
"engines": {
"node": ">=6.9.0"
@@ -2273,25 +2552,26 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.9.tgz",
- "integrity": "sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==",
+ "node_modules/@babel/plugin-syntax-unicode-sets-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz",
+ "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/plugin-transform-numeric-separator": {
+ "node_modules/@babel/plugin-transform-arrow-functions": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz",
- "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz",
+ "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.25.9"
@@ -2303,15 +2583,16 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-object-rest-spread": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz",
- "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==",
+ "node_modules/@babel/plugin-transform-async-generator-functions": {
+ "version": "7.23.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.9.tgz",
+ "integrity": "sha512-8Q3veQEDGe14dTYuwagbRtwxQDnytyg1JFu4/HwEMETeofocrB0U0ejBJIXoeG/t2oXZ8kzCyI0ZZfbT80VFNQ==",
"dev": true,
"dependencies": {
- "@babel/helper-compilation-targets": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/plugin-transform-parameters": "^7.25.9"
+ "@babel/helper-environment-visitor": "^7.22.20",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-remap-async-to-generator": "^7.22.20",
+ "@babel/plugin-syntax-async-generators": "^7.8.4"
},
"engines": {
"node": ">=6.9.0"
@@ -2320,14 +2601,15 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-object-super": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz",
- "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==",
+ "node_modules/@babel/plugin-transform-async-to-generator": {
+ "version": "7.23.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz",
+ "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/helper-replace-supers": "^7.25.9"
+ "@babel/helper-module-imports": "^7.22.15",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "@babel/helper-remap-async-to-generator": "^7.22.20"
},
"engines": {
"node": ">=6.9.0"
@@ -2336,10 +2618,10 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-optional-catch-binding": {
+ "node_modules/@babel/plugin-transform-block-scoped-functions": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz",
- "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.9.tgz",
+ "integrity": "sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.25.9"
@@ -2351,14 +2633,13 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-optional-chaining": {
+ "node_modules/@babel/plugin-transform-block-scoping": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz",
- "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz",
+ "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -2367,12 +2648,13 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-parameters": {
+ "node_modules/@babel/plugin-transform-class-properties": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz",
- "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz",
+ "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==",
"dev": true,
"dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.25.9",
"@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
@@ -2382,10 +2664,10 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-private-methods": {
+ "node_modules/@babel/plugin-transform-class-static-block": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz",
- "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.9.tgz",
+ "integrity": "sha512-UIf+72C7YJ+PJ685/PpATbCz00XqiFEzHX5iysRwfvNT0Ko+FaXSvRgLytFSp8xUItrG9pFM/KoBBZDrY/cYyg==",
"dev": true,
"dependencies": {
"@babel/helper-create-class-features-plugin": "^7.25.9",
@@ -2395,18 +2677,21 @@
"node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.12.0"
}
},
- "node_modules/@babel/plugin-transform-private-property-in-object": {
+ "node_modules/@babel/plugin-transform-classes": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz",
- "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz",
+ "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==",
"dev": true,
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.25.9",
- "@babel/helper-create-class-features-plugin": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-replace-supers": "^7.25.9",
+ "@babel/traverse": "^7.25.9",
+ "globals": "^11.1.0"
},
"engines": {
"node": ">=6.9.0"
@@ -2415,7 +2700,7 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-private-property-in-object/node_modules/@babel/helper-annotate-as-pure": {
+ "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-annotate-as-pure": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz",
"integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==",
@@ -2427,13 +2712,14 @@
"node": ">=6.9.0"
}
},
- "node_modules/@babel/plugin-transform-property-literals": {
+ "node_modules/@babel/plugin-transform-computed-properties": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz",
- "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz",
+ "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/template": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -2442,26 +2728,24 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-regenerator": {
+ "node_modules/@babel/plugin-transform-computed-properties/node_modules/@babel/template": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz",
- "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
+ "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9",
- "regenerator-transform": "^0.15.2"
+ "@babel/code-frame": "^7.25.9",
+ "@babel/parser": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-reserved-words": {
+ "node_modules/@babel/plugin-transform-destructuring": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz",
- "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz",
+ "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.25.9"
@@ -2473,18 +2757,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-runtime": {
- "version": "7.24.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.0.tgz",
- "integrity": "sha512-zc0GA5IitLKJrSfXlXmp8KDqLrnGECK7YRfQBmEKg1NmBOQ7e+KuclBEKJgzifQeUYLdNiAw4B4bjyvzWVLiSA==",
+ "node_modules/@babel/plugin-transform-dotall-regex": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz",
+ "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==",
"dev": true,
"dependencies": {
- "@babel/helper-module-imports": "^7.22.15",
- "@babel/helper-plugin-utils": "^7.24.0",
- "babel-plugin-polyfill-corejs2": "^0.4.8",
- "babel-plugin-polyfill-corejs3": "^0.9.0",
- "babel-plugin-polyfill-regenerator": "^0.5.5",
- "semver": "^6.3.1"
+ "@babel/helper-create-regexp-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -2493,19 +2773,10 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-runtime/node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/@babel/plugin-transform-shorthand-properties": {
+ "node_modules/@babel/plugin-transform-duplicate-keys": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz",
- "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz",
+ "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.25.9"
@@ -2517,14 +2788,13 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-spread": {
+ "node_modules/@babel/plugin-transform-dynamic-import": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz",
- "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz",
+ "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -2533,12 +2803,13 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-sticky-regex": {
+ "node_modules/@babel/plugin-transform-exponentiation-operator": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz",
- "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.9.tgz",
+ "integrity": "sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA==",
"dev": true,
"dependencies": {
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.9",
"@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
@@ -2548,10 +2819,10 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-template-literals": {
+ "node_modules/@babel/plugin-transform-export-namespace-from": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz",
- "integrity": "sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz",
+ "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.25.9"
@@ -2563,13 +2834,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-typeof-symbol": {
+ "node_modules/@babel/plugin-transform-for-of": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.9.tgz",
- "integrity": "sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz",
+ "integrity": "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -2578,13 +2850,15 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-unicode-escapes": {
+ "node_modules/@babel/plugin-transform-function-name": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz",
- "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz",
+ "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -2593,13 +2867,12 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-unicode-property-regex": {
+ "node_modules/@babel/plugin-transform-json-strings": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz",
- "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz",
+ "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==",
"dev": true,
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.25.9",
"@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
@@ -2609,13 +2882,12 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-unicode-regex": {
+ "node_modules/@babel/plugin-transform-literals": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz",
- "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz",
+ "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==",
"dev": true,
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.25.9",
"@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
@@ -2625,108 +2897,28 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-unicode-sets-regex": {
+ "node_modules/@babel/plugin-transform-logical-assignment-operators": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz",
- "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz",
+ "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==",
"dev": true,
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.25.9",
"@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0"
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/preset-env": {
- "version": "7.24.0",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.0.tgz",
- "integrity": "sha512-ZxPEzV9IgvGn73iK0E6VB9/95Nd7aMFpbE0l8KQFDG70cOV9IxRP7Y2FUPmlK0v6ImlLqYX50iuZ3ZTVhOF2lA==",
- "dev": true,
- "dependencies": {
- "@babel/compat-data": "^7.23.5",
- "@babel/helper-compilation-targets": "^7.23.6",
- "@babel/helper-plugin-utils": "^7.24.0",
- "@babel/helper-validator-option": "^7.23.5",
- "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3",
- "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3",
- "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7",
- "@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.23.3",
- "@babel/plugin-syntax-import-attributes": "^7.23.3",
- "@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.23.3",
- "@babel/plugin-transform-async-generator-functions": "^7.23.9",
- "@babel/plugin-transform-async-to-generator": "^7.23.3",
- "@babel/plugin-transform-block-scoped-functions": "^7.23.3",
- "@babel/plugin-transform-block-scoping": "^7.23.4",
- "@babel/plugin-transform-class-properties": "^7.23.3",
- "@babel/plugin-transform-class-static-block": "^7.23.4",
- "@babel/plugin-transform-classes": "^7.23.8",
- "@babel/plugin-transform-computed-properties": "^7.23.3",
- "@babel/plugin-transform-destructuring": "^7.23.3",
- "@babel/plugin-transform-dotall-regex": "^7.23.3",
- "@babel/plugin-transform-duplicate-keys": "^7.23.3",
- "@babel/plugin-transform-dynamic-import": "^7.23.4",
- "@babel/plugin-transform-exponentiation-operator": "^7.23.3",
- "@babel/plugin-transform-export-namespace-from": "^7.23.4",
- "@babel/plugin-transform-for-of": "^7.23.6",
- "@babel/plugin-transform-function-name": "^7.23.3",
- "@babel/plugin-transform-json-strings": "^7.23.4",
- "@babel/plugin-transform-literals": "^7.23.3",
- "@babel/plugin-transform-logical-assignment-operators": "^7.23.4",
- "@babel/plugin-transform-member-expression-literals": "^7.23.3",
- "@babel/plugin-transform-modules-amd": "^7.23.3",
- "@babel/plugin-transform-modules-commonjs": "^7.23.3",
- "@babel/plugin-transform-modules-systemjs": "^7.23.9",
- "@babel/plugin-transform-modules-umd": "^7.23.3",
- "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5",
- "@babel/plugin-transform-new-target": "^7.23.3",
- "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4",
- "@babel/plugin-transform-numeric-separator": "^7.23.4",
- "@babel/plugin-transform-object-rest-spread": "^7.24.0",
- "@babel/plugin-transform-object-super": "^7.23.3",
- "@babel/plugin-transform-optional-catch-binding": "^7.23.4",
- "@babel/plugin-transform-optional-chaining": "^7.23.4",
- "@babel/plugin-transform-parameters": "^7.23.3",
- "@babel/plugin-transform-private-methods": "^7.23.3",
- "@babel/plugin-transform-private-property-in-object": "^7.23.4",
- "@babel/plugin-transform-property-literals": "^7.23.3",
- "@babel/plugin-transform-regenerator": "^7.23.3",
- "@babel/plugin-transform-reserved-words": "^7.23.3",
- "@babel/plugin-transform-shorthand-properties": "^7.23.3",
- "@babel/plugin-transform-spread": "^7.23.3",
- "@babel/plugin-transform-sticky-regex": "^7.23.3",
- "@babel/plugin-transform-template-literals": "^7.23.3",
- "@babel/plugin-transform-typeof-symbol": "^7.23.3",
- "@babel/plugin-transform-unicode-escapes": "^7.23.3",
- "@babel/plugin-transform-unicode-property-regex": "^7.23.3",
- "@babel/plugin-transform-unicode-regex": "^7.23.3",
- "@babel/plugin-transform-unicode-sets-regex": "^7.23.3",
- "@babel/preset-modules": "0.1.6-no-external-plugins",
- "babel-plugin-polyfill-corejs2": "^0.4.8",
- "babel-plugin-polyfill-corejs3": "^0.9.0",
- "babel-plugin-polyfill-regenerator": "^0.5.5",
- "core-js-compat": "^3.31.0",
- "semver": "^6.3.1"
+ "node_modules/@babel/plugin-transform-member-expression-literals": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz",
+ "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -2735,601 +2927,1857 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/preset-env/node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/@babel/preset-modules": {
- "version": "0.1.6-no-external-plugins",
- "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz",
- "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==",
+ "node_modules/@babel/plugin-transform-modules-amd": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz",
+ "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/types": "^7.4.4",
- "esutils": "^2.0.2"
+ "@babel/helper-module-transforms": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0"
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/runtime": {
- "version": "7.24.0",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz",
- "integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==",
+ "node_modules/@babel/plugin-transform-modules-commonjs": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz",
+ "integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==",
+ "dev": true,
"dependencies": {
- "regenerator-runtime": "^0.14.0"
+ "@babel/helper-module-transforms": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-simple-access": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/template": {
- "version": "7.22.5",
+ "node_modules/@babel/plugin-transform-modules-systemjs": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz",
+ "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==",
"dev": true,
- "license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.22.5",
- "@babel/parser": "^7.22.5",
- "@babel/types": "^7.22.5"
+ "@babel/helper-module-transforms": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/traverse": {
+ "node_modules/@babel/plugin-transform-modules-umd": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz",
- "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz",
+ "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==",
"dev": true,
"dependencies": {
- "@babel/code-frame": "^7.25.9",
- "@babel/generator": "^7.25.9",
- "@babel/parser": "^7.25.9",
- "@babel/template": "^7.25.9",
- "@babel/types": "^7.25.9",
- "debug": "^4.3.1",
- "globals": "^11.1.0"
+ "@babel/helper-module-transforms": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/traverse/node_modules/@babel/generator": {
+ "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.9.tgz",
- "integrity": "sha512-omlUGkr5EaoIJrhLf9CJ0TvjBRpd9+AXRG//0GEQ9THSo8wPiTlbpy1/Ow8ZTrbXpjd9FHXfbFQx32I04ht0FA==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz",
+ "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==",
"dev": true,
"dependencies": {
- "@babel/types": "^7.25.9",
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.25",
- "jsesc": "^3.0.2"
+ "@babel/helper-create-regexp-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/traverse/node_modules/@babel/template": {
+ "node_modules/@babel/plugin-transform-new-target": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
- "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz",
+ "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==",
"dev": true,
"dependencies": {
- "@babel/code-frame": "^7.25.9",
- "@babel/parser": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/traverse/node_modules/jsesc": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz",
- "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==",
+ "node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.9.tgz",
+ "integrity": "sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==",
"dev": true,
- "bin": {
- "jsesc": "bin/jsesc"
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
- "node": ">=6"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/types": {
+ "node_modules/@babel/plugin-transform-numeric-separator": {
"version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.9.tgz",
- "integrity": "sha512-OwS2CM5KocvQ/k7dFJa8i5bNGJP0hXWfVCfDkqRFP1IreH1JDC7wG6eCYCi0+McbfT8OR/kNqsI0UU0xP9H6PQ==",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz",
+ "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==",
"dev": true,
"dependencies": {
- "@babel/helper-string-parser": "^7.25.9",
- "@babel/helper-validator-identifier": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@colors/colors": {
- "version": "1.5.0",
+ "node_modules/@babel/plugin-transform-object-rest-spread": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz",
+ "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==",
"dev": true,
- "license": "MIT",
+ "dependencies": {
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/plugin-transform-parameters": "^7.25.9"
+ },
"engines": {
- "node": ">=0.1.90"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@cspotcode/source-map-support": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
- "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
+ "node_modules/@babel/plugin-transform-object-super": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz",
+ "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==",
"dev": true,
"dependencies": {
- "@jridgewell/trace-mapping": "0.3.9"
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-replace-supers": "^7.25.9"
},
"engines": {
- "node": ">=12"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.9",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
- "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "node_modules/@babel/plugin-transform-optional-catch-binding": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz",
+ "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==",
"dev": true,
"dependencies": {
- "@jridgewell/resolve-uri": "^3.0.3",
- "@jridgewell/sourcemap-codec": "^1.4.10"
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@cypress/request": {
- "version": "3.0.1",
+ "node_modules/@babel/plugin-transform-optional-chaining": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz",
+ "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==",
"dev": true,
- "license": "Apache-2.0",
"dependencies": {
- "aws-sign2": "~0.7.0",
- "aws4": "^1.8.0",
- "caseless": "~0.12.0",
- "combined-stream": "~1.0.6",
- "extend": "~3.0.2",
- "forever-agent": "~0.6.1",
- "form-data": "~2.3.2",
- "http-signature": "~1.3.6",
- "is-typedarray": "~1.0.0",
- "isstream": "~0.1.2",
- "json-stringify-safe": "~5.0.1",
- "mime-types": "~2.1.19",
- "performance-now": "^2.1.0",
- "qs": "6.10.4",
- "safe-buffer": "^5.1.2",
- "tough-cookie": "^4.1.3",
- "tunnel-agent": "^0.6.0",
- "uuid": "^8.3.2"
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9"
},
"engines": {
- "node": ">= 6"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@cypress/request/node_modules/form-data": {
- "version": "2.3.3",
+ "node_modules/@babel/plugin-transform-parameters": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz",
+ "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==",
"dev": true,
- "license": "MIT",
"dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.6",
- "mime-types": "^2.1.12"
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
- "node": ">= 0.12"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@cypress/request/node_modules/qs": {
- "version": "6.10.4",
+ "node_modules/@babel/plugin-transform-private-methods": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz",
+ "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==",
"dev": true,
- "license": "BSD-3-Clause",
"dependencies": {
- "side-channel": "^1.0.4"
+ "@babel/helper-create-class-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
},
"engines": {
- "node": ">=0.6"
+ "node": ">=6.9.0"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@cypress/xvfb": {
- "version": "1.2.4",
+ "node_modules/@babel/plugin-transform-private-property-in-object": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz",
+ "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==",
"dev": true,
- "license": "MIT",
"dependencies": {
- "debug": "^3.1.0",
- "lodash.once": "^4.1.1"
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-create-class-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@cypress/xvfb/node_modules/debug": {
- "version": "3.2.7",
+ "node_modules/@babel/plugin-transform-private-property-in-object/node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz",
+ "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==",
"dev": true,
- "license": "MIT",
"dependencies": {
- "ms": "^2.1.1"
- }
- },
- "node_modules/@discoveryjs/json-ext": {
- "version": "0.5.7",
- "dev": true,
- "license": "MIT",
+ "@babel/types": "^7.25.9"
+ },
"engines": {
- "node": ">=10.0.0"
+ "node": ">=6.9.0"
}
},
- "node_modules/@esbuild/aix-ppc64": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.1.tgz",
- "integrity": "sha512-m55cpeupQ2DbuRGQMMZDzbv9J9PgVelPjlcmM5kxHnrBdBx6REaEd7LamYV7Dm8N7rCyR/XwU6rVP8ploKtIkA==",
- "cpu": [
- "ppc64"
- ],
+ "node_modules/@babel/plugin-transform-property-literals": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz",
+ "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==",
"dev": true,
- "optional": true,
- "os": [
- "aix"
- ],
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
"engines": {
- "node": ">=12"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@esbuild/android-arm": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.1.tgz",
- "integrity": "sha512-4j0+G27/2ZXGWR5okcJi7pQYhmkVgb4D7UKwxcqrjhvp5TKWx3cUjgB1CGj1mfdmJBQ9VnUGgUhign+FPF2Zgw==",
- "cpu": [
- "arm"
- ],
+ "node_modules/@babel/plugin-transform-regenerator": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz",
+ "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==",
"dev": true,
- "optional": true,
- "os": [
- "android"
- ],
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "regenerator-transform": "^0.15.2"
+ },
"engines": {
- "node": ">=12"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@esbuild/android-arm64": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.1.tgz",
- "integrity": "sha512-hCnXNF0HM6AjowP+Zou0ZJMWWa1VkD77BXe959zERgGJBBxB+sV+J9f/rcjeg2c5bsukD/n17RKWXGFCO5dD5A==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@babel/plugin-transform-reserved-words": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz",
+ "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==",
"dev": true,
- "optional": true,
- "os": [
- "android"
- ],
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
"engines": {
- "node": ">=12"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@esbuild/android-x64": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.1.tgz",
- "integrity": "sha512-MSfZMBoAsnhpS+2yMFYIQUPs8Z19ajwfuaSZx+tSl09xrHZCjbeXXMsUF/0oq7ojxYEpsSo4c0SfjxOYXRbpaA==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@babel/plugin-transform-runtime": {
+ "version": "7.24.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.0.tgz",
+ "integrity": "sha512-zc0GA5IitLKJrSfXlXmp8KDqLrnGECK7YRfQBmEKg1NmBOQ7e+KuclBEKJgzifQeUYLdNiAw4B4bjyvzWVLiSA==",
"dev": true,
- "optional": true,
- "os": [
- "android"
- ],
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.22.15",
+ "@babel/helper-plugin-utils": "^7.24.0",
+ "babel-plugin-polyfill-corejs2": "^0.4.8",
+ "babel-plugin-polyfill-corejs3": "^0.9.0",
+ "babel-plugin-polyfill-regenerator": "^0.5.5",
+ "semver": "^6.3.1"
+ },
"engines": {
- "node": ">=12"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@esbuild/darwin-arm64": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.1.tgz",
- "integrity": "sha512-Ylk6rzgMD8klUklGPzS414UQLa5NPXZD5tf8JmQU8GQrj6BrFA/Ic9tb2zRe1kOZyCbGl+e8VMbDRazCEBqPvA==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@babel/plugin-transform-runtime/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
+ "bin": {
+ "semver": "bin/semver.js"
}
},
- "node_modules/@esbuild/darwin-x64": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.1.tgz",
- "integrity": "sha512-pFIfj7U2w5sMp52wTY1XVOdoxw+GDwy9FsK3OFz4BpMAjvZVs0dT1VXs8aQm22nhwoIWUmIRaE+4xow8xfIDZA==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@babel/plugin-transform-shorthand-properties": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz",
+ "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==",
"dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
"engines": {
- "node": ">=12"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@esbuild/freebsd-arm64": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.1.tgz",
- "integrity": "sha512-UyW1WZvHDuM4xDz0jWun4qtQFauNdXjXOtIy7SYdf7pbxSWWVlqhnR/T2TpX6LX5NI62spt0a3ldIIEkPM6RHw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/freebsd-x64": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.1.tgz",
- "integrity": "sha512-itPwCw5C+Jh/c624vcDd9kRCCZVpzpQn8dtwoYIt2TJF3S9xJLiRohnnNrKwREvcZYx0n8sCSbvGH349XkcQeg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-arm": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.1.tgz",
- "integrity": "sha512-LojC28v3+IhIbfQ+Vu4Ut5n3wKcgTu6POKIHN9Wpt0HnfgUGlBuyDDQR4jWZUZFyYLiz4RBBBmfU6sNfn6RhLw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-arm64": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.1.tgz",
- "integrity": "sha512-cX8WdlF6Cnvw/DO9/X7XLH2J6CkBnz7Twjpk56cshk9sjYVcuh4sXQBy5bmTwzBjNVZze2yaV1vtcJS04LbN8w==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@babel/plugin-transform-spread": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz",
+ "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==",
"dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9"
+ },
"engines": {
- "node": ">=12"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@esbuild/linux-ia32": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.1.tgz",
- "integrity": "sha512-4H/sQCy1mnnGkUt/xszaLlYJVTz3W9ep52xEefGtd6yXDQbz/5fZE5dFLUgsPdbUOQANcVUa5iO6g3nyy5BJiw==",
- "cpu": [
- "ia32"
- ],
+ "node_modules/@babel/plugin-transform-sticky-regex": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz",
+ "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==",
"dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
"engines": {
- "node": ">=12"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.1.tgz",
- "integrity": "sha512-c0jgtB+sRHCciVXlyjDcWb2FUuzlGVRwGXgI+3WqKOIuoo8AmZAddzeOHeYLtD+dmtHw3B4Xo9wAUdjlfW5yYA==",
- "cpu": [
- "loong64"
- ],
+ "node_modules/@babel/plugin-transform-template-literals": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz",
+ "integrity": "sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==",
"dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
"engines": {
- "node": ">=12"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@esbuild/linux-mips64el": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.1.tgz",
- "integrity": "sha512-TgFyCfIxSujyuqdZKDZ3yTwWiGv+KnlOeXXitCQ+trDODJ+ZtGOzLkSWngynP0HZnTsDyBbPy7GWVXWaEl6lhA==",
- "cpu": [
- "mips64el"
- ],
+ "node_modules/@babel/plugin-transform-typeof-symbol": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.9.tgz",
+ "integrity": "sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==",
"dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
"engines": {
- "node": ">=12"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@esbuild/linux-ppc64": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.1.tgz",
- "integrity": "sha512-b+yuD1IUeL+Y93PmFZDZFIElwbmFfIKLKlYI8M6tRyzE6u7oEP7onGk0vZRh8wfVGC2dZoy0EqX1V8qok4qHaw==",
- "cpu": [
- "ppc64"
- ],
+ "node_modules/@babel/plugin-transform-unicode-escapes": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz",
+ "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==",
"dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
"engines": {
- "node": ">=12"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@esbuild/linux-riscv64": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.1.tgz",
- "integrity": "sha512-wpDlpE0oRKZwX+GfomcALcouqjjV8MIX8DyTrxfyCfXxoKQSDm45CZr9fanJ4F6ckD4yDEPT98SrjvLwIqUCgg==",
- "cpu": [
- "riscv64"
- ],
+ "node_modules/@babel/plugin-transform-unicode-property-regex": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz",
+ "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==",
"dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
"engines": {
- "node": ">=12"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@esbuild/linux-s390x": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.1.tgz",
- "integrity": "sha512-5BepC2Au80EohQ2dBpyTquqGCES7++p7G+7lXe1bAIvMdXm4YYcEfZtQrP4gaoZ96Wv1Ute61CEHFU7h4FMueQ==",
- "cpu": [
- "s390x"
- ],
+ "node_modules/@babel/plugin-transform-unicode-regex": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz",
+ "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==",
"dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
"engines": {
- "node": ">=12"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@esbuild/linux-x64": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.1.tgz",
- "integrity": "sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@babel/plugin-transform-unicode-sets-regex": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz",
+ "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==",
"dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
"engines": {
- "node": ">=12"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
}
},
- "node_modules/@esbuild/netbsd-x64": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.1.tgz",
- "integrity": "sha512-4fL68JdrLV2nVW2AaWZBv3XEm3Ae3NZn/7qy2KGAt3dexAgSVT+Hc97JKSZnqezgMlv9x6KV0ZkZY7UO5cNLCg==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@babel/preset-env": {
+ "version": "7.24.0",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.0.tgz",
+ "integrity": "sha512-ZxPEzV9IgvGn73iK0E6VB9/95Nd7aMFpbE0l8KQFDG70cOV9IxRP7Y2FUPmlK0v6ImlLqYX50iuZ3ZTVhOF2lA==",
"dev": true,
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/openbsd-x64": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.1.tgz",
- "integrity": "sha512-GhRuXlvRE+twf2ES+8REbeCb/zeikNqwD3+6S5y5/x+DYbAQUNl0HNBs4RQJqrechS4v4MruEr8ZtAin/hK5iw==",
- "cpu": [
- "x64"
- ],
+ "dependencies": {
+ "@babel/compat-data": "^7.23.5",
+ "@babel/helper-compilation-targets": "^7.23.6",
+ "@babel/helper-plugin-utils": "^7.24.0",
+ "@babel/helper-validator-option": "^7.23.5",
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3",
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3",
+ "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7",
+ "@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.23.3",
+ "@babel/plugin-syntax-import-attributes": "^7.23.3",
+ "@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.23.3",
+ "@babel/plugin-transform-async-generator-functions": "^7.23.9",
+ "@babel/plugin-transform-async-to-generator": "^7.23.3",
+ "@babel/plugin-transform-block-scoped-functions": "^7.23.3",
+ "@babel/plugin-transform-block-scoping": "^7.23.4",
+ "@babel/plugin-transform-class-properties": "^7.23.3",
+ "@babel/plugin-transform-class-static-block": "^7.23.4",
+ "@babel/plugin-transform-classes": "^7.23.8",
+ "@babel/plugin-transform-computed-properties": "^7.23.3",
+ "@babel/plugin-transform-destructuring": "^7.23.3",
+ "@babel/plugin-transform-dotall-regex": "^7.23.3",
+ "@babel/plugin-transform-duplicate-keys": "^7.23.3",
+ "@babel/plugin-transform-dynamic-import": "^7.23.4",
+ "@babel/plugin-transform-exponentiation-operator": "^7.23.3",
+ "@babel/plugin-transform-export-namespace-from": "^7.23.4",
+ "@babel/plugin-transform-for-of": "^7.23.6",
+ "@babel/plugin-transform-function-name": "^7.23.3",
+ "@babel/plugin-transform-json-strings": "^7.23.4",
+ "@babel/plugin-transform-literals": "^7.23.3",
+ "@babel/plugin-transform-logical-assignment-operators": "^7.23.4",
+ "@babel/plugin-transform-member-expression-literals": "^7.23.3",
+ "@babel/plugin-transform-modules-amd": "^7.23.3",
+ "@babel/plugin-transform-modules-commonjs": "^7.23.3",
+ "@babel/plugin-transform-modules-systemjs": "^7.23.9",
+ "@babel/plugin-transform-modules-umd": "^7.23.3",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5",
+ "@babel/plugin-transform-new-target": "^7.23.3",
+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4",
+ "@babel/plugin-transform-numeric-separator": "^7.23.4",
+ "@babel/plugin-transform-object-rest-spread": "^7.24.0",
+ "@babel/plugin-transform-object-super": "^7.23.3",
+ "@babel/plugin-transform-optional-catch-binding": "^7.23.4",
+ "@babel/plugin-transform-optional-chaining": "^7.23.4",
+ "@babel/plugin-transform-parameters": "^7.23.3",
+ "@babel/plugin-transform-private-methods": "^7.23.3",
+ "@babel/plugin-transform-private-property-in-object": "^7.23.4",
+ "@babel/plugin-transform-property-literals": "^7.23.3",
+ "@babel/plugin-transform-regenerator": "^7.23.3",
+ "@babel/plugin-transform-reserved-words": "^7.23.3",
+ "@babel/plugin-transform-shorthand-properties": "^7.23.3",
+ "@babel/plugin-transform-spread": "^7.23.3",
+ "@babel/plugin-transform-sticky-regex": "^7.23.3",
+ "@babel/plugin-transform-template-literals": "^7.23.3",
+ "@babel/plugin-transform-typeof-symbol": "^7.23.3",
+ "@babel/plugin-transform-unicode-escapes": "^7.23.3",
+ "@babel/plugin-transform-unicode-property-regex": "^7.23.3",
+ "@babel/plugin-transform-unicode-regex": "^7.23.3",
+ "@babel/plugin-transform-unicode-sets-regex": "^7.23.3",
+ "@babel/preset-modules": "0.1.6-no-external-plugins",
+ "babel-plugin-polyfill-corejs2": "^0.4.8",
+ "babel-plugin-polyfill-corejs3": "^0.9.0",
+ "babel-plugin-polyfill-regenerator": "^0.5.5",
+ "core-js-compat": "^3.31.0",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-env/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
- "optional": true,
- "os": [
- "openbsd"
- ],
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/preset-modules": {
+ "version": "0.1.6-no-external-plugins",
+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz",
+ "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/types": "^7.4.4",
+ "esutils": "^2.0.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.24.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz",
+ "integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==",
+ "dependencies": {
+ "regenerator-runtime": "^0.14.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.22.5",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.22.5",
+ "@babel/parser": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz",
+ "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.25.9",
+ "@babel/generator": "^7.25.9",
+ "@babel/parser": "^7.25.9",
+ "@babel/template": "^7.25.9",
+ "@babel/types": "^7.25.9",
+ "debug": "^4.3.1",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse/node_modules/@babel/generator": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.9.tgz",
+ "integrity": "sha512-omlUGkr5EaoIJrhLf9CJ0TvjBRpd9+AXRG//0GEQ9THSo8wPiTlbpy1/Ow8ZTrbXpjd9FHXfbFQx32I04ht0FA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.25.9",
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse/node_modules/@babel/template": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
+ "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.25.9",
+ "@babel/parser": "^7.25.9",
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse/node_modules/jsesc": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz",
+ "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.9.tgz",
+ "integrity": "sha512-OwS2CM5KocvQ/k7dFJa8i5bNGJP0hXWfVCfDkqRFP1IreH1JDC7wG6eCYCi0+McbfT8OR/kNqsI0UU0xP9H6PQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@colors/colors": {
+ "version": "1.5.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
+ "node_modules/@cspotcode/source-map-support": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
+ "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/trace-mapping": "0.3.9"
+ },
"engines": {
"node": ">=12"
}
},
- "node_modules/@esbuild/sunos-x64": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.1.tgz",
- "integrity": "sha512-ZnWEyCM0G1Ex6JtsygvC3KUUrlDXqOihw8RicRuQAzw+c4f1D66YlPNNV3rkjVW90zXVsHwZYWbJh3v+oQFM9Q==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+ "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
"dev": true,
- "optional": true,
- "os": [
- "sunos"
- ],
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "node_modules/@cypress/request": {
+ "version": "3.0.1",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "http-signature": "~1.3.6",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "performance-now": "^2.1.0",
+ "qs": "6.10.4",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "^4.1.3",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^8.3.2"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@cypress/request/node_modules/form-data": {
+ "version": "2.3.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 0.12"
+ }
+ },
+ "node_modules/@cypress/request/node_modules/qs": {
+ "version": "6.10.4",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/@cypress/xvfb": {
+ "version": "1.2.4",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^3.1.0",
+ "lodash.once": "^4.1.1"
+ }
+ },
+ "node_modules/@cypress/xvfb/node_modules/debug": {
+ "version": "3.2.7",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/@dabh/diagnostics": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz",
+ "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==",
+ "license": "MIT",
+ "dependencies": {
+ "colorspace": "1.1.x",
+ "enabled": "2.0.x",
+ "kuler": "^2.0.0"
+ }
+ },
+ "node_modules/@discoveryjs/json-ext": {
+ "version": "0.5.7",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.1.tgz",
+ "integrity": "sha512-m55cpeupQ2DbuRGQMMZDzbv9J9PgVelPjlcmM5kxHnrBdBx6REaEd7LamYV7Dm8N7rCyR/XwU6rVP8ploKtIkA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.1.tgz",
+ "integrity": "sha512-4j0+G27/2ZXGWR5okcJi7pQYhmkVgb4D7UKwxcqrjhvp5TKWx3cUjgB1CGj1mfdmJBQ9VnUGgUhign+FPF2Zgw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.1.tgz",
+ "integrity": "sha512-hCnXNF0HM6AjowP+Zou0ZJMWWa1VkD77BXe959zERgGJBBxB+sV+J9f/rcjeg2c5bsukD/n17RKWXGFCO5dD5A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.1.tgz",
+ "integrity": "sha512-MSfZMBoAsnhpS+2yMFYIQUPs8Z19ajwfuaSZx+tSl09xrHZCjbeXXMsUF/0oq7ojxYEpsSo4c0SfjxOYXRbpaA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.1.tgz",
+ "integrity": "sha512-Ylk6rzgMD8klUklGPzS414UQLa5NPXZD5tf8JmQU8GQrj6BrFA/Ic9tb2zRe1kOZyCbGl+e8VMbDRazCEBqPvA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.1.tgz",
+ "integrity": "sha512-pFIfj7U2w5sMp52wTY1XVOdoxw+GDwy9FsK3OFz4BpMAjvZVs0dT1VXs8aQm22nhwoIWUmIRaE+4xow8xfIDZA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.1.tgz",
+ "integrity": "sha512-UyW1WZvHDuM4xDz0jWun4qtQFauNdXjXOtIy7SYdf7pbxSWWVlqhnR/T2TpX6LX5NI62spt0a3ldIIEkPM6RHw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.1.tgz",
+ "integrity": "sha512-itPwCw5C+Jh/c624vcDd9kRCCZVpzpQn8dtwoYIt2TJF3S9xJLiRohnnNrKwREvcZYx0n8sCSbvGH349XkcQeg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.1.tgz",
+ "integrity": "sha512-LojC28v3+IhIbfQ+Vu4Ut5n3wKcgTu6POKIHN9Wpt0HnfgUGlBuyDDQR4jWZUZFyYLiz4RBBBmfU6sNfn6RhLw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.1.tgz",
+ "integrity": "sha512-cX8WdlF6Cnvw/DO9/X7XLH2J6CkBnz7Twjpk56cshk9sjYVcuh4sXQBy5bmTwzBjNVZze2yaV1vtcJS04LbN8w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.1.tgz",
+ "integrity": "sha512-4H/sQCy1mnnGkUt/xszaLlYJVTz3W9ep52xEefGtd6yXDQbz/5fZE5dFLUgsPdbUOQANcVUa5iO6g3nyy5BJiw==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.1.tgz",
+ "integrity": "sha512-c0jgtB+sRHCciVXlyjDcWb2FUuzlGVRwGXgI+3WqKOIuoo8AmZAddzeOHeYLtD+dmtHw3B4Xo9wAUdjlfW5yYA==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.1.tgz",
+ "integrity": "sha512-TgFyCfIxSujyuqdZKDZ3yTwWiGv+KnlOeXXitCQ+trDODJ+ZtGOzLkSWngynP0HZnTsDyBbPy7GWVXWaEl6lhA==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.1.tgz",
+ "integrity": "sha512-b+yuD1IUeL+Y93PmFZDZFIElwbmFfIKLKlYI8M6tRyzE6u7oEP7onGk0vZRh8wfVGC2dZoy0EqX1V8qok4qHaw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.1.tgz",
+ "integrity": "sha512-wpDlpE0oRKZwX+GfomcALcouqjjV8MIX8DyTrxfyCfXxoKQSDm45CZr9fanJ4F6ckD4yDEPT98SrjvLwIqUCgg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.1.tgz",
+ "integrity": "sha512-5BepC2Au80EohQ2dBpyTquqGCES7++p7G+7lXe1bAIvMdXm4YYcEfZtQrP4gaoZ96Wv1Ute61CEHFU7h4FMueQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.1.tgz",
+ "integrity": "sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.1.tgz",
+ "integrity": "sha512-4fL68JdrLV2nVW2AaWZBv3XEm3Ae3NZn/7qy2KGAt3dexAgSVT+Hc97JKSZnqezgMlv9x6KV0ZkZY7UO5cNLCg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.1.tgz",
+ "integrity": "sha512-GhRuXlvRE+twf2ES+8REbeCb/zeikNqwD3+6S5y5/x+DYbAQUNl0HNBs4RQJqrechS4v4MruEr8ZtAin/hK5iw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.1.tgz",
+ "integrity": "sha512-ZnWEyCM0G1Ex6JtsygvC3KUUrlDXqOihw8RicRuQAzw+c4f1D66YlPNNV3rkjVW90zXVsHwZYWbJh3v+oQFM9Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.1.tgz",
+ "integrity": "sha512-QZ6gXue0vVQY2Oon9WyLFCdSuYbXSoxaZrPuJ4c20j6ICedfsDilNPYfHLlMH7vGfU5DQR0czHLmJvH4Nzis/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.1.tgz",
+ "integrity": "sha512-HzcJa1NcSWTAU0MJIxOho8JftNp9YALui3o+Ny7hCh0v5f90nprly1U3Sj1Ldj/CvKKdvvFsCRvDkpsEMp4DNw==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.1.tgz",
+ "integrity": "sha512-0MBh53o6XtI6ctDnRMeQ+xoCN8kD2qI1rY1KgF/xdWQwoFeKou7puvDfV8/Wv4Ctx2rRpET/gGdz3YlNtNACSA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@firebase/analytics": {
+ "version": "0.10.9",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.9.tgz",
+ "integrity": "sha512-FrvW6u6xDBKXUGYUy1WIUh0J9tvbppMsk90mig0JhHST8iLveKu/dIBVeVE/ZYZhmXy4fkI7SPSWvD1V0O4tXw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/installations": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/analytics-compat": {
+ "version": "0.2.15",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.15.tgz",
+ "integrity": "sha512-C5to422Sr8FkL0MPwXcIecbMnF4o2Ll7MtoWvIm4Q/LPJvvM+tWa1DiU+LzsCdsd1/CYE9EIW9Ma3ko9XnAAYw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/analytics": "0.10.9",
+ "@firebase/analytics-types": "0.8.2",
+ "@firebase/component": "0.6.10",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/analytics-types": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.2.tgz",
+ "integrity": "sha512-EnzNNLh+9/sJsimsA/FGqzakmrAUKLeJvjRHlg8df1f97NLUlFidk9600y0ZgWOp3CAxn6Hjtk+08tixlUOWyw==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/app": {
+ "version": "0.10.15",
+ "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.15.tgz",
+ "integrity": "sha512-he6qlG3pmwL+LHdG/BrSMBQeJzzutciq4fpXN3lGa1uSwYSijJ24VtakS/bP2X9SiDf8jGywJ4u+OgXAenJsNg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/app-check": {
+ "version": "0.8.9",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.9.tgz",
+ "integrity": "sha512-YzVn1mMLzD2JboMPVVO0Pe20YOgWzrF+aXoAmmd0v3xec051n83YpxSUZbacL69uYvk0dHrEsbea44QtQ5WPDA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/app-check-compat": {
+ "version": "0.3.16",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.16.tgz",
+ "integrity": "sha512-AxIGzLRXrTFNL+H6V+4BO0w/gERloROfRbWI/FoJUnQd0qPZIzyfdHZBbThFzFGLfDt/mVs2kdjYFx/l9I8NhQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app-check": "0.8.9",
+ "@firebase/app-check-types": "0.5.2",
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/app-check-interop-types": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.2.tgz",
+ "integrity": "sha512-LMs47Vinv2HBMZi49C09dJxp0QT5LwDzFaVGf/+ITHe3BlIhUiLNttkATSXplc89A2lAaeTqjgqVkiRfUGyQiQ==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/app-check-types": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.2.tgz",
+ "integrity": "sha512-FSOEzTzL5bLUbD2co3Zut46iyPWML6xc4x+78TeaXMSuJap5QObfb+rVvZJtla3asN4RwU7elaQaduP+HFizDA==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/app-compat": {
+ "version": "0.2.45",
+ "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.45.tgz",
+ "integrity": "sha512-5rYbXq1ndtMTg+07oH4WrkYuP+NZq61uzVwW1hlmybp/gr4cXq2SfaP9fc6/9IzTKmu3dh3H0fjj++HG7Z7o/w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app": "0.10.15",
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/app-types": {
+ "version": "0.9.2",
+ "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.2.tgz",
+ "integrity": "sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/auth": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.8.0.tgz",
+ "integrity": "sha512-/O7UDWE5S5ux456fzNHSLx/0YN/Kykw/WyAzgDQ6wvkddZhSEmPX19EzxgsFldzhuFjsl5uOZTz8kzlosCiJjg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x",
+ "@react-native-async-storage/async-storage": "^1.18.1"
+ },
+ "peerDependenciesMeta": {
+ "@react-native-async-storage/async-storage": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@firebase/auth-compat": {
+ "version": "0.5.15",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.15.tgz",
+ "integrity": "sha512-jz6k1ridPiecKI8CBRiqCM6IMOhwYp2MD+YvoxnMiK8nQLSTm57GvHETlPNX3WlbyQnCjMCOvrAhe27whyxAEg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/auth": "1.8.0",
+ "@firebase/auth-types": "0.12.2",
+ "@firebase/component": "0.6.10",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/auth-interop-types": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.3.tgz",
+ "integrity": "sha512-Fc9wuJGgxoxQeavybiuwgyi+0rssr76b+nHpj+eGhXFYAdudMWyfBHvFL/I5fEHniUM/UQdFzi9VXJK2iZF7FQ==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/auth-types": {
+ "version": "0.12.2",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.2.tgz",
+ "integrity": "sha512-qsEBaRMoGvHO10unlDJhaKSuPn4pyoTtlQuP1ghZfzB6rNQPuhp/N/DcFZxm9i4v0SogjCbf9reWupwIvfmH6w==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "@firebase/app-types": "0.x",
+ "@firebase/util": "1.x"
+ }
+ },
+ "node_modules/@firebase/component": {
+ "version": "0.6.10",
+ "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.10.tgz",
+ "integrity": "sha512-OsNbEKyz9iLZSmMUhsl6+kCADzte00iisJIRUspnUqvDCX+RSGZOBIqekukv/jN177ovjApBQNFaxSYIDc/SyQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/data-connect": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.1.1.tgz",
+ "integrity": "sha512-RBJ7XE/a3oXFv31Jlw8cbMRdsxQoI8F3L7xm4n93ab+bIr1NQUiYGgW9L7TTw7obdNev91ZnW0xfqJtXcPA5yA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/auth-interop-types": "0.2.3",
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/database": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.9.tgz",
+ "integrity": "sha512-EkiPSKSu2TJJGtOjyISASf3UFpFJDil1lMbfqnxilfbmIsilvC8DzgjuLoYD+eOitcug4wtU9Fh1tt2vgBhskA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app-check-interop-types": "0.3.2",
+ "@firebase/auth-interop-types": "0.2.3",
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "faye-websocket": "0.11.4",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/database-compat": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.0.tgz",
+ "integrity": "sha512-2xlODKWwf/vNAxCmou0GFhymx2pqZKkhXMN9B5aiTjZ6+81sOxGim53ELY2lj+qKG2IvgiCYFc4X+ZJA2Ad5vg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/database": "1.0.9",
+ "@firebase/database-types": "1.0.6",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/database-types": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.6.tgz",
+ "integrity": "sha512-sMI7IynSZBsyGbUugc8PKE1jwKbnvaieAz/RxuM57PZQNCi6Rteiviwcw/jqZOX6igqYJwXWZ3UzKOZo2nUDRA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app-types": "0.9.2",
+ "@firebase/util": "1.10.1"
+ }
+ },
+ "node_modules/@firebase/firestore": {
+ "version": "4.7.4",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.4.tgz",
+ "integrity": "sha512-K2nq4w+NF8J1waGawY5OHLawP/Aw5CYxyDstVv1NZemGPcM3U+LZ9EPaXr1PatYIrPA7fS4DxZoWcbB0aGJ8Zg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "@firebase/webchannel-wrapper": "1.0.2",
+ "@grpc/grpc-js": "~1.9.0",
+ "@grpc/proto-loader": "^0.7.8",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/firestore-compat": {
+ "version": "0.3.39",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.39.tgz",
+ "integrity": "sha512-CsK8g34jNeHx95LISDRTcArJLonW+zJCqHI1Ez9WNiLAK2X8FeQ4UiD+RwOwxAIR+t2a6xED/5Fe6ZIqx7MuoQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/firestore": "4.7.4",
+ "@firebase/firestore-types": "3.0.2",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/firestore-types": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.2.tgz",
+ "integrity": "sha512-wp1A+t5rI2Qc/2q7r2ZpjUXkRVPtGMd6zCLsiWurjsQpqPgFin3AhNibKcIzoF2rnToNa/XYtyWXuifjOOwDgg==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "@firebase/app-types": "0.x",
+ "@firebase/util": "1.x"
+ }
+ },
+ "node_modules/@firebase/functions": {
+ "version": "0.11.9",
+ "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.11.9.tgz",
+ "integrity": "sha512-dhO5IUfQRCsrc20YD20nSOX+QCT+cH6N86HlZOLz2XgyEFgzOdBQnUot4EabBJQRkMBI7fZWUrbYfRcnov53ug==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app-check-interop-types": "0.3.2",
+ "@firebase/auth-interop-types": "0.2.3",
+ "@firebase/component": "0.6.10",
+ "@firebase/messaging-interop-types": "0.2.2",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/functions-compat": {
+ "version": "0.3.15",
+ "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.15.tgz",
+ "integrity": "sha512-eiHpc6Sd9Y/SNhBsGi944SapiFbfTPKsiSUQ74QxNSs0yoxvABeIRolVMFk4TokP57NGmstGYpYte02XGNPcYw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/functions": "0.11.9",
+ "@firebase/functions-types": "0.6.2",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/functions-types": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.2.tgz",
+ "integrity": "sha512-0KiJ9lZ28nS2iJJvimpY4nNccV21rkQyor5Iheu/nq8aKXJqtJdeSlZDspjPSBBiHRzo7/GMUttegnsEITqR+w==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/installations": {
+ "version": "0.6.10",
+ "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.10.tgz",
+ "integrity": "sha512-TuGSOMqkFrllxa0X/8VZIqBCRH4POndU/iWKWkRmkh12+/xKSpdp+y/kWaVbsySrelltan6LeYlcYPmLibWbwg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/util": "1.10.1",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/installations-compat": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.10.tgz",
+ "integrity": "sha512-YTonkcVz3AK7RF8xFhvs5CwDuJ0xbzzCJIwXoV14gnzdYbMgy6vWlUUbzkvbtEDXzPRHB0n7aGZl56oy9dLOFw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/installations": "0.6.10",
+ "@firebase/installations-types": "0.5.2",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/installations-types": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.2.tgz",
+ "integrity": "sha512-que84TqGRZJpJKHBlF2pkvc1YcXrtEDOVGiDjovP/a3s6W4nlbohGXEsBJo0JCeeg/UG9A+DEZVDUV9GpklUzA==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "@firebase/app-types": "0.x"
+ }
+ },
+ "node_modules/@firebase/logger": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.3.tgz",
+ "integrity": "sha512-Th42bWJg18EF5bJwhRosn2M/eYxmbWCwXZr4hHX7ltO0SE3QLrpgiMKeRBR/NW7vJke7i0n3i8esbCW2s93qBw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/messaging": {
+ "version": "0.12.13",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.13.tgz",
+ "integrity": "sha512-YLa8PWl+BgiOVR5WOyzl21fVJFJeBRfniNuN25d9DBrQzppSAahuN6yS+vt1OIjvZNPN4pZ/lcRLYupbGu4W0w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/installations": "0.6.10",
+ "@firebase/messaging-interop-types": "0.2.2",
+ "@firebase/util": "1.10.1",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/messaging-compat": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.13.tgz",
+ "integrity": "sha512-9ootPClS6m2c2KIzo7AqSHaWzAw28zWcjQPjVv7WeQDu6wjufpbOg+7tuVzb+gqpF9Issa3lDoYOwlO0ZudO3g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/messaging": "0.12.13",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/messaging-interop-types": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.2.tgz",
+ "integrity": "sha512-l68HXbuD2PPzDUOFb3aG+nZj5KA3INcPwlocwLZOzPp9rFM9yeuI9YLl6DQfguTX5eAGxO0doTR+rDLDvQb5tA==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/performance": {
+ "version": "0.6.10",
+ "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.10.tgz",
+ "integrity": "sha512-x/mNYKGxq7A+QV0EiEZeD2S+E+kw+UcZ8FXuE7qDJyGGt/0Wd+bIIL7RakG/VrFt7/UYc//nKygDc7/Ig7sOmQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/installations": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/performance-compat": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.10.tgz",
+ "integrity": "sha512-0h1qYkF6I79DSSpHfTQFvb91fo8shmmwiPzWFYAPdPK02bSWpKwVssNYlZX2iUnumxerDMbl7dWN+Im/W3bnXA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/performance": "0.6.10",
+ "@firebase/performance-types": "0.2.2",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/performance-types": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.2.tgz",
+ "integrity": "sha512-gVq0/lAClVH5STrIdKnHnCo2UcPLjJlDUoEB/tB4KM+hAeHUxWKnpT0nemUPvxZ5nbdY/pybeyMe8Cs29gEcHA==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/remote-config": {
+ "version": "0.4.10",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.10.tgz",
+ "integrity": "sha512-jTRjy3TdqzVna19m5a1HEHE5BG4Z3BQTxBgvQRTmMKlHacx4QS0CToAas7R9M9UkxpgFcVuAE7FpWIOWQGCEWw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/installations": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/remote-config-compat": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.10.tgz",
+ "integrity": "sha512-fIi5OB2zk0zpChMV/tTd0oEZcZI8TlwQDlLlcrDpMOV5l5dqd0JNlWKh6Fwmh4izmytk+rZIAIpnak/NjGVesQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/remote-config": "0.4.10",
+ "@firebase/remote-config-types": "0.3.2",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/remote-config-types": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.2.tgz",
+ "integrity": "sha512-0BC4+Ud7y2aPTyhXJTMTFfrGGLqdYXrUB9sJVAB8NiqJswDTc4/2qrE/yfUbnQJhbSi6ZaTTBKyG3n1nplssaA==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/storage": {
+ "version": "0.13.3",
+ "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.3.tgz",
+ "integrity": "sha512-B5HiJ7isYKaT4dOEV43f2ySdhQxzq+SQEm7lqXebJ8AYCsebdHrgGzrPR0LR962xGjPzJHFKx63gA8Be/P2MCw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/storage-compat": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.13.tgz",
+ "integrity": "sha512-15kje7JALswRCBKsCSvKg5FbqUYykaIMqMbZRD7I6uVRWwdyTvez5MBQfMhBia2JcEmPiDpXhJTXH4PAWFiA8g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.10",
+ "@firebase/storage": "0.13.3",
+ "@firebase/storage-types": "0.8.2",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app-compat": "0.x"
+ }
+ },
+ "node_modules/@firebase/storage-types": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.2.tgz",
+ "integrity": "sha512-0vWu99rdey0g53lA7IShoA2Lol1jfnPovzLDUBuon65K7uKG9G+L5uO05brD9pMw+l4HRFw23ah3GwTGpEav6g==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "@firebase/app-types": "0.x",
+ "@firebase/util": "1.x"
+ }
+ },
+ "node_modules/@firebase/util": {
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.1.tgz",
+ "integrity": "sha512-AIhFnCCjM8FmCqSNlNPTuOk3+gpHC1RkeNUBLtPbcqGYpN5MxI5q7Yby+rxycweOZOCboDzfIj8WyaY4tpQG/g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/vertexai": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@firebase/vertexai/-/vertexai-1.0.0.tgz",
+ "integrity": "sha512-48N3Lp/9GgiCCRfrSdHS+Y1IiMdYXvnHFO/f+HL1PgUtBq7WQ/fWmYOX3mzAN36zvytq13nb68ImF+GALopp+Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app-check-interop-types": "0.3.2",
+ "@firebase/component": "0.6.10",
+ "@firebase/logger": "0.4.3",
+ "@firebase/util": "1.10.1",
+ "tslib": "^2.1.0"
+ },
"engines": {
- "node": ">=12"
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x",
+ "@firebase/app-types": "0.x"
}
},
- "node_modules/@esbuild/win32-arm64": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.1.tgz",
- "integrity": "sha512-QZ6gXue0vVQY2Oon9WyLFCdSuYbXSoxaZrPuJ4c20j6ICedfsDilNPYfHLlMH7vGfU5DQR0czHLmJvH4Nzis/A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
+ "node_modules/@firebase/vertexai-preview": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/@firebase/vertexai-preview/-/vertexai-preview-0.0.4.tgz",
+ "integrity": "sha512-EBSqyu9eg8frQlVU9/HjKtHN7odqbh9MtAcVz3WwHj4gLCLOoN9F/o+oxlq3CxvFrd3CNTZwu6d2mZtVlEInng==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/app-check-interop-types": "0.3.2",
+ "@firebase/component": "0.6.9",
+ "@firebase/logger": "0.4.2",
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0"
+ },
"engines": {
- "node": ">=12"
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x",
+ "@firebase/app-types": "0.x"
}
},
- "node_modules/@esbuild/win32-ia32": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.1.tgz",
- "integrity": "sha512-HzcJa1NcSWTAU0MJIxOho8JftNp9YALui3o+Ny7hCh0v5f90nprly1U3Sj1Ldj/CvKKdvvFsCRvDkpsEMp4DNw==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
+ "node_modules/@firebase/vertexai-preview/node_modules/@firebase/component": {
+ "version": "0.6.9",
+ "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.9.tgz",
+ "integrity": "sha512-gm8EUEJE/fEac86AvHn8Z/QW8BvR56TBw3hMW0O838J/1mThYQXAIQBgUv75EqlCZfdawpWLrKt1uXvp9ciK3Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/util": "1.10.0",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@firebase/vertexai-preview/node_modules/@firebase/logger": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz",
+ "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@firebase/vertexai-preview/node_modules/@firebase/util": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.0.tgz",
+ "integrity": "sha512-xKtx4A668icQqoANRxyDLBLz51TAbDP9KRfpbKGxiCAW346d0BeJe5vN6/hKxxmWwnZ0mautyv39JxviwwQMOQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/@firebase/webchannel-wrapper": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.2.tgz",
+ "integrity": "sha512-3F4iA2E+NtdMbOU0XC1cHE8q6MqpGIKRj62oGOF38S6AAx5VHR9cXmoDUSj7ejvTAT7m6jxuEeQkHeq0F+mU2w==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@grpc/grpc-js": {
+ "version": "1.9.15",
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz",
+ "integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/proto-loader": "^0.7.8",
+ "@types/node": ">=12.12.47"
+ },
"engines": {
- "node": ">=12"
+ "node": "^8.13.0 || >=10.10.0"
}
},
- "node_modules/@esbuild/win32-x64": {
- "version": "0.20.1",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.1.tgz",
- "integrity": "sha512-0MBh53o6XtI6ctDnRMeQ+xoCN8kD2qI1rY1KgF/xdWQwoFeKou7puvDfV8/Wv4Ctx2rRpET/gGdz3YlNtNACSA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
+ "node_modules/@grpc/proto-loader": {
+ "version": "0.7.13",
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz",
+ "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "lodash.camelcase": "^4.3.0",
+ "long": "^5.0.0",
+ "protobufjs": "^7.2.5",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
+ },
"engines": {
- "node": ">=12"
+ "node": ">=6"
}
},
"node_modules/@isaacs/cliui": {
@@ -3493,7 +4941,6 @@
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.15",
- "dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
@@ -4410,6 +5857,18 @@
"webpack": "^5.54.0"
}
},
+ "node_modules/@nguniversal/express-engine": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@nguniversal/express-engine/-/express-engine-7.0.2.tgz",
+ "integrity": "sha512-mmNgDpUrcuFcjBOfUlmAliS3St4tSekLdQZWu6PK/d+kw5zicDDlSO/UoUw5g+wz7YHkGQK+VDy3wHc0Bo36rA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@angular/common": ">=6.0.0",
+ "@angular/core": ">=6.0.0",
+ "@angular/platform-server": ">=6.0.0",
+ "express": "^4.15.2"
+ }
+ },
"node_modules/@noble/hashes": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz",
@@ -4746,9 +6205,10 @@
}
},
"node_modules/@openmina/shared": {
- "version": "0.102.0",
- "resolved": "https://registry.npmjs.org/@openmina/shared/-/shared-0.102.0.tgz",
- "integrity": "sha512-Tk2kf0b+NQqLQTSqpF+qCeanfGtAfr34RHJcnE/T9iRhzej02Ss5IH2cgzvy5kgSW1IjxT6qsCpUONaRMMmZAw==",
+ "version": "0.117.0",
+ "resolved": "https://registry.npmjs.org/@openmina/shared/-/shared-0.117.0.tgz",
+ "integrity": "sha512-ZGf3JWQKK0rEoFGdhSwUT/TPAljP0wq//1TmWd0uToEKgst+XsMiuT6vR1QcnK2ugTfXpKJf6adJ8ldIrD50vA==",
+ "license": "Apache License, Version 2.0",
"dependencies": {
"tslib": ">=2.3.0"
},
@@ -4784,6 +6244,70 @@
"dev": true,
"license": "MIT"
},
+ "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==",
+ "license": "BSD-3-Clause"
+ },
+ "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==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/codegen": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
+ "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/eventemitter": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
+ "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
+ "license": "BSD-3-Clause"
+ },
+ "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==",
+ "license": "BSD-3-Clause",
+ "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==",
+ "license": "BSD-3-Clause"
+ },
+ "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==",
+ "license": "BSD-3-Clause"
+ },
+ "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==",
+ "license": "BSD-3-Clause"
+ },
+ "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==",
+ "license": "BSD-3-Clause"
+ },
+ "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==",
+ "license": "BSD-3-Clause"
+ },
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.24.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz",
@@ -4996,7 +6520,6 @@
"version": "17.3.10",
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-17.3.10.tgz",
"integrity": "sha512-cI+VB/WXlOeAMamni932lE/AZgui8o81dMyEXNXqCuYagNAMuKXliW79Mi5BwYQEABv/BUb4hB4zYtbQqHyACA==",
- "dev": true,
"dependencies": {
"@angular-devkit/core": "17.3.10",
"@angular-devkit/schematics": "17.3.10",
@@ -5011,8 +6534,7 @@
"node_modules/@schematics/angular/node_modules/jsonc-parser": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz",
- "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==",
- "dev": true
+ "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA=="
},
"node_modules/@sentry-internal/browser-utils": {
"version": "8.35.0",
@@ -5150,6 +6672,196 @@
"node": ">=14.18"
}
},
+ "node_modules/@sentry/cli": {
+ "version": "2.38.2",
+ "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.38.2.tgz",
+ "integrity": "sha512-CR0oujpAnhegK2pBAv6ZReMqbFTuNJLDZLvoD1B+syrKZX+R+oxkgT2e1htsBbht+wGxAsluVWsIAydSws1GAA==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "https-proxy-agent": "^5.0.0",
+ "node-fetch": "^2.6.7",
+ "progress": "^2.0.3",
+ "proxy-from-env": "^1.1.0",
+ "which": "^2.0.2"
+ },
+ "bin": {
+ "sentry-cli": "bin/sentry-cli"
+ },
+ "engines": {
+ "node": ">= 10"
+ },
+ "optionalDependencies": {
+ "@sentry/cli-darwin": "2.38.2",
+ "@sentry/cli-linux-arm": "2.38.2",
+ "@sentry/cli-linux-arm64": "2.38.2",
+ "@sentry/cli-linux-i686": "2.38.2",
+ "@sentry/cli-linux-x64": "2.38.2",
+ "@sentry/cli-win32-i686": "2.38.2",
+ "@sentry/cli-win32-x64": "2.38.2"
+ }
+ },
+ "node_modules/@sentry/cli-darwin": {
+ "version": "2.38.2",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.38.2.tgz",
+ "integrity": "sha512-21ywIcJCCFrCTyiF1o1PaT7rbelFC2fWmayKYgFElnQ55IzNYkcn8BYhbh/QknE0l1NBRaeWMXwTTdeoqETCCg==",
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli-linux-arm": {
+ "version": "2.38.2",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.38.2.tgz",
+ "integrity": "sha512-+AiKDBQKIdQe4NhBiHSHGl0KR+b//HHTrnfK1SaTrOm9HtM4ELXAkjkRF3bmbpSzSQCS5WzcbIxxCJOeaUaO0A==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "linux",
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli-linux-arm64": {
+ "version": "2.38.2",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.38.2.tgz",
+ "integrity": "sha512-4Fp/jjQpNZj4Th+ZckMQvldAuuP0ZcyJ9tJCP1CCOn5poIKPYtY6zcbTP036R7Te14PS4ALOcDNX3VNKfpsifA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "linux",
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli-linux-i686": {
+ "version": "2.38.2",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.38.2.tgz",
+ "integrity": "sha512-6zVJN10dHIn4R1v+fxuzlblzVBhIVwsaN/S7aBED6Vn1HhAyAcNG2tIzeCLGeDfieYjXlE2sCI82sZkQBCbAGw==",
+ "cpu": [
+ "x86",
+ "ia32"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "linux",
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli-linux-x64": {
+ "version": "2.38.2",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.38.2.tgz",
+ "integrity": "sha512-4UiLu9zdVtqPeltELR5MDGKcuqAdQY9xz3emISuA6bm+MXGbt2W1WgX+XY3GElwjZbmH8qpyLUEd34sw6sdcbQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "linux",
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli-win32-i686": {
+ "version": "2.38.2",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.38.2.tgz",
+ "integrity": "sha512-DYfSvd5qLPerLpIxj3Xu2rRe3CIlpGOOfGSNI6xvJ5D8j6hqbOHlCzvfC4oBWYVYGtxnwQLMeDGJ7o7RMYulig==",
+ "cpu": [
+ "x86",
+ "ia32"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli-win32-x64": {
+ "version": "2.38.2",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.38.2.tgz",
+ "integrity": "sha512-W5UX58PKY1hNUHo9YJxWNhGvgvv2uOYHI27KchRiUvFYBIqlUUcIdPZDfyzetDfd8qBCxlAsFnkL2VJSNdpA9A==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli/node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/@sentry/cli/node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@sentry/cli/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==",
+ "license": "MIT"
+ },
+ "node_modules/@sentry/cli/node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
"node_modules/@sentry/core": {
"version": "8.35.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.35.0.tgz",
@@ -5706,8 +7418,9 @@
"dev": true
},
"node_modules/@types/node": {
- "version": "20.10.3",
- "dev": true,
+ "version": "18.19.64",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.64.tgz",
+ "integrity": "sha512-955mDqvO2vFf/oL7V3WiUtiz+BugyX8uVbaT2H8oj3+8dRyH2FLiNdowe7eNqRM7IOIZvzDH76EoAT+gwm6aIQ==",
"license": "MIT",
"dependencies": {
"undici-types": "~5.26.4"
@@ -5789,6 +7502,12 @@
"@types/node": "*"
}
},
+ "node_modules/@types/triple-beam": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
+ "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==",
+ "license": "MIT"
+ },
"node_modules/@types/w3c-web-hid": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/w3c-web-hid/-/w3c-web-hid-1.0.6.tgz",
@@ -5999,7 +7718,6 @@
},
"node_modules/accepts": {
"version": "1.3.8",
- "dev": true,
"license": "MIT",
"dependencies": {
"mime-types": "~2.1.34",
@@ -6092,7 +7810,6 @@
},
"node_modules/ajv": {
"version": "8.12.0",
- "dev": true,
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.1",
@@ -6107,7 +7824,6 @@
},
"node_modules/ajv-formats": {
"version": "2.1.1",
- "dev": true,
"license": "MIT",
"dependencies": {
"ajv": "^8.0.0"
@@ -6142,7 +7858,6 @@
},
"node_modules/ansi-escapes": {
"version": "4.3.2",
- "dev": true,
"license": "MIT",
"dependencies": {
"type-fest": "^0.21.3"
@@ -6168,7 +7883,6 @@
},
"node_modules/ansi-regex": {
"version": "5.0.1",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -6188,7 +7902,7 @@
},
"node_modules/anymatch": {
"version": "3.1.3",
- "dev": true,
+ "devOptional": true,
"license": "ISC",
"dependencies": {
"normalize-path": "^3.0.0",
@@ -6234,8 +7948,7 @@
"node_modules/array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
- "dev": true
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
},
"node_modules/asn1": {
"version": "0.2.6",
@@ -6263,8 +7976,17 @@
},
"node_modules/async": {
"version": "3.2.5",
+ "license": "MIT"
+ },
+ "node_modules/async-each-series": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-0.1.1.tgz",
+ "integrity": "sha512-p4jj6Fws4Iy2m0iCmI2am2ZNZCgbdgE+P8F/8csmn2vx7ixXrO2zGcuNsD46X5uZSVecmkEy/M06X2vG8KD6dQ==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.0"
+ }
},
"node_modules/asynckit": {
"version": "0.4.0",
@@ -6500,7 +8222,7 @@
},
"node_modules/binary-extensions": {
"version": "2.2.0",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -6508,7 +8230,6 @@
},
"node_modules/bl": {
"version": "4.1.0",
- "dev": true,
"license": "MIT",
"dependencies": {
"buffer": "^5.5.0",
@@ -6520,7 +8241,6 @@
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -6559,7 +8279,6 @@
"version": "1.20.3",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
"integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
- "dev": true,
"dependencies": {
"bytes": "3.1.2",
"content-type": "~1.0.5",
@@ -6575,59 +8294,448 @@
"unpipe": "1.0.0"
},
"engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/body-parser/node_modules/debug": {
+ "version": "2.6.9",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/body-parser/node_modules/ms": {
+ "version": "2.0.0",
+ "license": "MIT"
+ },
+ "node_modules/bonjour-service": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz",
+ "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "multicast-dns": "^7.2.5"
+ }
+ },
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browser-sync": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-3.0.3.tgz",
+ "integrity": "sha512-91hoBHKk1C4pGeD+oE9Ld222k2GNQEAsI5AElqR8iLLWNrmZR2LPP8B0h8dpld9u7kro5IEUB3pUb0DJ3n1cRQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "browser-sync-client": "^3.0.3",
+ "browser-sync-ui": "^3.0.3",
+ "bs-recipes": "1.3.4",
+ "chalk": "4.1.2",
+ "chokidar": "^3.5.1",
+ "connect": "3.6.6",
+ "connect-history-api-fallback": "^1",
+ "dev-ip": "^1.0.1",
+ "easy-extender": "^2.3.4",
+ "eazy-logger": "^4.0.1",
+ "etag": "^1.8.1",
+ "fresh": "^0.5.2",
+ "fs-extra": "3.0.1",
+ "http-proxy": "^1.18.1",
+ "immutable": "^3",
+ "micromatch": "^4.0.8",
+ "opn": "5.3.0",
+ "portscanner": "2.2.0",
+ "raw-body": "^2.3.2",
+ "resp-modifier": "6.0.2",
+ "rx": "4.1.0",
+ "send": "^0.19.0",
+ "serve-index": "^1.9.1",
+ "serve-static": "^1.16.2",
+ "server-destroy": "1.0.1",
+ "socket.io": "^4.4.1",
+ "ua-parser-js": "^1.0.33",
+ "yargs": "^17.3.1"
+ },
+ "bin": {
+ "browser-sync": "dist/bin.js"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
+ "node_modules/browser-sync-client": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-3.0.3.tgz",
+ "integrity": "sha512-TOEXaMgYNjBYIcmX5zDlOdjEqCeCN/d7opf/fuyUD/hhGVCfP54iQIDhENCi012AqzYZm3BvuFl57vbwSTwkSQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "etag": "1.8.1",
+ "fresh": "0.5.2",
+ "mitt": "^1.1.3"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/browser-sync-ui": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-3.0.3.tgz",
+ "integrity": "sha512-FcGWo5lP5VodPY6O/f4pXQy5FFh4JK0f2/fTBsp0Lx1NtyBWs/IfPPJbW8m1ujTW/2r07oUXKTF2LYZlCZktjw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "async-each-series": "0.1.1",
+ "chalk": "4.1.2",
+ "connect-history-api-fallback": "^1",
+ "immutable": "^3",
+ "server-destroy": "1.0.1",
+ "socket.io-client": "^4.4.1",
+ "stream-throttle": "^0.1.3"
+ }
+ },
+ "node_modules/browser-sync-ui/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/browser-sync-ui/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "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/browser-sync-ui/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/browser-sync-ui/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/browser-sync-ui/node_modules/connect-history-api-fallback": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
+ "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/browser-sync-ui/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browser-sync-ui/node_modules/immutable": {
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz",
+ "integrity": "sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/browser-sync-ui/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browser-sync/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/browser-sync/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "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/browser-sync/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/browser-sync/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/browser-sync/node_modules/connect": {
+ "version": "3.6.6",
+ "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz",
+ "integrity": "sha512-OO7axMmPpu/2XuX1+2Yrg0ddju31B6xLZMWkJ5rYBu4YRmRVlOjvlY6kw2FJKiAzyxGwnrDUAG4s1Pf0sbBMCQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "finalhandler": "1.1.0",
+ "parseurl": "~1.3.2",
+ "utils-merge": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/browser-sync/node_modules/connect-history-api-fallback": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
+ "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/browser-sync/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/browser-sync/node_modules/finalhandler": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz",
+ "integrity": "sha512-ejnvM9ZXYzp6PUPUyQBMBf0Co5VX2gr5H2VQe2Ui2jWXNlxv+PYZo8wpAymJNJdLsG1R4p+M4aynF8KuoUEwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.1",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.2",
+ "statuses": "~1.3.1",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
}
},
- "node_modules/body-parser/node_modules/debug": {
- "version": "2.6.9",
+ "node_modules/browser-sync/node_modules/fs-extra": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz",
+ "integrity": "sha512-V3Z3WZWVUYd8hoCL5xfXJCaHWYzmtwW5XWYSlLgERi8PWd8bx1kUHUk8L1BT57e49oKnDDD180mjfrHc1yA9rg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "ms": "2.0.0"
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^3.0.0",
+ "universalify": "^0.1.0"
}
},
- "node_modules/body-parser/node_modules/ms": {
+ "node_modules/browser-sync/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browser-sync/node_modules/immutable": {
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz",
+ "integrity": "sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/browser-sync/node_modules/jsonfile": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz",
+ "integrity": "sha512-oBko6ZHlubVB5mRFkur5vgYR1UyqX+S6Y/oCfLhqNdcc2fYFlDpIoNc7AfKS1KOGcnNAkvsr0grLck9ANM815w==",
+ "dev": true,
+ "license": "MIT",
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/browser-sync/node_modules/ms": {
"version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true,
"license": "MIT"
},
- "node_modules/bonjour-service": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz",
- "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==",
+ "node_modules/browser-sync/node_modules/on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "fast-deep-equal": "^3.1.3",
- "multicast-dns": "^7.2.5"
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
}
},
- "node_modules/boolbase": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
- "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
- "dev": true
- },
- "node_modules/brace-expansion": {
- "version": "1.1.11",
+ "node_modules/browser-sync/node_modules/statuses": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
+ "integrity": "sha512-wuTCPGlJONk/a1kqZ4fQM2+908lC7fa7nPYpTC1EhnvqLX/IICbeP1OZGDtA374trpSq68YubKUMo8oRhN46yg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "engines": {
+ "node": ">= 0.6"
}
},
- "node_modules/braces": {
- "version": "3.0.2",
+ "node_modules/browser-sync/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "fill-range": "^7.0.1"
+ "has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
+ "node_modules/browser-sync/node_modules/ua-parser-js": {
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.39.tgz",
+ "integrity": "sha512-k24RCVWlEcjkdOxYmVJgeD/0a1TiSpqLg+ZalVGV9lsnr4yqu0w7tX/x2xX6G4zpkgQnRf89lxuZ1wsbjXM8lw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/ua-parser-js"
+ },
+ {
+ "type": "paypal",
+ "url": "https://paypal.me/faisalman"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/faisalman"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "ua-parser-js": "script/cli.js"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/browserslist": {
"version": "4.24.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz",
@@ -6660,6 +8768,13 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
+ "node_modules/bs-recipes": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/bs-recipes/-/bs-recipes-1.3.4.tgz",
+ "integrity": "sha512-BXvDkqhDNxXEjeGM8LFkSbR+jzmP/CYpCiVKYn+soB1dDldeU15EBNDkwVXndKuX35wnNUaPd0qSoQEAkmQtMw==",
+ "dev": true,
+ "license": "ISC"
+ },
"node_modules/bs58": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz",
@@ -6715,7 +8830,6 @@
},
"node_modules/bytes": {
"version": "3.1.2",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8"
@@ -6806,7 +8920,6 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
- "dev": true,
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
@@ -6880,8 +8993,7 @@
"node_modules/chardet": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
- "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
- "dev": true
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
},
"node_modules/check-more-types": {
"version": "2.24.0",
@@ -6893,7 +9005,7 @@
},
"node_modules/chokidar": {
"version": "3.5.3",
- "dev": true,
+ "devOptional": true,
"funding": [
{
"type": "individual",
@@ -6958,7 +9070,6 @@
},
"node_modules/cli-cursor": {
"version": "3.1.0",
- "dev": true,
"license": "MIT",
"dependencies": {
"restore-cursor": "^3.1.0"
@@ -6969,7 +9080,6 @@
},
"node_modules/cli-spinners": {
"version": "2.9.2",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -7018,7 +9128,6 @@
},
"node_modules/cliui": {
"version": "8.0.1",
- "dev": true,
"license": "ISC",
"dependencies": {
"string-width": "^4.2.0",
@@ -7031,7 +9140,6 @@
},
"node_modules/clone": {
"version": "1.0.4",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.8"
@@ -7050,11 +9158,20 @@
"node": ">=6"
}
},
+ "node_modules/color": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
+ "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^1.9.3",
+ "color-string": "^1.6.0"
+ }
+ },
"node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
"dependencies": {
"color-name": "1.1.3"
}
@@ -7062,14 +9179,33 @@
"node_modules/color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ },
+ "node_modules/color-string": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
+ "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
},
"node_modules/colorette": {
"version": "2.0.20",
"dev": true,
"license": "MIT"
},
+ "node_modules/colorspace": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz",
+ "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==",
+ "license": "MIT",
+ "dependencies": {
+ "color": "^3.1.3",
+ "text-hex": "1.0.x"
+ }
+ },
"node_modules/combined-stream": {
"version": "1.0.8",
"dev": true,
@@ -7215,7 +9351,6 @@
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
"integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
- "dev": true,
"dependencies": {
"safe-buffer": "5.2.1"
},
@@ -7225,7 +9360,6 @@
},
"node_modules/content-type": {
"version": "1.0.5",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.6"
@@ -7247,8 +9381,7 @@
"node_modules/cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
- "dev": true
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
},
"node_modules/copy-anything": {
"version": "2.0.6",
@@ -7311,8 +9444,7 @@
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
- "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
- "dev": true
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"node_modules/cors": {
"version": "2.8.5",
@@ -7380,7 +9512,6 @@
"version": "0.0.22",
"resolved": "https://registry.npmjs.org/critters/-/critters-0.0.22.tgz",
"integrity": "sha512-NU7DEcQZM2Dy8XTKFHxtdnIM/drE312j2T4PCVaSUcS0oBeyT/NImpRw/Ap0zOr/1SE7SgPK9tGPg1WK/sVakw==",
- "dev": true,
"dependencies": {
"chalk": "^4.1.0",
"css-select": "^5.1.0",
@@ -7395,7 +9526,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -7410,7 +9540,6 @@
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -7426,7 +9555,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
"dependencies": {
"color-name": "~1.1.4"
},
@@ -7437,14 +9565,12 @@
"node_modules/critters/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/critters/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -7453,7 +9579,6 @@
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -7555,7 +9680,6 @@
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
"integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
- "dev": true,
"dependencies": {
"boolbase": "^1.0.0",
"css-what": "^6.1.0",
@@ -7571,7 +9695,6 @@
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
- "dev": true,
"engines": {
"node": ">= 6"
},
@@ -7661,14 +9784,6 @@
"cypress": "^4.x || ^5.x || ^6.x || ^7.x || ^8.x || ^9.x || ^10.x || ^11.x || ^12.x || ^13.x"
}
},
- "node_modules/cypress/node_modules/@types/node": {
- "version": "18.19.2",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "undici-types": "~5.26.4"
- }
- },
"node_modules/cypress/node_modules/ansi-styles": {
"version": "4.3.0",
"dev": true,
@@ -8254,7 +10369,6 @@
},
"node_modules/debug": {
"version": "4.3.4",
- "dev": true,
"license": "MIT",
"dependencies": {
"ms": "2.1.2"
@@ -8286,7 +10400,6 @@
},
"node_modules/defaults": {
"version": "1.0.4",
- "dev": true,
"license": "MIT",
"dependencies": {
"clone": "^1.0.2"
@@ -8299,7 +10412,6 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
- "dev": true,
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
@@ -8314,7 +10426,6 @@
},
"node_modules/define-lazy-prop": {
"version": "2.0.0",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -8337,7 +10448,6 @@
},
"node_modules/depd": {
"version": "2.0.0",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8"
@@ -8345,7 +10455,6 @@
},
"node_modules/destroy": {
"version": "1.2.0",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8",
@@ -8358,6 +10467,18 @@
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
"dev": true
},
+ "node_modules/dev-ip": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dev-ip/-/dev-ip-1.0.1.tgz",
+ "integrity": "sha512-LmVkry/oDShEgSZPNgqCIp2/TlqtExeGmymru3uCELnfyjY11IzpAproLYs+1X88fXO6DBoYP3ul2Xo2yz2j6A==",
+ "dev": true,
+ "bin": {
+ "dev-ip": "lib/dev-ip.js"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
"node_modules/di": {
"version": "0.0.1",
"dev": true,
@@ -8410,7 +10531,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
- "dev": true,
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.2",
@@ -8424,7 +10544,6 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -8436,42 +10555,140 @@
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
+ "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/duplexer": {
+ "version": "0.1.2",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true
+ },
+ "node_modules/easy-extender": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/easy-extender/-/easy-extender-2.3.4.tgz",
+ "integrity": "sha512-8cAwm6md1YTiPpOvDULYJL4ZS6WfM5/cTeVVh4JsvyYZAoqlRVUpHL9Gr5Fy7HA6xcSZicUia3DeAgO3Us8E+Q==",
+ "dev": true,
+ "dependencies": {
+ "lodash": "^4.17.10"
+ },
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/eazy-logger": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/eazy-logger/-/eazy-logger-4.0.1.tgz",
+ "integrity": "sha512-2GSFtnnC6U4IEKhEI7+PvdxrmjJ04mdsj3wHZTFiw0tUtG4HCWzTr13ZYTk8XOGnA1xQMaDljoBOYlk3D/MMSw==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "4.1.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/eazy-logger/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/eazy-logger/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "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/eazy-logger/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/eazy-logger/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/eazy-logger/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
- "dependencies": {
- "domelementtype": "^2.3.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">= 4"
- },
- "funding": {
- "url": "https://github.com/fb55/domhandler?sponsor=1"
+ "node": ">=8"
}
},
- "node_modules/domutils": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
- "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
+ "node_modules/eazy-logger/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "dom-serializer": "^2.0.0",
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.3"
+ "has-flag": "^4.0.0"
},
- "funding": {
- "url": "https://github.com/fb55/domutils?sponsor=1"
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/duplexer": {
- "version": "0.1.2",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/eastasianwidth": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
- "dev": true
- },
"node_modules/ecc-jsbn": {
"version": "0.1.2",
"dev": true,
@@ -8483,7 +10700,6 @@
},
"node_modules/ee-first": {
"version": "1.1.1",
- "dev": true,
"license": "MIT"
},
"node_modules/eigen": {
@@ -8502,7 +10718,6 @@
},
"node_modules/emoji-regex": {
"version": "8.0.0",
- "dev": true,
"license": "MIT"
},
"node_modules/emojis-list": {
@@ -8513,9 +10728,14 @@
"node": ">= 4"
}
},
+ "node_modules/enabled": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
+ "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==",
+ "license": "MIT"
+ },
"node_modules/encodeurl": {
"version": "1.0.2",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8"
@@ -8525,7 +10745,6 @@
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
- "dev": true,
"optional": true,
"dependencies": {
"iconv-lite": "^0.6.2"
@@ -8535,7 +10754,6 @@
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
- "dev": true,
"optional": true,
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
@@ -8572,6 +10790,42 @@
"node": ">=10.2.0"
}
},
+ "node_modules/engine.io-client": {
+ "version": "6.6.2",
+ "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.2.tgz",
+ "integrity": "sha512-TAr+NKeoVTjEVW8P3iHguO1LO6RlUz9O5Y8o7EY0fU+gY1NYqas7NN3slpFtbXEsLMHk0h90fJMfKjRkQ0qUIw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@socket.io/component-emitter": "~3.1.0",
+ "debug": "~4.3.1",
+ "engine.io-parser": "~5.2.1",
+ "ws": "~8.17.1",
+ "xmlhttprequest-ssl": "~2.1.1"
+ }
+ },
+ "node_modules/engine.io-client/node_modules/ws": {
+ "version": "8.17.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
+ "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
+ "dev": true,
+ "license": "MIT",
+ "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/engine.io-parser": {
"version": "5.2.1",
"dev": true,
@@ -8632,7 +10886,6 @@
},
"node_modules/entities": {
"version": "4.5.0",
- "devOptional": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
@@ -8681,7 +10934,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
- "dev": true,
"dependencies": {
"get-intrinsic": "^1.2.4"
},
@@ -8693,7 +10945,6 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
- "dev": true,
"engines": {
"node": ">= 0.4"
}
@@ -8758,14 +11009,12 @@
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
- "dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/escape-html": {
"version": "1.0.3",
- "dev": true,
"license": "MIT"
},
"node_modules/escape-latex": {
@@ -8774,7 +11023,6 @@
},
"node_modules/escape-string-regexp": {
"version": "1.0.5",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.8.0"
@@ -8844,7 +11092,6 @@
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
- "dev": true,
"engines": {
"node": ">= 0.6"
}
@@ -8918,7 +11165,6 @@
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
"integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
- "dev": true,
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
@@ -8960,7 +11206,6 @@
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
"integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
- "dev": true,
"engines": {
"node": ">= 0.6"
}
@@ -8969,7 +11214,6 @@
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
"dependencies": {
"ms": "2.0.0"
}
@@ -8978,7 +11222,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
- "dev": true,
"engines": {
"node": ">= 0.8"
}
@@ -8987,7 +11230,6 @@
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
"integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
- "dev": true,
"dependencies": {
"debug": "2.6.9",
"encodeurl": "~2.0.0",
@@ -9004,14 +11246,12 @@
"node_modules/express/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/express/node_modules/statuses": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
- "dev": true,
"engines": {
"node": ">= 0.8"
}
@@ -9025,7 +11265,6 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
"integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
- "dev": true,
"dependencies": {
"chardet": "^0.7.0",
"iconv-lite": "^0.4.24",
@@ -9078,7 +11317,6 @@
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
- "dev": true,
"license": "MIT"
},
"node_modules/fast-glob": {
@@ -9113,7 +11351,6 @@
"version": "0.11.4",
"resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
"integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
- "dev": true,
"dependencies": {
"websocket-driver": ">=0.5.1"
},
@@ -9129,9 +11366,14 @@
"pend": "~1.2.0"
}
},
+ "node_modules/fecha": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
+ "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==",
+ "license": "MIT"
+ },
"node_modules/figures": {
"version": "3.2.0",
- "dev": true,
"license": "MIT",
"dependencies": {
"escape-string-regexp": "^1.0.5"
@@ -9144,8 +11386,10 @@
}
},
"node_modules/fill-range": {
- "version": "7.0.1",
- "dev": true,
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
@@ -9222,6 +11466,42 @@
"node": ">=8"
}
},
+ "node_modules/firebase": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/firebase/-/firebase-11.0.1.tgz",
+ "integrity": "sha512-qsFb8dMcQINEDhJteG7RP+GqwgSRvfyiexQqHd5JToDdm87i9I2rGC4XQsGawKGxzKwZ/ISdgwNWxXAFYdCC6A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/analytics": "0.10.9",
+ "@firebase/analytics-compat": "0.2.15",
+ "@firebase/app": "0.10.15",
+ "@firebase/app-check": "0.8.9",
+ "@firebase/app-check-compat": "0.3.16",
+ "@firebase/app-compat": "0.2.45",
+ "@firebase/app-types": "0.9.2",
+ "@firebase/auth": "1.8.0",
+ "@firebase/auth-compat": "0.5.15",
+ "@firebase/data-connect": "0.1.1",
+ "@firebase/database": "1.0.9",
+ "@firebase/database-compat": "2.0.0",
+ "@firebase/firestore": "4.7.4",
+ "@firebase/firestore-compat": "0.3.39",
+ "@firebase/functions": "0.11.9",
+ "@firebase/functions-compat": "0.3.15",
+ "@firebase/installations": "0.6.10",
+ "@firebase/installations-compat": "0.2.10",
+ "@firebase/messaging": "0.12.13",
+ "@firebase/messaging-compat": "0.2.13",
+ "@firebase/performance": "0.6.10",
+ "@firebase/performance-compat": "0.2.10",
+ "@firebase/remote-config": "0.4.10",
+ "@firebase/remote-config-compat": "0.2.10",
+ "@firebase/storage": "0.13.3",
+ "@firebase/storage-compat": "0.3.13",
+ "@firebase/util": "1.10.1",
+ "@firebase/vertexai": "1.0.0"
+ }
+ },
"node_modules/flat": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
@@ -9236,6 +11516,12 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/fn.name": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
+ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==",
+ "license": "MIT"
+ },
"node_modules/follow-redirects": {
"version": "1.15.3",
"dev": true,
@@ -9295,7 +11581,6 @@
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
- "dev": true,
"engines": {
"node": ">= 0.6"
}
@@ -9317,14 +11602,12 @@
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
- "dev": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/fs-extra": {
"version": "8.1.0",
- "dev": true,
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.0",
@@ -9372,12 +11655,19 @@
},
"node_modules/function-bind": {
"version": "1.1.2",
- "dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/fuzzy": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/fuzzy/-/fuzzy-0.1.3.tgz",
+ "integrity": "sha512-/gZffu4ykarLrCiP3Ygsa86UAo1E5vEVlvTrpkKywXSbP9Xhln3oSp9QSV57gEq3JFFpGJ4GZ+5zdEp3FcUh4w==",
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"dev": true,
@@ -9388,7 +11678,6 @@
},
"node_modules/get-caller-file": {
"version": "2.0.5",
- "dev": true,
"license": "ISC",
"engines": {
"node": "6.* || 8.* || >= 10.*"
@@ -9398,7 +11687,6 @@
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
- "dev": true,
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
@@ -9470,7 +11758,7 @@
},
"node_modules/glob-parent": {
"version": "5.1.2",
- "dev": true,
+ "devOptional": true,
"license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
@@ -9536,7 +11824,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
- "dev": true,
"dependencies": {
"get-intrinsic": "^1.1.3"
},
@@ -9546,7 +11833,6 @@
},
"node_modules/graceful-fs": {
"version": "4.2.11",
- "dev": true,
"license": "ISC"
},
"node_modules/gzip-size": {
@@ -9582,7 +11868,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
- "dev": true,
"dependencies": {
"es-define-property": "^1.0.0"
},
@@ -9592,7 +11877,6 @@
},
"node_modules/has-proto": {
"version": "1.0.1",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -9603,7 +11887,6 @@
},
"node_modules/has-symbols": {
"version": "1.0.3",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -9623,7 +11906,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
- "dev": true,
"dependencies": {
"function-bind": "^1.1.2"
},
@@ -9716,7 +11998,6 @@
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
- "dev": true,
"funding": [
"https://github.com/fb55/htmlparser2?sponsor=1",
{
@@ -9745,7 +12026,6 @@
},
"node_modules/http-errors": {
"version": "2.0.0",
- "dev": true,
"license": "MIT",
"dependencies": {
"depd": "2.0.0",
@@ -9760,7 +12040,6 @@
},
"node_modules/http-errors/node_modules/statuses": {
"version": "2.0.1",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8"
@@ -9769,8 +12048,7 @@
"node_modules/http-parser-js": {
"version": "0.5.8",
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz",
- "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==",
- "dev": true
+ "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q=="
},
"node_modules/http-proxy": {
"version": "1.18.1",
@@ -9859,7 +12137,6 @@
},
"node_modules/iconv-lite": {
"version": "0.4.24",
- "dev": true,
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
@@ -9880,6 +12157,12 @@
"postcss": "^8.1.0"
}
},
+ "node_modules/idb": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz",
+ "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==",
+ "license": "ISC"
+ },
"node_modules/ieee754": {
"version": "1.2.1",
"funding": [
@@ -9954,6 +12237,12 @@
"node": ">=0.10.0"
}
},
+ "node_modules/immediate": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
+ "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
+ "license": "MIT"
+ },
"node_modules/immutable": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz",
@@ -10013,7 +12302,6 @@
},
"node_modules/inherits": {
"version": "2.0.4",
- "dev": true,
"license": "ISC"
},
"node_modules/ini": {
@@ -10159,7 +12447,7 @@
},
"node_modules/is-binary-path": {
"version": "2.1.0",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"binary-extensions": "^2.0.0"
@@ -10196,7 +12484,6 @@
},
"node_modules/is-docker": {
"version": "2.2.1",
- "dev": true,
"license": "MIT",
"bin": {
"is-docker": "cli.js"
@@ -10210,7 +12497,7 @@
},
"node_modules/is-extglob": {
"version": "2.1.1",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -10218,7 +12505,6 @@
},
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -10226,7 +12512,7 @@
},
"node_modules/is-glob": {
"version": "4.0.3",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"is-extglob": "^2.1.1"
@@ -10252,7 +12538,6 @@
},
"node_modules/is-interactive": {
"version": "1.0.0",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -10266,12 +12551,24 @@
},
"node_modules/is-number": {
"version": "7.0.0",
- "dev": true,
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "devOptional": true,
"license": "MIT",
"engines": {
"node": ">=0.12.0"
}
},
+ "node_modules/is-number-like": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz",
+ "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "lodash.isfinite": "^3.3.2"
+ }
+ },
"node_modules/is-path-inside": {
"version": "3.0.3",
"dev": true,
@@ -10305,7 +12602,6 @@
},
"node_modules/is-stream": {
"version": "2.0.1",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -10321,7 +12617,6 @@
},
"node_modules/is-unicode-supported": {
"version": "0.1.0",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
@@ -10337,7 +12632,6 @@
},
"node_modules/is-wsl": {
"version": "2.2.0",
- "dev": true,
"license": "MIT",
"dependencies": {
"is-docker": "^2.0.0"
@@ -10349,8 +12643,7 @@
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
- "dev": true
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"node_modules/isbinaryfile": {
"version": "4.0.10",
@@ -10365,7 +12658,6 @@
},
"node_modules/isexe": {
"version": "2.0.0",
- "dev": true,
"license": "ISC"
},
"node_modules/isobject": {
@@ -10596,7 +12888,6 @@
},
"node_modules/json-schema-traverse": {
"version": "1.0.0",
- "dev": true,
"license": "MIT"
},
"node_modules/json-stringify-safe": {
@@ -10615,9 +12906,14 @@
"node": ">=6"
}
},
+ "node_modules/jsonc-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz",
+ "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==",
+ "license": "MIT"
+ },
"node_modules/jsonfile": {
"version": "4.0.0",
- "dev": true,
"license": "MIT",
"optionalDependencies": {
"graceful-fs": "^4.1.6"
@@ -10646,6 +12942,48 @@
"verror": "1.10.0"
}
},
+ "node_modules/jszip": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
+ "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
+ "license": "(MIT OR GPL-3.0-or-later)",
+ "dependencies": {
+ "lie": "~3.3.0",
+ "pako": "~1.0.2",
+ "readable-stream": "~2.3.6",
+ "setimmediate": "^1.0.5"
+ }
+ },
+ "node_modules/jszip/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "license": "MIT",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/jszip/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "license": "MIT"
+ },
+ "node_modules/jszip/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
"node_modules/karma": {
"version": "6.4.2",
"dev": true,
@@ -10809,6 +13147,12 @@
"node": ">= 8"
}
},
+ "node_modules/kuler": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
+ "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==",
+ "license": "MIT"
+ },
"node_modules/launch-editor": {
"version": "2.9.1",
"resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz",
@@ -10935,6 +13279,21 @@
}
}
},
+ "node_modules/lie": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
+ "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
+ "license": "MIT",
+ "dependencies": {
+ "immediate": "~3.0.5"
+ }
+ },
+ "node_modules/limiter": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz",
+ "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==",
+ "dev": true
+ },
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@@ -10996,7 +13355,12 @@
},
"node_modules/lodash": {
"version": "4.17.21",
- "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
"license": "MIT"
},
"node_modules/lodash.debounce": {
@@ -11005,6 +13369,13 @@
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
"dev": true
},
+ "node_modules/lodash.isfinite": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz",
+ "integrity": "sha512-7FGG40uhC8Mm633uKW1r58aElFlBlxCrg9JfSi3P6aYiWmfiWF0PgMd86ZUsxE5GwWPdHoS2+48bwTh2VPkIQA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/lodash.once": {
"version": "4.1.1",
"dev": true,
@@ -11012,7 +13383,6 @@
},
"node_modules/log-symbols": {
"version": "4.1.0",
- "dev": true,
"license": "MIT",
"dependencies": {
"chalk": "^4.1.0",
@@ -11027,7 +13397,6 @@
},
"node_modules/log-symbols/node_modules/ansi-styles": {
"version": "4.3.0",
- "dev": true,
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
@@ -11041,7 +13410,6 @@
},
"node_modules/log-symbols/node_modules/chalk": {
"version": "4.1.2",
- "dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
@@ -11056,7 +13424,6 @@
},
"node_modules/log-symbols/node_modules/color-convert": {
"version": "2.0.1",
- "dev": true,
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
@@ -11067,12 +13434,10 @@
},
"node_modules/log-symbols/node_modules/color-name": {
"version": "1.1.4",
- "dev": true,
"license": "MIT"
},
"node_modules/log-symbols/node_modules/has-flag": {
"version": "4.0.0",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -11080,7 +13445,6 @@
},
"node_modules/log-symbols/node_modules/supports-color": {
"version": "7.2.0",
- "dev": true,
"license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
@@ -11180,6 +13544,38 @@
"node": ">=8.0"
}
},
+ "node_modules/logform": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz",
+ "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@colors/colors": "1.6.0",
+ "@types/triple-beam": "^1.3.2",
+ "fecha": "^4.2.0",
+ "ms": "^2.1.1",
+ "safe-stable-stringify": "^2.3.1",
+ "triple-beam": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ }
+ },
+ "node_modules/logform/node_modules/@colors/colors": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz",
+ "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
+ "node_modules/long": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
+ "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==",
+ "license": "Apache-2.0"
+ },
"node_modules/lru-cache": {
"version": "5.1.1",
"dev": true,
@@ -11192,7 +13588,6 @@
"version": "0.30.8",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz",
"integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==",
- "dev": true,
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
},
@@ -11286,7 +13681,6 @@
},
"node_modules/media-typer": {
"version": "0.3.0",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.6"
@@ -11308,7 +13702,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
"integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
- "dev": true,
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
@@ -11330,17 +13723,18 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
- "dev": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/micromatch": {
- "version": "4.0.5",
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "braces": "^3.0.2",
+ "braces": "^3.0.3",
"picomatch": "^2.3.1"
},
"engines": {
@@ -11360,7 +13754,6 @@
},
"node_modules/mime-db": {
"version": "1.52.0",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.6"
@@ -11368,7 +13761,6 @@
},
"node_modules/mime-types": {
"version": "2.1.35",
- "dev": true,
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
@@ -11379,7 +13771,6 @@
},
"node_modules/mimic-fn": {
"version": "2.1.0",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -11626,6 +14017,13 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
+ "node_modules/mitt": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.2.0.tgz",
+ "integrity": "sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/mkdirp": {
"version": "0.5.6",
"dev": true,
@@ -11647,7 +14045,6 @@
},
"node_modules/ms": {
"version": "2.1.2",
- "dev": true,
"license": "MIT"
},
"node_modules/multicast-dns": {
@@ -11674,7 +14071,6 @@
},
"node_modules/nanoid": {
"version": "3.3.7",
- "dev": true,
"funding": [
{
"type": "github",
@@ -11729,7 +14125,6 @@
},
"node_modules/negotiator": {
"version": "0.6.3",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.6"
@@ -11769,6 +14164,26 @@
"dev": true,
"optional": true
},
+ "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==",
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
"node_modules/node-forge": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
@@ -11928,7 +14343,7 @@
},
"node_modules/normalize-path": {
"version": "3.0.0",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -12061,7 +14476,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
- "dev": true,
"dependencies": {
"boolbase": "^1.0.0"
},
@@ -12079,7 +14493,6 @@
},
"node_modules/object-inspect": {
"version": "1.13.1",
- "dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -12093,7 +14506,6 @@
},
"node_modules/on-finished": {
"version": "2.4.1",
- "dev": true,
"license": "MIT",
"dependencies": {
"ee-first": "1.1.1"
@@ -12119,9 +14531,17 @@
"wrappy": "1"
}
},
+ "node_modules/one-time": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
+ "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
+ "license": "MIT",
+ "dependencies": {
+ "fn.name": "1.x.x"
+ }
+ },
"node_modules/onetime": {
"version": "5.1.2",
- "dev": true,
"license": "MIT",
"dependencies": {
"mimic-fn": "^2.1.0"
@@ -12135,7 +14555,6 @@
},
"node_modules/open": {
"version": "8.4.2",
- "dev": true,
"license": "MIT",
"dependencies": {
"define-lazy-prop": "^2.0.0",
@@ -12157,9 +14576,31 @@
"opener": "bin/opener-bin.js"
}
},
+ "node_modules/opn": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz",
+ "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-wsl": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/opn/node_modules/is-wsl": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
+ "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/ora": {
"version": "5.4.1",
- "dev": true,
"license": "MIT",
"dependencies": {
"bl": "^4.1.0",
@@ -12181,7 +14622,6 @@
},
"node_modules/ora/node_modules/ansi-styles": {
"version": "4.3.0",
- "dev": true,
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
@@ -12195,7 +14635,6 @@
},
"node_modules/ora/node_modules/chalk": {
"version": "4.1.2",
- "dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
@@ -12210,7 +14649,6 @@
},
"node_modules/ora/node_modules/color-convert": {
"version": "2.0.1",
- "dev": true,
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
@@ -12221,12 +14659,10 @@
},
"node_modules/ora/node_modules/color-name": {
"version": "1.1.4",
- "dev": true,
"license": "MIT"
},
"node_modules/ora/node_modules/has-flag": {
"version": "4.0.0",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -12234,7 +14670,6 @@
},
"node_modules/ora/node_modules/supports-color": {
"version": "7.2.0",
- "dev": true,
"license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
@@ -12247,7 +14682,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -12364,6 +14798,12 @@
"node": "^16.14.0 || >=18.0.0"
}
},
+ "node_modules/pako": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
+ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
+ "license": "(MIT AND Zlib)"
+ },
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -12450,7 +14890,6 @@
},
"node_modules/parseurl": {
"version": "1.3.3",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8"
@@ -12511,8 +14950,7 @@
"node_modules/path-to-regexp": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
- "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
- "dev": true
+ "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w=="
},
"node_modules/path-type": {
"version": "4.0.0",
@@ -12535,12 +14973,11 @@
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
- "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
- "dev": true
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
},
"node_modules/picomatch": {
"version": "2.3.1",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"engines": {
"node": ">=8.6"
@@ -12646,9 +15083,33 @@
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
}
},
+ "node_modules/portscanner": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.2.0.tgz",
+ "integrity": "sha512-IFroCz/59Lqa2uBvzK3bKDbDDIEaAY8XJ1jFxcLWTqosrsc32//P4VuSB2vZXoHiHqOmx8B5L5hnKOxL/7FlPw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "async": "^2.6.0",
+ "is-number-like": "^1.0.3"
+ },
+ "engines": {
+ "node": ">=0.4",
+ "npm": ">=1.0.0"
+ }
+ },
+ "node_modules/portscanner/node_modules/async": {
+ "version": "2.6.4",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
+ "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "lodash": "^4.17.14"
+ }
+ },
"node_modules/postcss": {
"version": "8.4.31",
- "dev": true,
"funding": [
{
"type": "opencollective",
@@ -12707,8 +15168,7 @@
"node_modules/postcss-media-query-parser": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz",
- "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==",
- "dev": true
+ "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig=="
},
"node_modules/postcss-modules-extract-imports": {
"version": "3.1.0",
@@ -12819,8 +15279,16 @@
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
- "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
- "dev": true
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+ },
+ "node_modules/progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
},
"node_modules/promise-inflight": {
"version": "1.0.1",
@@ -12841,11 +15309,34 @@
"node": ">=10"
}
},
+ "node_modules/protobufjs": {
+ "version": "7.4.0",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz",
+ "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.4",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.0",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.0",
+ "@types/node": ">=13.7.0",
+ "long": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
- "dev": true,
"dependencies": {
"forwarded": "0.2.0",
"ipaddr.js": "1.9.1"
@@ -12858,7 +15349,6 @@
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
- "dev": true,
"engines": {
"node": ">= 0.10"
}
@@ -12890,7 +15380,6 @@
},
"node_modules/punycode": {
"version": "2.3.1",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -12908,7 +15397,6 @@
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
- "dev": true,
"dependencies": {
"side-channel": "^1.0.6"
},
@@ -12953,7 +15441,6 @@
},
"node_modules/range-parser": {
"version": "1.2.1",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.6"
@@ -12961,7 +15448,6 @@
},
"node_modules/raw-body": {
"version": "2.5.2",
- "dev": true,
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
@@ -13066,7 +15552,6 @@
},
"node_modules/readable-stream": {
"version": "3.6.2",
- "dev": true,
"license": "MIT",
"dependencies": {
"inherits": "^2.0.3",
@@ -13079,7 +15564,7 @@
},
"node_modules/readdirp": {
"version": "3.6.0",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"picomatch": "^2.2.1"
@@ -13188,7 +15673,6 @@
},
"node_modules/require-directory": {
"version": "2.1.1",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -13196,7 +15680,6 @@
},
"node_modules/require-from-string": {
"version": "2.0.2",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -13268,9 +15751,38 @@
"node": ">=0.10.0"
}
},
+ "node_modules/resp-modifier": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/resp-modifier/-/resp-modifier-6.0.2.tgz",
+ "integrity": "sha512-U1+0kWC/+4ncRFYqQWTx/3qkfE6a4B/h3XXgmXypfa0SPZ3t7cbbaFk297PjQS/yov24R18h6OZe6iZwj3NSLw==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^2.2.0",
+ "minimatch": "^3.0.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/resp-modifier/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/resp-modifier/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/restore-cursor": {
"version": "3.1.0",
- "dev": true,
"license": "MIT",
"dependencies": {
"onetime": "^5.1.0",
@@ -13391,6 +15903,13 @@
"version": "1.3.3",
"license": "BSD-3-Clause"
},
+ "node_modules/rx": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz",
+ "integrity": "sha512-CiaiuN6gapkdl+cZUr67W6I8jquN4lkak3vtIsIWCl4XIPP8ffsoyN6/+PuGXnQy8Cu8W2y9Xxh31Rq4M6wUug==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
"node_modules/rxjs": {
"version": "7.8.1",
"license": "Apache-2.0",
@@ -13400,7 +15919,6 @@
},
"node_modules/safe-buffer": {
"version": "5.2.1",
- "dev": true,
"funding": [
{
"type": "github",
@@ -13417,6 +15935,15 @@
],
"license": "MIT"
},
+ "node_modules/safe-stable-stringify": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
+ "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/safer-buffer": {
"version": "2.1.2",
"license": "MIT"
@@ -13561,7 +16088,6 @@
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
"integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
- "dev": true,
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
@@ -13585,7 +16111,6 @@
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
"dependencies": {
"ms": "2.0.0"
}
@@ -13593,14 +16118,12 @@
"node_modules/send/node_modules/debug/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/send/node_modules/mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
- "dev": true,
"bin": {
"mime": "cli.js"
},
@@ -13611,14 +16134,12 @@
"node_modules/send/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "dev": true
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/send/node_modules/statuses": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
- "dev": true,
"engines": {
"node": ">= 0.8"
}
@@ -13704,7 +16225,6 @@
"version": "1.16.2",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
"integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
- "dev": true,
"dependencies": {
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
@@ -13719,16 +16239,21 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
- "dev": true,
"engines": {
"node": ">= 0.8"
}
},
+ "node_modules/server-destroy": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz",
+ "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==",
+ "dev": true,
+ "license": "ISC"
+ },
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
- "dev": true,
"dependencies": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
@@ -13741,9 +16266,14 @@
"node": ">= 0.4"
}
},
+ "node_modules/setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+ "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
+ "license": "MIT"
+ },
"node_modules/setprototypeof": {
"version": "1.2.0",
- "dev": true,
"license": "ISC"
},
"node_modules/shallow-clone": {
@@ -13789,7 +16319,6 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
- "dev": true,
"dependencies": {
"call-bind": "^1.0.7",
"es-errors": "^1.3.0",
@@ -13805,7 +16334,6 @@
},
"node_modules/signal-exit": {
"version": "3.0.7",
- "dev": true,
"license": "ISC"
},
"node_modules/sigstore": {
@@ -13825,6 +16353,21 @@
"node": "^16.14.0 || >=18.0.0"
}
},
+ "node_modules/simple-swizzle": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+ "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.3.1"
+ }
+ },
+ "node_modules/simple-swizzle/node_modules/is-arrayish": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
+ "license": "MIT"
+ },
"node_modules/sirv": {
"version": "2.0.3",
"dev": true,
@@ -13947,6 +16490,22 @@
}
}
},
+ "node_modules/socket.io-client": {
+ "version": "4.8.1",
+ "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz",
+ "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@socket.io/component-emitter": "~3.1.0",
+ "debug": "~4.3.2",
+ "engine.io-client": "~6.6.1",
+ "socket.io-parser": "~4.2.4"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
"node_modules/socket.io-parser": {
"version": "4.2.4",
"dev": true,
@@ -14000,7 +16559,6 @@
},
"node_modules/source-map": {
"version": "0.7.4",
- "dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">= 8"
@@ -14010,7 +16568,6 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -14167,6 +16724,15 @@
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
+ "node_modules/stack-trace": {
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
+ "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==",
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/statuses": {
"version": "1.5.0",
"dev": true,
@@ -14175,6 +16741,23 @@
"node": ">= 0.6"
}
},
+ "node_modules/stream-throttle": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/stream-throttle/-/stream-throttle-0.1.3.tgz",
+ "integrity": "sha512-889+B9vN9dq7/vLbGyuHeZ6/ctf5sNuGWsDy89uNxkFTAgzy0eK7+w5fL3KLNRTkLle7EgZGvHUphZW0Q26MnQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "commander": "^2.2.0",
+ "limiter": "^1.0.5"
+ },
+ "bin": {
+ "throttleproxy": "bin/throttleproxy.js"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
"node_modules/streamroller": {
"version": "3.1.5",
"dev": true,
@@ -14190,7 +16773,6 @@
},
"node_modules/string_decoder": {
"version": "1.3.0",
- "dev": true,
"license": "MIT",
"dependencies": {
"safe-buffer": "~5.2.0"
@@ -14198,7 +16780,6 @@
},
"node_modules/string-width": {
"version": "4.2.3",
- "dev": true,
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
@@ -14226,7 +16807,6 @@
},
"node_modules/strip-ansi": {
"version": "6.0.1",
- "dev": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
@@ -14501,6 +17081,12 @@
"node": ">=8"
}
},
+ "node_modules/text-hex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
+ "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==",
+ "license": "MIT"
+ },
"node_modules/throttleit": {
"version": "1.0.1",
"dev": true,
@@ -14511,7 +17097,6 @@
},
"node_modules/through": {
"version": "2.3.8",
- "dev": true,
"license": "MIT"
},
"node_modules/thunky": {
@@ -14528,7 +17113,6 @@
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
- "dev": true,
"dependencies": {
"os-tmpdir": "~1.0.2"
},
@@ -14538,7 +17122,9 @@
},
"node_modules/to-regex-range": {
"version": "5.0.1",
- "dev": true,
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
@@ -14549,7 +17135,6 @@
},
"node_modules/toidentifier": {
"version": "1.0.1",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.6"
@@ -14585,6 +17170,12 @@
"node": ">= 4.0.0"
}
},
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "license": "MIT"
+ },
"node_modules/tree-kill": {
"version": "1.2.2",
"dev": true,
@@ -14593,6 +17184,15 @@
"tree-kill": "cli.js"
}
},
+ "node_modules/triple-beam": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz",
+ "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
"node_modules/ts-node": {
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
@@ -14687,7 +17287,6 @@
},
"node_modules/type-fest": {
"version": "0.21.3",
- "dev": true,
"license": "(MIT OR CC0-1.0)",
"engines": {
"node": ">=10"
@@ -14698,7 +17297,6 @@
},
"node_modules/type-is": {
"version": "1.6.18",
- "dev": true,
"license": "MIT",
"dependencies": {
"media-typer": "0.3.0",
@@ -14766,7 +17364,6 @@
},
"node_modules/undici-types": {
"version": "5.26.5",
- "dev": true,
"license": "MIT"
},
"node_modules/unicode-canonical-property-names-ecmascript": {
@@ -14835,7 +17432,6 @@
},
"node_modules/universalify": {
"version": "0.1.2",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 4.0.0"
@@ -14843,7 +17439,6 @@
},
"node_modules/unpipe": {
"version": "1.0.0",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8"
@@ -14889,7 +17484,6 @@
},
"node_modules/uri-js": {
"version": "4.4.1",
- "dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"punycode": "^2.1.0"
@@ -14906,12 +17500,10 @@
},
"node_modules/util-deprecate": {
"version": "1.0.2",
- "dev": true,
"license": "MIT"
},
"node_modules/utils-merge": {
"version": "1.0.1",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4.0"
@@ -14952,7 +17544,6 @@
},
"node_modules/vary": {
"version": "1.1.2",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8"
@@ -15496,12 +18087,17 @@
},
"node_modules/wcwidth": {
"version": "1.0.1",
- "dev": true,
"license": "MIT",
"dependencies": {
"defaults": "^1.0.3"
}
},
+ "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==",
+ "license": "BSD-2-Clause"
+ },
"node_modules/webpack": {
"version": "5.94.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz",
@@ -15836,7 +18432,6 @@
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
"integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
- "dev": true,
"dependencies": {
"http-parser-js": ">=0.5.1",
"safe-buffer": ">=5.1.0",
@@ -15850,11 +18445,20 @@
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
"integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
- "dev": true,
"engines": {
"node": ">=0.8.0"
}
},
+ "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==",
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
"node_modules/which": {
"version": "1.3.1",
"dev": true,
@@ -15871,9 +18475,53 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/winston": {
+ "version": "3.17.0",
+ "resolved": "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz",
+ "integrity": "sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==",
+ "license": "MIT",
+ "dependencies": {
+ "@colors/colors": "^1.6.0",
+ "@dabh/diagnostics": "^2.0.2",
+ "async": "^3.2.3",
+ "is-stream": "^2.0.0",
+ "logform": "^2.7.0",
+ "one-time": "^1.0.0",
+ "readable-stream": "^3.4.0",
+ "safe-stable-stringify": "^2.3.1",
+ "stack-trace": "0.0.x",
+ "triple-beam": "^1.3.0",
+ "winston-transport": "^4.9.0"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ }
+ },
+ "node_modules/winston-transport": {
+ "version": "4.9.0",
+ "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz",
+ "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==",
+ "license": "MIT",
+ "dependencies": {
+ "logform": "^2.7.0",
+ "readable-stream": "^3.6.2",
+ "triple-beam": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ }
+ },
+ "node_modules/winston/node_modules/@colors/colors": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz",
+ "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
"node_modules/wrap-ansi": {
"version": "7.0.0",
- "dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
@@ -15940,7 +18588,6 @@
},
"node_modules/wrap-ansi/node_modules/ansi-styles": {
"version": "4.3.0",
- "dev": true,
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
@@ -15954,7 +18601,6 @@
},
"node_modules/wrap-ansi/node_modules/color-convert": {
"version": "2.0.1",
- "dev": true,
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
@@ -15965,7 +18611,6 @@
},
"node_modules/wrap-ansi/node_modules/color-name": {
"version": "1.1.4",
- "dev": true,
"license": "MIT"
},
"node_modules/wrappy": {
@@ -15993,9 +18638,26 @@
}
}
},
+ "node_modules/xhr2": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.2.1.tgz",
+ "integrity": "sha512-sID0rrVCqkVNUn8t6xuv9+6FViXjUVXq8H5rWOH2rz9fDNQEd4g0EA2XlcEdJXRz5BMEn4O1pJFdT+z4YHhoWw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/xmlhttprequest-ssl": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz",
+ "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/y18n": {
"version": "5.0.8",
- "dev": true,
"license": "ISC",
"engines": {
"node": ">=10"
@@ -16008,7 +18670,6 @@
},
"node_modules/yargs": {
"version": "17.7.2",
- "dev": true,
"license": "MIT",
"dependencies": {
"cliui": "^8.0.1",
@@ -16025,7 +18686,6 @@
},
"node_modules/yargs-parser": {
"version": "21.1.1",
- "dev": true,
"license": "ISC",
"engines": {
"node": ">=12"
diff --git a/frontend/package.json b/frontend/package.json
index 925c2379d1..f77c5d1ec6 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,16 +1,25 @@
{
"name": "frontend",
- "version": "0.8.20",
+ "version": "1.0.59",
"scripts": {
"install:deps": "npm install",
"start": "npm install && ng serve --configuration local --open",
"start:dev": "ng serve --configuration development",
+ "start:dev:mobile": "ng serve --configuration development --host 0.0.0.0",
"build": "ng build",
- "build:prod": "ng build --configuration production",
+ "build:prod": "ng build --configuration production && npm run sentry:sourcemaps",
"tests": "npx cypress open --config baseUrl=http://localhost:4200",
"tests:headless": "npx cypress run --headless --config baseUrl=http://localhost:4200",
"docker": "npm run build:prod && docker buildx build --platform linux/amd64 -t openmina/frontend:latest . && docker push openmina/frontend:latest",
- "start:bundle": "npx http-server dist/frontend -p 4200"
+ "start:bundle": "serve dist/frontend/browser -s -l 4200",
+ "prebuild": "node scripts/update-frontend-version.js",
+ "dev:ssr": "ng run frontend:serve-ssr",
+ "serve:ssr": "node dist/frontend/server/main.js",
+ "build:ssr": "ng build && ng run frontend:server",
+ "prerender": "ng run frontend:prerender",
+ "sentry:sourcemaps": "sentry-cli sourcemaps inject --org openmina-uv --project openmina ./dist/frontend/browser && sentry-cli sourcemaps upload --org openmina-uv --project openmina ./dist/frontend/browser",
+ "copy-env": "cp dist/frontend/browser/assets/environments/webnode.js dist/frontend/browser/assets/environments/env.js",
+ "deploy": "npm run prebuild && npm run build:prod && npm run copy-env && firebase deploy"
},
"private": true,
"dependencies": {
@@ -19,24 +28,32 @@
"@angular/common": "^17.3.12",
"@angular/compiler": "^17.3.12",
"@angular/core": "^17.3.12",
+ "@angular/fire": "^17.1.0",
"@angular/forms": "^17.3.12",
"@angular/material": "^17.3.10",
"@angular/platform-browser": "^17.3.12",
"@angular/platform-browser-dynamic": "^17.3.12",
+ "@angular/platform-server": "^17.3.12",
"@angular/router": "^17.3.12",
+ "@angular/ssr": "^17.3.10",
"@ledgerhq/hw-transport-webhid": "^6.29.4",
"@ngneat/until-destroy": "^10.0.0",
"@ngrx/effects": "^17.2.0",
"@ngrx/router-store": "^17.2.0",
"@ngrx/store": "^17.2.0",
- "@openmina/shared": "^0.102.0",
+ "@nguniversal/express-engine": "^7.0.2",
+ "@openmina/shared": "^0.117.0",
"@sentry/angular": "^8.35.0",
+ "@sentry/cli": "^2.38.2",
"@sentry/tracing": "^7.114.0",
"base-x": "^5.0.0",
"bs58check": "^4.0.0",
"buffer": "^6.0.3",
"d3": "^7.8.4",
"eigen": "^0.2.2",
+ "express": "^4.18.2",
+ "firebase": "^11.0.1",
+ "jszip": "^3.10.1",
"mathjs": "^12.3.0",
"mina-signer": "^3.0.7",
"ngx-json-viewer": "^3.2.1",
@@ -52,9 +69,11 @@
"@angular/compiler-cli": "^17.3.12",
"@ngrx/store-devtools": "^17.2.0",
"@types/d3": "^7.4.0",
+ "@types/express": "^4.17.17",
"@types/jasmine": "~4.3.0",
- "@types/node": "^20.4.8",
+ "@types/node": "^18.19.64",
"@types/w3c-web-hid": "^1.0.6",
+ "browser-sync": "^3.0.0",
"cypress": "^13.3.2",
"cypress-real-events": "^1.10.0",
"jasmine-core": "~4.6.0",
@@ -68,4 +87,4 @@
"webpack": "^5.88.2",
"webpack-bundle-analyzer": "^4.9.0"
}
-}
+}
\ No newline at end of file
diff --git a/frontend/scripts/download-webnode.sh b/frontend/scripts/download-webnode.sh
new file mode 100644
index 0000000000..619cc97347
--- /dev/null
+++ b/frontend/scripts/download-webnode.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+
+# Set the base URL for OpenMina
+OPENMINA_BASE_URL="https://github.com/openmina"
+
+# Function to download circuit files
+download_circuit_files() {
+ CIRCUITS_BASE_URL="$OPENMINA_BASE_URL/circuit-blobs/releases/download"
+ CIRCUITS_VERSION="3.0.1devnet"
+
+ DEVNET_CIRCUIT_FILES=(
+ "block_verifier_index.postcard"
+ "transaction_verifier_index.postcard"
+ "step-step-proving-key-blockchain-snark-step-0-55f640777b6486a6fd3fdbc3fcffcc60_gates.json"
+ "step-step-proving-key-blockchain-snark-step-0-55f640777b6486a6fd3fdbc3fcffcc60_internal_vars.bin"
+ "step-step-proving-key-blockchain-snark-step-0-55f640777b6486a6fd3fdbc3fcffcc60_rows_rev.bin"
+ "step-step-proving-key-transaction-snark-merge-1-ba1d52dfdc2dd4d2e61f6c66ff2a5b2f_gates.json"
+ "step-step-proving-key-transaction-snark-merge-1-ba1d52dfdc2dd4d2e61f6c66ff2a5b2f_internal_vars.bin"
+ "step-step-proving-key-transaction-snark-merge-1-ba1d52dfdc2dd4d2e61f6c66ff2a5b2f_rows_rev.bin"
+ "step-step-proving-key-transaction-snark-opt_signed-3-9eefed16953d2bfa78a257adece02d47_gates.json"
+ "step-step-proving-key-transaction-snark-opt_signed-3-9eefed16953d2bfa78a257adece02d47_internal_vars.bin"
+ "step-step-proving-key-transaction-snark-opt_signed-3-9eefed16953d2bfa78a257adece02d47_rows_rev.bin"
+ "step-step-proving-key-transaction-snark-opt_signed-opt_signed-2-48925e6a97197028e1a7c1ecec09021d_gates.json"
+ "step-step-proving-key-transaction-snark-opt_signed-opt_signed-2-48925e6a97197028e1a7c1ecec09021d_internal_vars.bin"
+ "step-step-proving-key-transaction-snark-opt_signed-opt_signed-2-48925e6a97197028e1a7c1ecec09021d_rows_rev.bin"
+ "step-step-proving-key-transaction-snark-proved-4-0cafcbc6dffccddbc82f8c2519c16341_gates.json"
+ "step-step-proving-key-transaction-snark-proved-4-0cafcbc6dffccddbc82f8c2519c16341_internal_vars.bin"
+ "step-step-proving-key-transaction-snark-proved-4-0cafcbc6dffccddbc82f8c2519c16341_rows_rev.bin"
+ "step-step-proving-key-transaction-snark-transaction-0-c33ec5211c07928c87e850a63c6a2079_gates.json"
+ "step-step-proving-key-transaction-snark-transaction-0-c33ec5211c07928c87e850a63c6a2079_internal_vars.bin"
+ "step-step-proving-key-transaction-snark-transaction-0-c33ec5211c07928c87e850a63c6a2079_rows_rev.bin"
+ "wrap-wrap-proving-key-blockchain-snark-bbecaf158ca543ec8ac9e7144400e669_gates.json"
+ "wrap-wrap-proving-key-blockchain-snark-bbecaf158ca543ec8ac9e7144400e669_internal_vars.bin"
+ "wrap-wrap-proving-key-blockchain-snark-bbecaf158ca543ec8ac9e7144400e669_rows_rev.bin"
+ "wrap-wrap-proving-key-transaction-snark-b9a01295c8cc9bda6d12142a581cd305_gates.json"
+ "wrap-wrap-proving-key-transaction-snark-b9a01295c8cc9bda6d12142a581cd305_internal_vars.bin"
+ "wrap-wrap-proving-key-transaction-snark-b9a01295c8cc9bda6d12142a581cd305_rows_rev.bin"
+ )
+ DOWNLOAD_DIR="../src/assets/webnode/circuit-blobs/$CIRCUITS_VERSION"
+
+ mkdir -p "$DOWNLOAD_DIR"
+
+ for FILE in "${DEVNET_CIRCUIT_FILES[@]}"; do
+ if [[ -f "$DOWNLOAD_DIR/$FILE" ]]; then
+ echo "$FILE already exists in $DOWNLOAD_DIR, skipping download."
+ else
+ echo "Downloading $FILE to $DOWNLOAD_DIR..."
+ curl -s -L --retry 3 --retry-delay 5 -o "$DOWNLOAD_DIR/$FILE" "$CIRCUITS_BASE_URL/$CIRCUITS_VERSION/$FILE"
+ if [[ $? -ne 0 ]]; then
+ echo "Failed to download $FILE after 3 attempts, exiting."
+ exit 1
+ else
+ echo "$FILE downloaded successfully to $DOWNLOAD_DIR"
+ fi
+ fi
+ done
+}
+
+# Call the function to download circuit files
+download_circuit_files
diff --git a/frontend/scripts/update-frontend-version.js b/frontend/scripts/update-frontend-version.js
new file mode 100644
index 0000000000..a186a2cc50
--- /dev/null
+++ b/frontend/scripts/update-frontend-version.js
@@ -0,0 +1,56 @@
+import {readFileSync, writeFileSync} from 'fs';
+import {platform, release} from 'os';
+
+console.log('⏳ Updating Deployment Info...');
+
+const packageJsonPath = './package.json';
+const packageJson = readFileSync(packageJsonPath, 'utf8');
+const packageJsonObj = JSON.parse(packageJson);
+const version = packageJsonObj.version.split('.');
+const newVersion = `${version[0]}.${version[1]}.${parseInt(version[2]) + 1}`;
+packageJsonObj.version = newVersion;
+writeFileSync(packageJsonPath, JSON.stringify(packageJsonObj, null, 2));
+
+const publicIp = await getPublicIpAddress();
+const deploymentInfo = {
+ dateUTC: new Date().toISOString(),
+ deviceIp: publicIp,
+ deviceOS: formatOS(platform()),
+ deviceOSVersion: release(),
+ version: newVersion,
+};
+
+const newDeploymentScript = `
+const deployment = {
+ dateUTC: '${deploymentInfo.dateUTC}',
+ deviceIp: '${deploymentInfo.deviceIp}',
+ deviceOS: '${deploymentInfo.deviceOS}',
+ deviceOSVersion: '${deploymentInfo.deviceOSVersion}',
+ version: '${deploymentInfo.version}',
+};
+window.deployment = deployment;
+`;
+const deploymentScriptPattern = /const deployment = \{[\s\S]*?\};[\s\S]*?window\.deployment = deployment;/;
+
+// Read and update index.html
+const indexPath = './src/index.html';
+let indexHtml = readFileSync(indexPath, 'utf8');
+indexHtml = indexHtml.replace(deploymentScriptPattern, newDeploymentScript.trim());
+
+writeFileSync(indexPath, indexHtml);
+
+console.log('✅ Updated Deployment Info!');
+
+async function getPublicIpAddress() {
+ const response = await fetch('https://api.ipify.org/');
+ return await response.text();
+}
+
+function formatOS(platform) {
+ const osMap = {
+ 'darwin': 'macOS',
+ 'win32': 'Windows',
+ 'linux': 'Linux',
+ };
+ return osMap[platform] || platform;
+}
diff --git a/frontend/server.ts b/frontend/server.ts
new file mode 100644
index 0000000000..a127b5bb47
--- /dev/null
+++ b/frontend/server.ts
@@ -0,0 +1,69 @@
+import 'zone.js/node';
+
+import { APP_BASE_HREF } from '@angular/common';
+import { CommonEngine } from '@angular/ssr';
+import * as express from 'express';
+import { existsSync } from 'node:fs';
+import { join } from 'node:path';
+import AppServerModule from './src/main.server';
+
+// The Express app is exported so that it can be used by serverless Functions.
+export function app(): express.Express {
+ const server = express();
+ const distFolder = join(process.cwd(), 'dist/frontend/browser');
+ const indexHtml = existsSync(join(distFolder, 'index.original.html'))
+ ? join(distFolder, 'index.original.html')
+ : join(distFolder, 'index.html');
+
+ const commonEngine = new CommonEngine();
+
+ server.set('view engine', 'html');
+ server.set('views', distFolder);
+
+ // Example Express Rest API endpoints
+ // server.get('/api/**', (req, res) => { });
+ // Serve static files from /browser
+ server.get('*.*', express.static(distFolder, {
+ maxAge: '1y'
+ }));
+
+ // All regular routes use the Angular engine
+ server.get('*', (req, res, next) => {
+ const { protocol, originalUrl, baseUrl, headers } = req;
+
+ commonEngine
+ .render({
+ bootstrap: AppServerModule,
+ documentFilePath: indexHtml,
+ url: `${protocol}://${headers.host}${originalUrl}`,
+ publicPath: distFolder,
+ providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }],
+ })
+ .then((html) => res.send(html))
+ .catch((err) => next(err));
+ });
+
+ return server;
+}
+
+function run(): void {
+ const port = process.env['PORT'] || 4000;
+
+ // Start up the Node server
+ const server = app();
+ server.listen(port, () => {
+ console.log(`Node Express server listening on http://localhost:${port}`);
+ });
+}
+
+// Webpack will replace 'require' with '__webpack_require__'
+// '__non_webpack_require__' is a proxy to Node 'require'
+// The below code is to ensure that the server is run only when not requiring the bundle.
+declare const __non_webpack_require__: NodeRequire;
+const mainModule = __non_webpack_require__.main;
+const moduleFilename = mainModule && mainModule.filename || '';
+if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
+ run();
+}
+
+export default AppServerModule;
diff --git a/frontend/src/app/app.actions.ts b/frontend/src/app/app.actions.ts
index 0045b01454..59afd73900 100644
--- a/frontend/src/app/app.actions.ts
+++ b/frontend/src/app/app.actions.ts
@@ -2,6 +2,7 @@ import { MinaNode } from '@shared/types/core/environment/mina-env.type';
import { createType } from '@shared/constants/store-functions';
import { createAction, props } from '@ngrx/store';
import { AppNodeDetails } from '@shared/types/app/app-node-details.type';
+import { AppEnvBuild } from '@shared/types/app/app-env-build.type';
export const APP_KEY = 'app';
export const APP_PREFIX = 'App';
@@ -14,6 +15,8 @@ const initSuccess = createAction(type('Init Success'), props<{ activeNode: MinaN
const changeActiveNode = createAction(type('Change Active Node'), props<{ node: MinaNode }>());
const getNodeDetails = createAction(type('Get Node Details'));
const getNodeDetailsSuccess = createAction(type('Get Node Details Success'), props<{ details: AppNodeDetails }>());
+const getNodeEnvBuild = createAction(type('Get Node Env Build'));
+const getNodeEnvBuildSuccess = createAction(type('Get Node Env Build Success'), props<{ envBuild: AppEnvBuild }>());
const deleteNode = createAction(type('Delete Node'), props<{ node: MinaNode }>());
const addNode = createAction(type('Add Node'), props<{ node: MinaNode }>());
@@ -28,6 +31,8 @@ export const AppActions = {
changeActiveNode,
getNodeDetails,
getNodeDetailsSuccess,
+ getNodeEnvBuild,
+ getNodeEnvBuildSuccess,
deleteNode,
addNode,
changeMenuCollapsing,
diff --git a/frontend/src/app/app.component.html b/frontend/src/app/app.component.html
index fdd63676c1..bf25b5a9c8 100644
--- a/frontend/src/app/app.component.html
+++ b/frontend/src/app/app.component.html
@@ -1,30 +1,38 @@
@if (showLandingPage$ | async) {
-} @else {
+} @else if (showLoadingWebNodePage$ | async) {
+
+} @else if (loaded) {
-
-
-
-
+ @if (isDesktop) {
+
+
+
+
+ }
-
-
+ }
+
-
+ @if (!isDesktop) {
+
+
+ }
}
diff --git a/frontend/src/app/app.component.scss b/frontend/src/app/app.component.scss
index a01a79524a..bd5100f44f 100644
--- a/frontend/src/app/app.component.scss
+++ b/frontend/src/app/app.component.scss
@@ -2,7 +2,7 @@
mat-sidenav {
width: 160px;
- border-right: 1px solid $base-divider;
+ border-right: none;
background-color: $base-background;
transition: 200ms ease-out !important;
visibility: visible !important;
@@ -44,39 +44,45 @@ mat-sidenav {
}
mat-sidenav-content {
- transition: 200ms ease-out !important;
+ @media (min-width: 768px) {
+ transition: 200ms ease-out !important;
+ }
overflow: hidden;
}
mat-sidenav-container,
mat-sidenav-content {
color: inherit;
- background-color: $base-surface;
-
- @media (max-width: 699px) {
- background-color: $base-background;
- }
+ background-color: $base-background;
}
-.mina-content {
+#mina-content {
$toolbar: 40px;
height: calc(100% - #{$toolbar});
+ border-top-left-radius: 6px;
+ overflow: hidden;
+ background-color: $base-surface;
&.no-toolbar {
height: 100%;
}
&.mobile {
- $toolbar: 56px;
+ $toolbar: 96px;
$subMenus: 56px;
- height: calc(100% - #{$toolbar} - #{$subMenus});
+ $tabs: 56px;
+ height: calc(100% - #{$toolbar} - #{$subMenus} - #{$tabs});
+ margin-left: 4px;
+ margin-right: 4px;
+ margin-bottom: 4px;
+ border-top-right-radius: 6px;
&.no-toolbar {
- height: calc(100% - #{$subMenus});
+ height: calc(100% - #{$subMenus} - #{$tabs});
}
&.no-submenus {
- height: calc(100% - #{$toolbar});
+ height: calc(100% - #{$toolbar} - #{$tabs});
&.no-toolbar {
height: 100%;
diff --git a/frontend/src/app/app.component.ts b/frontend/src/app/app.component.ts
index 2d36c7a388..b8cb9147be 100644
--- a/frontend/src/app/app.component.ts
+++ b/frontend/src/app/app.component.ts
@@ -1,13 +1,15 @@
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
-import { any, getMergedRoute, MAX_WIDTH_700, MergedRoute } from '@openmina/shared';
+import { any, getMergedRoute, getWindow, isBrowser, isDesktop, MAX_WIDTH_700, MergedRoute, safelyExecuteInBrowser } from '@openmina/shared';
import { AppMenu } from '@shared/types/app/app-menu.type';
import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout';
import { AppSelectors } from '@app/app.state';
import { AppActions } from '@app/app.actions';
import { filter, map, Observable, Subscription, take, timer } from 'rxjs';
-import { CONFIG, getFirstFeature } from '@shared/constants/config';
+import { CONFIG } from '@shared/constants/config';
import { StoreDispatcher } from '@shared/base-classes/store-dispatcher.class';
import { Router } from '@angular/router';
+import { Routes } from '@shared/enums/routes.enum';
+import { WebNodeService } from '@core/services/web-node.service';
@Component({
selector: 'app-root',
@@ -18,38 +20,65 @@ import { Router } from '@angular/router';
})
export class AppComponent extends StoreDispatcher implements OnInit {
- protected readonly menu$: Observable
= this.select$(AppSelectors.menu);
- protected readonly showLandingPage$: Observable = this.select$(getMergedRoute).pipe(filter(Boolean), map((route: MergedRoute) => route.url === '/'));
+ readonly menu$: Observable = this.select$(AppSelectors.menu);
+ readonly showLandingPage$: Observable = this.select$(getMergedRoute).pipe(filter(Boolean), map((route: MergedRoute) => route.url === '/' || route.url.startsWith('/?')));
+ readonly showLoadingWebNodePage$: Observable = this.select$(getMergedRoute).pipe(filter(Boolean), map((route: MergedRoute) => route.url.startsWith(`/${Routes.LOADING_WEB_NODE}`)));
subMenusLength: number = 0;
hideToolbar: boolean = CONFIG.hideToolbar;
+ loaded: boolean;
+ isDesktop: boolean = isDesktop();
private nodeUpdateSubscription: Subscription | null = null;
constructor(private breakpointObserver: BreakpointObserver,
- private router: Router) {
+ private router: Router,
+ private webNodeService: WebNodeService) {
super();
- if (any(window).Cypress) {
- any(window).config = CONFIG;
- any(window).store = this.store;
- }
+ safelyExecuteInBrowser(() => {
+ if (any(window).Cypress) {
+ any(window).config = CONFIG;
+ any(window).store = this.store;
+ }
+ });
}
ngOnInit(): void {
+ if (isBrowser()) {
+ const args = new URLSearchParams(window.location.search).get('a');
+ if (!!args) {
+ localStorage.setItem('webnodeArgs', args);
+ }
+ }
+
this.select(
getMergedRoute,
() => this.initAppFunctionalities(),
filter(Boolean),
take(1),
- filter((route: MergedRoute) => route.url !== '/'),
+ filter((route: MergedRoute) => route.url !== '/' && !route.url.startsWith('/?')),
+ );
+ this.select(
+ getMergedRoute,
+ () => {
+ this.loaded = true;
+ this.detect();
+ },
+ filter(Boolean),
+ take(1),
);
}
goToWebNode(): void {
- this.router.navigate([getFirstFeature()]);
+ this.router.navigate([Routes.LOADING_WEB_NODE], { queryParamsHandling: 'merge' });
this.initAppFunctionalities();
}
private initAppFunctionalities(): void {
+ if (this.webNodeService.hasWebNodeConfig() && !this.webNodeService.isWebNodeLoaded()) {
+ if (!getWindow()?.location.href.includes(`/${Routes.LOADING_WEB_NODE}`)) {
+ this.router.navigate([Routes.LOADING_WEB_NODE], { queryParamsHandling: 'preserve' });
+ }
+ }
this.dispatch2(AppActions.init());
if (!this.hideToolbar && !CONFIG.hideNodeStats) {
this.scheduleNodeUpdates();
diff --git a/frontend/src/app/app.effects.ts b/frontend/src/app/app.effects.ts
index 4c4539d715..d72e583f36 100644
--- a/frontend/src/app/app.effects.ts
+++ b/frontend/src/app/app.effects.ts
@@ -2,8 +2,8 @@ import { Injectable } from '@angular/core';
import { MinaState, selectMinaState } from '@app/app.setup';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { Store } from '@ngrx/store';
-import { createNonDispatchableEffect, Effect, NonDispatchableEffect, removeParamsFromURL } from '@openmina/shared';
-import { filter, from, map, switchMap, tap } from 'rxjs';
+import { createNonDispatchableEffect, Effect, removeParamsFromURL } from '@openmina/shared';
+import { filter, map, mergeMap, of, switchMap, tap } from 'rxjs';
import { AppActions } from '@app/app.actions';
import { Router } from '@angular/router';
import { FeatureType, MinaNode } from '@shared/types/core/environment/mina-env.type';
@@ -22,9 +22,10 @@ import { AppNodeStatus } from '@shared/types/app/app-node-details.type';
export class AppEffects extends BaseEffect {
readonly init$: Effect;
- readonly initSuccess$: NonDispatchableEffect;
+ readonly initSuccess$: Effect;
readonly onNodeChange$: Effect;
readonly getNodeDetails$: Effect;
+ readonly getNodeEnvBuild$: Effect;
private requestInProgress: boolean = false;
@@ -46,7 +47,7 @@ export class AppEffects extends BaseEffect {
map((payload: { activeNode: MinaNode, nodes: MinaNode[] }) => AppActions.initSuccess(payload)),
));
- this.initSuccess$ = createNonDispatchableEffect(() => this.actions$.pipe(
+ this.initSuccess$ = createEffect(() => this.actions$.pipe(
ofType(AppActions.initSuccess),
this.latestActionState(),
switchMap(({ state }) => {
@@ -55,8 +56,9 @@ export class AppEffects extends BaseEffect {
switchMap(() => this.webNodeService.startWasm$()),
);
}
- return from([]);
+ return of({});
}),
+ map(() => AppActions.getNodeEnvBuild()),
));
this.onNodeChange$ = createNonDispatchableEffect(() => this.actions$.pipe(
@@ -79,9 +81,16 @@ export class AppEffects extends BaseEffect {
switchMap(() => this.webNodeService.startWasm$()),
);
}
- return from([]);
+ return of({});
}),
- map(() => AppActions.getNodeDetails()),
+ switchMap(() => [AppActions.getNodeDetails(), AppActions.getNodeEnvBuild()]),
+ ));
+
+ this.getNodeEnvBuild$ = createEffect(() => this.actions$.pipe(
+ ofType(AppActions.getNodeEnvBuild),
+ mergeMap(() => this.appService.getEnvBuild()),
+ map(envBuild => AppActions.getNodeEnvBuildSuccess({ envBuild })),
+ catchErrorAndRepeat2(MinaErrorType.RUST, AppActions.getNodeEnvBuildSuccess({ envBuild: undefined })),
));
this.getNodeDetails$ = createEffect(() => this.actions$.pipe(
@@ -89,20 +98,23 @@ export class AppEffects extends BaseEffect {
filter(() => !this.requestInProgress),
tap(() => this.requestInProgress = true),
switchMap(() => this.appService.getActiveNodeDetails()),
- tap(() => this.requestInProgress = false),
map(details => AppActions.getNodeDetailsSuccess({ details })),
catchErrorAndRepeat2(MinaErrorType.GENERIC, AppActions.getNodeDetailsSuccess({
details: {
status: AppNodeStatus.OFFLINE,
blockHeight: null,
blockTime: null,
- peers: 0,
- download: 0,
- upload: 0,
+ peersConnected: 0,
+ peersDisconnected: 0,
+ peersConnecting: 0,
transactions: 0,
snarks: 0,
+ producingBlockAt: null,
+ producingBlockGlobalSlot: null,
+ producingBlockStatus: null,
},
})),
+ tap(() => this.requestInProgress = false),
));
}
}
diff --git a/frontend/src/app/app.module.server.ts b/frontend/src/app/app.module.server.ts
new file mode 100644
index 0000000000..795380cd22
--- /dev/null
+++ b/frontend/src/app/app.module.server.ts
@@ -0,0 +1,14 @@
+import { NgModule } from '@angular/core';
+import { ServerModule } from '@angular/platform-server';
+
+import { AppModule } from './app.module';
+import { AppComponent } from './app.component';
+
+@NgModule({
+ imports: [
+ AppModule,
+ ServerModule,
+ ],
+ bootstrap: [AppComponent],
+})
+export class AppServerModule {}
diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts
index f2dbdf9b12..eb0917ec77 100644
--- a/frontend/src/app/app.module.ts
+++ b/frontend/src/app/app.module.ts
@@ -1,5 +1,5 @@
-import { APP_INITIALIZER, ErrorHandler, Injectable, LOCALE_ID, NgModule, Provider } from '@angular/core';
-import { BrowserModule } from '@angular/platform-browser';
+import { APP_INITIALIZER, ErrorHandler, Injectable, LOCALE_ID, NgModule } from '@angular/core';
+import { BrowserModule, provideClientHydration } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { AppRouting } from './app.routing';
@@ -10,6 +10,7 @@ import {
HorizontalMenuComponent,
NgrxRouterStoreModule,
OpenminaEagerSharedModule,
+ safelyExecuteInBrowser,
THEME_PROVIDER,
} from '@openmina/shared';
import { CommonModule, registerLocaleData } from '@angular/common';
@@ -29,24 +30,98 @@ import { metaReducers, reducers } from '@app/app.setup';
import { EffectsModule } from '@ngrx/effects';
import { AppEffects } from '@app/app.effects';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
-import { HttpClientModule } from '@angular/common/http';
+import { HttpClientModule, provideHttpClient, withFetch } from '@angular/common/http';
import { NewNodeComponent } from './layout/new-node/new-node.component';
import { ReactiveFormsModule } from '@angular/forms';
import { WebNodeLandingPageComponent } from '@app/layout/web-node-landing-page/web-node-landing-page.component';
import * as Sentry from '@sentry/angular';
import { Router } from '@angular/router';
+import { initializeApp, provideFirebaseApp } from '@angular/fire/app';
+import { getAnalytics, provideAnalytics, ScreenTrackingService } from '@angular/fire/analytics';
+import { getPerformance, providePerformance } from '@angular/fire/performance';
+import { BlockProductionPillComponent } from '@app/layout/block-production-pill/block-production-pill.component';
+import { MenuTabsComponent } from '@app/layout/menu-tabs/menu-tabs.component';
registerLocaleData(localeFr, 'fr');
registerLocaleData(localeEn, 'en');
@Injectable()
export class AppGlobalErrorhandler implements ErrorHandler {
- constructor(private errorHandlerService: GlobalErrorHandlerService) {}
+ constructor(private errorHandlerService: GlobalErrorHandlerService) {
+ safelyExecuteInBrowser(() => {
+ this.setupErrorHandlers();
+ });
+
+ if (WebAssembly) {
+ this.interceptWebAssembly();
+ }
+ }
+
+ private setupErrorHandlers(): void {
+ const self = this;
+
+ // Global error handler
+ window.onerror = function (msg, url, line, column, error) {
+ self.handleError(error || msg);
+ return false;
+ };
+
+ // Unhandled promise rejections
+ window.onunhandledrejection = function (event) {
+ event.preventDefault();
+ self.handleError(event.reason);
+ };
+
+ // Regular error listener
+ window.addEventListener('error', (event: ErrorEvent) => {
+ event.preventDefault();
+ this.handleError(event.error);
+ }, { capture: true });
+
+ // Override console.error with proper error extraction
+ const originalConsoleError = console.error;
+ console.error = (...args) => {
+ // Find the actual error object in the arguments
+ const error = args.find(arg => arg instanceof Error) ||
+ args.join(' ');
+
+ this.handleError(error);
+ originalConsoleError.apply(console, args);
+ };
+ }
+
+ private interceptWebAssembly(): void {
+ const self = this;
+
+ const originalInstantiateStreaming = WebAssembly.instantiateStreaming;
+ if (originalInstantiateStreaming) {
+ WebAssembly.instantiateStreaming = async function (response: any, importObject?: any): Promise {
+ try {
+ return await originalInstantiateStreaming.call(WebAssembly, response, importObject);
+ } catch (error) {
+ self.handleError(error);
+ throw error;
+ }
+ };
+ }
+
+ const originalInstantiate = WebAssembly.instantiate;
+ WebAssembly.instantiate = async function (moduleObject: any, importObject?: any): Promise {
+ try {
+ return await originalInstantiate.call(WebAssembly, moduleObject, importObject);
+ } catch (error) {
+ self.handleError(error);
+ throw error;
+ }
+ };
+ }
handleError(error: any): void {
Sentry.captureException(error);
+ if (typeof error === 'string') {
+ error = new Error(error);
+ }
this.errorHandlerService.handleError(error);
- console.error(error);
}
}
@@ -86,12 +161,14 @@ export class AppGlobalErrorhandler implements ErrorHandler {
ReactiveFormsModule,
CopyComponent,
WebNodeLandingPageComponent,
+ BlockProductionPillComponent,
+ MenuTabsComponent,
],
providers: [
THEME_PROVIDER,
- { provide: ErrorHandler, useClass: AppGlobalErrorhandler, deps: [GlobalErrorHandlerService] },
{ provide: LOCALE_ID, useValue: 'en' },
{ provide: ErrorHandler, useValue: Sentry.createErrorHandler() },
+ { provide: ErrorHandler, useClass: AppGlobalErrorhandler, deps: [GlobalErrorHandlerService], multi: false },
{ provide: Sentry.TraceService, deps: [Router] },
{
provide: APP_INITIALIZER,
@@ -99,7 +176,29 @@ export class AppGlobalErrorhandler implements ErrorHandler {
deps: [Sentry.TraceService],
multi: true,
},
+ provideClientHydration(),
+ provideHttpClient(withFetch()),
+ provideFirebaseApp(() => initializeApp({
+ 'projectId': 'openminawebnode',
+ 'appId': '1:120031499786:web:9af56c50ebce25c619f1f3',
+ 'storageBucket': 'openminawebnode.firebasestorage.app',
+ 'apiKey': 'AIzaSyBreMkb5-8ANb5zL6yWKgRAk9owbDS1g9s',
+ 'authDomain': 'openminawebnode.firebaseapp.com',
+ 'messagingSenderId': '120031499786',
+ 'measurementId': 'G-V0ZC81T9RQ',
+ })),
+ provideAnalytics(() => getAnalytics()),
+ ScreenTrackingService,
+ // provideAppCheck(() => {
+ // // TODO get a reCAPTCHA Enterprise here https://console.cloud.google.com/security/recaptcha?project=_
+ // const provider = new ReCaptchaEnterpriseProvider(/* reCAPTCHA Enterprise site key */);
+ // return initializeAppCheck(undefined, { provider, isTokenAutoRefreshEnabled: true });
+ // }),
+ providePerformance(() => getPerformance()),
],
bootstrap: [AppComponent],
+ exports: [
+ MenuComponent,
+ ],
})
export class AppModule {}
diff --git a/frontend/src/app/app.reducer.ts b/frontend/src/app/app.reducer.ts
index 0688276357..de4c8bb694 100644
--- a/frontend/src/app/app.reducer.ts
+++ b/frontend/src/app/app.reducer.ts
@@ -3,10 +3,11 @@ import { AppState } from '@app/app.state';
import { MinaNode } from '@shared/types/core/environment/mina-env.type';
import { createReducer, on } from '@ngrx/store';
import { AppNodeStatus } from '@shared/types/app/app-node-details.type';
+import { getLocalStorage } from '@openmina/shared';
const initialState: AppState = {
menu: {
- collapsed: JSON.parse(localStorage.getItem('menu_collapsed')) || false,
+ collapsed: JSON.parse(getLocalStorage()?.getItem('menu_collapsed') ?? 'false') || false,
isMobile: false,
open: true,
},
@@ -16,12 +17,16 @@ const initialState: AppState = {
status: AppNodeStatus.PENDING,
blockHeight: null,
blockTime: null,
- peers: 0,
- download: 0,
- upload: 0,
+ peersConnected: 0,
+ peersDisconnected: 0,
+ peersConnecting: 0,
transactions: 0,
snarks: 0,
+ producingBlockAt: null,
+ producingBlockGlobalSlot: null,
+ producingBlockStatus: null,
},
+ envBuild: undefined,
};
export const appReducer = createReducer(
@@ -30,7 +35,7 @@ export const appReducer = createReducer(
on(AppActions.changeActiveNode, (state, { node }) => ({ ...state, activeNode: node })),
on(AppActions.getNodeDetailsSuccess, (state, { details }) => ({ ...state, activeNodeDetails: details })),
on(AppActions.changeMenuCollapsing, (state, { isCollapsing }) => {
- localStorage.setItem('menu_collapsed', JSON.stringify(isCollapsing));
+ getLocalStorage()?.setItem('menu_collapsed', JSON.stringify(isCollapsing));
return { ...state, menu: { ...state.menu, collapsed: isCollapsing } };
}),
on(AppActions.toggleMobile, (state, { isMobile }) => ({
@@ -39,14 +44,15 @@ export const appReducer = createReducer(
})),
on(AppActions.toggleMenuOpening, (state) => ({ ...state, menu: { ...state.menu, open: !state.menu.open } })),
on(AppActions.addNode, (state, { node }) => {
- const customNodes = JSON.parse(localStorage.getItem('custom_nodes') ?? '[]');
- localStorage.setItem('custom_nodes', JSON.stringify([node, ...customNodes]));
+ const customNodes = JSON.parse(getLocalStorage()?.getItem('custom_nodes') ?? '[]');
+ getLocalStorage()?.setItem('custom_nodes', JSON.stringify([node, ...customNodes]));
return { ...state, nodes: [node, ...state.nodes] };
}),
on(AppActions.deleteNode, (state, { node }) => {
- const customNodes = JSON.parse(localStorage.getItem('custom_nodes') ?? '[]');
- localStorage.setItem('custom_nodes', JSON.stringify(customNodes.filter((n: MinaNode) => n.name !== node.name)));
+ const customNodes = JSON.parse(getLocalStorage()?.getItem('custom_nodes') ?? '[]');
+ getLocalStorage()?.setItem('custom_nodes', JSON.stringify(customNodes.filter((n: MinaNode) => n.name !== node.name)));
const nodes = state.nodes.filter(n => n.name !== node.name);
return { ...state, nodes, activeNode: state.activeNode?.name === node.name ? nodes[0] : state.activeNode };
}),
+ on(AppActions.getNodeEnvBuildSuccess, (state, { envBuild }) => ({ ...state, envBuild })),
);
diff --git a/frontend/src/app/app.routing.ts b/frontend/src/app/app.routing.ts
index ccf6903619..0a8cf9194a 100644
--- a/frontend/src/app/app.routing.ts
+++ b/frontend/src/app/app.routing.ts
@@ -14,6 +14,7 @@ export const SNARKS_TITLE: string = APP_TITLE + ' - Snarks';
export const BLOCK_PRODUCTION_TITLE: string = APP_TITLE + ' - Block Production';
export const MEMPOOL_TITLE: string = APP_TITLE + ' - Mempool';
export const BENCHMARKS_TITLE: string = APP_TITLE + ' - Benchmarks';
+export const WEBNODE_TITLE: string = APP_TITLE + ' - Web Node';
function generateRoutes(): Routes {
@@ -64,6 +65,11 @@ function generateRoutes(): Routes {
loadChildren: () => import('./features/benchmarks/benchmarks.module').then(m => m.BenchmarksModule),
title: BENCHMARKS_TITLE,
},
+ {
+ path: 'loading-web-node',
+ loadChildren: () => import('./features/webnode/webnode.module').then(m => m.WebnodeModule),
+ title: WEBNODE_TITLE,
+ },
];
if (CONFIG.showWebNodeLandingPage) {
routes.push({
@@ -76,7 +82,7 @@ function generateRoutes(): Routes {
...routes,
{
path: '**',
- redirectTo: getFirstFeature(),
+ redirectTo: CONFIG.showWebNodeLandingPage ? '' : getFirstFeature(),
pathMatch: 'full',
},
];
diff --git a/frontend/src/app/app.service.ts b/frontend/src/app/app.service.ts
index 7090d81d17..e6fc2bbaf7 100644
--- a/frontend/src/app/app.service.ts
+++ b/frontend/src/app/app.service.ts
@@ -5,6 +5,9 @@ import { CONFIG } from '@shared/constants/config';
import { RustService } from '@core/services/rust.service';
import { AppNodeDetails, AppNodeStatus } from '@shared/types/app/app-node-details.type';
import { getNetwork } from '@shared/helpers/mina.helper';
+import { getLocalStorage, ONE_MILLION } from '@openmina/shared';
+import { BlockProductionWonSlotsStatus } from '@shared/types/block-production/won-slots/block-production-won-slots-slot.type';
+import { AppEnvBuild } from '@shared/types/app/app-env-build.type';
@Injectable({
providedIn: 'root',
@@ -23,24 +26,31 @@ export class AppService {
getNodes(): Observable {
return of([
...CONFIG.configs,
- ...JSON.parse(localStorage.getItem('custom_nodes') ?? '[]'),
+ ...JSON.parse(getLocalStorage()?.getItem('custom_nodes') ?? '[]'),
]);
}
+ getEnvBuild(): Observable {
+ return this.rust.get('/build_env');
+ }
+
getActiveNodeDetails(): Observable {
return this.rust.get('/status')
.pipe(
- map((data: NodeDetailsResponse) => ({
+ map((data: NodeDetailsResponse): AppNodeDetails => ({
status: this.getStatus(data),
blockHeight: data.transition_frontier.best_tip?.height,
blockTime: data.transition_frontier.sync.time,
- peers: data.peers.filter(p => p.connection_status === 'Connected').length,
- download: 0,
- upload: 0,
+ peersConnected: data.peers.filter(p => p.connection_status === 'Connected').length,
+ peersDisconnected: data.peers.filter(p => p.connection_status === 'Disconnected').length,
+ peersConnecting: data.peers.filter(p => p.connection_status === 'Connecting').length,
snarks: data.snark_pool.snarks,
transactions: data.transaction_pool.transactions,
chainId: data.chain_id,
network: getNetwork(data.chain_id),
+ producingBlockAt: data.current_block_production_attempt?.won_slot.slot_time / ONE_MILLION,
+ producingBlockGlobalSlot: data.current_block_production_attempt?.won_slot.global_slot,
+ producingBlockStatus: data.current_block_production_attempt?.status,
} as AppNodeDetails)),
);
}
@@ -65,8 +75,38 @@ export interface NodeDetailsResponse {
peers: Peer[];
snark_pool: SnarkPool;
chain_id: string | undefined;
+ current_block_production_attempt: BlockProductionAttempt;
+}
+
+export interface BlockProductionAttempt {
+ won_slot: WonSlot;
+ block: any;
+ times: Times;
+ status: BlockProductionWonSlotsStatus;
+}
+
+export interface WonSlot {
+ slot_time: number;
+ global_slot: number;
+ epoch: number;
+ delegator: [string, number];
+ value_with_threshold: number[];
}
+export interface Times {
+ scheduled: number;
+ staged_ledger_diff_create_start: any;
+ staged_ledger_diff_create_end: any;
+ produced: any;
+ proof_create_start: any;
+ proof_create_end: any;
+ block_apply_start: any;
+ block_apply_end: any;
+ committed: any;
+ discarded: any;
+}
+
+
interface TransitionFrontier {
best_tip: BestTip;
sync: Sync;
diff --git a/frontend/src/app/app.state.ts b/frontend/src/app/app.state.ts
index bacf1f859b..5899469521 100644
--- a/frontend/src/app/app.state.ts
+++ b/frontend/src/app/app.state.ts
@@ -3,12 +3,14 @@ import { AppMenu } from '@shared/types/app/app-menu.type';
import { createSelector, MemoizedSelector } from '@ngrx/store';
import { MinaNode } from '@shared/types/core/environment/mina-env.type';
import { AppNodeDetails } from '@shared/types/app/app-node-details.type';
+import { AppEnvBuild } from '@shared/types/app/app-env-build.type';
export interface AppState {
menu: AppMenu;
nodes: MinaNode[];
activeNode: MinaNode;
activeNodeDetails: AppNodeDetails;
+ envBuild: AppEnvBuild | undefined;
}
const select = (selector: (state: AppState) => T): MemoizedSelector => createSelector(
@@ -20,10 +22,12 @@ const menu = select(state => state.menu);
const nodes = select(state => state.nodes);
const activeNode = select(state => state.activeNode);
const activeNodeDetails = select(state => state.activeNodeDetails);
+const envBuild = select(state => state.envBuild);
export const AppSelectors = {
menu,
nodes,
activeNode,
activeNodeDetails,
+ envBuild,
};
diff --git a/frontend/src/app/core/helpers/file-progress.helper.ts b/frontend/src/app/core/helpers/file-progress.helper.ts
new file mode 100644
index 0000000000..2c5652b6b9
--- /dev/null
+++ b/frontend/src/app/core/helpers/file-progress.helper.ts
@@ -0,0 +1,100 @@
+import { BehaviorSubject } from 'rxjs';
+import { safelyExecuteInBrowser } from '@openmina/shared';
+
+class AssetMonitor {
+ readonly downloads: Map = new Map();
+ readonly progress$: BehaviorSubject;
+
+ constructor(progress$: BehaviorSubject) {
+ this.progress$ = progress$;
+ safelyExecuteInBrowser(() => {
+ this.setupInterceptor();
+ });
+ }
+
+ private setupInterceptor(): void {
+ const originalFetch = window.fetch;
+ const self = this;
+
+ window.fetch = async function (resource, options) {
+ // Only intercept asset requests (you can modify these extensions as needed)
+ const assetExtensions = ['.wasm'];
+ const isAsset = assetExtensions.some(ext =>
+ resource.toString().toLowerCase().endsWith(ext),
+ );
+
+ if (!isAsset) {
+ return originalFetch(resource, options);
+ }
+
+ const startTime = performance.now();
+ const downloadInfo = {
+ url: resource.toString(),
+ startTime,
+ progress: 0,
+ totalSize: 30111552,
+ status: 'pending',
+ endTime: 0,
+ duration: 0,
+ };
+
+ self.downloads.set(resource.toString(), downloadInfo);
+ self.emitProgress(downloadInfo);
+
+ try {
+ const response = await originalFetch(resource, options);
+ const reader = response.clone().body.getReader();
+ let receivedLength = 0;
+
+ while (true) {
+ try {
+ const { done, value } = await reader.read();
+
+ if (done) {
+ break;
+ }
+
+ receivedLength += value.length;
+ downloadInfo.progress = (receivedLength / downloadInfo.totalSize) * 100;
+ self.emitProgress(downloadInfo);
+ } catch (error) {
+ downloadInfo.status = 'error';
+ self.emitProgress(downloadInfo);
+ throw error;
+ }
+ }
+
+ downloadInfo.status = 'complete';
+ downloadInfo.endTime = performance.now();
+ downloadInfo.duration = downloadInfo.endTime - downloadInfo.startTime;
+ self.emitProgress(downloadInfo);
+ return await response;
+ } catch (error_1) {
+ downloadInfo.status = 'error';
+ self.emitProgress(downloadInfo);
+ throw error_1;
+ }
+ };
+ }
+
+ private emitProgress(downloadInfo: any): void {
+ this.progress$.next({
+ url: downloadInfo.url,
+ progress: downloadInfo.progress.toFixed(2),
+ totalSize: downloadInfo.totalSize,
+ status: downloadInfo.status,
+ duration: downloadInfo.duration,
+ startTime: downloadInfo.startTime,
+ endTime: downloadInfo.endTime,
+ downloaded: downloadInfo.progress * downloadInfo.totalSize / 100,
+ });
+ }
+}
+
+export class FileProgressHelper {
+ static progress$: BehaviorSubject = new BehaviorSubject(null);
+
+ static initDownloadProgress(): void {
+ new AssetMonitor(this.progress$);
+ }
+}
diff --git a/frontend/src/app/core/services/rust.service.ts b/frontend/src/app/core/services/rust.service.ts
index 6f428c7436..0a2d8a64a1 100644
--- a/frontend/src/app/core/services/rust.service.ts
+++ b/frontend/src/app/core/services/rust.service.ts
@@ -18,6 +18,10 @@ export class RustService {
this.node = node;
}
+ get activeNodeIsWebNode(): boolean {
+ return this.node.isWebNode;
+ }
+
get URL(): string {
return this.node.url;
}
@@ -68,6 +72,8 @@ export class RustService {
return this.webNodeService.accounts$;
case '/best-chain-user-commands':
return this.webNodeService.bestChainUserCommands$;
+ case '/build_env':
+ return this.webNodeService.envBuildDetails$;
default:
throw new Error(`Web node doesn't support "${path}" path!`);
}
diff --git a/frontend/src/app/core/services/sentry.service.ts b/frontend/src/app/core/services/sentry.service.ts
new file mode 100644
index 0000000000..18a3d1db70
--- /dev/null
+++ b/frontend/src/app/core/services/sentry.service.ts
@@ -0,0 +1,70 @@
+import { inject, Injectable } from '@angular/core';
+import { NodesOverviewLedger, NodesOverviewLedgerStepState } from '@shared/types/nodes/dashboard/nodes-overview-ledger.type';
+import * as Sentry from '@sentry/angular';
+import { NodesOverviewBlock, NodesOverviewNodeBlockStatus } from '@shared/types/nodes/dashboard/nodes-overview-block.type';
+import { lastItem, ONE_BILLION } from '@openmina/shared';
+import { RustService } from '@core/services/rust.service';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class SentryService {
+
+ private ledgerIsSynced: boolean = false;
+ private blockIsSynced: boolean = false;
+ private rustService: RustService = inject(RustService);
+
+ updateLedgerSyncStatus(ledger: NodesOverviewLedger): void {
+ if (this.ledgerIsSynced) {
+ return;
+ }
+ if (ledger.rootStaged.state === NodesOverviewLedgerStepState.SUCCESS) {
+ this.ledgerIsSynced = true;
+ const syncDetails = {
+ stakingLedger: {
+ fetchHashes: ledger.stakingEpoch.snarked.fetchHashesDuration + 's',
+ fetchAccounts: ledger.stakingEpoch.snarked.fetchAccountsDuration + 's',
+ },
+ nextEpochLedger: {
+ fetchHashes: ledger.nextEpoch.snarked.fetchHashesDuration + 's',
+ fetchAccounts: ledger.nextEpoch.snarked.fetchAccountsDuration + 's',
+ },
+ snarkedRootLedger: {
+ fetchHashes: ledger.rootSnarked.snarked.fetchHashesDuration + 's',
+ fetchAccounts: ledger.rootSnarked.snarked.fetchAccountsDuration + 's',
+ },
+ stagedRootLedger: {
+ fetchParts: ledger.rootStaged.staged.fetchPartsDuration + 's',
+ reconstruct: ledger.rootStaged.staged.reconstructDuration + 's',
+ },
+ };
+
+ const syncedIn = Math.round((ledger.rootStaged.staged.reconstructEnd - ledger.stakingEpoch.snarked.fetchHashesStart) / ONE_BILLION);
+
+ Sentry.captureMessage(`Ledger synced in ${syncedIn}s`, {
+ level: 'info',
+ tags: { type: 'webnode', subType: 'sync.ledger' },
+ contexts: { ledger: syncDetails },
+ });
+ }
+ }
+
+ updateBlockSyncStatus(blocks: NodesOverviewBlock[], startTime: number): void {
+ if (this.blockIsSynced || !this.rustService.activeNodeIsWebNode) {
+ return;
+ }
+
+ const blocksSynced = blocks.every(b => b.status === NodesOverviewNodeBlockStatus.APPLIED);
+ if (blocksSynced && blocks[0]) {
+ this.blockIsSynced = true;
+ blocks = blocks.slice(1);
+ const bestTipBlock = blocks[0].height;
+ const root = lastItem(blocks).height;
+ Sentry.captureMessage(`Last 290 blocks synced in ${Math.round((Date.now() - startTime) / 1000)}s`, {
+ level: 'info',
+ tags: { type: 'webnode', subType: 'sync.block' },
+ contexts: { blocks: { bestTipBlock, root } },
+ });
+ }
+ }
+}
diff --git a/frontend/src/app/core/services/web-node.service.ts b/frontend/src/app/core/services/web-node.service.ts
index 612b29b6eb..5f5f0beca2 100644
--- a/frontend/src/app/core/services/web-node.service.ts
+++ b/frontend/src/app/core/services/web-node.service.ts
@@ -1,10 +1,12 @@
import { Injectable } from '@angular/core';
-import { BehaviorSubject, catchError, filter, from, fromEvent, map, merge, Observable, of, switchMap, tap } from 'rxjs';
+import { BehaviorSubject, catchError, EMPTY, filter, from, fromEvent, map, merge, Observable, of, switchMap, tap, throwError } from 'rxjs';
import base from 'base-x';
-import { any } from '@openmina/shared';
+import { any, isBrowser, safelyExecuteInBrowser } from '@openmina/shared';
import { HttpClient } from '@angular/common/http';
import { sendSentryEvent } from '@shared/helpers/webnode.helper';
import { DashboardPeerStatus } from '@shared/types/dashboard/dashboard.peer';
+import { FileProgressHelper } from '@core/helpers/file-progress.helper';
+import { CONFIG } from '@shared/constants/config';
@Injectable({
providedIn: 'root',
@@ -12,68 +14,131 @@ import { DashboardPeerStatus } from '@shared/types/dashboard/dashboard.peer';
export class WebNodeService {
private readonly webnode$: BehaviorSubject = new BehaviorSubject(null);
+ private readonly wasm$: BehaviorSubject = new BehaviorSubject(null);
private webNodeKeyPair: { publicKey: string, privateKey: string };
+ private webNodeNetwork: String;
private webNodeStartTime: number;
private sentryEvents: any = {};
+ readonly webnodeProgress$: BehaviorSubject = new BehaviorSubject('');
+
+ memory: WebAssembly.MemoryDescriptor;
+
constructor(private http: HttpClient) {
+ FileProgressHelper.initDownloadProgress();
const basex = base('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz');
- any(window)['bs58btc'] = {
- encode: (buffer: Uint8Array | number[]) => 'z' + basex.encode(buffer),
- decode: (string: string) => basex.decode(string.substring(1)),
- };
+ safelyExecuteInBrowser(() => {
+ any(window).bs58btc = {
+ encode: (buffer: Uint8Array | number[]) => 'z' + basex.encode(buffer),
+ decode: (string: string) => basex.decode(string.substring(1)),
+ };
+ });
}
- loadWasm$(): Observable {
- sendSentryEvent('Loading WebNode JS');
- return merge(
- of(any(window).webnode).pipe(filter(Boolean)),
- fromEvent(window, 'webNodeLoaded'),
- ).pipe(
- switchMap(() => this.http.get<{ publicKey: string, privateKey: string }>('assets/webnode/web-node-secrets.json')),
- tap(data => {
- this.webNodeKeyPair = data;
- sendSentryEvent('WebNode JS Loaded. Loading WebNode Wasm');
- }),
- map(() => void 0),
- );
+ hasWebNodeConfig(): boolean {
+ return CONFIG.configs.some(c => c.isWebNode);
}
- startWasm$(): Observable {
- return of(any(window).webnode)
- .pipe(
- switchMap((wasm: any) => from(wasm.default('assets/webnode/pkg/openmina_node_web_bg.wasm')).pipe(map(() => wasm))),
- switchMap((wasm) => {
- sendSentryEvent('WebNode Wasm loaded. Starting WebNode');
- return from(wasm.run(this.webNodeKeyPair.privateKey));
- }),
- tap((webnode: any) => {
- sendSentryEvent('WebNode Started');
- this.webNodeStartTime = Date.now();
- (window as any)['webnode'] = webnode;
- this.webnode$.next(webnode);
+ isWebNodeLoaded(): boolean {
+ if (isBrowser()) {
+ return !!any(window).webnode;
+ }
+ return false;
+ }
+
+ loadWasm$(): Observable {
+ this.webNodeStartTime = Date.now();
+
+ if (isBrowser()) {
+ const args = (() => {
+ const raw = localStorage.getItem('webnodeArgs');
+ if (raw === null) {
+ return null;
+ }
+ return JSON.parse(atob(raw));
+ })();
+ return merge(
+ of(any(window).webnode).pipe(filter(Boolean)),
+ fromEvent(window, 'webNodeLoaded'),
+ ).pipe(
+ switchMap(() => {
+ const DEFAULT_NETWORK = 'devnet';
+ if (!args) {
+ return this.http.get<{ publicKey: string, privateKey: string }>('assets/webnode/web-node-secrets.json')
+ .pipe(map(blockProducer => ({ blockProducer, network: DEFAULT_NETWORK })));
+ }
+ const data = { network: args['network'] || DEFAULT_NETWORK, blockProducer: {} as any };
+ if (!!args['block_producer']) {
+ data['blockProducer'] = {
+ privateKey: args['block_producer'].sec_key,
+ publicKey: args['block_producer'].pub_key,
+ };
+ }
+ return of(data);
}),
- catchError((error) => {
- sendSentryEvent('WebNode failed to start');
- console.error(error);
- return of(null);
+ tap(data => {
+ this.webNodeKeyPair = data.blockProducer;
+ this.webNodeNetwork = data.network;
}),
- switchMap(() => this.webnode$.asObservable()),
- filter(Boolean),
+ map(() => void 0),
);
+ }
+ return EMPTY;
+ }
+
+ startWasm$(): Observable {
+ if (isBrowser()) {
+ return of(any(window).webnode)
+ .pipe(
+ switchMap((wasm: any) => {
+ this.wasm$.next(wasm);
+ return from(wasm.default(undefined, new WebAssembly.Memory(this.memory)))
+ .pipe(map(() => wasm));
+ }),
+ switchMap((wasm) => {
+ this.webnodeProgress$.next('Loaded');
+ const urls = (() => {
+ if (typeof this.webNodeNetwork === 'number') {
+ const url = `${window.location.origin}/clusters/${this.webNodeNetwork}/`;
+ return {
+ seeds: url + 'seeds',
+ genesisConfig: url + 'genesis/config',
+ };
+ } else {
+ return {
+ seeds: 'https://bootnodes.minaprotocol.com/networks/devnet-webrtc.txt',
+ };
+ }
+ })();
+ console.log('webnode config:', !!this.webNodeKeyPair.privateKey, this.webNodeNetwork, urls);
+ return from(wasm.run(this.webNodeKeyPair.privateKey, urls.seeds, urls.genesisConfig));
+ }),
+ tap((webnode: any) => {
+ any(window).webnode = webnode;
+ this.webnode$.next(webnode);
+ this.webnodeProgress$.next('Started');
+ }),
+ catchError((error) => {
+ sendSentryEvent('WebNode failed to start: ' + error.message);
+ return throwError(() => new Error(error.message));
+ }),
+ switchMap(() => this.webnode$.asObservable()),
+ );
+ }
+ return EMPTY;
}
get status$(): Observable {
return this.webnode$.asObservable().pipe(
filter(Boolean),
- switchMap(handle => from((handle as any).status())),
+ switchMap(handle => from(any(handle).status())),
);
}
get blockProducerStats$(): Observable {
return this.webnode$.asObservable().pipe(
filter(Boolean),
- switchMap(handle => from((handle as any).stats().block_producer())),
+ switchMap(handle => from(any(handle).stats().block_producer())),
);
}
@@ -82,20 +147,18 @@ export class WebNodeService {
filter(Boolean),
switchMap(handle => from(any(handle).state().peers())),
tap((peers) => {
- if (!this.sentryEvents.sentNoPeersEvent && Date.now() - this.webNodeStartTime >= 5000 && peers.length === 0) {
- console.log('WebNode has no peers after 5 seconds from startup.');
- sendSentryEvent('WebNode has no peers after 5 seconds from startup.');
- this.sentryEvents.sentNoPeersEvent = true;
- }
- if (!this.sentryEvents.sentPeersEvent && peers.length > 0) {
- const seconds = (Date.now() - this.webNodeStartTime) / 1000;
- sendSentryEvent(`WebNode found its first peer after ${seconds}s`);
- this.sentryEvents.sentPeersEvent = true;
- }
+ // if (!this.sentryEvents.sentNoPeersEvent && Date.now() - this.webNodeStartTime >= 5000 && peers.length === 0) {
+ // sendSentryEvent('WebNode has no peers after 5 seconds from startup.');
+ // this.sentryEvents.sentNoPeersEvent = true;
+ // }
+ // if (!this.sentryEvents.sentPeersEvent && peers.length > 0) {
+ // this.sentryEvents.sentPeersEvent = true;
+ // }
if (!this.sentryEvents.firstPeerConnected && peers.some((p: any) => p.connection_status === DashboardPeerStatus.CONNECTED)) {
const seconds = (Date.now() - this.webNodeStartTime) / 1000;
- sendSentryEvent(`WebNode connected to its first peer after ${seconds}s`);
+ sendSentryEvent(`WebNode connected in ${seconds.toFixed(1)}s`, 'info');
this.sentryEvents.firstPeerConnected = true;
+ this.webnodeProgress$.next('Connected');
}
}),
);
@@ -104,42 +167,49 @@ export class WebNodeService {
get messageProgress$(): Observable {
return this.webnode$.asObservable().pipe(
filter(Boolean),
- switchMap(handle => from((handle as any).state().message_progress())),
+ switchMap(handle => from(any(handle).state().message_progress())),
);
}
get sync$(): Observable {
return this.webnode$.asObservable().pipe(
filter(Boolean),
- switchMap(handle => from((handle as any).stats().sync())),
+ switchMap(handle => from(any(handle).stats().sync())),
);
}
get accounts$(): Observable {
return this.webnode$.asObservable().pipe(
filter(Boolean),
- switchMap(handle => from((handle as any).ledger().latest().accounts().all())),
+ switchMap(handle => from(any(handle).ledger().latest().accounts().all())),
);
}
get bestChainUserCommands$(): Observable {
return this.webnode$.asObservable().pipe(
filter(Boolean),
- switchMap(handle => from((handle as any).transition_frontier().best_chain().user_commands())),
+ switchMap(handle => from(any(handle).transition_frontier().best_chain().user_commands())),
);
}
sendPayment$(payment: any): Observable {
return this.webnode$.asObservable().pipe(
filter(Boolean),
- switchMap(handle => from((handle as any).transaction_pool().inject().payment(payment))),
+ switchMap(handle => from(any(handle).transaction_pool().inject().payment(payment))),
);
}
get transactionPool$(): Observable {
return this.webnode$.asObservable().pipe(
filter(Boolean),
- switchMap(handle => from((handle as any).transaction_pool().get())),
+ switchMap(handle => from(any(handle).transaction_pool().get())),
+ );
+ }
+
+ get envBuildDetails$(): Observable {
+ return this.wasm$.asObservable().pipe(
+ filter(Boolean),
+ map(handle => handle.build_env()),
);
}
}
diff --git a/frontend/src/app/features/benchmarks/wallets/benchmarks-wallets-zk.service.ts b/frontend/src/app/features/benchmarks/wallets/benchmarks-wallets-zk.service.ts
index 2c425391df..f1896a2c64 100644
--- a/frontend/src/app/features/benchmarks/wallets/benchmarks-wallets-zk.service.ts
+++ b/frontend/src/app/features/benchmarks/wallets/benchmarks-wallets-zk.service.ts
@@ -3,7 +3,7 @@ import { BehaviorSubject, catchError, filter, map, Observable, of, switchMap } f
import { BenchmarksZkapp } from '@shared/types/benchmarks/transactions/benchmarks-zkapp.type';
import { fromPromise } from 'rxjs/internal/observable/innerFrom';
import { CONFIG } from '@shared/constants/config';
-import { any } from '@openmina/shared';
+import { any, safelyExecuteInBrowser } from '@openmina/shared';
import { DOCUMENT } from '@angular/common';
@Injectable()
@@ -16,7 +16,9 @@ export class BenchmarksWalletsZkService {
readonly updates$ = this.updates.asObservable();
loadO1js(): void {
- this.loadScript();
+ safelyExecuteInBrowser(() => {
+ this.loadScript();
+ });
}
sendZkApp(zkApps: BenchmarksZkapp[]): Observable
-
-
+ }
+
diff --git a/frontend/src/app/features/benchmarks/wallets/benchmarks-wallets.effects.ts b/frontend/src/app/features/benchmarks/wallets/benchmarks-wallets.effects.ts
index 54f5215991..d831c35149 100644
--- a/frontend/src/app/features/benchmarks/wallets/benchmarks-wallets.effects.ts
+++ b/frontend/src/app/features/benchmarks/wallets/benchmarks-wallets.effects.ts
@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
import { MinaState, selectMinaState } from '@app/app.setup';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { Effect } from '@openmina/shared';
-import { EMPTY, forkJoin, map, switchMap } from 'rxjs';
+import { combineLatest, EMPTY, map, switchMap } from 'rxjs';
import { Store } from '@ngrx/store';
import {
BENCHMARKS_WALLETS_CLOSE,
@@ -11,8 +11,11 @@ import {
BENCHMARKS_WALLETS_GET_WALLETS,
BENCHMARKS_WALLETS_GET_WALLETS_SUCCESS,
BENCHMARKS_WALLETS_SEND_TX_SUCCESS,
- BENCHMARKS_WALLETS_SEND_TXS, BENCHMARKS_WALLETS_SEND_ZKAPPS, BENCHMARKS_WALLETS_SEND_ZKAPPS_SUCCESS,
- BenchmarksWalletsActions, BenchmarksWalletsClose,
+ BENCHMARKS_WALLETS_SEND_TXS,
+ BENCHMARKS_WALLETS_SEND_ZKAPPS,
+ BENCHMARKS_WALLETS_SEND_ZKAPPS_SUCCESS,
+ BenchmarksWalletsActions,
+ BenchmarksWalletsClose,
BenchmarksWalletsGetWallets,
BenchmarksWalletsSendTxs,
} from '@benchmarks/wallets/benchmarks-wallets.actions';
@@ -74,7 +77,7 @@ export class BenchmarksWalletsEffects extends MinaRustBaseEffect
this.actions$.pipe(
ofType(BENCHMARKS_WALLETS_GET_ALL_TXS),
switchMap(() =>
- forkJoin([
+ combineLatest([
this.mempoolService.getTransactionPool(),
this.benchmarksService.getAllIncludedTransactions(),
]),
diff --git a/frontend/src/app/features/benchmarks/wallets/benchmarks-wallets.reducer.ts b/frontend/src/app/features/benchmarks/wallets/benchmarks-wallets.reducer.ts
index 326dba5040..6c6aadad29 100644
--- a/frontend/src/app/features/benchmarks/wallets/benchmarks-wallets.reducer.ts
+++ b/frontend/src/app/features/benchmarks/wallets/benchmarks-wallets.reducer.ts
@@ -21,7 +21,7 @@ import {
BenchmarksWalletTransactionStatus,
} from '@shared/types/benchmarks/wallets/benchmarks-wallet.type';
import { BenchmarksWalletTransaction } from '@shared/types/benchmarks/wallets/benchmarks-wallet-transaction.type';
-import { hasValue, lastItem, ONE_BILLION } from '@openmina/shared';
+import { getLocalStorage, hasValue, lastItem, ONE_BILLION } from '@openmina/shared';
import { BenchmarksWalletsState } from '@benchmarks/wallets/benchmarks-wallets.state';
import { getTimeFromMemo } from '@shared/helpers/transaction.helper';
import { BenchmarksZkapp } from '@shared/types/benchmarks/transactions/benchmarks-zkapp.type';
@@ -110,7 +110,7 @@ export function reducer(state: BenchmarksWalletsState = initialState, action: Be
.map((wallet: BenchmarksWallet, i: number) => {
const nonce = getNonceForWallet(wallet, state).toString();
const counter = state.sentTxCount + i;
- const memo = 'S.T.' + Date.now() + ',' + (counter + 1) + ',' + localStorage.getItem('browserId');
+ const memo = 'S.T.' + Date.now() + ',' + (counter + 1) + ',' + getLocalStorage()?.getItem('browserId');
const payment = {
from: wallet.publicKey,
nonce,
@@ -133,7 +133,7 @@ export function reducer(state: BenchmarksWalletsState = initialState, action: Be
txsToSend = Array(state.txSendingBatch).fill(void 0).map((_, i: number) => {
const counter = state.sentTxCount + i;
- const memo = 'S.T.' + Date.now() + ',' + (counter + 1) + ',' + localStorage.getItem('browserId');
+ const memo = 'S.T.' + Date.now() + ',' + (counter + 1) + ',' + getLocalStorage()?.getItem('browserId');
const payment = {
from: wallet.publicKey,
nonce: nonce.toString(),
@@ -299,7 +299,7 @@ export function reducer(state: BenchmarksWalletsState = initialState, action: Be
.map((wallet: BenchmarksWallet, i: number) => {
const nonce = getNonceForWallet(wallet, state).toString();
const counter = state.sentTxCount + i;
- const memo = 'S.T.' + Date.now() + ',' + (counter + 1) + ',' + localStorage.getItem('browserId');
+ const memo = 'S.T.' + Date.now() + ',' + (counter + 1) + ',' + getLocalStorage()?.getItem('browserId');
return {
payerPublicKey: wallet.publicKey,
payerPrivateKey: wallet.privateKey,
@@ -315,7 +315,7 @@ export function reducer(state: BenchmarksWalletsState = initialState, action: Be
zkAppsToSend = Array(state.zkAppsSendingBatch).fill(void 0).map((_, i: number) => {
const counter = state.sentTxCount + i;
- const memo = 'S.T.' + Date.now() + ',' + (counter + 1) + ',' + localStorage.getItem('browserId');
+ const memo = 'S.T.' + Date.now() + ',' + (counter + 1) + ',' + getLocalStorage()?.getItem('browserId');
const payment = {
payerPublicKey: wallet.publicKey,
payerPrivateKey: wallet.privateKey,
diff --git a/frontend/src/app/features/benchmarks/wallets/benchmarks-wallets.service.ts b/frontend/src/app/features/benchmarks/wallets/benchmarks-wallets.service.ts
index 8fafa4ff04..b91a1462b6 100644
--- a/frontend/src/app/features/benchmarks/wallets/benchmarks-wallets.service.ts
+++ b/frontend/src/app/features/benchmarks/wallets/benchmarks-wallets.service.ts
@@ -11,7 +11,7 @@ import {
ZkappCommand,
} from '@shared/types/mempool/mempool-transaction.type';
import { decodeMemo, getTimeFromMemo, removeUnicodeEscapes } from '@shared/helpers/transaction.helper';
-import { ONE_BILLION } from '@openmina/shared';
+import { getLocalStorage, ONE_BILLION } from '@openmina/shared';
import { MempoolTransactionResponseKind } from '@app/features/mempool/mempool.service';
export const WALLETS: { privateKey: string, publicKey: string }[] = [
@@ -4029,8 +4029,8 @@ export class BenchmarksWalletsService {
private client: Client = new Client({ network: 'testnet' });
constructor(private rust: RustService) {
- if (!localStorage.getItem('browserId')) {
- localStorage.setItem('browserId', Math.floor(Math.random() * 999999999).toString());
+ if (!getLocalStorage()?.getItem('browserId')) {
+ getLocalStorage()?.setItem('browserId', Math.floor(Math.random() * 999999999).toString());
}
}
@@ -4120,7 +4120,7 @@ export class BenchmarksWalletsService {
memo: removeUnicodeEscapes(memo),
transactionData: tx,
sentFromStressingTool: memo.includes('S.T.'),
- sentByMyBrowser: memo.includes(localStorage.getItem('browserId')),
+ sentByMyBrowser: memo.includes(getLocalStorage()?.getItem('browserId')),
} as MempoolTransaction;
case MempoolTransactionResponseKind.ZkappCommand:
const zkTx = command as ZkappCommand;
@@ -4133,7 +4133,7 @@ export class BenchmarksWalletsService {
memo: removeUnicodeEscapes(zkMemo),
transactionData: zkTx,
sentFromStressingTool: zkMemo.includes('S.T.'),
- sentByMyBrowser: zkMemo.includes(localStorage.getItem('browserId')),
+ sentByMyBrowser: zkMemo.includes(getLocalStorage()?.getItem('browserId')),
} as MempoolTransaction;
}
diff --git a/frontend/src/app/features/block-production/overview/block-production-overview.component.ts b/frontend/src/app/features/block-production/overview/block-production-overview.component.ts
index 5fec6775a5..dcf8ba1de0 100644
--- a/frontend/src/app/features/block-production/overview/block-production-overview.component.ts
+++ b/frontend/src/app/features/block-production/overview/block-production-overview.component.ts
@@ -1,17 +1,14 @@
import { ChangeDetectionStrategy, Component, ElementRef, OnDestroy, OnInit } from '@angular/core';
import { StoreDispatcher } from '@shared/base-classes/store-dispatcher.class';
import { BlockProductionOverviewActions } from '@block-production/overview/block-production-overview.actions';
-import { getMergedRoute, isDesktop, MergedRoute } from '@openmina/shared';
-import { debounceTime, filter, fromEvent, skip, take } from 'rxjs';
+import { getMergedRoute, isDesktop, MergedRoute, safelyExecuteInBrowser } from '@openmina/shared';
+import { debounceTime, filter, fromEvent, take } from 'rxjs';
import { isNaN } from 'mathjs';
import { untilDestroyed } from '@ngneat/until-destroy';
import { BlockProductionOverviewSelectors } from '@block-production/overview/block-production-overview.state';
import { SLOTS_PER_EPOCH } from '@shared/constants/mina';
-import {
- BlockProductionOverviewEpoch,
-} from '@shared/types/block-production/overview/block-production-overview-epoch.type';
+import { BlockProductionOverviewEpoch } from '@shared/types/block-production/overview/block-production-overview-epoch.type';
import { AppSelectors } from '@app/app.state';
-import { MinaNode } from '@shared/types/core/environment/mina-env.type';
@Component({
selector: 'mina-block-production-overview',
@@ -64,16 +61,18 @@ export class BlockProductionOverviewComponent extends StoreDispatcher implements
}
private listenToResize(): void {
- fromEvent(window, 'resize')
- .pipe(
- debounceTime(100),
- filter(() => this.showSidePanel !== isDesktop()),
- untilDestroyed(this),
- )
- .subscribe(() => {
- this.showSidePanel = isDesktop();
- this.detect();
- });
+ safelyExecuteInBrowser(() => {
+ fromEvent(window, 'resize')
+ .pipe(
+ debounceTime(100),
+ filter(() => this.showSidePanel !== isDesktop()),
+ untilDestroyed(this),
+ )
+ .subscribe(() => {
+ this.showSidePanel = isDesktop();
+ this.detect();
+ });
+ });
}
override ngOnDestroy(): void {
diff --git a/frontend/src/app/features/block-production/overview/slot-details/block-production-overview-slot-details.component.ts b/frontend/src/app/features/block-production/overview/slot-details/block-production-overview-slot-details.component.ts
index fda854dbd3..788621a3e6 100644
--- a/frontend/src/app/features/block-production/overview/slot-details/block-production-overview-slot-details.component.ts
+++ b/frontend/src/app/features/block-production/overview/slot-details/block-production-overview-slot-details.component.ts
@@ -6,6 +6,7 @@ import { AppSelectors } from '@app/app.state';
import { StoreDispatcher } from '@shared/base-classes/store-dispatcher.class';
import { AppNodeDetails } from '@shared/types/app/app-node-details.type';
import { filter } from 'rxjs';
+import { safelyExecuteInBrowser } from '@openmina/shared';
@Component({
selector: 'mina-block-production-overview-slot-details',
@@ -32,6 +33,6 @@ export class BlockProductionOverviewSlotDetailsComponent extends StoreDispatcher
viewInMinaExplorer(): void {
const network = this.minaExplorer !== 'mainnet' ? (this.minaExplorer + '.') : '';
const url = `https://${network}minaexplorer.com/block/${this.activeSlot.hash}`;
- window.open(url, '_blank');
+ safelyExecuteInBrowser(() => window.open(url, '_blank'));
}
}
diff --git a/frontend/src/app/features/block-production/overview/slots/block-production-overview-slots.component.ts b/frontend/src/app/features/block-production/overview/slots/block-production-overview-slots.component.ts
index 0e3b5e325c..32149d6196 100644
--- a/frontend/src/app/features/block-production/overview/slots/block-production-overview-slots.component.ts
+++ b/frontend/src/app/features/block-production/overview/slots/block-production-overview-slots.component.ts
@@ -13,7 +13,7 @@ import {
BlockProductionOverviewFilters,
} from '@shared/types/block-production/overview/block-production-overview-filters.type';
import { untilDestroyed } from '@ngneat/until-destroy';
-import { ONE_THOUSAND, toReadableDate } from '@openmina/shared';
+import { ONE_THOUSAND, safelyExecuteInBrowser, toReadableDate } from '@openmina/shared';
import { BlockProductionOverviewActions } from '@block-production/overview/block-production-overview.actions';
import { Router } from '@angular/router';
import { Routes } from '@shared/enums/routes.enum';
@@ -211,7 +211,10 @@ export class BlockProductionOverviewSlotsComponent extends StoreDispatcher imple
let desiredLeft = Math.min(nodeRect.left + nodeRect.width / 2 - tooltipWidth / 2, chartLeft + this.width - tooltipWidth);
desiredLeft = Math.max(desiredLeft, chartLeft);
- let desiredTop = nodeRect.bottom + window.scrollY + 12;
+ let desiredTop = 0;
+ safelyExecuteInBrowser(() => {
+ desiredTop = nodeRect.bottom + window.scrollY + 12;
+ });
if (desiredTop + tooltipHeight > chartBottom) {
desiredTop = nodeRect.top - tooltipHeight - 12;
}
diff --git a/frontend/src/app/features/block-production/won-slots/block-production-won-slots-epoch/block-production-won-slots-epoch.component.html b/frontend/src/app/features/block-production/won-slots/block-production-won-slots-epoch/block-production-won-slots-epoch.component.html
new file mode 100644
index 0000000000..9b82e4dbad
--- /dev/null
+++ b/frontend/src/app/features/block-production/won-slots/block-production-won-slots-epoch/block-production-won-slots-epoch.component.html
@@ -0,0 +1 @@
+{{ epoch }}
diff --git a/frontend/src/app/features/block-production/won-slots/block-production-won-slots-epoch/block-production-won-slots-epoch.component.scss b/frontend/src/app/features/block-production/won-slots/block-production-won-slots-epoch/block-production-won-slots-epoch.component.scss
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/frontend/src/app/features/block-production/won-slots/block-production-won-slots-epoch/block-production-won-slots-epoch.component.ts b/frontend/src/app/features/block-production/won-slots/block-production-won-slots-epoch/block-production-won-slots-epoch.component.ts
new file mode 100644
index 0000000000..d51a76a631
--- /dev/null
+++ b/frontend/src/app/features/block-production/won-slots/block-production-won-slots-epoch/block-production-won-slots-epoch.component.ts
@@ -0,0 +1,46 @@
+import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
+import { StoreDispatcher } from '@shared/base-classes/store-dispatcher.class';
+import { BlockProductionWonSlotsSelectors } from '@block-production/won-slots/block-production-won-slots.state';
+import { filter } from 'rxjs';
+import { BlockProductionWonSlotsSlot } from '@shared/types/block-production/won-slots/block-production-won-slots-slot.type';
+import { BlockProductionWonSlotsEpoch } from '@shared/types/block-production/won-slots/block-production-won-slots-epoch.type';
+import { ONE_BILLION, ONE_THOUSAND } from '@openmina/shared';
+import { getTimeDiff } from '@shared/helpers/date.helper';
+
+@Component({
+ selector: 'mina-block-production-won-slots-epoch',
+ templateUrl: './block-production-won-slots-epoch.component.html',
+ styleUrl: './block-production-won-slots-epoch.component.scss',
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ host: { class: 'h-lg pl-12 f-600 fx-row-vert-cent border-bottom' },
+})
+export class BlockProductionWonSlotsEpochComponent extends StoreDispatcher implements OnInit {
+ epoch: string;
+ startedAgo: string;
+
+ ngOnInit(): void {
+ this.listenToEpoch();
+ this.listenToEpoch2();
+ }
+
+ private listenToEpoch(): void {
+ this.select(BlockProductionWonSlotsSelectors.slots, (slots: BlockProductionWonSlotsSlot[]) => {
+ this.epoch = 'Epoch ' + slots[0].epoch;
+ this.detect();
+ }, filter(slots => slots.length > 0));
+ }
+
+ private listenToEpoch2(): void {
+ this.select(BlockProductionWonSlotsSelectors.epoch, (epoch: BlockProductionWonSlotsEpoch) => {
+ const epochStartTime = this.addMinutesToTimestamp(Math.floor(epoch.currentTime / ONE_BILLION), -(epoch.currentGlobalSlot - epoch.start) * 3);
+ this.startedAgo = getTimeDiff(Math.floor(epochStartTime * ONE_THOUSAND)).diff;
+
+ this.detect();
+ }, filter(Boolean));
+ }
+
+ private addMinutesToTimestamp(timestampInSeconds: number, minutesToAdd: number): number {
+ const secondsToAdd = minutesToAdd * 60;
+ return timestampInSeconds + secondsToAdd;
+ }
+}
diff --git a/frontend/src/app/features/block-production/won-slots/block-production-won-slots.actions.ts b/frontend/src/app/features/block-production/won-slots/block-production-won-slots.actions.ts
index e3bf056f9b..a027623765 100644
--- a/frontend/src/app/features/block-production/won-slots/block-production-won-slots.actions.ts
+++ b/frontend/src/app/features/block-production/won-slots/block-production-won-slots.actions.ts
@@ -26,6 +26,7 @@ const getSlotsSuccess = createAction(type('Get Slots Success'), props<{
}>());
const changeFilters = createAction(type('Change Filters'), props<{ filters: BlockProductionWonSlotsFilters }>());
const setActiveSlot = createAction(type('Set Active Slot'), props<{ slot: BlockProductionWonSlotsSlot }>());
+const setActiveSlotNumber = createAction(type('Set Active Slot Number'), props<{ slotNumber: number }>());
const sort = createAction(type('Sort'), props<{ sort: TableSort }>());
const toggleSidePanel = createAction(type('Toggle Side Panel'));
@@ -36,6 +37,7 @@ export const BlockProductionWonSlotsActions = {
getSlotsSuccess,
changeFilters,
setActiveSlot,
+ setActiveSlotNumber,
sort,
toggleSidePanel,
};
diff --git a/frontend/src/app/features/block-production/won-slots/block-production-won-slots.component.html b/frontend/src/app/features/block-production/won-slots/block-production-won-slots.component.html
index 0f2bc3efd6..811b8e7310 100644
--- a/frontend/src/app/features/block-production/won-slots/block-production-won-slots.component.html
+++ b/frontend/src/app/features/block-production/won-slots/block-production-won-slots.component.html
@@ -1,21 +1,55 @@
-
-
-
-
-
-
-
-
-
+@if ((isPending || nodeIsBootstrapping || isCalculatingVRF || isLoading) && emptySlots) {
+
+
+
+ @if (isPending || isLoading) {
+
Loading
+ } @else if (nodeIsBootstrapping) {
+
Waiting For Sync
+
Only a synced node can calculate block production rights
+ } @else {
+
Calculating Block Producing Rights
+
+ Epoch {{ epoch }} - Slot {{ vrfStats?.evaluated }}/{{ vrfStats?.total }}
+
+ }
-
+} @else {
+
+
+
+
+
+
+ @if (isDesktop) {
+
+ }
+
+
+ @if (!emptySlots) {
+
+ } @else {
+
+
cancel_presentation
+
No won slots yet
+
+ New won slots will appear here when the node receives them
+
+
+ }
+
+
+
-
-
-
+
+
+
+}
diff --git a/frontend/src/app/features/block-production/won-slots/block-production-won-slots.component.scss b/frontend/src/app/features/block-production/won-slots/block-production-won-slots.component.scss
index 76009ed69f..053b423114 100644
--- a/frontend/src/app/features/block-production/won-slots/block-production-won-slots.component.scss
+++ b/frontend/src/app/features/block-production/won-slots/block-production-won-slots.component.scss
@@ -1,3 +1,18 @@
-mina-block-production-won-slots-cards + div {
+@media (max-width: 767px) {
+ :host ::ng-deep mina-horizontal-resizable-container aside {
+ right: unset !important;
+ transition: left .4s cubic-bezier(.22, 1, .36, 1) !important;
+ &.in-view {
+ left: 0;
+ }
+
+ &:not(.in-view) {
+ left: -100%;
+ }
+ }
+}
+
+.mina-icon {
+ font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' -25, 'opsz' 24 !important;
}
diff --git a/frontend/src/app/features/block-production/won-slots/block-production-won-slots.component.ts b/frontend/src/app/features/block-production/won-slots/block-production-won-slots.component.ts
index 666a02d44d..15951b189e 100644
--- a/frontend/src/app/features/block-production/won-slots/block-production-won-slots.component.ts
+++ b/frontend/src/app/features/block-production/won-slots/block-production-won-slots.component.ts
@@ -1,37 +1,73 @@
import { ChangeDetectionStrategy, Component, ElementRef, OnDestroy, OnInit } from '@angular/core';
import { StoreDispatcher } from '@shared/base-classes/store-dispatcher.class';
-import { getMergedRoute, isDesktop, isMobile, MergedRoute } from '@openmina/shared';
-import { debounceTime, filter, fromEvent, skip, take, timer } from 'rxjs';
+import { getMergedRoute, isDesktop, MergedRoute } from '@openmina/shared';
+import { take, timer } from 'rxjs';
import { untilDestroyed } from '@ngneat/until-destroy';
import { BlockProductionWonSlotsActions } from '@block-production/won-slots/block-production-won-slots.actions';
import { AppSelectors } from '@app/app.state';
import { BlockProductionWonSlotsSelectors } from '@block-production/won-slots/block-production-won-slots.state';
+import { AppNodeDetails, AppNodeStatus } from '@shared/types/app/app-node-details.type';
+import { animate, style, transition, trigger } from '@angular/animations';
@Component({
selector: 'mina-block-production-won-slots',
templateUrl: './block-production-won-slots.component.html',
styleUrls: ['./block-production-won-slots.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
+ animations: [
+ trigger('fadeInOut', [
+ transition(':enter', [
+ style({ opacity: 0 }),
+ animate('400ms ease-in', style({ opacity: 1 })),
+ ]),
+ transition(':leave', [
+ animate('400ms ease-out', style({ opacity: 0 })),
+ ]),
+ ]),
+ ],
})
export class BlockProductionWonSlotsComponent extends StoreDispatcher implements OnInit, OnDestroy {
showSidePanel: boolean = isDesktop();
+ isDesktop: boolean = isDesktop();
+ nodeIsBootstrapping: boolean = false;
+ isPending: boolean = true;
+ isCalculatingVRF: boolean = false;
+ vrfStats: {
+ evaluated: number;
+ total: number;
+ };
+ epoch: number;
+ emptySlots: boolean = true;
+ isLoading: boolean = true;
constructor(protected el: ElementRef) { super(); }
ngOnInit(): void {
this.listenToActiveNode();
+ this.listenToNodeChange();
timer(10000, 10000)
.pipe(untilDestroyed(this))
.subscribe(() => {
this.dispatch2(BlockProductionWonSlotsActions.getSlots());
});
this.listenToResize();
+ this.listenToActiveEpoch();
+ this.listenToSlots();
+ }
+
+ private listenToNodeChange(): void {
+ this.select(AppSelectors.activeNodeDetails, (node: AppNodeDetails) => {
+ this.nodeIsBootstrapping = node?.status === AppNodeStatus.BOOTSTRAP;
+ this.isPending = node?.status === AppNodeStatus.PENDING;
+ this.detect();
+ });
}
private listenToActiveNode(): void {
this.select(AppSelectors.activeNode, () => {
this.select(getMergedRoute, (data: MergedRoute) => {
+ this.isLoading = true;
this.dispatch2(BlockProductionWonSlotsActions.init({ activeSlotRoute: data.params['id'] }));
}, take(1));
});
@@ -44,6 +80,29 @@ export class BlockProductionWonSlotsComponent extends StoreDispatcher implements
});
}
+ private listenToActiveEpoch(): void {
+ this.select(BlockProductionWonSlotsSelectors.epoch, (activeEpoch) => {
+ this.epoch = activeEpoch?.epochNumber;
+ this.vrfStats = activeEpoch.vrfStats;
+ this.isCalculatingVRF = activeEpoch.vrfStats?.evaluated < activeEpoch.vrfStats?.total;
+ this.detect();
+ });
+ }
+
+ private listenToSlots(): void {
+ this.select(BlockProductionWonSlotsSelectors.slots, (slots) => {
+ const emptySlots = slots.length === 0;
+ if (emptySlots !== this.emptySlots) {
+ this.emptySlots = emptySlots;
+ this.detect();
+ }
+ });
+ this.select(BlockProductionWonSlotsSelectors.serverResponded, (responded) => {
+ this.isLoading = !responded;
+ this.detect();
+ });
+ }
+
override ngOnDestroy(): void {
super.ngOnDestroy();
this.dispatch2(BlockProductionWonSlotsActions.close());
diff --git a/frontend/src/app/features/block-production/won-slots/block-production-won-slots.effects.ts b/frontend/src/app/features/block-production/won-slots/block-production-won-slots.effects.ts
index 6cb1e24b4f..68f2412866 100644
--- a/frontend/src/app/features/block-production/won-slots/block-production-won-slots.effects.ts
+++ b/frontend/src/app/features/block-production/won-slots/block-production-won-slots.effects.ts
@@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { MinaState, selectMinaState } from '@app/app.setup';
import { Actions, createEffect, ofType } from '@ngrx/effects';
-import { Effect } from '@openmina/shared';
+import { Effect, isDesktop, isMobile } from '@openmina/shared';
import { EMPTY, map, switchMap } from 'rxjs';
import { catchErrorAndRepeat2 } from '@shared/constants/store-functions';
import { MinaErrorType } from '@shared/types/error-preview/mina-error-type.enum';
@@ -9,13 +9,8 @@ import { Store } from '@ngrx/store';
import { BaseEffect } from '@shared/base-classes/mina-rust-base.effect';
import { BlockProductionModule } from '@block-production/block-production.module';
import { BlockProductionWonSlotsService } from '@block-production/won-slots/block-production-won-slots.service';
-import {
- BLOCK_PRODUCTION_WON_SLOTS_KEY,
- BlockProductionWonSlotsActions,
-} from '@block-production/won-slots/block-production-won-slots.actions';
-import {
- BlockProductionWonSlotsStatus,
-} from '@shared/types/block-production/won-slots/block-production-won-slots-slot.type';
+import { BLOCK_PRODUCTION_WON_SLOTS_KEY, BlockProductionWonSlotsActions } from '@block-production/won-slots/block-production-won-slots.actions';
+import { BlockProductionWonSlotsStatus } from '@shared/types/block-production/won-slots/block-production-won-slots-slot.type';
import { Router } from '@angular/router';
import { Routes } from '@shared/enums/routes.enum';
import { fromPromise } from 'rxjs/internal/observable/innerFrom';
@@ -27,6 +22,7 @@ export class BlockProductionWonSlotsEffects extends BaseEffect {
readonly init$: Effect;
readonly getSlots$: Effect;
+ readonly setActiveSlotNumber$: Effect;
constructor(private router: Router,
private actions$: Actions,
@@ -47,17 +43,26 @@ export class BlockProductionWonSlotsEffects extends BaseEffect {
? EMPTY
: this.wonSlotsService.getSlots().pipe(
switchMap(({ slots, epoch }) => {
- const activeSlotRoute = state.blockProduction[BLOCK_PRODUCTION_WON_SLOTS_KEY].activeSlotRoute;
+ const bpState = state.blockProduction[BLOCK_PRODUCTION_WON_SLOTS_KEY];
+ const activeSlotRoute = bpState.activeSlotRoute;
let newActiveSlot = slots.find(s => s.globalSlot.toString() === activeSlotRoute);
- if (!activeSlotRoute || (activeSlotRoute && !newActiveSlot)) {
+ if (
+ (isDesktop() && !activeSlotRoute)
+ || (activeSlotRoute && !newActiveSlot)
+ || (isMobile() && !activeSlotRoute && bpState.slots.length === 0)
+ ) {
newActiveSlot = slots.find(s => s.active)
?? slots.find(s => s.status === BlockProductionWonSlotsStatus.Committed)
?? slots.find(s => s.status === BlockProductionWonSlotsStatus.Scheduled)
- ?? null;
+ ?? slots.find(s => !s.status);
}
const routes: string[] = [Routes.BLOCK_PRODUCTION, Routes.WON_SLOTS];
- if (newActiveSlot) {
- routes.push(newActiveSlot.globalSlot.toString());
+ if (
+ newActiveSlot && isDesktop()
+ || (activeSlotRoute && !bpState.activeSlot)
+ || (activeSlotRoute && bpState.openSidePanel)
+ ) {
+ routes.push(newActiveSlot?.globalSlot.toString() ?? '');
}
return fromPromise(this.router.navigate(routes, { queryParamsHandling: 'merge' })).pipe(map(() => ({
slots,
@@ -74,5 +79,13 @@ export class BlockProductionWonSlotsEffects extends BaseEffect {
activeSlot: undefined,
})),
));
+
+ this.setActiveSlotNumber$ = createEffect(() => this.actions$.pipe(
+ ofType(BlockProductionWonSlotsActions.setActiveSlotNumber),
+ this.latestActionState(),
+ map(({ action, state }) => BlockProductionWonSlotsActions.setActiveSlot({
+ slot: state.blockProduction[BLOCK_PRODUCTION_WON_SLOTS_KEY].slots.find(s => s.globalSlot === action.slotNumber),
+ })),
+ ));
}
}
diff --git a/frontend/src/app/features/block-production/won-slots/block-production-won-slots.module.ts b/frontend/src/app/features/block-production/won-slots/block-production-won-slots.module.ts
index df36ef612c..ce1b55df9c 100644
--- a/frontend/src/app/features/block-production/won-slots/block-production-won-slots.module.ts
+++ b/frontend/src/app/features/block-production/won-slots/block-production-won-slots.module.ts
@@ -20,6 +20,7 @@ import {
BlockProductionWonSlotsCardsComponent,
} from '@block-production/won-slots/cards/block-production-won-slots-cards.component';
import { SharedModule } from '@shared/shared.module';
+import { BlockProductionWonSlotsEpochComponent } from '@block-production/won-slots/block-production-won-slots-epoch/block-production-won-slots-epoch.component';
@NgModule({
@@ -29,6 +30,7 @@ import { SharedModule } from '@shared/shared.module';
BlockProductionWonSlotsSidePanelComponent,
BlockProductionWonSlotsFiltersComponent,
BlockProductionWonSlotsCardsComponent,
+ BlockProductionWonSlotsEpochComponent,
],
imports: [
CommonModule,
diff --git a/frontend/src/app/features/block-production/won-slots/block-production-won-slots.reducer.ts b/frontend/src/app/features/block-production/won-slots/block-production-won-slots.reducer.ts
index 9243daa5f7..8cd720605e 100644
--- a/frontend/src/app/features/block-production/won-slots/block-production-won-slots.reducer.ts
+++ b/frontend/src/app/features/block-production/won-slots/block-production-won-slots.reducer.ts
@@ -1,6 +1,6 @@
import { createReducer, on } from '@ngrx/store';
import { BlockProductionWonSlotsState } from '@block-production/won-slots/block-production-won-slots.state';
-import { isMobile, sort, SortDirection, TableSort } from '@openmina/shared';
+import { isDesktop, isMobile, sort, SortDirection, TableSort } from '@openmina/shared';
import { BlockProductionWonSlotsActions } from '@block-production/won-slots/block-production-won-slots.actions';
import {
BlockProductionWonSlotsSlot,
@@ -24,6 +24,7 @@ const initialState: BlockProductionWonSlotsState = {
sortBy: 'slotTime',
sortDirection: SortDirection.ASC,
},
+ serverResponded: false,
};
export const blockProductionWonSlotsReducer = createReducer(
@@ -31,6 +32,7 @@ export const blockProductionWonSlotsReducer = createReducer(
on(BlockProductionWonSlotsActions.init, (state, { activeSlotRoute }) => ({
...state,
activeSlotRoute,
+ serverResponded: false,
})),
on(BlockProductionWonSlotsActions.getSlotsSuccess, (state, { slots, epoch, activeSlot }) => ({
...state,
@@ -38,7 +40,8 @@ export const blockProductionWonSlotsReducer = createReducer(
epoch,
filteredSlots: filterSlots(sortSlots(slots, state.sort), state.filters),
activeSlot,
- openSidePanel: !!activeSlot,
+ openSidePanel: state.activeSlot ? state.openSidePanel : isDesktop(),
+ serverResponded: true,
})),
on(BlockProductionWonSlotsActions.setActiveSlot, (state, { slot }) => ({
...state,
@@ -56,7 +59,12 @@ export const blockProductionWonSlotsReducer = createReducer(
filters,
filteredSlots: filterSlots(sortSlots(state.slots, state.sort), filters),
})),
- on(BlockProductionWonSlotsActions.toggleSidePanel, state => ({ ...state, openSidePanel: !state.openSidePanel })),
+ on(BlockProductionWonSlotsActions.toggleSidePanel, state => ({
+ ...state,
+ openSidePanel: !state.openSidePanel,
+ activeSlot: state.openSidePanel ? undefined : state.activeSlot,
+ activeSlotRoute: state.openSidePanel ? undefined : state.activeSlotRoute,
+ })),
on(BlockProductionWonSlotsActions.close, () => initialState),
);
diff --git a/frontend/src/app/features/block-production/won-slots/block-production-won-slots.service.ts b/frontend/src/app/features/block-production/won-slots/block-production-won-slots.service.ts
index fb6e7bfbab..fa83219e63 100644
--- a/frontend/src/app/features/block-production/won-slots/block-production-won-slots.service.ts
+++ b/frontend/src/app/features/block-production/won-slots/block-production-won-slots.service.ts
@@ -5,16 +5,13 @@ import {
BlockProductionWonSlotsSlot,
BlockProductionWonSlotsStatus,
} from '@shared/types/block-production/won-slots/block-production-won-slots-slot.type';
-import { BlockProductionModule } from '@block-production/block-production.module';
-import { hasValue, nanOrElse, ONE_BILLION, ONE_MILLION } from '@openmina/shared';
+import { hasValue, isDesktop, nanOrElse, ONE_BILLION, ONE_MILLION } from '@openmina/shared';
import { getTimeDiff } from '@shared/helpers/date.helper';
import { RustService } from '@core/services/rust.service';
-import {
- BlockProductionWonSlotsEpoch,
-} from '@shared/types/block-production/won-slots/block-production-won-slots-epoch.type';
+import { BlockProductionWonSlotsEpoch } from '@shared/types/block-production/won-slots/block-production-won-slots-epoch.type';
@Injectable({
- providedIn: BlockProductionModule,
+ providedIn: 'root',
})
export class BlockProductionWonSlotsService {
@@ -25,11 +22,11 @@ export class BlockProductionWonSlotsService {
.pipe(
map((response: WonSlotResponse) => {
if (!response) {
- throw new Error('Empty response from /stats/block_producer');
+ return { slots: [], epoch: undefined };
}
const attemptsSlots = response.attempts.map((attempt: Attempt) => {
attempt.won_slot.slot_time = Math.floor(attempt.won_slot.slot_time / ONE_MILLION); // converted to milliseconds
- attempt.active = BlockProductionWonSlotsService.getActive(attempt);
+ attempt.active = this.getActive(attempt);
let slot = {
epoch: attempt.won_slot.epoch,
message: this.getMessage(attempt),
@@ -90,7 +87,7 @@ export class BlockProductionWonSlotsService {
const futureWonSlots = response.future_won_slots.map((slot: WonSlot) => {
slot.slot_time = Math.floor(slot.slot_time / ONE_MILLION);
return {
- message: 'Upcoming Won Slot',
+ message: this.getMessage({ won_slot: slot } as Attempt),
age: this.calculateTimeAgo({ won_slot: slot }),
slotTime: slot.slot_time,
globalSlot: slot.global_slot,
@@ -102,17 +99,22 @@ export class BlockProductionWonSlotsService {
return {
slots: [...attemptsSlots, ...futureWonSlots],
epoch: {
+ epochNumber: response.current_epoch,
start: response.epoch_start,
end: response.epoch_end,
currentGlobalSlot: response.current_global_slot,
currentTime: response.current_time,
+ vrfStats: {
+ evaluated: response.current_epoch_vrf_stats?.evaluated_slots,
+ total: response.current_epoch_vrf_stats?.total_slots,
+ },
},
};
}),
);
}
- private static getActive(attempt: Attempt): boolean {
+ private getActive(attempt: Attempt): boolean {
const slotTime = attempt.won_slot.slot_time;
const now = Date.now();
return slotTime <= now && (now < 3 * 60 * 1000 + slotTime) && !attempt.times?.discarded;
@@ -120,10 +122,10 @@ export class BlockProductionWonSlotsService {
private getMessage(attempt: Attempt): string {
if (attempt.active) {
- return 'Produced';
+ return 'Producing';
}
if (attempt.status === BlockProductionWonSlotsStatus.Scheduled) {
- return 'Production Scheduled';
+ return (isDesktop() ? 'Production ' : '') + 'Scheduled';
} else if (attempt.status === BlockProductionWonSlotsStatus.Canonical) {
return 'Produced Block';
} else if (attempt.status === BlockProductionWonSlotsStatus.Orphaned) {
@@ -131,9 +133,9 @@ export class BlockProductionWonSlotsService {
} else if (attempt.status === BlockProductionWonSlotsStatus.Discarded) {
return BlockProductionWonSlotsStatus.Discarded + ' Block';
} else if (attempt.status === BlockProductionWonSlotsStatus.Committed) {
- return 'Waiting for Confirmation';
+ return isDesktop() ? 'Waiting for Confirmation' : 'Confirming';
}
- return 'Upcoming Won Slot';
+ return (isDesktop() ? 'Upcoming ' : '') + 'Won Slot';
}
private calculateTimeAgo({ active, won_slot }: { active?: boolean; won_slot: WonSlot }): string {
@@ -158,6 +160,17 @@ export interface WonSlotResponse {
current_time: number;
epoch_end: number;
epoch_start: number;
+ current_epoch: number;
+ current_epoch_vrf_stats: {
+ evaluated_slots: number;
+ total_slots: number;
+ };
+ vrf_stats: {
+ [epochNumber: string]: {
+ evaluated_slots: number;
+ total_slots: number;
+ };
+ };
}
interface Attempt {
diff --git a/frontend/src/app/features/block-production/won-slots/block-production-won-slots.state.ts b/frontend/src/app/features/block-production/won-slots/block-production-won-slots.state.ts
index 1a0f211b2a..f97282a156 100644
--- a/frontend/src/app/features/block-production/won-slots/block-production-won-slots.state.ts
+++ b/frontend/src/app/features/block-production/won-slots/block-production-won-slots.state.ts
@@ -21,6 +21,7 @@ export interface BlockProductionWonSlotsState {
openSidePanel: boolean;
filters: BlockProductionWonSlotsFilters;
sort: TableSort
;
+ serverResponded: boolean;
}
@@ -36,6 +37,7 @@ const activeSlot = select(state => state.activeSlot);
const filters = select(state => state.filters);
const sort = select(state => state.sort);
const openSidePanel = select(state => state.openSidePanel);
+const serverResponded = select(state => state.serverResponded);
export const BlockProductionWonSlotsSelectors = {
epoch,
@@ -45,4 +47,5 @@ export const BlockProductionWonSlotsSelectors = {
filters,
sort,
openSidePanel,
+ serverResponded,
};
diff --git a/frontend/src/app/features/block-production/won-slots/cards/block-production-won-slots-cards.component.html b/frontend/src/app/features/block-production/won-slots/cards/block-production-won-slots-cards.component.html
index 37d961d2b3..e20de21d1f 100644
--- a/frontend/src/app/features/block-production/won-slots/cards/block-production-won-slots-cards.component.html
+++ b/frontend/src/app/features/block-production/won-slots/cards/block-production-won-slots-cards.component.html
@@ -2,38 +2,31 @@
-
diff --git a/frontend/src/app/features/block-production/won-slots/cards/block-production-won-slots-cards.component.ts b/frontend/src/app/features/block-production/won-slots/cards/block-production-won-slots-cards.component.ts
index bc5a056ce0..57c63f1808 100644
--- a/frontend/src/app/features/block-production/won-slots/cards/block-production-won-slots-cards.component.ts
+++ b/frontend/src/app/features/block-production/won-slots/cards/block-production-won-slots-cards.component.ts
@@ -22,12 +22,11 @@ import { BlockProductionWonSlotsActions } from '@block-production/won-slots/bloc
})
export class BlockProductionWonSlotsCardsComponent extends StoreDispatcher implements OnInit {
- card1: { epoch: number; startedAgo: string; } = { epoch: null, startedAgo: null };
- card2: { nextWonSlot: string; slot: number; } = { nextWonSlot: '-', slot: null };
- card3: { wonSlots: number; slotsUsed: number; } = { wonSlots: null, slotsUsed: null };
- card4: { acceptedBlocks: number; lastBlockTime: string; } = { acceptedBlocks: null, lastBlockTime: null };
- card5: { epochProgress: string; endIn: string; } = { epochProgress: '-', endIn: null };
- card6: { totalRewards: string; } = { totalRewards: null };
+ card1: { nextWonSlot: string; slot: number; } = { nextWonSlot: '-', slot: null };
+ card2: { wonSlots: number; slotsUsed: number; } = { wonSlots: null, slotsUsed: null };
+ card3: { acceptedBlocks: number; lastBlockTime: string; } = { acceptedBlocks: null, lastBlockTime: null };
+ card4: { epochProgress: string; endIn: string; } = { epochProgress: '-', endIn: null };
+ card5: { totalRewards: string; } = { totalRewards: null };
ngOnInit(): void {
this.listenToSlots();
@@ -36,12 +35,9 @@ export class BlockProductionWonSlotsCardsComponent extends StoreDispatcher imple
private listenToEpoch(): void {
this.select(BlockProductionWonSlotsSelectors.epoch, (epoch: BlockProductionWonSlotsEpoch) => {
- const epochStartTime = this.addMinutesToTimestamp(Math.floor(epoch.currentTime / ONE_BILLION), -(epoch.currentGlobalSlot - epoch.start) * 3);
- this.card1.startedAgo = getTimeDiff(Math.floor(epochStartTime * ONE_THOUSAND)).diff;
-
const epochEndTime = this.addMinutesToTimestamp(epoch.currentTime / ONE_BILLION, (epoch.end - epoch.currentGlobalSlot) * 3);
- this.card5.endIn = getTimeDiff(epochEndTime * ONE_THOUSAND).diff;
- this.card5.epochProgress = Math.floor((epoch.currentGlobalSlot - epoch.start) / (epoch.end - epoch.start) * 100) + '%';
+ this.card4.endIn = getTimeDiff(epochEndTime * ONE_THOUSAND).diff;
+ this.card4.epochProgress = Math.floor((epoch.currentGlobalSlot - epoch.start) / (epoch.end - epoch.start) * 100) + '%';
this.detect();
}, filter(Boolean));
@@ -49,29 +45,28 @@ export class BlockProductionWonSlotsCardsComponent extends StoreDispatcher imple
private listenToSlots(): void {
this.select(BlockProductionWonSlotsSelectors.slots, (slots: BlockProductionWonSlotsSlot[]) => {
- this.card1.epoch = slots[0].epoch;
const nextSlot = slots.find(s => s.status === BlockProductionWonSlotsStatus.Scheduled || !s.status);
if (nextSlot) {
- this.card2.nextWonSlot = getTimeDiff(nextSlot.slotTime).diff;
- this.card2.slot = nextSlot.globalSlot;
+ this.card1.nextWonSlot = getTimeDiff(nextSlot.slotTime).diff;
+ this.card1.slot = nextSlot.globalSlot;
} else {
- this.card2.nextWonSlot = 'Now';
- this.card2.slot = slots.find(s => s.active)?.globalSlot;
+ this.card1.nextWonSlot = 'Now';
+ this.card1.slot = slots.find(s => s.active)?.globalSlot;
}
- this.card3.wonSlots = slots.length;
- this.card3.slotsUsed = slots.filter(
+ this.card2.wonSlots = slots.length;
+ this.card2.slotsUsed = slots.filter(
s => [BlockProductionWonSlotsStatus.Canonical, BlockProductionWonSlotsStatus.Orphaned, BlockProductionWonSlotsStatus.Discarded].includes(s.status),
).length;
- this.card4.acceptedBlocks = slots.filter(s => s.status === BlockProductionWonSlotsStatus.Canonical).length;
- this.card4.lastBlockTime = getTimeDiff(lastItem(slots.filter(s => s.status === BlockProductionWonSlotsStatus.Canonical))?.slotTime).diff;
+ this.card3.acceptedBlocks = slots.filter(s => s.status === BlockProductionWonSlotsStatus.Canonical).length;
+ this.card3.lastBlockTime = getTimeDiff(lastItem(slots.filter(s => s.status === BlockProductionWonSlotsStatus.Canonical))?.slotTime).diff;
- this.card6.totalRewards = slots
+ this.card5.totalRewards = slots
.filter(s => [BlockProductionWonSlotsStatus.Canonical].includes(s.status))
.map(s => s.coinbaseRewards + s.txFeesRewards).reduce((a, b) => a + b, 0).toFixed(0);
- this.card6.totalRewards = isNaN(+this.card6.totalRewards) ? '0' : this.card6.totalRewards;
+ this.card5.totalRewards = isNaN(+this.card5.totalRewards) ? '0' : this.card5.totalRewards;
this.detect();
}, filter(slots => slots.length > 0));
}
diff --git a/frontend/src/app/features/block-production/won-slots/side-panel/block-production-won-slots-side-panel.component.html b/frontend/src/app/features/block-production/won-slots/side-panel/block-production-won-slots-side-panel.component.html
index 4c48efdc23..dc6ca90815 100644
--- a/frontend/src/app/features/block-production/won-slots/side-panel/block-production-won-slots-side-panel.component.html
+++ b/frontend/src/app/features/block-production/won-slots/side-panel/block-production-won-slots-side-panel.component.html
@@ -1,13 +1,19 @@
-
-
{{ title }}
+
+
+ @if (isMobile) {
+
+ }
+
{{ title }}
+
@if (percentage !== null && percentage !== undefined) {
{{ percentage }}%
}
- @if (isMobile) {
-
close
- }
0" [style.width.%]="percentage"
class="progress-bar p-absolute">
@@ -15,7 +21,7 @@
-
+
Global slot
diff --git a/frontend/src/app/features/block-production/won-slots/side-panel/block-production-won-slots-side-panel.component.scss b/frontend/src/app/features/block-production/won-slots/side-panel/block-production-won-slots-side-panel.component.scss
index d2b6dceb15..bb189a824f 100644
--- a/frontend/src/app/features/block-production/won-slots/side-panel/block-production-won-slots-side-panel.component.scss
+++ b/frontend/src/app/features/block-production/won-slots/side-panel/block-production-won-slots-side-panel.component.scss
@@ -1,10 +1,23 @@
@import 'openmina';
+$blue: #57d7ff;
+$pink: #fda2ff;
+$orange: #ff833d;
+
+:host {
+ //linear-gradient(64deg, rgba(87, 215, 255, 0.15) 10%, rgba(253, 162, 255, 0.15) 60%, rgba(255, 131, 61, 0.15) 82%)
+ background: linear-gradient(70deg, rgba($blue, .15) 5%, rgba($pink, .15) 45%, rgba($orange, .15) 90%);
+}
+
+.top {
+ border-bottom: 2px solid transparent;
+}
+
.progress-bar {
overflow: hidden;
height: 6px;
left: 0;
- bottom: 0;
+ bottom: -3px;
transition: width 0.4s ease-in-out;
min-width: 20px;
diff --git a/frontend/src/app/features/block-production/won-slots/side-panel/block-production-won-slots-side-panel.component.ts b/frontend/src/app/features/block-production/won-slots/side-panel/block-production-won-slots-side-panel.component.ts
index 6183ba1631..486440ef00 100644
--- a/frontend/src/app/features/block-production/won-slots/side-panel/block-production-won-slots-side-panel.component.ts
+++ b/frontend/src/app/features/block-production/won-slots/side-panel/block-production-won-slots-side-panel.component.ts
@@ -1,12 +1,4 @@
-import {
- ChangeDetectionStrategy,
- Component,
- OnDestroy,
- OnInit,
- TemplateRef,
- ViewChild,
- ViewContainerRef,
-} from '@angular/core';
+import { ChangeDetectionStrategy, Component, OnDestroy, OnInit, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core';
import { StoreDispatcher } from '@shared/base-classes/store-dispatcher.class';
import { BlockProductionWonSlotsSelectors } from '@block-production/won-slots/block-production-won-slots.state';
import {
@@ -15,25 +7,20 @@ import {
BlockProductionWonSlotTimes,
} from '@shared/types/block-production/won-slots/block-production-won-slots-slot.type';
import { getTimeDiff } from '@shared/helpers/date.helper';
-import {
- any,
- hasValue,
- isMobile,
- noMillisFormat,
- ONE_THOUSAND,
- SecDurationConfig,
- toReadableDate,
-} from '@openmina/shared';
+import { any, hasValue, isDesktop, isMobile, noMillisFormat, ONE_THOUSAND, safelyExecuteInBrowser, SecDurationConfig, toReadableDate } from '@openmina/shared';
import { filter } from 'rxjs';
import { BlockProductionWonSlotsActions } from '@block-production/won-slots/block-production-won-slots.actions';
import { AppSelectors } from '@app/app.state';
import { AppNodeDetails } from '@shared/types/app/app-node-details.type';
+import { Router } from '@angular/router';
+import { Routes } from '@shared/enums/routes.enum';
@Component({
selector: 'mina-block-production-won-slots-side-panel',
templateUrl: './block-production-won-slots-side-panel.component.html',
styleUrls: ['./block-production-won-slots-side-panel.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
+ host: { class: 'flex-column h-100' },
})
export class BlockProductionWonSlotsSidePanelComponent extends StoreDispatcher implements OnInit, OnDestroy {
@@ -70,6 +57,8 @@ export class BlockProductionWonSlotsSidePanelComponent extends StoreDispatcher i
@ViewChild('discarded') private discardedTemplate: TemplateRef
;
+ constructor(private router: Router) {super();}
+
ngOnInit(): void {
this.listenToActiveSlot();
this.parseRemainingTime();
@@ -119,7 +108,7 @@ export class BlockProductionWonSlotsSidePanelComponent extends StoreDispatcher i
viewInMinaExplorer(): void {
const network = this.minaExplorer !== 'mainnet' ? (this.minaExplorer + '.') : '';
const url = `https://${network}minaexplorer.com/block/${this.slot.hash}`;
- window.open(url, '_blank');
+ safelyExecuteInBrowser(() => window.open(url, '_blank'));
}
private get getVrfText(): string {
@@ -198,6 +187,7 @@ export class BlockProductionWonSlotsSidePanelComponent extends StoreDispatcher i
}
closeSidePanel(): void {
+ this.router.navigate([Routes.BLOCK_PRODUCTION, Routes.WON_SLOTS]);
this.dispatch2(BlockProductionWonSlotsActions.toggleSidePanel());
}
@@ -205,4 +195,5 @@ export class BlockProductionWonSlotsSidePanelComponent extends StoreDispatcher i
super.ngOnDestroy();
clearInterval(this.timer);
}
+
}
diff --git a/frontend/src/app/features/block-production/won-slots/table/block-production-won-slots-table.component.html b/frontend/src/app/features/block-production/won-slots/table/block-production-won-slots-table.component.html
index 3e42122963..1c4d6d44ca 100644
--- a/frontend/src/app/features/block-production/won-slots/table/block-production-won-slots-table.component.html
+++ b/frontend/src/app/features/block-production/won-slots/table/block-production-won-slots-table.component.html
@@ -6,7 +6,7 @@
*ngIf="row.active || row.status === BlockProductionWonSlotsStatus.Committed; else icon">
schedule
+ class="schedule mina-icon icon-200 f-20">schedule
circle
diff --git a/frontend/src/app/features/block-production/won-slots/table/block-production-won-slots-table.component.scss b/frontend/src/app/features/block-production/won-slots/table/block-production-won-slots-table.component.scss
index 25d6f79317..f8fc4575fc 100644
--- a/frontend/src/app/features/block-production/won-slots/table/block-production-won-slots-table.component.scss
+++ b/frontend/src/app/features/block-production/won-slots/table/block-production-won-slots-table.component.scss
@@ -1,5 +1,9 @@
@import 'openmina';
+$blue: #57d7ff;
+$pink: #fda2ff;
+$orange: #ff833d;
+
.mina-icon.f-big {
font-variation-settings: 'FILL' 1, 'wght' 400 !important;
}
@@ -36,6 +40,21 @@
border-color: $selected-primary !important;
border-top-color: transparent !important;
}
+
+ .schedule,
+ .Scheduled,
+ .Producing {
+ background: linear-gradient(5deg, $blue 30%, $pink 55%, $orange 100%);
+ -webkit-background-clip: text;
+ background-clip: text;
+ -webkit-text-fill-color: transparent;
+ }
+
+ .schedule {
+ @media (max-width: 767px) {
+ font-size: 16px !important;
+ }
+ }
}
.fx-row-vert-cent {
diff --git a/frontend/src/app/features/block-production/won-slots/table/block-production-won-slots-table.component.ts b/frontend/src/app/features/block-production/won-slots/table/block-production-won-slots-table.component.ts
index 0334986ccb..4f23b56c9c 100644
--- a/frontend/src/app/features/block-production/won-slots/table/block-production-won-slots-table.component.ts
+++ b/frontend/src/app/features/block-production/won-slots/table/block-production-won-slots-table.component.ts
@@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { MinaTableRustWrapper } from '@shared/base-classes/mina-table-rust-wrapper.class';
-import { getMergedRoute, MergedRoute, SecDurationConfig, TableColumnList } from '@openmina/shared';
+import { getMergedRoute, isDesktop, MergedRoute, SecDurationConfig, TableColumnList } from '@openmina/shared';
import { Router } from '@angular/router';
import { SnarksWorkPoolToggleSidePanel } from '@snarks/work-pool/snarks-work-pool.actions';
import { filter, take } from 'rxjs';
@@ -57,7 +57,7 @@ export class BlockProductionWonSlotsTableComponent extends MinaTableRustWrapper<
}
protected override setupTable(): void {
- this.table.gridTemplateColumns = [210, 140, 90, 140, 120, 120, 120, 120, 150, 150];
+ this.table.gridTemplateColumns = isDesktop() ? [210, 140, 90, 142, 120, 120, 120, 124, 159, 150] : [150, 100, 90, 130, 100, 105, 100, 114, 139, 130];
this.table.propertyForActiveCheck = 'globalSlot';
this.table.thGroupsTemplate = this.thGroupsTemplate;
this.table.sortAction = BlockProductionWonSlotsActions.sort;
@@ -96,7 +96,7 @@ export class BlockProductionWonSlotsTableComponent extends MinaTableRustWrapper<
this.table.activeRow = slot;
this.table.detect();
this.detect();
- }, filter(Boolean));
+ });
}
private scrollToElement(): void {
@@ -107,11 +107,11 @@ export class BlockProductionWonSlotsTableComponent extends MinaTableRustWrapper<
this.onRowClick(this.table.rows[i]);
}
- protected override onRowClick(slot: BlockProductionWonSlotsSlot): void {
+ protected override onRowClick(slot: BlockProductionWonSlotsSlot, isRealClick?: boolean): void {
if (!slot) {
return;
}
- if (this.table.activeRow?.globalSlot !== slot?.globalSlot) {
+ if (this.table.activeRow?.globalSlot !== slot?.globalSlot || isRealClick) {
this.dispatch2(BlockProductionWonSlotsActions.setActiveSlot({ slot }));
this.router.navigate([Routes.BLOCK_PRODUCTION, Routes.WON_SLOTS, slot.globalSlot], { queryParamsHandling: 'merge' });
}
diff --git a/frontend/src/app/features/dashboard/dashboard-blocks-sync/dashboard-blocks-sync.component.html b/frontend/src/app/features/dashboard/dashboard-blocks-sync/dashboard-blocks-sync.component.html
index 46037f53df..0e89fd94b9 100644
--- a/frontend/src/app/features/dashboard/dashboard-blocks-sync/dashboard-blocks-sync.component.html
+++ b/frontend/src/app/features/dashboard/dashboard-blocks-sync/dashboard-blocks-sync.component.html
@@ -1,38 +1,46 @@
-
-
-
Last 290 blocks
-
{{ syncProgress }}
-
-
-
+
+
+
+ @if (appliedPercentage === 100) {
+
check_circle
+ } @else {
+
+ }
+
Last 290 blocks
+
{{ remaining ? 'ETA ~' + remaining + 's' : syncProgress }}
-
+
-
+ @if (isDesktop) {
+
+ }
-
+ @if (isDesktop) {
+
+ }
diff --git a/frontend/src/app/features/dashboard/dashboard-blocks-sync/dashboard-blocks-sync.component.scss b/frontend/src/app/features/dashboard/dashboard-blocks-sync/dashboard-blocks-sync.component.scss
index 51d9324e02..687cb478cd 100644
--- a/frontend/src/app/features/dashboard/dashboard-blocks-sync/dashboard-blocks-sync.component.scss
+++ b/frontend/src/app/features/dashboard/dashboard-blocks-sync/dashboard-blocks-sync.component.scss
@@ -1,42 +1,16 @@
-@import 'openmina';
-.progress-bar {
- overflow: hidden;
- height: 6px;
- left: 0;
- bottom: 0;
- transition: width 0.6s ease-in-out;
- min-width: 20px;
-
- .highlight {
- height: 4px;
- top: 1px;
- left: -50px;
- width: 50px;
- background: radial-gradient($success-primary, $success-primary, $success-primary, $success-primary, transparent, transparent);
- border-radius: 20px;
- animation: move 9s linear infinite;
+:host {
+ .mina-icon {
+ font-variation-settings: 'FILL' 1, 'wght' 300 !important;
}
- .progress {
- height: 2px;
- background-color: $success-primary;
- top: 2px;
- left: 0;
- }
-}
+ @media (max-width: 767px) {
+ .mobile mina-card {
+ width: 33.333%;
-@keyframes move {
- 0% {
- left: -50px;
- }
- 10% {
- left: -50px;
- }
- 80% {
- left: 100%;
- }
- 100% {
- left: 100%;
+ &:not(:first-child) {
+ padding-left: 10px !important;
+ }
+ }
}
}
diff --git a/frontend/src/app/features/dashboard/dashboard-blocks-sync/dashboard-blocks-sync.component.ts b/frontend/src/app/features/dashboard/dashboard-blocks-sync/dashboard-blocks-sync.component.ts
index bd29e3cb04..465b5bdbd4 100644
--- a/frontend/src/app/features/dashboard/dashboard-blocks-sync/dashboard-blocks-sync.component.ts
+++ b/frontend/src/app/features/dashboard/dashboard-blocks-sync/dashboard-blocks-sync.component.ts
@@ -2,10 +2,10 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { StoreDispatcher } from '@shared/base-classes/store-dispatcher.class';
import { selectDashboardNodesAndPeers } from '@dashboard/dashboard.state';
import { NodesOverviewNode } from '@shared/types/nodes/dashboard/nodes-overview-node.type';
-import { filter } from 'rxjs';
import { NodesOverviewNodeBlockStatus } from '@shared/types/nodes/dashboard/nodes-overview-block.type';
-import { lastItem, ONE_MILLION } from '@openmina/shared';
+import { isDesktop, lastItem, ONE_MILLION } from '@openmina/shared';
import { DashboardPeer } from '@shared/types/dashboard/dashboard.peer';
+import { SentryService } from '@core/services/sentry.service';
const PENDING = 'Pending';
const SYNCED = 'Synced';
@@ -28,6 +28,12 @@ export class DashboardBlocksSyncComponent extends StoreDispatcher implements OnI
bestTipBlockSyncedText: string = PENDING;
targetBlock: number;
syncProgress: string;
+ isDesktop: boolean = isDesktop();
+ remaining: number;
+
+ private syncStartTime: number = Date.now();
+
+ constructor(private sentryService: SentryService) {super();}
ngOnInit(): void {
this.listenToNodesChanges();
@@ -47,8 +53,36 @@ export class DashboardBlocksSyncComponent extends StoreDispatcher implements OnI
this.targetBlock = undefined;
this.syncProgress = undefined;
} else {
+ const blocks = nodes[0].blocks;
+
+ const blocksFetched = blocks.filter(b => b.fetchEnd).length;
+ const blocksApplied = blocks.filter(b => b.applyEnd).length;
+ if (blocksApplied < 291) {
+
+ const syncStart = Math.min(...blocks.map(b => b.fetchStart).filter(Boolean)) / ONE_MILLION;
+ const now = Date.now();
+ const secondsPassed = (now - syncStart) / 1000;
+
+ const fetchWeight = 1;
+ const applyWeight = 5;
+
+ // Apply weights: 1 for each fetched block, and 5 for each applied block
+ const weightedBlocksTotal = (blocksFetched * fetchWeight) + (blocksApplied * applyWeight);
+ const blocksPerSecond = weightedBlocksTotal / secondsPassed;
+
+ if (blocksPerSecond > 0) {
+ const weightedBlocksRemaining = (291 * fetchWeight) + (291 * applyWeight) - weightedBlocksTotal;
+ const secondsRemaining = weightedBlocksRemaining / blocksPerSecond;
+ this.remaining = Math.ceil(secondsRemaining);
+ }
+ } else {
+ this.remaining = null;
+ }
+
this.extractNodesData(nodes);
this.extractPeersData(peers);
+
+ this.sentryService.updateBlockSyncStatus(nodes[0].blocks, this.syncStartTime);
}
this.detect();
});
@@ -69,6 +103,9 @@ export class DashboardBlocksSyncComponent extends StoreDispatcher implements OnI
this.bestTipBlock = blocks[0].height;
this.bestTipBlockSyncedText = 'Fetched ' + this.calculateProgressTime(nodes[0].bestTipReceivedTimestamp * ONE_MILLION).slice(7);
this.syncProgress = this.bestTipBlockSyncedText.slice(8);
+ if (lastItem(blocks).status !== NodesOverviewNodeBlockStatus.APPLIED) {
+ this.syncProgress = 'Pending';
+ }
}
if (blocks.length === 291) {
@@ -85,8 +122,8 @@ export class DashboardBlocksSyncComponent extends StoreDispatcher implements OnI
this.fetched = blocks.filter(b => ![NodesOverviewNodeBlockStatus.MISSING, NodesOverviewNodeBlockStatus.FETCHING].includes(b.status)).length;
this.applied = blocks.filter(b => b.status === NodesOverviewNodeBlockStatus.APPLIED).length;
- this.fetchedPercentage = Math.round(this.fetched * 100 / 291) + '%';
- this.appliedPercentage = Math.round(this.applied * 100 / 291);
+ this.fetchedPercentage = Math.round(this.fetched * 100 / 290) + '%';
+ this.appliedPercentage = Math.round(this.applied * 100 / 290);
}
private calculateProgressTime(timestamp: number): string {
diff --git a/frontend/src/app/features/dashboard/dashboard-ledger/dashboard-ledger.component.html b/frontend/src/app/features/dashboard/dashboard-ledger/dashboard-ledger.component.html
index def4089c6b..84703092f4 100644
--- a/frontend/src/app/features/dashboard/dashboard-ledger/dashboard-ledger.component.html
+++ b/frontend/src/app/features/dashboard/dashboard-ledger/dashboard-ledger.component.html
@@ -1,12 +1,14 @@
-
-
-
Ledgers
-
{{ progress }}
-
0" [style.width.%]="totalProgress"
- class="progress-bar p-absolute">
-
-
+
+
+
+ @if (totalProgress === 100) {
+
check_circle
+ } @else {
+
+ }
+
Ledgers
+
{{ progress }}
Staking ledger
-
{{ stakingProgress | number: '1.0-0' }}%
-
+ @if (stakingProgress === 100) {
+
100%
+ } @else if (remainingStakingLedger) {
+
ETA ~{{ remainingStakingLedger }}s
+ }
Next epoch ledger
-
- {{ nextProgress | number: '1.0-0' }}%
-
+ @if (nextProgress === 100) {
+
100%
+ } @else if (remainingNextLedger) {
+
ETA ~{{ remainingNextLedger }}s
+ }
Snarked ledger at the root
-
- {{ rootSnarkedProgress | number: '1.0-0' }}%
-
+ @if (rootSnarkedProgress === 100) {
+
100%
+ } @else if (remainingRootSnarkedLedger) {
+
ETA ~{{ remainingRootSnarkedLedger }}s
+ }
Staged ledger at the root
-
- {{ rootStagedProgress | number: '1.0-0' }}%
-
+ @if ((rootStagedProgress === 100 || !isWebNode) && rootSnarkedProgress === 100) {
+
{{ rootStagedProgress }}%
+ } @else if (remainingReconstruct && remainingRootStagedLedgerFetchParts + remainingReconstruct) {
+
ETA ~{{ remainingRootStagedLedgerFetchParts + remainingReconstruct }}s
+ }
diff --git a/frontend/src/app/features/dashboard/dashboard-ledger/dashboard-ledger.component.scss b/frontend/src/app/features/dashboard/dashboard-ledger/dashboard-ledger.component.scss
index 331b09ebc6..acb2f24ab6 100644
--- a/frontend/src/app/features/dashboard/dashboard-ledger/dashboard-ledger.component.scss
+++ b/frontend/src/app/features/dashboard/dashboard-ledger/dashboard-ledger.component.scss
@@ -1,44 +1,7 @@
@import 'openmina';
-.progress-bar {
- overflow: hidden;
- height: 6px;
- left: 0;
- bottom: 0;
- transition: width 0.6s ease-in-out;
- min-width: 20px;
-
- .highlight {
- height: 4px;
- top: 1px;
- left: -50px;
- width: 50px;
- background: radial-gradient($success-primary, $success-primary, $success-primary, $success-primary, transparent, transparent);
- border-radius: 20px;
- animation: move 9s linear infinite;
- }
-
- .progress {
- height: 2px;
- background-color: $success-primary;
- top: 2px;
- left: 0;
- }
-}
-
-@keyframes move {
- 0% {
- left: -50px;
- }
- 10% {
- left: -50px;
- }
- 80% {
- left: 100%;
- }
- 100% {
- left: 100%;
- }
+.mina-icon {
+ font-variation-settings: 'FILL' 1, 'wght' 300 !important;
}
.group {
@@ -53,7 +16,7 @@
top: -5px;
left: 10px;
width: 1px;
- height: calc(100% - 13px);
+ height: calc(100% + 10px);
background-color: $base-divider;
}
@@ -63,7 +26,7 @@
&::before {
content: '';
position: absolute;
- top: calc(50% - 1px);
+ top: calc(50% + 0px);
left: -29px;
width: 20px;
height: 1px;
@@ -72,6 +35,10 @@
}
}
+ &:last-child .steps::before {
+ height: calc(100% - 13px);
+ }
+
&.pending {
.group-title {
color: $base-tertiary;
@@ -83,9 +50,13 @@
}
&.success {
+ .group-title {
+ color: $success-primary;
+ }
+
.steps::before,
.steps .step::before {
- background-color: $success-tertiary;
+ background-color: $base-tertiary;
}
}
diff --git a/frontend/src/app/features/dashboard/dashboard-ledger/dashboard-ledger.component.ts b/frontend/src/app/features/dashboard/dashboard-ledger/dashboard-ledger.component.ts
index bb4d2ea011..b0c46c1526 100644
--- a/frontend/src/app/features/dashboard/dashboard-ledger/dashboard-ledger.component.ts
+++ b/frontend/src/app/features/dashboard/dashboard-ledger/dashboard-ledger.component.ts
@@ -1,12 +1,4 @@
-import {
- ChangeDetectionStrategy,
- Component,
- OnDestroy,
- OnInit,
- TemplateRef,
- ViewChild,
- ViewContainerRef,
-} from '@angular/core';
+import { ChangeDetectionStrategy, Component, OnDestroy, OnInit, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core';
import { StoreDispatcher } from '@shared/base-classes/store-dispatcher.class';
import { selectDashboardNodesAndRpcStats } from '@dashboard/dashboard.state';
import {
@@ -15,12 +7,14 @@ import {
NodesOverviewLedgerStepState,
NodesOverviewRootStagedLedgerStep,
} from '@shared/types/nodes/dashboard/nodes-overview-ledger.type';
-import { filter } from 'rxjs';
import { NodesOverviewNode } from '@shared/types/nodes/dashboard/nodes-overview-node.type';
import { ONE_MILLION, SecDurationConfig } from '@openmina/shared';
import { Overlay, OverlayRef } from '@angular/cdk/overlay';
import { TemplatePortal } from '@angular/cdk/portal';
import { DashboardRpcStats } from '@shared/types/dashboard/dashboard-rpc-stats.type';
+import { AppSelectors } from '@app/app.state';
+import { MinaNode } from '@shared/types/core/environment/mina-env.type';
+import { SentryService } from '@core/services/sentry.service';
type LedgerConfigMap = {
stakingEpoch: SecDurationConfig,
@@ -85,19 +79,41 @@ export class DashboardLedgerComponent extends StoreDispatcher implements OnInit,
rootSnarkedProgress: number = 0;
rootStagedProgress: number = 0;
totalProgress: number;
+ isWebNode: boolean;
+
+ private startSync: number = Date.now();
@ViewChild('tooltipRef') private tooltipRef: TemplateRef<{ start: number, end: number }>;
private overlayRef: OverlayRef;
constructor(private overlay: Overlay,
- private viewContainerRef: ViewContainerRef) {
+ private viewContainerRef: ViewContainerRef,
+ private sentryService: SentryService) {
super();
}
ngOnInit(): void {
+ this.listenToActiveNode();
this.listenToNodesChanges();
}
+ private listenToActiveNode(): void {
+ this.select(AppSelectors.activeNode, (node: MinaNode) => {
+ this.isWebNode = node.isWebNode;
+ });
+ }
+
+ remainingStakingLedger: number;
+ private previousStakingLedgerDownloaded: number;
+ remainingNextLedger: number;
+ private previousNextLedgerDownloaded: number;
+ remainingRootSnarkedLedger: number;
+ private previousRootSnarkedLedgerDownloaded: number;
+ remainingRootStagedLedgerFetchParts: number;
+ private previousRootStagedLedgerDownloaded: number;
+ remainingReconstruct: number = 20;
+ private reconstructTimer: any;
+
private listenToNodesChanges(): void {
this.select(selectDashboardNodesAndRpcStats, ([nodes, rpcStats]: [NodesOverviewNode[], DashboardRpcStats]) => {
if (nodes.length === 0) {
@@ -132,10 +148,77 @@ export class DashboardLedgerComponent extends StoreDispatcher implements OnInit,
rootStaged: getConfig(this.ledgers.rootStaged.state),
};
this.setProgressTime();
+
+ const stakingLedgerStartTime = this.ledgers.stakingEpoch.snarked.fetchHashesStart / ONE_MILLION;
+ const currentStakingLedgerDownloaded = rpcStats.stakingLedger?.fetched;
+ if (
+ this.previousStakingLedgerDownloaded && currentStakingLedgerDownloaded &&
+ stakingLedgerStartTime < Date.now()
+ ) {
+ const timeSinceDownloadStarted = Date.now() - stakingLedgerStartTime;
+ const remaining = rpcStats.stakingLedger?.estimation - currentStakingLedgerDownloaded;
+ const remainingTime = (remaining / currentStakingLedgerDownloaded) * timeSinceDownloadStarted;
+ this.remainingStakingLedger = Math.floor(remainingTime / 1000);
+ }
+ this.previousStakingLedgerDownloaded = currentStakingLedgerDownloaded;
+
+ const nextLedgerStartTime = this.ledgers.nextEpoch.snarked.fetchHashesStart / ONE_MILLION;
+ const currentNextLedgerDownloaded = rpcStats.nextLedger?.fetched;
+ if (
+ this.previousNextLedgerDownloaded && currentNextLedgerDownloaded &&
+ nextLedgerStartTime < Date.now()
+ ) {
+ const timeSinceDownloadStarted = Date.now() - nextLedgerStartTime;
+ const remaining = rpcStats.nextLedger?.estimation - currentNextLedgerDownloaded;
+ const remainingTime = (remaining / currentNextLedgerDownloaded) * timeSinceDownloadStarted;
+ this.remainingNextLedger = Math.floor(remainingTime / 1000);
+ }
+ this.previousNextLedgerDownloaded = currentNextLedgerDownloaded;
+
+ const rootSnarkedLedgerStartTime = this.ledgers.rootSnarked.snarked.fetchHashesStart / ONE_MILLION;
+ const currentRootSnarkedLedgerDownloaded = rpcStats.snarkedRootLedger?.fetched;
+ if (
+ this.previousRootSnarkedLedgerDownloaded && currentRootSnarkedLedgerDownloaded &&
+ rootSnarkedLedgerStartTime < Date.now()
+ ) {
+ const timeSinceDownloadStarted = Date.now() - rootSnarkedLedgerStartTime;
+ const remaining = rpcStats.snarkedRootLedger?.estimation - currentRootSnarkedLedgerDownloaded;
+ const remainingTime = (remaining / currentRootSnarkedLedgerDownloaded) * timeSinceDownloadStarted;
+ this.remainingRootSnarkedLedger = Math.floor(remainingTime / 1000);
+ }
+ this.previousRootSnarkedLedgerDownloaded = currentRootSnarkedLedgerDownloaded;
+
+ if (this.isWebNode) {
+ const rootStagedLedgerStartTime = this.ledgers.rootStaged.staged.fetchPartsStart / ONE_MILLION;
+ const currentRootStagedLedgerDownloaded = rpcStats.stagedRootLedger?.fetched;
+ if (
+ this.previousRootStagedLedgerDownloaded && currentRootStagedLedgerDownloaded &&
+ rootStagedLedgerStartTime < Date.now()
+ ) {
+ const timeSinceDownloadStarted = Date.now() - rootStagedLedgerStartTime;
+ const remaining = rpcStats.stagedRootLedger?.estimation - currentRootStagedLedgerDownloaded;
+ const remainingTime = (remaining / currentRootStagedLedgerDownloaded) * timeSinceDownloadStarted;
+ this.remainingRootStagedLedgerFetchParts = Math.floor(remainingTime / 1000);
+ }
+ this.previousRootStagedLedgerDownloaded = currentRootStagedLedgerDownloaded;
+ }
+
this.stakingProgress = rpcStats.stakingLedger?.fetched / rpcStats.stakingLedger?.estimation * 100 || 0;
this.nextProgress = rpcStats.nextLedger?.fetched / rpcStats.nextLedger?.estimation * 100 || 0;
- this.rootSnarkedProgress = rpcStats.rootLedger?.fetched / rpcStats.rootLedger?.estimation * 100 || 0;
- this.rootStagedProgress = this.ledgers.rootStaged.staged.fetchPartsEnd ? 50 : 0;
+ this.rootSnarkedProgress = rpcStats.snarkedRootLedger?.fetched / rpcStats.snarkedRootLedger?.estimation * 100 || 0;
+
+ this.rootStagedProgress = 0;
+ if (this.ledgers.rootStaged.staged.fetchPartsEnd) {
+ this.rootStagedProgress += 50;
+ }
+ if (this.ledgers.rootStaged.staged.reconstructEnd) {
+ this.rootStagedProgress += 50;
+ }
+ if (this.rootStagedProgress < 100 && this.isWebNode && this.ledgers.rootStaged.staged.fetchPartsEnd && !this.reconstructTimer) {
+ this.startTimerForReconstruct();
+ } else if (this.rootStagedProgress === 100) {
+ clearTimeout(this.reconstructTimer);
+ }
if (this.ledgers.stakingEpoch.state === NodesOverviewLedgerStepState.SUCCESS) {
this.stakingProgress = 100;
@@ -150,11 +233,23 @@ export class DashboardLedgerComponent extends StoreDispatcher implements OnInit,
this.rootStagedProgress = 100;
}
this.totalProgress = (this.stakingProgress + this.nextProgress + this.rootSnarkedProgress + this.rootStagedProgress) / 4;
+
+ this.sentryService.updateLedgerSyncStatus(this.ledgers);
}
this.detect();
});
}
+ startTimerForReconstruct(): void {
+ this.reconstructTimer = setInterval(() => {
+ this.remainingReconstruct = this.remainingReconstruct - 1;
+ this.detect();
+ if (this.remainingReconstruct === Math.floor(Math.random() * 2) + 2) {
+ clearTimeout(this.reconstructTimer);
+ }
+ }, 1000);
+ }
+
show(event: MouseEvent, start: number, end: number): void {
if (this.overlayRef?.hasAttached()) {
this.overlayRef.detach();
@@ -183,9 +278,7 @@ export class DashboardLedgerComponent extends StoreDispatcher implements OnInit,
}
hide(): void {
- if (this.overlayRef?.hasAttached()) {
- this.overlayRef.detach();
- }
+ this.overlayRef?.dispose();
}
private get emptyConfig(): SecDurationConfig {
@@ -205,11 +298,6 @@ export class DashboardLedgerComponent extends StoreDispatcher implements OnInit,
};
}
- override ngOnDestroy(): void {
- super.ngOnDestroy();
- this.hide();
- }
-
private setProgressTime(): void {
if (!this.ledgers.stakingEpoch.snarked.fetchHashesStart) {
return;
@@ -238,4 +326,9 @@ export class DashboardLedgerComponent extends StoreDispatcher implements OnInit,
return `${action} <1m ago`;
}
}
+
+ override ngOnDestroy(): void {
+ super.ngOnDestroy();
+ this.hide();
+ }
}
diff --git a/frontend/src/app/features/dashboard/dashboard-network/dashboard-network.component.html b/frontend/src/app/features/dashboard/dashboard-network/dashboard-network.component.html
index cc24d97e3d..6b758e9783 100644
--- a/frontend/src/app/features/dashboard/dashboard-network/dashboard-network.component.html
+++ b/frontend/src/app/features/dashboard/dashboard-network/dashboard-network.component.html
@@ -1,19 +1,13 @@
-
-
- Network
-
-
-
-
Peers
-
0"
- [style.width.%]="stats.connected === 0 ? 0 : 100"
- class="progress-bar p-absolute">
-
-
-
+
+
+ @if (stats.connected) {
+
check_circle
+ } @else {
+
+ }
+
Peers
-
+
-
-
-
- account_tree
-
-
-
-
diff --git a/frontend/src/app/features/dashboard/dashboard-network/dashboard-network.component.scss b/frontend/src/app/features/dashboard/dashboard-network/dashboard-network.component.scss
index 818da2c61d..6e1afba0ea 100644
--- a/frontend/src/app/features/dashboard/dashboard-network/dashboard-network.component.scss
+++ b/frontend/src/app/features/dashboard/dashboard-network/dashboard-network.component.scss
@@ -1,60 +1,3 @@
-@import 'openmina';
-
-:host {
- max-width: 384px;
-}
-
-.loading-icon {
- animation: spin 2s linear infinite;
-}
-
-@keyframes spin {
- 0% {
- transform: rotate(0);
- }
- 100% {
- transform: rotate(360deg);
- }
-}
-
-
-.progress-bar {
- overflow: hidden;
- height: 6px;
- left: 0;
- bottom: 0;
- transition: width 0.6s ease-in-out;
- min-width: 20px;
-
- .highlight {
- height: 4px;
- top: 1px;
- left: -50px;
- width: 50px;
- background: radial-gradient($success-primary, $success-primary, $success-primary, $success-primary, transparent, transparent);
- border-radius: 20px;
- animation: move 9s linear infinite;
- }
-
- .progress {
- height: 2px;
- background-color: $success-primary;
- top: 2px;
- left: 0;
- }
-}
-
-@keyframes move {
- 0% {
- left: -50px;
- }
- 10% {
- left: -50px;
- }
- 80% {
- left: 100%;
- }
- 100% {
- left: 100%;
- }
+.mina-icon {
+ font-variation-settings: 'FILL' 1, 'wght' 300 !important;
}
diff --git a/frontend/src/app/features/dashboard/dashboard-network/dashboard-network.component.ts b/frontend/src/app/features/dashboard/dashboard-network/dashboard-network.component.ts
index 3c8b63e204..ff47a7e17f 100644
--- a/frontend/src/app/features/dashboard/dashboard-network/dashboard-network.component.ts
+++ b/frontend/src/app/features/dashboard/dashboard-network/dashboard-network.component.ts
@@ -3,7 +3,6 @@ import { DashboardPeersStats } from '@shared/types/dashboard/dashboard-peers-sta
import { selectDashboardPeersStats } from '@dashboard/dashboard.state';
import { skip } from 'rxjs';
import { StoreDispatcher } from '@shared/base-classes/store-dispatcher.class';
-import { NodesOverviewLedgerStepState } from '@shared/types/nodes/dashboard/nodes-overview-ledger.type';
@Component({
selector: 'mina-dashboard-network',
diff --git a/frontend/src/app/features/dashboard/dashboard-peers-minimal-table/dashboard-peers-minimal-table.component.scss b/frontend/src/app/features/dashboard/dashboard-peers-minimal-table/dashboard-peers-minimal-table.component.scss
index bb3787a918..53e4ca2058 100644
--- a/frontend/src/app/features/dashboard/dashboard-peers-minimal-table/dashboard-peers-minimal-table.component.scss
+++ b/frontend/src/app/features/dashboard/dashboard-peers-minimal-table/dashboard-peers-minimal-table.component.scss
@@ -14,6 +14,7 @@
:host ::ng-deep cdk-virtual-scroll-viewport {
overflow-y: auto !important;
+ border-bottom: none !important;
}
.fx-row-vert-cent {
diff --git a/frontend/src/app/features/dashboard/dashboard-transition-frontier/dashboard-transition-frontier.component.html b/frontend/src/app/features/dashboard/dashboard-transition-frontier/dashboard-transition-frontier.component.html
deleted file mode 100644
index 549dcca28f..0000000000
--- a/frontend/src/app/features/dashboard/dashboard-transition-frontier/dashboard-transition-frontier.component.html
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
- Transition frontier
-
-
-
-
-
-
-
- margin
-
-
-
-
diff --git a/frontend/src/app/features/dashboard/dashboard-transition-frontier/dashboard-transition-frontier.component.scss b/frontend/src/app/features/dashboard/dashboard-transition-frontier/dashboard-transition-frontier.component.scss
deleted file mode 100644
index 17d80cb52d..0000000000
--- a/frontend/src/app/features/dashboard/dashboard-transition-frontier/dashboard-transition-frontier.component.scss
+++ /dev/null
@@ -1,34 +0,0 @@
-@import 'openmina';
-
-.tracing-container {
- gap: 8px;
-
- mina-dashboard-ledger {
- width: 100%;
- max-width: 410px;
- min-width: 250px;
- }
-
- mina-dashboard-blocks-sync {
- width: 100%;
- max-width: 640px;
- }
-
- @media (max-width: 1374px) {
- display: flex;
- flex-direction: column;
- }
-}
-
-.loading-icon {
- animation: spin 2s linear infinite;
-}
-
-@keyframes spin {
- 0% {
- transform: rotate(0);
- }
- 100% {
- transform: rotate(360deg);
- }
-}
diff --git a/frontend/src/app/features/dashboard/dashboard-transition-frontier/dashboard-transition-frontier.component.ts b/frontend/src/app/features/dashboard/dashboard-transition-frontier/dashboard-transition-frontier.component.ts
deleted file mode 100644
index 7af4da1482..0000000000
--- a/frontend/src/app/features/dashboard/dashboard-transition-frontier/dashboard-transition-frontier.component.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
-import { StoreDispatcher } from '@shared/base-classes/store-dispatcher.class';
-import { selectDashboardNodes } from '@dashboard/dashboard.state';
-import { NodesOverviewNode, NodesOverviewNodeKindType } from '@shared/types/nodes/dashboard/nodes-overview-node.type';
-
-@Component({
- selector: 'mina-dashboard-transition-frontier',
- templateUrl: './dashboard-transition-frontier.component.html',
- styleUrls: ['./dashboard-transition-frontier.component.scss'],
- changeDetection: ChangeDetectionStrategy.OnPush,
- host: { class: 'flex-column flex-1' },
-})
-export class DashboardTransitionFrontierComponent extends StoreDispatcher implements OnInit {
-
- loading: boolean = true;
-
- ngOnInit(): void {
- this.listenToNodesChanges();
- }
-
- private listenToNodesChanges(): void {
- this.select(selectDashboardNodes, (nodes: NodesOverviewNode[]) => {
- this.loading = !nodes.length || nodes[0].kind !== NodesOverviewNodeKindType.SYNCED;
- this.detect();
- });
- }
-}
diff --git a/frontend/src/app/features/dashboard/dashboard.component.html b/frontend/src/app/features/dashboard/dashboard.component.html
index 97e54aa457..7e2a718d84 100644
--- a/frontend/src/app/features/dashboard/dashboard.component.html
+++ b/frontend/src/app/features/dashboard/dashboard.component.html
@@ -1,4 +1,18 @@
-
+
+
-
+
+
diff --git a/frontend/src/app/features/dashboard/dashboard.component.scss b/frontend/src/app/features/dashboard/dashboard.component.scss
index cd151fd9f7..6f38a175ae 100644
--- a/frontend/src/app/features/dashboard/dashboard.component.scss
+++ b/frontend/src/app/features/dashboard/dashboard.component.scss
@@ -4,6 +4,89 @@
background-color: $base-background;
}
-div {
+.comps {
gap: 8px;
+ padding-right: 8px;
+}
+
+mina-dashboard-network {
+ max-width: 384px;
+}
+
+mina-dashboard-ledger {
+ width: 100%;
+ max-width: 384px;
+ min-width: 250px;
+}
+
+mina-dashboard-blocks-sync {
+ width: 100%;
+ max-width: 644px;
+}
+
+@media (max-width: 767px) {
+ mina-dashboard-network,
+ mina-dashboard-ledger,
+ mina-dashboard-blocks-sync {
+ max-width: 100%;
+ }
+}
+
+.header {
+ transition: height .6s ease-in, opacity .4s .4s ease-in;
+
+ &.hide {
+ height: 0 !important;
+ opacity: 0;
+ }
+
+ @media (max-width: 767px) {
+ &.hide {
+ height: 8px !important;
+ }
+ .primary {
+ padding-left: 4px;
+ }
+ }
+}
+
+.progress-bar {
+ overflow: hidden;
+ height: 4px;
+ left: 0;
+ top: -2px;
+ transition: width 0.6s ease-in-out;
+ min-width: 20px;
+
+ .highlight {
+ height: 4px;
+ top: 1px;
+ left: -50px;
+ width: 50px;
+ background: radial-gradient($success-primary, $success-primary, $success-primary, $success-primary, transparent, transparent);
+ border-radius: 20px;
+ animation: move 9s linear infinite;
+ }
+
+ .progress {
+ height: 2px;
+ background-color: $success-primary;
+ top: 2px;
+ left: 0;
+ }
+}
+
+@keyframes move {
+ 0% {
+ left: -50px;
+ }
+ 10% {
+ left: -50px;
+ }
+ 80% {
+ left: 100%;
+ }
+ 100% {
+ left: 100%;
+ }
}
diff --git a/frontend/src/app/features/dashboard/dashboard.component.ts b/frontend/src/app/features/dashboard/dashboard.component.ts
index cc2dbaaf7e..1ff872cf57 100644
--- a/frontend/src/app/features/dashboard/dashboard.component.ts
+++ b/frontend/src/app/features/dashboard/dashboard.component.ts
@@ -1,33 +1,162 @@
-import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
+import { ChangeDetectionStrategy, Component, Inject, OnDestroy, OnInit } from '@angular/core';
import { StoreDispatcher } from '@shared/base-classes/store-dispatcher.class';
import { DashboardGetData, DashboardInit } from '@dashboard/dashboard.actions';
-import { filter, skip, tap, timer } from 'rxjs';
-import { untilDestroyed } from '@ngneat/until-destroy';
+import { filter, skip, Subscription, tap, timer } from 'rxjs';
import { AppSelectors } from '@app/app.state';
+import { selectDashboardNodesAndRpcStats, selectDashboardPeersStats } from '@dashboard/dashboard.state';
+import { DashboardPeersStats } from '@shared/types/dashboard/dashboard-peers-stats.type';
+import { NodesOverviewNode } from '@shared/types/nodes/dashboard/nodes-overview-node.type';
+import { DashboardRpcStats } from '@shared/types/dashboard/dashboard-rpc-stats.type';
+import { NodesOverviewLedgerStepState } from '@shared/types/nodes/dashboard/nodes-overview-ledger.type';
+import { NodesOverviewNodeBlockStatus } from '@shared/types/nodes/dashboard/nodes-overview-block.type';
+import { AppNodeDetails, AppNodeStatus } from '@shared/types/app/app-node-details.type';
+import { untilDestroyed } from '@ngneat/until-destroy';
@Component({
selector: 'mina-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
- host: { class: 'h-100 w-100 flex-row' },
+ host: { class: 'h-100 w-100 flex-column' },
})
-export class DashboardComponent extends StoreDispatcher implements OnInit {
+export class DashboardComponent extends StoreDispatcher implements OnInit, OnDestroy {
+
+ updateAction: string;
+ updateDetail: string;
+ connectedProgress: number = 0;
+ ledgerProgress: number = 0;
+ blockSyncProgress: number = 0;
+
+ private connected: boolean = false;
+ timer: Subscription;
+ lastStatus: AppNodeStatus;
ngOnInit(): void {
+ // this.document.getElementById('mina-content').style.borderTopLeftRadius = '0';
+ this.updateAction = 'Connecting to peers';
+
this.listenToNodeChanging();
+ this.listenToPeersChanges();
+ this.getDashboardData();
+ this.listenToNodesChanges();
+ }
+
+ private getDashboardData(): void {
this.dispatch(DashboardInit);
- timer(4000, 4000)
- .pipe(
- tap(() => this.dispatch(DashboardGetData)),
- untilDestroyed(this),
- )
- .subscribe();
+ this.resetTimer();
}
private listenToNodeChanging(): void {
this.select(AppSelectors.activeNode, () => {
this.dispatch(DashboardGetData, { force: true });
- }, filter(Boolean), skip(1), untilDestroyed(this));
+ }, filter(Boolean), skip(1));
+ this.select(AppSelectors.activeNodeDetails, (details: AppNodeDetails) => {
+ if (this.lastStatus !== details.status) {
+ this.lastStatus = details.status;
+ this.resetTimer();
+ }
+ });
+ }
+
+ private resetTimer(): void {
+ this.timer?.unsubscribe();
+ const timerInterval = this.lastStatus === AppNodeStatus.SYNCED || this.lastStatus === AppNodeStatus.OFFLINE ? 5000 : 1000;
+ this.timer = timer(timerInterval, timerInterval)
+ .pipe(
+ tap(() => this.dispatch(DashboardGetData)),
+ untilDestroyed(this),
+ ).subscribe();
}
+
+ private listenToPeersChanges(): void {
+ this.select(selectDashboardPeersStats, (stats: DashboardPeersStats) => {
+ if (this.connected && stats.connected === 0 || !this.connected) {
+ if (stats.connected > 0) {
+ this.updateAction = 'Downloading Staking Epoch Ledger';
+ } else if (stats.connecting > 0) {
+ this.updateAction = `Connecting to ${stats.connecting} peer${stats.connecting !== 1 ? 's' : ''}`;
+ } else {
+ this.updateAction = 'Looking for peers';
+ }
+ if (stats.connected) {
+ this.connectedProgress = 33;
+ } else {
+ this.connectedProgress = 0;
+ this.ledgerProgress = 0;
+ this.blockSyncProgress = 0;
+ }
+ this.detect();
+ }
+ this.connected = stats.connected > 0;
+ }, skip(1));
+ }
+
+ private listenToNodesChanges(): void {
+ this.select(selectDashboardNodesAndRpcStats, ([nodes, rpcStats]: [NodesOverviewNode[], DashboardRpcStats]) => {
+ if (nodes.length !== 0) {
+ const ledgers = nodes[0].ledgers;
+
+ let stakingProgress = rpcStats.stakingLedger?.fetched / rpcStats.stakingLedger?.estimation * 100 || 0;
+ let nextProgress = rpcStats.nextLedger?.fetched / rpcStats.nextLedger?.estimation * 100 || 0;
+ let rootSnarkedProgress = rpcStats.snarkedRootLedger?.fetched / rpcStats.snarkedRootLedger?.estimation * 100 || 0;
+ let rootStagedProgress = rpcStats.stagedRootLedger?.fetched / rpcStats.stagedRootLedger?.estimation * 100 || 0;
+
+ if (ledgers.stakingEpoch.state === NodesOverviewLedgerStepState.SUCCESS) {
+ stakingProgress = 100;
+ this.updateAction = 'Downloading Next Epoch Ledger';
+ }
+ if (ledgers.nextEpoch.state === NodesOverviewLedgerStepState.SUCCESS) {
+ nextProgress = 100;
+ this.updateAction = 'Downloading Root Snarked Ledger';
+ }
+ if (ledgers.rootSnarked.state === NodesOverviewLedgerStepState.SUCCESS) {
+ rootSnarkedProgress = 100;
+ this.updateAction = 'Downloading Root Staged Ledger';
+ }
+ if (ledgers.rootStaged.state === NodesOverviewLedgerStepState.SUCCESS) {
+ rootStagedProgress = 100;
+ this.updateAction = 'Fetching Blocks';
+ }
+ const ledgerProgressTotal = (stakingProgress + nextProgress + rootSnarkedProgress + rootStagedProgress) / 4;
+ this.ledgerProgress = ledgerProgressTotal * 0.33;
+ if (ledgerProgressTotal !== 100) {
+ this.blockSyncProgress = 0;
+ this.detect();
+ return;
+ }
+
+ let blocks = nodes[0].blocks;
+
+ blocks = blocks.slice(1);
+
+ const fetched = blocks.filter(b => ![NodesOverviewNodeBlockStatus.MISSING, NodesOverviewNodeBlockStatus.FETCHING].includes(b.status)).length;
+ const fetchedPercentage = Math.round(fetched * 100 / 291);
+
+ const applied = blocks.filter(b => b.status === NodesOverviewNodeBlockStatus.APPLIED).length;
+ const appliedPercentage = Math.round(applied * 100 / 291);
+ this.blockSyncProgress = appliedPercentage * 0.34;
+
+ if (fetchedPercentage < 100) {
+ this.updateAction = `Fetching Blocks (${fetchedPercentage}%)`;
+ } else if (appliedPercentage < 100) {
+ this.updateAction = `Applying Blocks (${appliedPercentage}%)`;
+ } else {
+ this.updateAction = '';
+ }
+
+ } else {
+ this.ledgerProgress = 0;
+ this.blockSyncProgress = 0;
+ }
+ this.detect();
+ });
+ }
+
+ override ngOnDestroy(): void {
+ super.ngOnDestroy();
+ }
+
+ // cleanup() {
+ // document.getElementById('mina-content').style.borderTopLeftRadius = '6px';
+ // }
}
diff --git a/frontend/src/app/features/dashboard/dashboard.module.ts b/frontend/src/app/features/dashboard/dashboard.module.ts
index e06adfdf47..ed91563182 100644
--- a/frontend/src/app/features/dashboard/dashboard.module.ts
+++ b/frontend/src/app/features/dashboard/dashboard.module.ts
@@ -9,13 +9,9 @@ import { LoadingSpinnerComponent } from '@shared/loading-spinner/loading-spinner
import { CopyComponent } from '@openmina/shared';
import { DashboardNetworkComponent } from './dashboard-network/dashboard-network.component';
import { DashboardLedgerComponent } from './dashboard-ledger/dashboard-ledger.component';
-import {
- DashboardTransitionFrontierComponent,
-} from './dashboard-transition-frontier/dashboard-transition-frontier.component';
import { DashboardBlocksSyncComponent } from './dashboard-blocks-sync/dashboard-blocks-sync.component';
-import {
- DashboardPeersMinimalTableComponent,
-} from './dashboard-peers-minimal-table/dashboard-peers-minimal-table.component';
+import { DashboardPeersMinimalTableComponent } from './dashboard-peers-minimal-table/dashboard-peers-minimal-table.component';
+import { BlockProductionPillComponent } from '@app/layout/block-production-pill/block-production-pill.component';
@NgModule({
@@ -23,7 +19,6 @@ import {
DashboardComponent,
DashboardNetworkComponent,
DashboardLedgerComponent,
- DashboardTransitionFrontierComponent,
DashboardBlocksSyncComponent,
DashboardPeersMinimalTableComponent,
],
@@ -33,6 +28,7 @@ import {
EffectsModule.forFeature(DashboardEffects),
LoadingSpinnerComponent,
CopyComponent,
+ BlockProductionPillComponent,
],
})
export class DashboardModule {}
diff --git a/frontend/src/app/features/dashboard/dashboard.reducer.ts b/frontend/src/app/features/dashboard/dashboard.reducer.ts
index 7ee9016523..0d9a23b56d 100644
--- a/frontend/src/app/features/dashboard/dashboard.reducer.ts
+++ b/frontend/src/app/features/dashboard/dashboard.reducer.ts
@@ -24,7 +24,8 @@ const initialState: DashboardState = {
peerResponses: [],
stakingLedger: null,
nextLedger: null,
- rootLedger: null,
+ snarkedRootLedger: null,
+ stagedRootLedger: null,
},
nodeBootstrappingPercentage: 0,
appliedBlocks: 0,
diff --git a/frontend/src/app/features/dashboard/dashboard.service.ts b/frontend/src/app/features/dashboard/dashboard.service.ts
index 889502a595..507f5c89c3 100644
--- a/frontend/src/app/features/dashboard/dashboard.service.ts
+++ b/frontend/src/app/features/dashboard/dashboard.service.ts
@@ -52,19 +52,23 @@ export class DashboardService {
);
}
- private mapMessageProgressResponse(response: MessageProgressResponse): DashboardRpcStats {
- const peerResponses = Object.keys(response.messages_stats).map(peerId => ({
+ private mapMessageProgressResponse(progress: MessageProgressResponse): DashboardRpcStats {
+ const peerResponses = Object.keys(progress.messages_stats).map(peerId => ({
peerId,
requestsMade: Object
- .keys(response.messages_stats[peerId].responses)
- .reduce((sum: number, curr: string) => sum + response.messages_stats[peerId].responses[curr], 0),
+ .keys(progress.messages_stats[peerId].responses)
+ .reduce((sum: number, curr: string) => sum + progress.messages_stats[peerId].responses[curr], 0),
} as DashboardPeerRpcResponses));
return {
peerResponses,
- stakingLedger: response.staking_ledger_sync,
- nextLedger: response.next_epoch_ledger_sync,
- rootLedger: response.root_ledger_sync,
+ stakingLedger: progress.staking_ledger_sync,
+ nextLedger: progress.next_epoch_ledger_sync,
+ snarkedRootLedger: progress.root_ledger_sync,
+ stagedRootLedger: {
+ fetched: progress.root_ledger_sync?.staged?.fetched,
+ estimation: progress.root_ledger_sync?.staged?.total,
+ },
};
}
}
@@ -84,7 +88,12 @@ export interface MessageProgressResponse {
messages_stats: MessagesStats;
staking_ledger_sync: Estimation;
next_epoch_ledger_sync: Estimation;
- root_ledger_sync: Estimation;
+ root_ledger_sync: Estimation & {
+ staged: {
+ fetched: number;
+ total: number;
+ }
+ };
}
export interface MessagesStats {
diff --git a/frontend/src/app/features/dashboard/dashboard.state.ts b/frontend/src/app/features/dashboard/dashboard.state.ts
index 5e002c51e7..f84b91456c 100644
--- a/frontend/src/app/features/dashboard/dashboard.state.ts
+++ b/frontend/src/app/features/dashboard/dashboard.state.ts
@@ -3,7 +3,6 @@ import { createFeatureSelector, createSelector, MemoizedSelector } from '@ngrx/s
import { MinaState } from '@app/app.setup';
import { DashboardPeersStats } from '@shared/types/dashboard/dashboard-peers-stats.type';
import { TableSort } from '@openmina/shared';
-import { DashboardPeersSort } from '@dashboard/dashboard.actions';
import { NodesOverviewNode } from '@shared/types/nodes/dashboard/nodes-overview-node.type';
import { DashboardRpcStats } from '@shared/types/dashboard/dashboard-rpc-stats.type';
@@ -33,5 +32,4 @@ export const selectDashboardPeersStats = select((state: DashboardState): Dashboa
export const selectDashboardPeersSort = select((state: DashboardState): TableSort
=> state.peersSort);
export const selectDashboardNodes = select((state: DashboardState): NodesOverviewNode[] => state.nodes);
export const selectDashboardNodesAndPeers = select((state: DashboardState): [NodesOverviewNode[], DashboardPeer[]] => [state.nodes, state.peers]);
-export const selectDashboardRpcStats = select((state: DashboardState): DashboardRpcStats => state.rpcStats);
export const selectDashboardNodesAndRpcStats = select((state: DashboardState): [NodesOverviewNode[], DashboardRpcStats] => [state.nodes, state.rpcStats]);
diff --git a/frontend/src/app/features/dashboard/mina-card/mina-card.component.html b/frontend/src/app/features/dashboard/mina-card/mina-card.component.html
deleted file mode 100644
index a83c6194b1..0000000000
--- a/frontend/src/app/features/dashboard/mina-card/mina-card.component.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
- {{ label }}
- {{ icon }}
-
-{{ value ?? '-' }}
-{{ hint }}
diff --git a/frontend/src/app/features/dashboard/mina-card/mina-card.component.scss b/frontend/src/app/features/dashboard/mina-card/mina-card.component.scss
deleted file mode 100644
index a5a87f8b45..0000000000
--- a/frontend/src/app/features/dashboard/mina-card/mina-card.component.scss
+++ /dev/null
@@ -1,18 +0,0 @@
-:host {
- height: 128px;
- width: 128px;
-
- @media (max-width: 700px) {
- height: 140px;
- width: 140px;
- }
-}
-
-.mina-icon {
- margin-left: 3px;
-}
-
-.value {
- font-size: 24px;
- letter-spacing: 0.15px;
-}
diff --git a/frontend/src/app/features/dashboard/mina-card/mina-card.component.ts b/frontend/src/app/features/dashboard/mina-card/mina-card.component.ts
deleted file mode 100644
index 9681cbd29a..0000000000
--- a/frontend/src/app/features/dashboard/mina-card/mina-card.component.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
-
-@Component({
- selector: 'mina-card',
- templateUrl: './mina-card.component.html',
- styleUrls: ['./mina-card.component.scss'],
- changeDetection: ChangeDetectionStrategy.OnPush,
- host: { class: 'flex-column flex-between pt-8 pb-8 pl-12 border-rad-8 bg-surface' },
-})
-export class MinaCardComponent {
-
- @Input() color: string = 'var(--base-primary)';
- @Input() labelColor: string = 'var(--base-primary)';
- @Input() hintColor: string = 'var(--base-tertiary)';
- @Input() icon: string;
- @Input() label: string | number;
- @Input() value: string | number;
- @Input() hint: string | number;
- @Input() tooltipText: string;
-
-}
diff --git a/frontend/src/app/features/mempool/mempool.service.ts b/frontend/src/app/features/mempool/mempool.service.ts
index 649d0ff0c1..94f302a8fb 100644
--- a/frontend/src/app/features/mempool/mempool.service.ts
+++ b/frontend/src/app/features/mempool/mempool.service.ts
@@ -8,7 +8,7 @@ import {
ZkappCommand,
} from '@shared/types/mempool/mempool-transaction.type';
import { decodeMemo, removeUnicodeEscapes } from '@shared/helpers/transaction.helper';
-import { ONE_BILLION } from '@openmina/shared';
+import { getLocalStorage, ONE_BILLION } from '@openmina/shared';
@Injectable({
providedIn: 'root',
@@ -31,7 +31,7 @@ export class MempoolService {
const memo = decodeMemo(tx.data[1].payload.common.memo);
return {
kind: MempoolTransactionKind.PAYMENT,
- txHash: tx.hash.join(''),
+ txHash: tx.hash,
sender: tx.data[1].payload.common.fee_payer_pk,
fee: Number(tx.data[1].payload.common.fee),
amount: Number(tx.data[1].payload.body[1].amount) / ONE_BILLION,
@@ -39,14 +39,14 @@ export class MempoolService {
memo: removeUnicodeEscapes(memo),
transactionData: tx.data[1],
sentFromStressingTool: memo.includes('S.T.'),
- sentByMyBrowser: memo.includes(localStorage.getItem('browserId')),
+ sentByMyBrowser: memo.includes(getLocalStorage()?.getItem('browserId')),
} as MempoolTransaction;
case MempoolTransactionResponseKind.ZkappCommand:
const zkapp = tx.data[1] as ZkappCommand;
const zkMemo = decodeMemo(zkapp.memo);
return {
kind: MempoolTransactionKind.ZK_APP,
- txHash: tx.hash.join(''),
+ txHash: tx.hash,
sender: zkapp.fee_payer.body.public_key,
fee: Number(zkapp.fee_payer.body.fee),
amount: null,
@@ -54,7 +54,7 @@ export class MempoolService {
memo: removeUnicodeEscapes(zkMemo),
transactionData: tx.data[1],
sentFromStressingTool: zkMemo.includes('S.T.'),
- sentByMyBrowser: zkMemo.includes(localStorage.getItem('browserId')),
+ sentByMyBrowser: zkMemo.includes(getLocalStorage()?.getItem('browserId')),
} as MempoolTransaction;
}
});
@@ -64,7 +64,7 @@ export class MempoolService {
export interface MempoolTransactionResponse {
data: [MempoolTransactionResponseKind, SignedCommand | ZkappCommand];
- hash: number[];
+ hash: string;
}
export enum MempoolTransactionResponseKind {
diff --git a/frontend/src/app/features/network/messages/network-messages-side-panel/network-messages-side-panel.component.ts b/frontend/src/app/features/network/messages/network-messages-side-panel/network-messages-side-panel.component.ts
index a8e044d207..5b90dbc1b3 100644
--- a/frontend/src/app/features/network/messages/network-messages-side-panel/network-messages-side-panel.component.ts
+++ b/frontend/src/app/features/network/messages/network-messages-side-panel/network-messages-side-panel.component.ts
@@ -8,7 +8,7 @@ import {
selectNetworkFullMessage,
selectNetworkMessageHex,
} from '@network/messages/network-messages.state';
-import { downloadJson, downloadJsonFromURL, ExpandTracking, MinaJsonViewerComponent } from '@openmina/shared';
+import { downloadJson, downloadJsonFromURL, ExpandTracking, MinaJsonViewerComponent, safelyExecuteInBrowser } from '@openmina/shared';
import { filter } from 'rxjs';
import { Router } from '@angular/router';
import { Routes } from '@shared/enums/routes.enum';
@@ -154,6 +154,8 @@ export class NetworkMessagesSidePanelComponent extends StoreDispatcher implement
}
copyToClipboard(): void {
- this.clipboard.copy(window.location.href);
+ safelyExecuteInBrowser(() => {
+ this.clipboard.copy(window.location.href);
+ });
}
}
diff --git a/frontend/src/app/features/network/splits/dashboard-splits-graph/dashboard-splits-graph.component.ts b/frontend/src/app/features/network/splits/dashboard-splits-graph/dashboard-splits-graph.component.ts
index 755b73c63e..1f290c00dc 100644
--- a/frontend/src/app/features/network/splits/dashboard-splits-graph/dashboard-splits-graph.component.ts
+++ b/frontend/src/app/features/network/splits/dashboard-splits-graph/dashboard-splits-graph.component.ts
@@ -16,6 +16,7 @@ import { DashboardSplitsSet } from '@shared/types/network/splits/dashboard-split
import { DashboardSplitsSetActivePeer } from '@network/splits/dashboard-splits.actions';
import { eigs } from 'mathjs';
import * as math from 'mathjs';
+import { getLocalStorage } from '@openmina/shared';
type DashboardSplitsPeerSimulation = DashboardSplitsPeer & SimulationNodeDatum;
type DashboardSplitsLinkSimulation = {
@@ -128,7 +129,7 @@ export class DashboardSplitsGraphComponent extends StoreDispatcher implements On
console.log('Laplacian Matrix:', laplacianMatrix);
// check is same as localstorage
- let item = localStorage.getItem('laplacianMatrix');
+ let item = getLocalStorage()?.getItem('laplacianMatrix');
if (item) {
let storedMatrix = JSON.parse(item);
let storedMatrixString = JSON.stringify(storedMatrix);
@@ -139,7 +140,7 @@ export class DashboardSplitsGraphComponent extends StoreDispatcher implements On
console.log('Laplacian Matrix is different from the stored one');
}
}
- localStorage.setItem('laplacianMatrix', JSON.stringify(laplacianMatrix));
+ getLocalStorage()?.setItem('laplacianMatrix', JSON.stringify(laplacianMatrix));
const computeEigenvalues = async (matrix: number[][]): Promise => {
return eigs(matrix).values as number[];
diff --git a/frontend/src/app/features/nodes/overview/nodes-overview-table/nodes-overview-table.component.scss b/frontend/src/app/features/nodes/overview/nodes-overview-table/nodes-overview-table.component.scss
index 60c7f13cc0..d747628141 100644
--- a/frontend/src/app/features/nodes/overview/nodes-overview-table/nodes-overview-table.component.scss
+++ b/frontend/src/app/features/nodes/overview/nodes-overview-table/nodes-overview-table.component.scss
@@ -8,7 +8,7 @@
border-bottom: 1px solid $base-tertiary;
&:last-child {
- min-width: 600px;
+ min-width: 510px;
}
}
}
diff --git a/frontend/src/app/features/nodes/overview/nodes-overview-table/nodes-overview-table.component.ts b/frontend/src/app/features/nodes/overview/nodes-overview-table/nodes-overview-table.component.ts
index efc1983514..d720f69351 100644
--- a/frontend/src/app/features/nodes/overview/nodes-overview-table/nodes-overview-table.component.ts
+++ b/frontend/src/app/features/nodes/overview/nodes-overview-table/nodes-overview-table.component.ts
@@ -37,11 +37,6 @@ export class NodesOverviewTableComponent extends MinaTableRustWrapper implements OnDestroy {
activeResource: MemoryResource;
- tooltipWidth: number = Math.max(window.innerWidth - 40, 1500);
+ tooltipWidth: number = isBrowser() ? Math.max(window.innerWidth - 40, 1500) : 0;
position: TooltipPosition = TooltipPosition.RIGHT;
protected readonly tableHeads: TableColumnList = [
diff --git a/frontend/src/app/features/resources/memory/memory-resources-treemap/memory-resources-treemap.component.ts b/frontend/src/app/features/resources/memory/memory-resources-treemap/memory-resources-treemap.component.ts
index 6cf4e6ef52..538d5f0777 100644
--- a/frontend/src/app/features/resources/memory/memory-resources-treemap/memory-resources-treemap.component.ts
+++ b/frontend/src/app/features/resources/memory/memory-resources-treemap/memory-resources-treemap.component.ts
@@ -32,7 +32,7 @@ import { ResourcesSizePipe } from '@resources/memory/memory-resources.pipe';
import { MemoryResourcesSetActiveResource } from '@resources/memory/memory-resources.actions';
import { untilDestroyed } from '@ngneat/until-destroy';
import { TreemapView } from '@shared/types/resources/memory/treemap-view.type';
-import { isDesktop, TooltipService } from '@openmina/shared';
+import { isDesktop, safelyExecuteInBrowser, TooltipService } from '@openmina/shared';
import { AppSelectors } from '@app/app.state';
@Component({
@@ -83,9 +83,11 @@ export class MemoryResourcesTreemapComponent extends StoreDispatcher implements
private listenToResizeEvent(): void {
this.ngZone.runOutsideAngular(() => {
- fromEvent(window, 'resize')
- .pipe(untilDestroyed(this), debounceTime(200))
- .subscribe(() => this.redrawChart());
+ safelyExecuteInBrowser(() =>
+ fromEvent(window, 'resize')
+ .pipe(untilDestroyed(this), debounceTime(200))
+ .subscribe(() => this.redrawChart()),
+ );
this.select(
AppSelectors.menu,
() => this.redrawChart(),
@@ -358,7 +360,10 @@ export class MemoryResourcesTreemapComponent extends StoreDispatcher implements
const x = event.clientX - tooltipWidth / 2 + xMargin;
const y = event.clientY + yMargin;
- const maxX = window.innerWidth - tooltipWidth - xMargin;
+ let maxX = 0;
+ safelyExecuteInBrowser(() => {
+ maxX = window.innerWidth - tooltipWidth - xMargin;
+ });
if (x > maxX) {
this.tooltip.style.left = maxX + 'px';
} else {
diff --git a/frontend/src/app/features/resources/memory/memory-resources.reducer.ts b/frontend/src/app/features/resources/memory/memory-resources.reducer.ts
index 9d4978bbcb..df61e6ff4e 100644
--- a/frontend/src/app/features/resources/memory/memory-resources.reducer.ts
+++ b/frontend/src/app/features/resources/memory/memory-resources.reducer.ts
@@ -8,13 +8,14 @@ import {
MemoryResourcesActions,
} from '@resources/memory/memory-resources.actions';
import { TreemapView } from '@shared/types/resources/memory/treemap-view.type';
+import { getLocalStorage, nanOrElse } from '@openmina/shared';
const initialState: MemoryResourcesState = {
resource: undefined,
activeResource: undefined,
breadcrumbs: [],
- granularity: Number(localStorage.getItem('memory-granularity')) || 512,
- treemapView: localStorage.getItem('memory-view') as TreemapView || TreemapView.BINARY,
+ granularity: nanOrElse(Number(getLocalStorage()?.getItem('memory-granularity')), 512),
+ treemapView: getLocalStorage()?.getItem('memory-view') as TreemapView || TreemapView.BINARY,
};
export function memoryResourcesReducer(state: MemoryResourcesState = initialState, action: MemoryResourcesActions): MemoryResourcesState {
@@ -51,7 +52,7 @@ export function memoryResourcesReducer(state: MemoryResourcesState = initialStat
}
case MEMORY_RESOURCES_SET_GRANULARITY: {
- localStorage.setItem('memory-granularity', String(action.payload));
+ getLocalStorage()?.setItem('memory-granularity', String(action.payload));
return {
...state,
granularity: action.payload,
@@ -62,7 +63,7 @@ export function memoryResourcesReducer(state: MemoryResourcesState = initialStat
}
case MEMORY_RESOURCES_SET_TREEMAP_VIEW: {
- localStorage.setItem('memory-view', String(action.payload));
+ getLocalStorage()?.setItem('memory-view', String(action.payload));
return {
...state,
treemapView: action.payload,
diff --git a/frontend/src/app/features/snarks/scan-state/scan-state-side-panel/scan-state-side-panel.component.ts b/frontend/src/app/features/snarks/scan-state/scan-state-side-panel/scan-state-side-panel.component.ts
index 68ca64921b..da9442c169 100644
--- a/frontend/src/app/features/snarks/scan-state/scan-state-side-panel/scan-state-side-panel.component.ts
+++ b/frontend/src/app/features/snarks/scan-state/scan-state-side-panel/scan-state-side-panel.component.ts
@@ -11,6 +11,7 @@ import { TemplatePortal } from '@angular/cdk/portal';
import { ScanStateLeaf } from '@shared/types/snarks/scan-state/scan-state-leaf.type';
import { AppSelectors } from '@app/app.state';
import { getFeaturesConfig } from '@shared/constants/config';
+import { getWindow } from '@openmina/shared';
@Component({
selector: 'mina-scan-state-side-panel',
@@ -124,8 +125,8 @@ export class ScanStateSidePanelComponent extends StoreDispatcher implements OnIn
goToWorkPool(): void {
const queryParams = this.router.parseUrl(this.router.url).queryParams;
- let url = `${window.location.origin}/${Routes.SNARKS}/${Routes.WORK_POOL}/${this.activeLeaf.bundle_job_id}`;
+ let url = `${getWindow()?.location.origin}/${Routes.SNARKS}/${Routes.WORK_POOL}/${this.activeLeaf.bundle_job_id}`;
url += `?node=${queryParams['node']}`;
- window.open(url, '_blank');
+ getWindow()?.open(url, '_blank');
}
}
diff --git a/frontend/src/app/features/snarks/scan-state/scan-state-tree-chart/scan-state-tree-chart.component.ts b/frontend/src/app/features/snarks/scan-state/scan-state-tree-chart/scan-state-tree-chart.component.ts
index 3ef320c3cc..61b9bfe01b 100644
--- a/frontend/src/app/features/snarks/scan-state/scan-state-tree-chart/scan-state-tree-chart.component.ts
+++ b/frontend/src/app/features/snarks/scan-state/scan-state-tree-chart/scan-state-tree-chart.component.ts
@@ -4,7 +4,7 @@ import { ScanStateTree } from '@shared/types/snarks/scan-state/scan-state-tree.t
import { ScanStateLeaf, ScanStateLeafStatus } from '@shared/types/snarks/scan-state/scan-state-leaf.type';
import { debounceTime, delay, distinctUntilChanged, filter, fromEvent, skip, tap } from 'rxjs';
import { untilDestroyed } from '@ngneat/until-destroy';
-import { any, hasValue, isMobile } from '@openmina/shared';
+import { any, hasValue, isMobile, safelyExecuteInBrowser } from '@openmina/shared';
import { StoreDispatcher } from '@shared/base-classes/store-dispatcher.class';
import { ScanStateSetActiveLeaf } from '@snarks/scan-state/scan-state.actions';
import { Router } from '@angular/router';
@@ -110,9 +110,11 @@ export class ScanStateTreeChartComponent extends StoreDispatcher implements OnIn
}
private handleResizing(): void {
- fromEvent(window, 'resize')
- .pipe(untilDestroyed(this), debounceTime(200))
- .subscribe(() => this.redrawChart());
+ safelyExecuteInBrowser(() => {
+ fromEvent(window, 'resize')
+ .pipe(untilDestroyed(this), debounceTime(200))
+ .subscribe(() => this.redrawChart());
+ });
this.select(selectScanStateSideBarResized, () => this.redrawChart(), filter(Boolean));
this.select(selectScanStateOpenSidePanel, () => this.redrawChart(), delay(400), skip(1));
this.select(AppSelectors.menu, () => this.redrawChart(),
@@ -372,9 +374,11 @@ export class ScanStateTreeChartComponent extends StoreDispatcher implements OnIn
const chartLeft = this.chartContainer.nativeElement.getBoundingClientRect().left;
let desiredLeft = Math.min(nodeRect.left + nodeRect.width / 2 - tooltipWidth / 2, chartLeft + this.width - tooltipWidth);
desiredLeft = Math.max(desiredLeft, chartLeft);
- selection
- .style('left', `${desiredLeft}px`)
- .style('top', `${nodeRect.bottom + window.scrollY + 12}px`);
+ safelyExecuteInBrowser(() => {
+ selection
+ .style('left', `${desiredLeft}px`)
+ .style('top', `${nodeRect.bottom + window.scrollY + 12}px`);
+ });
}
private mouseOutHandler(event: MouseEvent & { target: HTMLElement }, d: any): void {
diff --git a/frontend/src/app/features/snarks/scan-state/scan-state.reducer.ts b/frontend/src/app/features/snarks/scan-state/scan-state.reducer.ts
index d78d12936c..1c7832a573 100644
--- a/frontend/src/app/features/snarks/scan-state/scan-state.reducer.ts
+++ b/frontend/src/app/features/snarks/scan-state/scan-state.reducer.ts
@@ -10,9 +10,9 @@ import {
SCAN_STATE_START,
SCAN_STATE_TOGGLE_SIDE_PANEL,
SCAN_STATE_TOGGLE_TREE_VIEW,
- ScanStateActions
+ ScanStateActions,
} from '@snarks/scan-state/scan-state.actions';
-import { isDesktop } from '@openmina/shared';
+import { getLocalStorage, isDesktop } from '@openmina/shared';
const initialState: ScanStateState = {
block: undefined,
@@ -21,7 +21,7 @@ const initialState: ScanStateState = {
openSidePanel: isDesktop(),
sideBarResized: 0,
stream: true,
- treeView: JSON.parse(localStorage.getItem('scan_state_tree_view')) || false,
+ treeView: JSON.parse(getLocalStorage()?.getItem('scan_state_tree_view') ?? 'false') || false,
highlightSnarkPool: true,
};
@@ -90,7 +90,7 @@ export function reducer(state: ScanStateState = initialState, action: ScanStateA
}
case SCAN_STATE_TOGGLE_TREE_VIEW: {
- localStorage.setItem('scan_state_tree_view', JSON.stringify(!state.treeView));
+ getLocalStorage()?.setItem('scan_state_tree_view', JSON.stringify(!state.treeView));
return {
...state,
diff --git a/frontend/src/app/features/snarks/work-pool/snarks-work-pool-side-panel/snarks-work-pool-side-panel.component.ts b/frontend/src/app/features/snarks/work-pool/snarks-work-pool-side-panel/snarks-work-pool-side-panel.component.ts
index cc2a04989a..3bc9a53d3c 100644
--- a/frontend/src/app/features/snarks/work-pool/snarks-work-pool-side-panel/snarks-work-pool-side-panel.component.ts
+++ b/frontend/src/app/features/snarks/work-pool/snarks-work-pool-side-panel/snarks-work-pool-side-panel.component.ts
@@ -7,6 +7,7 @@ import { Router } from '@angular/router';
import { Routes } from '@shared/enums/routes.enum';
import { Overlay, OverlayRef } from '@angular/cdk/overlay';
import { TemplatePortal } from '@angular/cdk/portal';
+import { getWindow } from '@openmina/shared';
@Component({
selector: 'mina-snarks-work-pool-side-panel',
@@ -89,9 +90,9 @@ export class SnarksWorkPoolSidePanelComponent extends StoreDispatcher implements
goToScanState(): void {
const queryParams = this.router.parseUrl(this.router.url).queryParams;
const jobId = this.router.url.split('/').pop().split('?')[0];
- let url = `${window.location.origin}/${Routes.SNARKS}/${Routes.SCAN_STATE}`;
+ let url = `${getWindow()?.location.origin}/${Routes.SNARKS}/${Routes.SCAN_STATE}`;
url += `?node=${queryParams['node']}`;
url += `&jobId=${jobId}`;
- window.open(url, '_blank');
+ getWindow()?.open(url, '_blank');
}
}
diff --git a/frontend/src/app/features/webnode/web-node-initialization/web-node-initialization.component.html b/frontend/src/app/features/webnode/web-node-initialization/web-node-initialization.component.html
new file mode 100644
index 0000000000..5fac9c6f20
--- /dev/null
+++ b/frontend/src/app/features/webnode/web-node-initialization/web-node-initialization.component.html
@@ -0,0 +1,52 @@
+
+
+
+
+
+ Produce blocks,
+ right in your browser
+
+
+
{{ loadingMessage || downloadingMessage }}
+
+
+
+
+
+
+ @for (item of loading; track $index) {
+
+ @if (item.status === WebNodeStepStatus.LOADING) {
+
+ } @else if (item.status === WebNodeStepStatus.PENDING) {
+
panorama_fish_eye
+ } @else {
+
check_circle
+ }
+
{{ item.name }}
+
+
+ }
+
+
+
+
+
diff --git a/frontend/src/app/features/webnode/web-node-initialization/web-node-initialization.component.scss b/frontend/src/app/features/webnode/web-node-initialization/web-node-initialization.component.scss
new file mode 100644
index 0000000000..d81a6a14e8
--- /dev/null
+++ b/frontend/src/app/features/webnode/web-node-initialization/web-node-initialization.component.scss
@@ -0,0 +1,102 @@
+@import 'openmina';
+
+$green: #59bfb5;
+$light-peach: #0d0d0d;
+$peach: #acdea0;
+$sand: #5bb3fb;
+$white: #000000;
+
+.font-16 {
+ font-size: 16px;
+}
+
+.logo-header {
+ height: 56px;
+
+ img {
+ opacity: 0.5;
+ }
+}
+
+.data-wrapper {
+ height: calc(100% - 56px - 72px);
+
+ .loading-content {
+ max-width: 568px;
+
+ .header {
+ .loading-webnode {
+ font-size: 20px;
+ line-height: 30px;
+ }
+ }
+
+ mina-loading-spinner {
+ margin: 0 2px;
+ }
+
+ .mina-icon.circle-check {
+ font-variation-settings: 'FILL' 1, 'wght' 300 !important;
+ }
+
+ .mina-icon.aware-primary {
+ animation: fadeIn 1500ms ease-in-out infinite;
+ }
+
+ .progress {
+ min-height: 256px;
+ @media (max-width: 768px) {
+ min-height: 30vh;
+ }
+ }
+ }
+}
+
+.footer {
+ height: 72px;
+ max-width: 568px;
+
+ button {
+ width: 158px;
+ height: 48px !important;
+ background-color: $base-background;
+ color: $base-primary;
+ filter: invert(1);
+
+ &.disabled {
+ opacity: 0.25;
+ pointer-events: none;
+ }
+ }
+
+ @media (max-width: 768px) {
+ border: none !important;
+ > div {
+ display: none;
+ }
+ button {
+ width: 100%;
+ }
+ }
+}
+
+@keyframes fadeIn {
+ 10% {
+ opacity: 1;
+ }
+ 38% {
+ opacity: 0.1;
+ }
+ 42% {
+ opacity: 0.1;
+ }
+ 70% {
+ opacity: 1;
+ }
+}
+
+@media (max-width: 568px) {
+ .loading-webnode span {
+ display: block;
+ }
+}
diff --git a/frontend/src/app/features/webnode/web-node-initialization/web-node-initialization.component.ts b/frontend/src/app/features/webnode/web-node-initialization/web-node-initialization.component.ts
new file mode 100644
index 0000000000..2c563d5c13
--- /dev/null
+++ b/frontend/src/app/features/webnode/web-node-initialization/web-node-initialization.component.ts
@@ -0,0 +1,366 @@
+import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
+import { untilDestroyed } from '@ngneat/until-destroy';
+import { StoreDispatcher } from '@shared/base-classes/store-dispatcher.class';
+import { WebNodeService } from '@core/services/web-node.service';
+import { any, GlobalErrorHandlerService, safelyExecuteInBrowser } from '@openmina/shared';
+import { NgClass, NgForOf, NgIf, NgOptimizedImage } from '@angular/common';
+import { Router } from '@angular/router';
+import { CONFIG, getFirstFeature } from '@shared/constants/config';
+import { animate, style, transition, trigger } from '@angular/animations';
+import { filter, switchMap, timer } from 'rxjs';
+import { LoadingSpinnerComponent } from '@shared/loading-spinner/loading-spinner.component';
+import { FileProgressHelper } from '@core/helpers/file-progress.helper';
+import * as d3 from 'd3';
+
+export enum WebNodeStepStatus {
+ DONE,
+ LOADING,
+ PENDING,
+}
+
+export interface WebNodeLoadingStep {
+ name: string;
+ loaded: boolean;
+ status: WebNodeStepStatus;
+}
+
+@Component({
+ selector: 'mina-web-node-initialization',
+ templateUrl: './web-node-initialization.component.html',
+ styleUrls: ['./web-node-initialization.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ host: { class: 'flex-column h-100 w-100 align-center' },
+ standalone: true,
+ imports: [
+ NgClass,
+ NgIf,
+ NgForOf,
+ NgOptimizedImage,
+ LoadingSpinnerComponent,
+ ],
+ animations: [
+ trigger('messageChange', [
+ transition('* => *', [
+ style({ opacity: 0, transform: 'translateY(-10px)' }),
+ animate('300ms ease-out', style({ opacity: 1, transform: 'translateY(0)' })),
+ ]),
+ ]),
+ ],
+})
+export class WebNodeInitializationComponent extends StoreDispatcher implements OnInit, AfterViewInit {
+
+ protected readonly WebNodeStepStatus = WebNodeStepStatus;
+ readonly loading: WebNodeLoadingStep[] = [
+ { name: 'Setting up browser for Web Node', loaded: false, status: WebNodeStepStatus.LOADING },
+ { name: 'Getting ready to produce blocks', loaded: false, status: WebNodeStepStatus.PENDING },
+ { name: 'Connecting directly to Mina network', loaded: false, status: WebNodeStepStatus.PENDING },
+ ];
+ loadingMessage: string = '';
+ downloadingMessage: string = '';
+ ready: boolean = false;
+ hasError: boolean = false;
+ hasWarn: boolean = false;
+ errors: string[] = [];
+
+ private stepsPercentages: number[];
+ private secondStepInterval: any;
+ private thirdStepInterval: any;
+ private progress: number = 0;
+ private svg: any;
+ private progressBar: any;
+ private arc: any;
+ @ViewChild('progress', { static: true }) private chartContainer: ElementRef;
+
+ constructor(private errorHandler: GlobalErrorHandlerService,
+ private webNodeService: WebNodeService,
+ private router: Router) { super(); }
+
+ ngOnInit(): void {
+ if (!this.webNodeService.hasWebNodeConfig()) {
+ this.router.navigate([getFirstFeature()]);
+ return;
+ }
+ safelyExecuteInBrowser(() => {
+ window.dispatchEvent(new CustomEvent('startWebNode'));
+ });
+ this.stepsPercentages = this.getStepPercentages();
+ if (this.webNodeService.isWebNodeLoaded()) {
+ this.loading.forEach((step: WebNodeLoadingStep) => {
+ step.loaded = true;
+ step.status = WebNodeStepStatus.DONE;
+ });
+ this.ready = true;
+ return;
+ }
+ this.fetchProgress();
+ this.listenToErrorIssuing();
+ this.checkWebNodeProgress();
+ this.fetchPeersInformation();
+ }
+
+ ngAfterViewInit(): void {
+ this.buildProgressBar();
+ }
+
+ private checkWebNodeProgress(): void {
+ this.webNodeService.webnodeProgress$.pipe(untilDestroyed(this)).subscribe((state: string) => {
+ if (state === 'Loaded') {
+ this.updateLoadingMessage('~5 seconds left');
+ setTimeout(() => {
+ if (!this.hasError && this.loading[1].status !== WebNodeStepStatus.DONE) {
+ this.updateLoadingMessage('Slower than usual');
+ this.hasWarn = true;
+ this.detect();
+ }
+ }, 5000);
+ this.loading[0].loaded = true;
+ this.loading[0].status = WebNodeStepStatus.DONE;
+ this.loading[1].status = WebNodeStepStatus.LOADING;
+ this.advanceProgressFor2ndStep();
+ } else if (state === 'Started') {
+ this.updateLoadingMessage('~3 seconds left');
+ setTimeout(() => {
+ if (!this.hasError && this.loading[2].status !== WebNodeStepStatus.DONE) {
+ this.updateLoadingMessage('Slower than usual');
+ this.hasWarn = true;
+ this.detect();
+ }
+ }, 3500);
+ clearInterval(this.secondStepInterval);
+ this.loading[0].loaded = true;
+ this.loading[1].loaded = true;
+ this.loading[0].status = WebNodeStepStatus.DONE;
+ this.loading[1].status = WebNodeStepStatus.DONE;
+ this.loading[2].status = WebNodeStepStatus.LOADING;
+ this.advanceProgressFor3rdStep();
+ } else if (state === 'Connected') {
+ this.updateLoadingMessage('Web Node is ready');
+ clearInterval(this.thirdStepInterval);
+ this.loading[0].status = WebNodeStepStatus.DONE;
+ this.loading[1].status = WebNodeStepStatus.DONE;
+ this.loading[2].status = WebNodeStepStatus.DONE;
+ this.loading.forEach((step: WebNodeLoadingStep) => step.loaded = true);
+ this.goToEndProgress();
+ }
+ this.detect();
+ });
+ }
+
+ private getStepPercentages(): number[] {
+ // random between 65 and 80
+ const first = Math.floor(Math.random() * 15) + 65;
+ // random between 15 and 17
+ const second = Math.floor(Math.random() * 2) + 15;
+ const third = 100 - first - second;
+ return [first, second, third];
+ }
+
+ private advanceProgressFor2ndStep(): void {
+ // first step is done, now we are working on the second step.
+ // each second add 1% to the progress.
+ // but the second step is only 10% of the total progress.
+ // so never go above 10%. Stop at 9% if the second step is not done yet.
+ let progress = 0;
+ this.secondStepInterval = setInterval(() => {
+ if (progress < this.stepsPercentages[1] - 1) {
+ progress += 0.125;
+ this.updateProgressBar(this.stepsPercentages[0] + progress);
+ }
+ }, 75);
+ }
+
+ private async advanceProgressFor3rdStep(): Promise {
+ // second step is done, now we are working on the third step.
+ // each second add 1% to the progress.
+ // but the third step is only 10% of the total progress.
+ // so never go above 10%. Stop at 9% if the third step is not done yet.
+
+ const currentProgress = this.progress;
+ const targetProgress = this.stepsPercentages[0] + this.stepsPercentages[1] - 1;
+ // run fast 5 increments to reach the target progress
+ const diff = targetProgress - currentProgress;
+
+ for (let i = 0; i < diff; i++) {
+ await new Promise(resolve => setTimeout(resolve, 25));
+ this.updateProgressBar(currentProgress + i);
+ this.detect();
+ }
+
+ let progress = 0;
+ this.thirdStepInterval = setInterval(() => {
+ if (progress < this.stepsPercentages[2] - 1) {
+ progress += 0.125;
+ this.updateProgressBar(this.stepsPercentages[0] + this.stepsPercentages[1] + progress);
+ }
+ }, 75);
+ }
+
+ private goToEndProgress(): void {
+ // increase it to 100% to make sure it's done.
+ // make it smooth, do a lot of increases from where it left
+ // to make it look like it's finishing.
+
+ let progress = this.progress;
+ let interval = setInterval(() => {
+ if (progress <= 100) {
+ progress += 1;
+ this.updateProgressBar(progress);
+ } else {
+ clearInterval(interval);
+ }
+ }, 30);
+ setTimeout(() => this.detect(), 500);
+ }
+
+ private fetchPeersInformation(): void {
+ timer(0, 1000).pipe(
+ switchMap(() => this.webNodeService.peers$),
+ untilDestroyed(this),
+ ).subscribe();
+ }
+
+ private updateLoadingMessage(message: string): void {
+ if (this.hasError || this.hasWarn) {
+ return;
+ }
+ this.loadingMessage = message;
+ }
+
+ private listenToErrorIssuing(): void {
+ this.errorHandler.errors$
+ .pipe(filter(errors => !!errors.length), untilDestroyed(this))
+ .subscribe((error: string) => {
+ this.errors.push(error);
+ this.loadingMessage = error;
+ this.hasError = true;
+ this.markErrorOnD3();
+
+ this.detect();
+ });
+ }
+
+ private fetchProgress(): void {
+ FileProgressHelper.progress$.pipe(
+ filter(Boolean),
+ untilDestroyed(this),
+ ).subscribe((progress) => {
+ this.downloadingMessage = `Downloading ${(progress.downloaded / 1e6).toFixed(1)} of ${(progress.totalSize / 1e6).toFixed(1)} MB`;
+ if (this.svg) {
+ const totalProgress = (progress.progress * this.stepsPercentages[0]) / 100;
+ this.updateProgressBar(totalProgress);
+ }
+ this.detect();
+ });
+ }
+
+ goToDashboard(): void {
+ if (!this.ready) {
+ return;
+ }
+ this.router.navigate([getFirstFeature()]);
+ }
+
+ private buildProgressBar(): void {
+ const width = this.chartContainer.nativeElement.offsetWidth;
+ const height = this.chartContainer.nativeElement.offsetHeight;
+ const barWidth = 4;
+ const progress = 0;
+
+ this.svg = d3
+ .select(this.chartContainer.nativeElement)
+ .append('svg')
+ .attr('width', width)
+ .attr('height', height);
+
+ this.progressBar = this.svg.append('g')
+ .attr('transform', `translate(${width / 2}, ${height / 2})`);
+
+ const radius = Math.min(width, height) / 2 - barWidth;
+
+ this.progressBar.append('circle')
+ .attr('r', radius)
+ .attr('fill', 'none')
+ .attr('stroke', 'var(--base-tertiary2)')
+ .attr('stroke-width', 1);
+
+ this.arc = d3.arc()
+ .innerRadius(radius - barWidth)
+ .outerRadius(radius)
+ .startAngle(0)
+ .endAngle(Math.PI * 2 * (progress / 100));
+
+ this.progressBar.append('path')
+ .attr('d', this.arc)
+ .attr('opacity', 0.8)
+ .attr('fill', 'url(#progress-gradient)');
+
+ const defs = this.svg.append('defs');
+ const gradient = defs.append('linearGradient')
+ .attr('id', 'progress-gradient')
+ .attr('x1', '0%')
+ .attr('x2', '75%')
+ .attr('y1', '25%')
+ .attr('y2', '0%');
+
+ gradient.append('stop')
+ .attr('offset', '8%')
+ .attr('stop-color', '#57d7ff');
+ gradient.append('stop')
+ .attr('offset', '60%')
+ .attr('stop-color', '#fda2ff');
+ gradient.append('stop')
+ .attr('offset', '100%')
+ .attr('stop-color', '#ff833d');
+
+ this.progressBar.append('text')
+ .attr('text-anchor', 'middle')
+ .attr('alignment-baseline', 'central')
+ .attr('dominant-baseline', 'central')
+ .attr('font-size', '40px')
+ .attr('fill', 'var(--base-primary)')
+ .attr('opacity', 0.8)
+ .attr('dx', '-.2em')
+ .text((progress).toFixed(0));
+ this.progressBar.append('text')
+ .attr('class', 'symbol')
+ .attr('text-anchor', 'middle')
+ .attr('alignment-baseline', 'central')
+ .attr('dominant-baseline', 'central')
+ .attr('font-size', '20px')
+ .attr('fill', 'var(--base-tertiary)')
+ .attr('opacity', 0.8)
+ .attr('dy', '-.3em')
+ .attr('dx', '1.5em')
+ .text('%');
+ }
+
+ private updateProgressBar(newProgress: number): void {
+ if (newProgress >= 100) {
+ this.ready = true;
+ newProgress = 100;
+ this.detect();
+ setTimeout(() => this.detect(), 500);
+ }
+ this.progress = newProgress;
+ this.arc.endAngle(Math.PI * 2 * (newProgress / 100));
+ this.progressBar
+ .select('path')
+ .attr('d', this.arc);
+ this.progressBar
+ .select('text')
+ .text((newProgress).toFixed(0));
+ const numberOfDigits = newProgress.toFixed(0).length + 1;
+ this.progressBar.select('.symbol')
+ .attr('dx', `${numberOfDigits * 0.45}em`)
+ .text('%');
+ }
+
+ private markErrorOnD3(): void {
+ this.progressBar.select('path').attr('fill', 'var(--warn-primary)');
+ this.progressBar.select('text').attr('fill', 'var(--warn-primary)');
+ this.progressBar.select('.symbol').attr('fill', 'var(--warn-primary)');
+ this.progressBar.select('path').attr('opacity', 0.4);
+ this.progressBar.select('text').attr('opacity', 0.8);
+ this.progressBar.select('.symbol').attr('opacity', 0.4);
+ }
+}
diff --git a/frontend/src/app/features/webnode/web-node-not-supported/web-node-not-supported.component.html b/frontend/src/app/features/webnode/web-node-not-supported/web-node-not-supported.component.html
new file mode 100644
index 0000000000..ef3d9e3b80
--- /dev/null
+++ b/frontend/src/app/features/webnode/web-node-not-supported/web-node-not-supported.component.html
@@ -0,0 +1,50 @@
+
+@if (isPhone) {
+
+
iOS
+
+
Your iOS {{ iOSVersion ?? '' }} isn't supported
+
+ To use the Web Node please update your device to the latest iOS version.
+
+
+
+
Learn how to update
+
+} @else {
+
+
+
Your browser isn't supported
+
+
To run a Mina node in your browser,
+
we recommend one of the following.
+
+
+
+
+
+
+
+ Chrome
+
+
+
+ Safari
+
+
+
+ Edge
+
+
+
+
+}
+@if (devMode) {
+ You entered Dev mode!
+
+
+ Run Web Node
+
+}
diff --git a/frontend/src/app/features/webnode/web-node-not-supported/web-node-not-supported.component.scss b/frontend/src/app/features/webnode/web-node-not-supported/web-node-not-supported.component.scss
new file mode 100644
index 0000000000..e44bc5b434
--- /dev/null
+++ b/frontend/src/app/features/webnode/web-node-not-supported/web-node-not-supported.component.scss
@@ -0,0 +1,68 @@
+@import 'openmina';
+
+.header {
+ height: 56px;
+
+ .mina-svg {
+ height: 32px;
+ }
+}
+
+.phone-content,
+.browser-content {
+ height: calc(100% - 56px);
+
+ .ios {
+ width: 96px;
+ height: 96px;
+ font-size: 30px;
+ border-radius: 100px;
+ }
+
+ .ios-box {
+ margin-top: 40px;
+ margin-bottom: 40px;
+ padding: 0 32px;
+ }
+
+ .learn-btn {
+ background-color: $base-background;
+ color: $base-primary;
+ max-width: 330px;
+ margin: 0 12px;
+ filter: invert(1);
+ }
+
+ .headline {
+ font-size: 20px;
+ line-height: 30px;
+ margin-bottom: 8px;
+ }
+
+ .img-wrapper {
+ margin-top: 24px;
+ gap: 30px;
+ }
+
+ img {
+ height: 44px;
+ width: 44px;
+ }
+
+ .sub-headline {
+ font-size: 16px;
+ }
+
+ .browser {
+ margin-top: 64px;
+ }
+}
+
+.browser-content {
+ max-width: 600px;
+
+ img {
+ height: 56px;
+ width: 56px;
+ }
+}
diff --git a/frontend/src/app/features/webnode/web-node-not-supported/web-node-not-supported.component.ts b/frontend/src/app/features/webnode/web-node-not-supported/web-node-not-supported.component.ts
new file mode 100644
index 0000000000..37ffb3247a
--- /dev/null
+++ b/frontend/src/app/features/webnode/web-node-not-supported/web-node-not-supported.component.ts
@@ -0,0 +1,59 @@
+import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
+import { Platform } from '@angular/cdk/platform';
+import { iOSversion, sendSentryEvent } from '@shared/helpers/webnode.helper';
+import { safelyExecuteInBrowser } from '@openmina/shared';
+
+const code = [1, 2, 3, 2];
+
+@Component({
+ selector: 'mina-web-node-not-supported',
+ standalone: true,
+ imports: [],
+ templateUrl: './web-node-not-supported.component.html',
+ styleUrl: './web-node-not-supported.component.scss',
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ host: { class: 'h-100 flex-column align-center' },
+})
+export class WebNodeNotSupportedComponent {
+
+ @Input() isPhone!: boolean;
+
+ @Output() bypassUnsupportedDevice = new EventEmitter();
+
+ iOSVersion: string = iOSversion().join('.');
+ devMode: boolean = false;
+ private codeVerifier: number[] = [];
+
+ constructor(private platform: Platform) {}
+
+ addDevKey2(): void {
+ this.codeVerifier.push(code[this.codeVerifier.length]);
+ this.checkCode();
+ }
+
+ addDevKey(key: number): void {
+ this.codeVerifier.push(key);
+ this.checkCode();
+ }
+
+ private checkCode(): void {
+ if (this.codeVerifier.length === code.length) {
+ if (this.codeVerifier.every((v, i) => v === code[i])) {
+ this.devMode = true;
+ } else {
+ this.codeVerifier = [];
+ }
+ }
+ }
+
+ c_hcK1_V_a_l_id(input: HTMLInputElement): void {
+ if (input.value === 'allowme') {
+ sendSentryEvent('A developer is testing the app on ' + this.platform, 'debug');
+ this.bypassUnsupportedDevice.emit();
+ }
+ }
+
+ howToUpdate(): void {
+ safelyExecuteInBrowser(() => window.open('https://support.apple.com/en-us/118575', '_blank'));
+ }
+}
diff --git a/frontend/src/app/features/webnode/webnode.component.html b/frontend/src/app/features/webnode/webnode.component.html
new file mode 100644
index 0000000000..71207172ed
--- /dev/null
+++ b/frontend/src/app/features/webnode/webnode.component.html
@@ -0,0 +1,5 @@
+@if (supported) {
+
+} @else {
+
+}
diff --git a/frontend/src/app/features/webnode/webnode.component.scss b/frontend/src/app/features/webnode/webnode.component.scss
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/frontend/src/app/features/webnode/webnode.component.ts b/frontend/src/app/features/webnode/webnode.component.ts
new file mode 100644
index 0000000000..913ed0c4d0
--- /dev/null
+++ b/frontend/src/app/features/webnode/webnode.component.ts
@@ -0,0 +1,67 @@
+import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
+import { WebNodeInitializationComponent } from '@app/features/webnode/web-node-initialization/web-node-initialization.component';
+import { Platform } from '@angular/cdk/platform';
+import { WebNodeNotSupportedComponent } from '@app/features/webnode/web-node-not-supported/web-node-not-supported.component';
+import { StoreDispatcher } from '@shared/base-classes/store-dispatcher.class';
+import { getMergedRoute, MergedRoute } from '@openmina/shared';
+import { filter } from 'rxjs';
+import { WebNodeService } from '@core/services/web-node.service';
+import { iOSversion } from '@shared/helpers/webnode.helper';
+
+@Component({
+ selector: 'mina-webnode',
+ standalone: true,
+ imports: [
+ WebNodeInitializationComponent,
+ WebNodeNotSupportedComponent,
+ ],
+ templateUrl: './webnode.component.html',
+ styleUrl: './webnode.component.scss',
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class WebnodeComponent extends StoreDispatcher implements OnInit {
+
+ supported: boolean = false;
+ isPhone: boolean = false;
+
+ constructor(private platform: Platform,
+ private webNodeService: WebNodeService) { super(); }
+
+ ngOnInit(): void {
+ this.checkIfDeviceIsSupported();
+ this.listenToRoute();
+ }
+
+ private listenToRoute(): void {
+ this.select(getMergedRoute, (route: MergedRoute) => {
+ let initial = 174;
+ if (route.queryParams['initial']) {
+ initial = Number(route.queryParams['initial']);
+ }
+ let maximum = 65536;
+ if (route.queryParams['maximum']) {
+ maximum = Number(route.queryParams['maximum']);
+ }
+ let shared = true;
+ if (route.queryParams['shared']) {
+ shared = route.queryParams['shared'] === 'true';
+ }
+ this.webNodeService.memory = { initial, maximum, shared };
+ }, filter(Boolean));
+ }
+
+ private checkIfDeviceIsSupported(): void {
+ if (this.platform.IOS) {
+ this.supported = iOSversion()[0] >= 18;
+ this.isPhone = true;
+ return;
+ }
+
+ if (this.platform.FIREFOX) {
+ this.supported = false;
+ return;
+ }
+
+ this.supported = true;
+ }
+}
diff --git a/frontend/src/app/features/webnode/webnode.module.ts b/frontend/src/app/features/webnode/webnode.module.ts
new file mode 100644
index 0000000000..b9f10c30ef
--- /dev/null
+++ b/frontend/src/app/features/webnode/webnode.module.ts
@@ -0,0 +1,14 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { WebnodeRouting } from './webnode.routing';
+
+
+@NgModule({
+ declarations: [],
+ imports: [
+ CommonModule,
+ WebnodeRouting,
+ ],
+})
+export class WebnodeModule {}
diff --git a/frontend/src/app/features/webnode/webnode.routing.ts b/frontend/src/app/features/webnode/webnode.routing.ts
new file mode 100644
index 0000000000..fc0e9b4e9d
--- /dev/null
+++ b/frontend/src/app/features/webnode/webnode.routing.ts
@@ -0,0 +1,16 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { WebnodeComponent } from '@app/features/webnode/webnode.component';
+
+const routes: Routes = [
+ {
+ path: '',
+ component: WebnodeComponent,
+ },
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule],
+})
+export class WebnodeRouting {}
diff --git a/frontend/src/app/layout/block-production-pill/block-production-pill.component.html b/frontend/src/app/layout/block-production-pill/block-production-pill.component.html
new file mode 100644
index 0000000000..9b6a2015b8
--- /dev/null
+++ b/frontend/src/app/layout/block-production-pill/block-production-pill.component.html
@@ -0,0 +1,22 @@
+
+
+
+ @if (!isMobile) {
+
schedule
+ }
+
Block Production
+
+ @if (text) {
+ {{ text }}
+ } @else {
+ @if (producingIn) {
+ in
+ {{ producingIn }}
+ } @else {
+ in ...
+ }
+ }
+
+
+
diff --git a/frontend/src/app/layout/block-production-pill/block-production-pill.component.scss b/frontend/src/app/layout/block-production-pill/block-production-pill.component.scss
new file mode 100644
index 0000000000..4e274c7ec0
--- /dev/null
+++ b/frontend/src/app/layout/block-production-pill/block-production-pill.component.scss
@@ -0,0 +1,164 @@
+@import 'openmina';
+
+$blue: #57d7ff;
+$pink: #fda2ff;
+$orange: #ff833d;
+@media (max-width: 767px) {
+ :host.h-sm {
+ height: 24px !important;
+ }
+}
+
+:host {
+ position: relative;
+ min-width: 178px;
+ height: 34px;
+ @media (min-width: 768px) {
+ margin-right: 8px;
+ height: 26px;
+ }
+}
+
+.pill {
+ background-color: $base-background;
+ height: 100%;
+ min-width: 170px;
+ @media (max-width: 767px) {
+ font-size: 12px;
+ min-width: unset;
+ .pill-inside2 {
+ justify-content: center;
+ }
+ }
+
+ .pill-inside1 {
+ position: absolute;
+ background-color: $base-background;
+ top: 1px;
+ left: 1px;
+ height: calc(100% - 2px);
+ width: calc(100% - 2px);
+
+ .pill-inside2 {
+ padding-left: 6px;
+ background: linear-gradient(25deg, rgba($blue, 0.2), rgba($pink, 0.2), rgba($orange, 0.2));
+
+ .mina-icon,
+ .bp,
+ .time {
+ background: linear-gradient(12deg, $blue, $pink, $orange);
+ -webkit-background-clip: text;
+ background-clip: text;
+ -webkit-text-fill-color: transparent;
+ }
+
+ &:hover {
+ .mina-icon,
+ .bp,
+ .time {
+ background: linear-gradient(100deg, $blue, $pink, $orange);
+ -webkit-background-clip: text;
+ background-clip: text;
+ -webkit-text-fill-color: transparent;
+ }
+ }
+ }
+ }
+}
+
+
+.comet-border {
+ position: relative;
+ margin: auto;
+ border-radius: 5px;
+ overflow: hidden;
+}
+
+.comet-border:before {
+ content: "";
+ background-image: conic-gradient(
+ $orange 5deg,
+ $pink 10deg,
+ $pink 50deg,
+ $blue 90deg,
+ transparent 140deg
+ );
+ height: 80px;
+ width: 80px;
+ position: absolute;
+ animation: rotate 5s infinite linear;
+}
+
+@media (min-width: 768px) {
+ @keyframes rotate {
+ /* From left bottom to right bottom */
+ 0% {
+ left: -10%;
+ transform: rotate(-45deg);
+ }
+ 5% {
+ left: -10%;
+ transform: rotate(-185deg);
+ }
+ /* Turn around */
+ 15% {
+ transform: rotate(-235deg);
+ }
+ /* From right top to left top */
+ 50% {
+ left: 71%;
+ transform: rotate(-235deg);
+ }
+ 55% {
+ left: 65%;
+ }
+ 62% {
+ transform: rotate(-420deg);
+ }
+ 80% {
+ transform: rotate(-420deg);
+ }
+ 95% {
+ left: 0;
+ }
+ /* No turn around. -405 = -45 visually */
+ 100% {
+ left: -10%;
+ transform: rotate(-405deg);
+ }
+ }
+}
+
+@media (max-width: 767px) {
+ @keyframes rotate {
+ 0% {
+ left: -10%;
+ transform: rotate(-45deg);
+ }
+ 5% {
+ left: -10%;
+ transform: rotate(-185deg);
+ }
+ 15% {
+ transform: rotate(-255deg);
+ }
+ 40% {
+ transform: rotate(-255deg);
+ }
+ 45% {
+ left: 75%;
+ transform: rotate(-340deg);
+ }
+ 50% {
+ transform: rotate(-405deg);
+ }
+ 58% {
+ left: 50%;
+ transform: rotate(-405deg);
+ }
+ 100% {
+ left: -10%;
+ transform: rotate(-405deg);
+ }
+ }
+}
diff --git a/frontend/src/app/layout/block-production-pill/block-production-pill.component.ts b/frontend/src/app/layout/block-production-pill/block-production-pill.component.ts
new file mode 100644
index 0000000000..ccc7c581d9
--- /dev/null
+++ b/frontend/src/app/layout/block-production-pill/block-production-pill.component.ts
@@ -0,0 +1,84 @@
+import { ChangeDetectionStrategy, Component, HostBinding, OnDestroy, OnInit } from '@angular/core';
+import { AppSelectors } from '@app/app.state';
+import { StoreDispatcher } from '@shared/base-classes/store-dispatcher.class';
+import { AppNodeDetails, AppNodeStatus } from '@shared/types/app/app-node-details.type';
+import { getTimeDiff } from '@shared/helpers/date.helper';
+import { Router } from '@angular/router';
+import { Routes } from '@shared/enums/routes.enum';
+import { BlockProductionWonSlotsStatus } from '@shared/types/block-production/won-slots/block-production-won-slots-slot.type';
+import { filter } from 'rxjs';
+import { isSubFeatureEnabled } from '@shared/constants/config';
+import { getMergedRoute, isMobile, MergedRoute, removeParamsFromURL } from '@openmina/shared';
+import { BlockProductionWonSlotsActions } from '@block-production/won-slots/block-production-won-slots.actions';
+
+@Component({
+ selector: 'mina-block-production-pill',
+ standalone: true,
+ imports: [],
+ templateUrl: './block-production-pill.component.html',
+ styleUrl: './block-production-pill.component.scss',
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ host: { class: 'border-rad-6' },
+})
+export class BlockProductionPillComponent extends StoreDispatcher implements OnInit, OnDestroy {
+ text: string = null;
+ producingIn: string = null;
+ isMobile: boolean = isMobile();
+
+ private globalSlot: number = null;
+ private interval: any;
+ private producingValue: number = null;
+ private activeSubMenu: string;
+
+ constructor(private router: Router) { super(); }
+
+ ngOnInit(): void {
+ this.listenToActiveNode();
+ this.listenToRouteChange();
+ }
+
+ private listenToActiveNode(): void {
+ this.select(AppSelectors.activeNodeDetails, (details: AppNodeDetails) => {
+ if (details.producingBlockStatus === BlockProductionWonSlotsStatus.Committed) {
+ this.text = 'active';
+ } else if (details.producingBlockStatus === BlockProductionWonSlotsStatus.Produced) {
+ this.text = 'done';
+ } else {
+ this.text = null;
+ }
+ this.globalSlot = details.producingBlockGlobalSlot;
+ this.producingValue = details.producingBlockAt;
+ this.producingIn = getTimeDiff(this.producingValue, { only1unit: true }).diff;
+ this.detect();
+ }, filter((details: AppNodeDetails) => !!details));
+ }
+
+ private listenToRouteChange(): void {
+ this.select(getMergedRoute, (route: MergedRoute) => {
+ this.activeSubMenu = route.url.split('/')[2] ? removeParamsFromURL(route.url.split('/')[2]) : null;
+ }, filter(Boolean));
+ }
+
+ private clearInterval(): void {
+ if (this.interval) {
+ clearInterval(this.interval);
+ this.interval = null;
+ }
+ }
+
+ goToWonSlots(): void {
+ if (!this.globalSlot) {
+ return;
+ }
+ if (this.activeSubMenu === Routes.WON_SLOTS) {
+ this.dispatch2(BlockProductionWonSlotsActions.setActiveSlotNumber({ slotNumber: this.globalSlot }));
+ return;
+ }
+ this.router.navigate([Routes.BLOCK_PRODUCTION, Routes.WON_SLOTS, this.globalSlot], { queryParamsHandling: 'merge' });
+ }
+
+ override ngOnDestroy(): void {
+ super.ngOnDestroy();
+ this.clearInterval();
+ }
+}
diff --git a/frontend/src/app/layout/env-build-modal/env-build-modal.component.html b/frontend/src/app/layout/env-build-modal/env-build-modal.component.html
new file mode 100644
index 0000000000..02ece42212
--- /dev/null
+++ b/frontend/src/app/layout/env-build-modal/env-build-modal.component.html
@@ -0,0 +1,9 @@
+
+
Build Details
+
+ close
+
+
+
+
+
diff --git a/frontend/src/app/layout/env-build-modal/env-build-modal.component.scss b/frontend/src/app/layout/env-build-modal/env-build-modal.component.scss
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/frontend/src/app/layout/env-build-modal/env-build-modal.component.ts b/frontend/src/app/layout/env-build-modal/env-build-modal.component.ts
new file mode 100644
index 0000000000..f88cc05b1b
--- /dev/null
+++ b/frontend/src/app/layout/env-build-modal/env-build-modal.component.ts
@@ -0,0 +1,19 @@
+import { ChangeDetectionStrategy, Component, EventEmitter } from '@angular/core';
+import { AppEnvBuild } from '@shared/types/app/app-env-build.type';
+import { ManualDetection, MinaJsonViewerComponent } from '@openmina/shared';
+
+@Component({
+ selector: 'mina-env-build-modal',
+ standalone: true,
+ imports: [
+ MinaJsonViewerComponent,
+ ],
+ templateUrl: './env-build-modal.component.html',
+ styleUrl: './env-build-modal.component.scss',
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ host: { class: 'flex-column w-100 bg-surface border-rad-6 border pb-12' },
+})
+export class EnvBuildModalComponent extends ManualDetection {
+ envBuild: AppEnvBuild;
+ close: EventEmitter = new EventEmitter();
+}
diff --git a/frontend/src/app/layout/error-preview/error-preview.component.ts b/frontend/src/app/layout/error-preview/error-preview.component.ts
index d75d835854..71f80dac62 100644
--- a/frontend/src/app/layout/error-preview/error-preview.component.ts
+++ b/frontend/src/app/layout/error-preview/error-preview.component.ts
@@ -1,7 +1,7 @@
import { ChangeDetectionStrategy, Component, ComponentRef, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { MinaState } from '@app/app.setup';
-import { ManualDetection } from '@openmina/shared';
+import { isDesktop, isMobile, ManualDetection } from '@openmina/shared';
import { selectErrorPreviewErrors } from '@error-preview/error-preview.state';
import { filter, take } from 'rxjs';
import { Overlay, OverlayRef } from '@angular/cdk/overlay';
@@ -23,6 +23,7 @@ export class ErrorPreviewComponent extends ManualDetection implements OnInit {
newError: MinaError;
unreadErrors: boolean;
openedOverlay: boolean;
+ isMobile: boolean = isMobile();
private overlayRef: OverlayRef;
private errorListComponent: ComponentRef;
diff --git a/frontend/src/app/layout/menu-tabs/menu-tabs.component.html b/frontend/src/app/layout/menu-tabs/menu-tabs.component.html
new file mode 100644
index 0000000000..cfa70df50e
--- /dev/null
+++ b/frontend/src/app/layout/menu-tabs/menu-tabs.component.html
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+ commit
+ Build
+
+
+ {{ envBuild ? envBuild.git.commit_hash.slice(0, 6) : '' }}..
+ open_in_full
+
+
+
+
+ wifi_tethering
+ {{ network }}
+
+
+ {{ chainId?.slice(0, 6) }}..
+ content_copy
+
+
+
+
+ wb_sunny
+ Light
+
+ @if (currentTheme === ThemeType.LIGHT) {
+
check
+ }
+
+
+
+ dark_mode
+ Dark
+
+ @if (currentTheme === ThemeType.DARK) {
+
check
+ }
+
+
+
diff --git a/frontend/src/app/layout/menu-tabs/menu-tabs.component.scss b/frontend/src/app/layout/menu-tabs/menu-tabs.component.scss
new file mode 100644
index 0000000000..19811948a3
--- /dev/null
+++ b/frontend/src/app/layout/menu-tabs/menu-tabs.component.scss
@@ -0,0 +1,28 @@
+@import 'openmina';
+
+:host {
+ height: 56px;
+
+ .menus {
+ gap: 12px;
+
+ .menu {
+ color: $base-tertiary;
+ min-width: 72px;
+ flex: 1 0 auto;
+
+ &.active {
+ color: $selected-primary;
+
+ .mina-icon {
+ color: $selected-primary;
+ font-variation-settings: 'FILL' 1, 'wght' 300, 'GRAD' 0, 'opsz' 20;
+ }
+ }
+ }
+ }
+}
+
+.theme {
+ font-variation-settings: 'FILL' 1, 'wght' 200 !important;
+}
diff --git a/frontend/src/app/layout/menu-tabs/menu-tabs.component.ts b/frontend/src/app/layout/menu-tabs/menu-tabs.component.ts
new file mode 100644
index 0000000000..de338345d4
--- /dev/null
+++ b/frontend/src/app/layout/menu-tabs/menu-tabs.component.ts
@@ -0,0 +1,174 @@
+import { ChangeDetectionStrategy, Component, OnInit, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core';
+import {
+ getMergedRoute,
+ HorizontalMenuComponent, isDesktop,
+ MergedRoute,
+ OpenminaEagerSharedModule,
+ removeParamsFromURL,
+ ThemeSwitcherService,
+ ThemeType,
+} from '@openmina/shared';
+import { getAvailableFeatures } from '@shared/constants/config';
+import { MENU_ITEMS, MenuItem } from '@app/layout/menu/menu.component';
+import { filter, map, merge, skip, take, tap } from 'rxjs';
+import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
+import { MinaNode } from '@shared/types/core/environment/mina-env.type';
+import { AppSelectors } from '@app/app.state';
+import { RouterLink } from '@angular/router';
+import { StoreDispatcher } from '@shared/base-classes/store-dispatcher.class';
+import { AppEnvBuild } from '@shared/types/app/app-env-build.type';
+import { Overlay, OverlayRef } from '@angular/cdk/overlay';
+import { ComponentPortal, TemplatePortal } from '@angular/cdk/portal';
+import { MinaNetwork } from '@shared/types/core/mina/mina.type';
+import { EnvBuildModalComponent } from '@app/layout/env-build-modal/env-build-modal.component';
+
+@UntilDestroy()
+@Component({
+ selector: 'mina-menu-tabs',
+ standalone: true,
+ imports: [
+ HorizontalMenuComponent,
+ RouterLink,
+ OpenminaEagerSharedModule,
+ ],
+ templateUrl: './menu-tabs.component.html',
+ styleUrl: './menu-tabs.component.scss',
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ host: { class: 'flex-column w-100' },
+})
+export class MenuTabsComponent extends StoreDispatcher implements OnInit {
+
+ menuItems: MenuItem[] = this.allowedMenuItems;
+ activeRoute: string;
+ activeNode: MinaNode;
+ network?: MinaNetwork;
+ chainId?: string;
+ envBuild: AppEnvBuild;
+ isOpenMore: boolean;
+ currentTheme: ThemeType;
+ readonly trackMenus = (_: number, item: MenuItem): string => item.name;
+ readonly ThemeType = ThemeType;
+
+ @ViewChild('dropdown') private dropdown: TemplateRef;
+
+ private overlayRef: OverlayRef;
+
+ constructor(private overlay: Overlay,
+ private viewContainerRef: ViewContainerRef,
+ private themeService: ThemeSwitcherService) {super();}
+
+ ngOnInit(): void {
+ this.currentTheme = this.themeService.activeTheme;
+ this.listenToActiveNodeChange();
+ this.listenToEnvBuild();
+ this.listenToNetwork();
+
+ let lastUrl: string;
+ this.store.select(getMergedRoute)
+ .pipe(
+ filter(Boolean),
+ map((route: MergedRoute) => route.url),
+ filter(url => url !== lastUrl),
+ tap(url => lastUrl = url),
+ untilDestroyed(this),
+ )
+ .subscribe((url: string) => {
+ this.activeRoute = removeParamsFromURL(url).split('/')[1];
+ this.detect();
+ });
+ }
+
+ changeTheme(type: ThemeType): void {
+ this.closeOverlay();
+ if (type === this.currentTheme) {
+ return;
+ }
+ this.themeService.changeTheme();
+ this.currentTheme = this.themeService.activeTheme;
+ }
+
+
+ private listenToActiveNodeChange(): void {
+ this.select(AppSelectors.activeNode, (node: MinaNode) => {
+ this.activeNode = node;
+ this.menuItems = this.allowedMenuItems;
+ this.detect();
+ }, filter(node => !!node));
+ }
+
+ private get allowedMenuItems(): MenuItem[] {
+ const features = getAvailableFeatures(this.activeNode || { features: {} } as any);
+ return MENU_ITEMS.filter((opt: MenuItem) => features.find(f => f === opt.name.toLowerCase().split(' ').join('-')));
+ }
+
+ private listenToEnvBuild(): void {
+ this.select(AppSelectors.envBuild, (env: AppEnvBuild) => {
+ this.envBuild = env;
+ this.detect();
+ });
+ }
+
+ private listenToNetwork(): void {
+ this.select(AppSelectors.activeNodeDetails, ({ chainId, network }) => {
+ this.chainId = chainId;
+ this.network = network as MinaNetwork;
+ this.detect();
+ }, filter(Boolean));
+ }
+
+ openMore(anchor: HTMLDivElement): void {
+ this.isOpenMore = true;
+ if (this.overlayRef?.hasAttached()) {
+ this.closeOverlay();
+ return;
+ }
+ this.overlayRef = this.overlay.create({
+ hasBackdrop: false,
+ width: window.innerWidth - 6,
+ positionStrategy: this.overlay.position()
+ .flexibleConnectedTo(anchor)
+ .withPositions([{
+ originX: 'start',
+ originY: 'top',
+ overlayX: 'start',
+ overlayY: 'bottom',
+ offsetY: -10,
+ offsetX: -4,
+ }]),
+ });
+
+ const portal = new TemplatePortal(this.dropdown, this.viewContainerRef);
+ this.overlayRef.attach(portal);
+ }
+
+ closeOverlay(): void {
+ this.overlayRef?.dispose();
+ this.isOpenMore = false;
+ this.detect();
+ }
+
+ openEnvBuildModal(): void {
+ this.closeOverlay();
+ this.overlayRef = this.overlay.create({
+ hasBackdrop: true,
+ backdropClass: 'openmina-backdrop',
+ width: 'calc(100% - 8px)',
+ height: 'calc(100% - 8px)',
+ positionStrategy: this.overlay.position().global().centerVertically().centerHorizontally(),
+ });
+
+ const portal = new ComponentPortal(EnvBuildModalComponent);
+ const component = this.overlayRef.attach(portal);
+ component.instance.envBuild = this.envBuild;
+ component.instance.detect();
+
+ merge(
+ component.instance.close,
+ this.overlayRef.backdropClick(),
+ )
+ .pipe(take(1))
+ .subscribe(() => this.overlayRef.dispose());
+
+ }
+
+}
diff --git a/frontend/src/app/layout/menu/menu.component.html b/frontend/src/app/layout/menu/menu.component.html
index 474dbd42f5..c4e13250c8 100644
--- a/frontend/src/app/layout/menu/menu.component.html
+++ b/frontend/src/app/layout/menu/menu.component.html
@@ -47,7 +47,22 @@
-
+
+
+
+ commit
+ Build
+
+
+ {{ envBuild ? envBuild.git.commit_hash.slice(0, 6) : '' }}..
+ open_in_full
+
+
+
+
- {{ chainId.slice(0, 6) }}..
+ {{ chainId?.slice(0, 6) }}..
content_copy
diff --git a/frontend/src/app/layout/menu/menu.component.scss b/frontend/src/app/layout/menu/menu.component.scss
index 1e8329053b..81b7ae7000 100644
--- a/frontend/src/app/layout/menu/menu.component.scss
+++ b/frontend/src/app/layout/menu/menu.component.scss
@@ -5,7 +5,6 @@
padding: 8px 12px;
border: none;
border-radius: 0;
- border-bottom: 1px solid $base-divider;
background-color: unset;
transition: width 200ms ease-out, background-color 80ms;
@@ -103,7 +102,7 @@
}
}
-@media (max-width: 768px) {
+@media (max-width: 767px) {
.menu {
.menu-toggle {
height: 56px !important;
@@ -148,7 +147,7 @@
transform: translate(0) rotate(0);
animation: rotWithOpc 0.3s linear;
- @media (min-width: 769px) {
+ @media (min-width: 768px) {
left: 42px;
&.collapsed {
transform: translate(-75px, -76px) rotate(-90deg);
diff --git a/frontend/src/app/layout/menu/menu.component.ts b/frontend/src/app/layout/menu/menu.component.ts
index 49d59de000..97486f0e83 100644
--- a/frontend/src/app/layout/menu/menu.component.ts
+++ b/frontend/src/app/layout/menu/menu.component.ts
@@ -6,7 +6,8 @@ import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { AppMenu } from '@shared/types/app/app-menu.type';
import { AppActions } from '@app/app.actions';
import {
- getMergedRoute,
+ getMergedRoute, isDesktop,
+ isMobile,
ManualDetection,
MergedRoute,
removeParamsFromURL,
@@ -15,17 +16,21 @@ import {
TooltipPosition,
} from '@openmina/shared';
import { MinaNode } from '@shared/types/core/environment/mina-env.type';
-import { filter, map, tap } from 'rxjs';
+import { filter, map, merge, take, tap } from 'rxjs';
import { CONFIG, getAvailableFeatures } from '@shared/constants/config';
import { MinaNetwork } from '@shared/types/core/mina/mina.type';
+import { AppEnvBuild } from '@shared/types/app/app-env-build.type';
+import { Overlay, OverlayRef } from '@angular/cdk/overlay';
+import { ComponentPortal } from '@angular/cdk/portal';
+import { EnvBuildModalComponent } from '@app/layout/env-build-modal/env-build-modal.component';
-interface MenuItem {
+export interface MenuItem {
name: string;
icon: string;
tooltip?: string;
}
-const MENU_ITEMS: MenuItem[] = [
+export const MENU_ITEMS: MenuItem[] = [
{ name: 'Dashboard', icon: 'dashboard' },
{ name: 'Block Production', icon: 'library_add' },
{ name: 'Nodes', icon: 'margin' },
@@ -57,14 +62,20 @@ export class MenuComponent extends ManualDetection implements OnInit {
activeRoute: string;
network?: MinaNetwork;
chainId?: string;
+ envBuild: AppEnvBuild;
- constructor(private store: Store
,
+ private overlayRef: OverlayRef;
+
+ constructor(private overlay: Overlay,
+ private store: Store,
private themeService: ThemeSwitcherService) { super(); }
ngOnInit(): void {
this.currentTheme = this.themeService.activeTheme;
this.listenToCollapsingMenu();
this.listenToActiveNodeChange();
+ this.listenToEnvBuild();
+
let lastUrl: string;
this.store.select(getMergedRoute)
.pipe(
@@ -118,6 +129,18 @@ export class MenuComponent extends ManualDetection implements OnInit {
});
}
+ private listenToEnvBuild(): void {
+ this.store.select(AppSelectors.envBuild)
+ .pipe(
+ filter(Boolean),
+ untilDestroyed(this),
+ )
+ .subscribe((env: AppEnvBuild | undefined) => {
+ this.envBuild = env;
+ this.detect();
+ });
+ }
+
private get allowedMenuItems(): MenuItem[] {
const features = getAvailableFeatures(this.activeNode || { features: {} } as any);
return MENU_ITEMS.filter((opt: MenuItem) => features.find(f => f === opt.name.toLowerCase().split(' ').join('-')));
@@ -140,4 +163,28 @@ export class MenuComponent extends ManualDetection implements OnInit {
collapseMenu(): void {
this.store.dispatch(AppActions.changeMenuCollapsing({ isCollapsing: !this.menu.collapsed }));
}
+
+ openEnvBuildModal(): void {
+ this.overlayRef = this.overlay.create({
+ hasBackdrop: true,
+ backdropClass: 'openmina-backdrop',
+ width: '99%',
+ height: '99%',
+ maxWidth: 600,
+ maxHeight: 460,
+ positionStrategy: this.overlay.position().global().centerVertically().centerHorizontally(),
+ });
+
+ const portal = new ComponentPortal(EnvBuildModalComponent);
+ const component = this.overlayRef.attach(portal);
+ component.instance.envBuild = this.envBuild;
+ component.instance.detect();
+
+ merge(
+ component.instance.close,
+ this.overlayRef.backdropClick(),
+ )
+ .pipe(take(1))
+ .subscribe(() => this.overlayRef.dispose());
+ }
}
diff --git a/frontend/src/app/layout/parse-files/parse-files.component.html b/frontend/src/app/layout/parse-files/parse-files.component.html
new file mode 100644
index 0000000000..ad62091962
--- /dev/null
+++ b/frontend/src/app/layout/parse-files/parse-files.component.html
@@ -0,0 +1,12 @@
+parse-files works!
+
+
+ 0">
+
+
File Contents:
+
{{ fileContent }}
+
+
diff --git a/frontend/src/app/layout/parse-files/parse-files.component.scss b/frontend/src/app/layout/parse-files/parse-files.component.scss
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/frontend/src/app/layout/parse-files/parse-files.component.ts b/frontend/src/app/layout/parse-files/parse-files.component.ts
new file mode 100644
index 0000000000..d8a7725887
--- /dev/null
+++ b/frontend/src/app/layout/parse-files/parse-files.component.ts
@@ -0,0 +1,112 @@
+import { ChangeDetectionStrategy, Component } from '@angular/core';
+import { NgFor, NgIf } from '@angular/common';
+import * as JSZip from 'jszip';
+
+@Component({
+ selector: 'mina-parse-files',
+ standalone: true,
+ imports: [
+ NgIf, NgFor,
+ ],
+ templateUrl: './parse-files.component.html',
+ styleUrl: './parse-files.component.scss',
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class ParseFilesComponent {
+
+ fileContents: string[] = [];
+
+ onFileSelected(event: any) {
+ const files: FileList = event.target.files;
+
+ // Reset previous file contents
+ this.fileContents = [];
+
+ // Loop through selected files
+ for (let i = 0; i < files.length; i++) {
+ const file = files[i];
+
+ // Ensure it's a .txt file
+ }
+ this.handleFileUpload(event);
+ }
+
+ async processZipFile(zipFile: File) {
+ try {
+ // Load the ZIP file
+ const zip = await JSZip.loadAsync(zipFile);
+
+ // Array to store file contents
+ const fileContents: { name: string, content: string }[] = [];
+
+ // Iterate through each file in the ZIP
+ await Promise.all(Object.keys(zip.files).map(async (filename) => {
+ // Skip directories
+ if (!zip.files[filename].dir) {
+ try {
+ // Read file as text
+ const content = await zip.files[filename].async('string');
+ fileContents.push({
+ name: filename,
+ content: content,
+ });
+ } catch (readError) {
+ console.error(`Error reading file ${filename}:`, readError);
+ }
+ }
+ }));
+
+ // Return or process the file contents
+ return fileContents;
+ } catch (error) {
+ console.error('Error processing ZIP file:', error);
+ return [];
+ }
+ }
+
+// Usage example
+ handleFileUpload(event: Event) {
+ const input = event.target as HTMLInputElement;
+ if (input.files && input.files.length > 0) {
+ const zipFile = input.files[0];
+ this.processZipFile(zipFile).then(files => {
+ files.forEach(file => {
+ console.log(`File: ${file.name}`);
+ console.log(`Content: ${file.content.substring(0, 200)}...`);
+ });
+ });
+ }
+ }
+
+ private readFileContent(file: File) {
+ const reader = new FileReader();
+
+ reader.onload = (e: any) => {
+ const content = e.target.result as string;
+ this.fileContents.push(content);
+
+ // Perform operations on the content here
+ this.processFileContent(content);
+ };
+
+ reader.onerror = (e) => {
+ console.error('Error reading file', e);
+ };
+
+ // Read the file as text
+ reader.readAsText(file);
+ }
+
+ private processFileContent(content: string) {
+ // Example operations
+ const lines = content.split('\n');
+ const wordCount = content.split(/\s+/).length;
+ const characterCount = content.length;
+
+ console.log('Lines:', lines);
+ console.log('Word Count:', wordCount);
+ console.log('Character Count:', characterCount);
+
+ // Add your specific file processing logic here
+ }
+}
diff --git a/frontend/src/app/layout/server-status/server-status.component.html b/frontend/src/app/layout/server-status/server-status.component.html
index a9b01e4f38..6b727bb5c2 100644
--- a/frontend/src/app/layout/server-status/server-status.component.html
+++ b/frontend/src/app/layout/server-status/server-status.component.html
@@ -1,29 +1,25 @@
-
-
+
blur_circular
-
- {{ details.transactions }} Txs
- {{ details.snarks }} SNARKs
-
+
{{ details.transactions }} Tx{{ details.transactions | plural }}
+
{{ details.snarks }} SNARK{{ details.snarks | plural }}
-
language
- @if (!isMobile) {
-
{{ details.peers }} Peers
-
{{ details.download }} / {{ details.upload }} MBps
- }
+
{{ details.peersConnected }} Peer{{ details.peersConnected | plural }}
-
@@ -32,85 +28,87 @@
-
dns
-
- {{ details.status }}
- # {{ details.blockHeight }}
- {{ blockTimeAgo ? blockTimeAgo + ' ago' : '' }}
-
+ @if (!isMobile) {
+
dns
+ }
+
{{ details.status }}
+
# {{ details.blockHeight }}
+
{{ blockTimeAgo ? blockTimeAgo + ' ago' : '' }}
-
-
-
+ @if (!isMobile || (isMobile && switchForbidden)) {
+
+
{{ !switchForbidden ? activeNode?.name : 'All Nodes' }}
-
- arrow_drop_down
+ @if (!switchForbidden && (canAddNodes || nodes.length > 1)) {
+ arrow_drop_down
+ }
+
-
+ }
-
Mempools
+ class="bg-surface-top secondary border-rad-8 popup-box-shadow-weak p-8 pb-5 w-100 h-100">
+
Mempool
Transactions
-
{{ details.transactions }}
+
{{ details.transactions }}
SNARKs
-
{{ details.snarks }}
+
{{ details.snarks }}
+ class="bg-surface-top secondary border-rad-8 popup-box-shadow-weak p-8 pb-5 w-100 h-100">
Network Traffic
Connected Peers
-
{{ details.peers }}
+
{{ details.peersConnected }}
-
Download
-
{{ details.download }} MB/s
+
Connecting Peers
+
{{ details.peersConnecting }}
-
Upload
-
{{ details.upload }} MB/s
+
Disconnected Peers
+
{{ details.peersDisconnected }}
+ class="node-status-popup secondary bg-surface-top border-rad-8 popup-box-shadow-weak p-8 pb-5 w-100 h-100 text-nowrap">
Node Status
MINA short history
-
{{ details.status }}
+
{{ details.status }}
Latest applied block
-
{{ details.blockHeight }}
+
{{ details.blockHeight }}
Last updated
-
{{ blockTimeAgo ? blockTimeAgo + ' ago' : '' }}
+
{{ blockTimeAgo ? blockTimeAgo + ' ago' : '' }}
diff --git a/frontend/src/app/layout/server-status/server-status.component.scss b/frontend/src/app/layout/server-status/server-status.component.scss
index 505c0ea331..a3de40e2d0 100644
--- a/frontend/src/app/layout/server-status/server-status.component.scss
+++ b/frontend/src/app/layout/server-status/server-status.component.scss
@@ -100,24 +100,46 @@
.chip {
gap: 4px;
- margin-left: 4px;
+ }
+
+ @media (max-width: 767px) {
+ width: 100%;
+ &.h-sm,
+ .h-sm {
+ height: 32px !important;
+ }
}
}
.node-status {
- &.can-add-nodes {
- .chip,
- .chip::before {
- border-bottom-right-radius: 0 !important;
- border-top-right-radius: 0 !important;
+
+ @media (min-width: 768px) {
+ &.can-add-nodes {
+ .chip,
+ .chip::before {
+ border-bottom-right-radius: 0 !important;
+ border-top-right-radius: 0 !important;
+ }
}
- }
- .chip {
+ .chip {
+ &,
+ &::before {
+ border-top-right-radius: 0 !important;
+ border-bottom-right-radius: 0 !important;
+ }
+ }
+ }
+ @media (max-width: 767px) {
+ font-size: 12px;
&,
- &::before {
- border-top-right-radius: 0 !important;
- border-bottom-right-radius: 0 !important;
+ .shine-parent,
+ .chip {
+ width: 100%;
+ margin: 0 !important;
+ }
+ .chip {
+ justify-content: center;
}
}
diff --git a/frontend/src/app/layout/server-status/server-status.component.ts b/frontend/src/app/layout/server-status/server-status.component.ts
index 60dba80042..4f459b9705 100644
--- a/frontend/src/app/layout/server-status/server-status.component.ts
+++ b/frontend/src/app/layout/server-status/server-status.component.ts
@@ -62,8 +62,7 @@ export class ServerStatusComponent extends StoreDispatcher implements OnInit {
protected readonly AppNodeStatus = AppNodeStatus;
protected readonly canAddNodes = CONFIG.canAddNodes;
- @Input() switchForbidden: boolean;
-
+ switchForbidden: boolean;
isMobile: boolean;
activeNode: MinaNode;
details: AppNodeDetails;
@@ -73,7 +72,7 @@ export class ServerStatusComponent extends StoreDispatcher implements OnInit {
@ViewChild('overlayOpener') private overlayOpener: ElementRef
;
- private nodes: MinaNode[] = [];
+ nodes: MinaNode[] = [];
private tooltipOverlayRef: OverlayRef;
private nodePickerOverlayRef: OverlayRef;
private nodePickerComponent: ComponentRef;
@@ -162,7 +161,7 @@ export class ServerStatusComponent extends StoreDispatcher implements OnInit {
minWidth: isMobile() ? '100%' : '220px',
scrollStrategy: this.overlay.scrollStrategies.close(),
positionStrategy: this.overlay.position()
- .flexibleConnectedTo(this.overlayOpener.nativeElement)
+ .flexibleConnectedTo(this.overlayOpener ? this.overlayOpener.nativeElement : (event.target as HTMLElement))
.withPositions([{
originX: 'end',
originY: 'bottom',
diff --git a/frontend/src/app/layout/toolbar/loading.reducer.ts b/frontend/src/app/layout/toolbar/loading.reducer.ts
index 8f9666026f..6fcb7d8253 100644
--- a/frontend/src/app/layout/toolbar/loading.reducer.ts
+++ b/frontend/src/app/layout/toolbar/loading.reducer.ts
@@ -8,16 +8,8 @@ import {
STATE_ACTIONS_GET_EARLIEST_SLOT,
STATE_ACTIONS_GET_EARLIEST_SLOT_SUCCESS,
} from '@state/actions/state-actions.actions';
-import {
- NODES_OVERVIEW_CLOSE,
- NODES_OVERVIEW_GET_NODES_SUCCESS,
- NODES_OVERVIEW_INIT,
-} from '@nodes/overview/nodes-overview.actions';
-import {
- NODES_BOOTSTRAP_CLOSE,
- NODES_BOOTSTRAP_GET_NODES_SUCCESS,
- NODES_BOOTSTRAP_INIT,
-} from '@nodes/bootstrap/nodes-bootstrap.actions';
+import { NODES_OVERVIEW_CLOSE, NODES_OVERVIEW_GET_NODES_SUCCESS, NODES_OVERVIEW_INIT } from '@nodes/overview/nodes-overview.actions';
+import { NODES_BOOTSTRAP_CLOSE, NODES_BOOTSTRAP_GET_NODES_SUCCESS, NODES_BOOTSTRAP_INIT } from '@nodes/bootstrap/nodes-bootstrap.actions';
import { NODES_LIVE_CLOSE, NODES_LIVE_GET_NODES_SUCCESS, NODES_LIVE_INIT } from '@nodes/live/nodes-live.actions';
import {
SNARKS_WORK_POOL_CLOSE,
@@ -27,17 +19,8 @@ import {
SNARKS_WORK_POOL_INIT,
} from '@snarks/work-pool/snarks-work-pool.actions';
import { SCAN_STATE_CLOSE, SCAN_STATE_GET_BLOCK_SUCCESS, SCAN_STATE_INIT } from '@snarks/scan-state/scan-state.actions';
-import { DASHBOARD_CLOSE, DASHBOARD_GET_DATA_SUCCESS, DASHBOARD_INIT } from '@dashboard/dashboard.actions';
-import {
- MEMORY_RESOURCES_CLOSE,
- MEMORY_RESOURCES_GET,
- MEMORY_RESOURCES_GET_SUCCESS,
-} from '@resources/memory/memory-resources.actions';
-import {
- NETWORK_NODE_DHT_CLOSE,
- NETWORK_NODE_DHT_GET_PEERS_SUCCESS,
- NETWORK_NODE_DHT_INIT,
-} from '@network/node-dht/network-node-dht.actions';
+import { MEMORY_RESOURCES_CLOSE, MEMORY_RESOURCES_GET, MEMORY_RESOURCES_GET_SUCCESS } from '@resources/memory/memory-resources.actions';
+import { NETWORK_NODE_DHT_CLOSE, NETWORK_NODE_DHT_GET_PEERS_SUCCESS, NETWORK_NODE_DHT_INIT } from '@network/node-dht/network-node-dht.actions';
import {
NETWORK_BOOTSTRAP_STATS_CLOSE,
NETWORK_BOOTSTRAP_STATS_GET_BOOTSTRAP_STATS_SUCCESS,
@@ -48,7 +31,8 @@ import {
BENCHMARKS_WALLETS_CLOSE,
BENCHMARKS_WALLETS_GET_ALL_TXS,
BENCHMARKS_WALLETS_GET_ALL_TXS_SUCCESS,
- BENCHMARKS_WALLETS_GET_WALLETS, BENCHMARKS_WALLETS_GET_WALLETS_SUCCESS,
+ BENCHMARKS_WALLETS_GET_WALLETS,
+ BENCHMARKS_WALLETS_GET_WALLETS_SUCCESS,
} from '@benchmarks/wallets/benchmarks-wallets.actions';
export type LoadingState = string[];
@@ -60,8 +44,6 @@ export function loadingReducer(state: LoadingState = initialState, action: Featu
/* ------------ ADD ------------ */
case `[${APP_PREFIX}] Init`:
- case DASHBOARD_INIT:
-
case `[${BLOCK_PRODUCTION_PREFIX} Overview] Get Slots`:
case `[${BLOCK_PRODUCTION_PREFIX} Won Slots] Init`:
@@ -90,11 +72,6 @@ export function loadingReducer(state: LoadingState = initialState, action: Featu
case `[${APP_PREFIX}] Init Success`:
return remove(state, `[${APP_PREFIX}] Init`);
- case DASHBOARD_GET_DATA_SUCCESS:
- return remove(state, DASHBOARD_INIT);
- case DASHBOARD_CLOSE:
- return remove(state, [DASHBOARD_INIT]);
-
case `[${BLOCK_PRODUCTION_PREFIX} Overview] Get Slots Success`:
return remove(state, `[${BLOCK_PRODUCTION_PREFIX} Overview] Get Slots`);
case `[${BLOCK_PRODUCTION_PREFIX} Overview] Close`:
diff --git a/frontend/src/app/layout/toolbar/toolbar.component.html b/frontend/src/app/layout/toolbar/toolbar.component.html
index 9d2980871f..0bdd8f4ad4 100644
--- a/frontend/src/app/layout/toolbar/toolbar.component.html
+++ b/frontend/src/app/layout/toolbar/toolbar.component.html
@@ -1,16 +1,25 @@
-