From a13ec828d99bac98896fa50903a41182961bbcf4 Mon Sep 17 00:00:00 2001 From: Liu <34062520+liuzhenyilang@users.noreply.github.com> Date: Mon, 1 Apr 2024 01:19:23 +0800 Subject: [PATCH 01/28] Fix: modify comments about packet loss rate calculation (#1362) Co-authored-by: liuzhen890106@163.com --- worker/src/RTC/TransportCongestionControlClient.cpp | 2 +- worker/src/RTC/TransportCongestionControlServer.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/worker/src/RTC/TransportCongestionControlClient.cpp b/worker/src/RTC/TransportCongestionControlClient.cpp index e6622b75e6..c8f82b64d3 100644 --- a/worker/src/RTC/TransportCongestionControlClient.cpp +++ b/worker/src/RTC/TransportCongestionControlClient.cpp @@ -241,7 +241,7 @@ namespace RTC void TransportCongestionControlClient::UpdatePacketLoss(double packetLoss) { - // Add the score into the histogram. + // Add the lost into the histogram. if (this->packetLossHistory.size() == PacketLossHistogramLength) { this->packetLossHistory.pop_front(); diff --git a/worker/src/RTC/TransportCongestionControlServer.cpp b/worker/src/RTC/TransportCongestionControlServer.cpp index 001bf6b9e0..c5d21de37a 100644 --- a/worker/src/RTC/TransportCongestionControlServer.cpp +++ b/worker/src/RTC/TransportCongestionControlServer.cpp @@ -397,7 +397,7 @@ namespace RTC void TransportCongestionControlServer::UpdatePacketLoss(double packetLoss) { - // Add the score into the histogram. + // Add the lost into the histogram. if (this->packetLossHistory.size() == PacketLossHistogramLength) { this->packetLossHistory.pop_front(); From cafe45642ef0eadc30e26729ed0575345abb1e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 2 Apr 2024 12:39:41 +0200 Subject: [PATCH 02/28] CI: Install PIP invoke package with --break-system-packages (#1364) --- .github/workflows/mediasoup-worker-fuzzer.yaml | 6 ++++++ .github/workflows/mediasoup-worker.yaml | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/.github/workflows/mediasoup-worker-fuzzer.yaml b/.github/workflows/mediasoup-worker-fuzzer.yaml index 211754342f..c72c3e89b6 100644 --- a/.github/workflows/mediasoup-worker-fuzzer.yaml +++ b/.github/workflows/mediasoup-worker-fuzzer.yaml @@ -32,6 +32,12 @@ jobs: # We need to install pip invoke manually. - name: pip3 install invoke run: pip3 install invoke + if: runner.os != 'macOS' + + # In macOS we need to specify this option. + - name: pip3 install --break-system-packages invoke + run: pip3 install --break-system-packages invoke + if: runner.os == 'macOS' # Build the mediasoup-worker-fuzzer binary (which uses libFuzzer). - name: invoke -r worker fuzzer diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 0ff40d5497..99c256e487 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -67,6 +67,12 @@ jobs: # We need to install pip invoke manually. - name: pip3 install invoke run: pip3 install invoke + if: runner.os != 'macOS' + + # In macOS we need to specify this option. + - name: pip3 install --break-system-packages invoke + run: pip3 install --break-system-packages invoke + if: runner.os == 'macOS' # We need to install npm deps of worker/scripts/package.json. - name: npm ci --prefix worker/scripts From 4408526d1987a0923564a8e8ec9af415d9fc6bb6 Mon Sep 17 00:00:00 2001 From: Arush Kurundodi <69193694+arcinston@users.noreply.github.com> Date: Tue, 2 Apr 2024 18:08:17 +0530 Subject: [PATCH 03/28] add arm64 prebuilt workers for linux (#1363) --- .github/workflows/mediasoup-node.yaml | 9 ++++++++ .github/workflows/mediasoup-rust.yaml | 22 +++++++++++-------- .../workflows/mediasoup-worker-fuzzer.yaml | 4 ++++ .../workflows/mediasoup-worker-prebuild.yaml | 10 +++++++++ .github/workflows/mediasoup-worker.yaml | 16 ++++++++++++++ 5 files changed, 52 insertions(+), 9 deletions(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index 1c66a6e855..0b5d7c420b 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -19,6 +19,15 @@ jobs: node: 18 - os: ubuntu-22.04 node: 20 + - os: ubuntu-20.04 + node: 16 + arch: arm64 + - os: ubuntu-20.04 + node: 18 + arch: arm64 + - os: ubuntu-22.04 + node: 20 + arch: arm64 - os: macos-12 node: 18 - os: macos-14 diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index 5622ccc573..c2f449c010 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -15,14 +15,18 @@ jobs: ci: strategy: matrix: - os: - - ubuntu-20.04 - - ubuntu-22.04 - - macos-12 - - macos-14 - - windows-2022 - - runs-on: ${{ matrix.os }} + ci: + - os: ubuntu-20.04 + - os: ubuntu-22.04 + - os: ubuntu-20.04 + arch: arm64 + - os: ubuntu-22.04 + arch: arm64 + - os: macos-12 + - os: macos-14 + - os: windows-2022 + + runs-on: ${{ matrix.ci.os }} env: KEEP_BUILD_ARTIFACTS: '1' @@ -37,7 +41,7 @@ jobs: path: | ~/.cargo/registry ~/.cargo/git - key: ${{ matrix.os }}-cargo-${{ hashFiles('**/Cargo.toml') }} + key: ${{ matrix.ci.os }}-cargo-${{ hashFiles('**/Cargo.toml') }} - name: cargo fmt run: cargo fmt --all -- --check diff --git a/.github/workflows/mediasoup-worker-fuzzer.yaml b/.github/workflows/mediasoup-worker-fuzzer.yaml index c72c3e89b6..6662e144ac 100644 --- a/.github/workflows/mediasoup-worker-fuzzer.yaml +++ b/.github/workflows/mediasoup-worker-fuzzer.yaml @@ -16,6 +16,10 @@ jobs: - os: ubuntu-22.04 cc: clang cxx: clang++ + - os: ubuntu-22.04 + cc: clang + cxx: clang++ + arch: arm64 runs-on: ${{ matrix.build.os }} diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index 4b6f61c532..e6616f033d 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -22,6 +22,16 @@ jobs: - os: ubuntu-22.04 cc: gcc cxx: g++ + # Worker prebuild for Linux on arm64. + - os: ubuntu-20.04 + cc: gcc + cxx: g++ + arch: arm64 + # Worker prebuild for Linux on arm64. + - os: ubuntu-22.04 + cc: gcc + cxx: g++ + arch: arm64 - os: macos-12 cc: clang cxx: clang++ diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 99c256e487..6851658a8f 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -25,6 +25,22 @@ jobs: - os: ubuntu-22.04 cc: clang cxx: clang++ + - os: ubuntu-20.04 + cc: gcc + cxx: g++ + arch: arm64 + - os: ubuntu-20.04 + cc: clang + cxx: clang++ + arch: arm64 + - os: ubuntu-22.04 + cc: gcc + cxx: g++ + arch: arm64 + - os: ubuntu-22.04 + cc: clang + cxx: clang++ + arch: arm64 - os: macos-12 cc: gcc cxx: g++ From 4d3f5c552f39cedb77cc3a38eed4a726ab9b250a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 2 Apr 2024 19:10:16 +0200 Subject: [PATCH 04/28] Update NPM dev deps --- package-lock.json | 332 +++++++++++++++++++++++----------------------- package.json | 4 +- 2 files changed, 168 insertions(+), 168 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5011e3ce8d..e65843070c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,8 +24,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.12.2", - "@typescript-eslint/eslint-plugin": "^7.4.0", - "@typescript-eslint/parser": "^7.4.0", + "@typescript-eslint/eslint-plugin": "^7.5.0", + "@typescript-eslint/parser": "^7.5.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^27.9.0", @@ -1669,16 +1669,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.4.0.tgz", - "integrity": "sha512-yHMQ/oFaM7HZdVrVm/M2WHaNPgyuJH4WelkSVEWSSsir34kxW2kDJCxlXRhhGWEsMN0WAW/vLpKfKVcm8k+MPw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.5.0.tgz", + "integrity": "sha512-HpqNTH8Du34nLxbKgVMGljZMG0rJd2O9ecvr2QLYp+7512ty1j42KnsFwspPXg1Vh8an9YImf6CokUBltisZFQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/type-utils": "7.4.0", - "@typescript-eslint/utils": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/type-utils": "7.5.0", + "@typescript-eslint/utils": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1704,13 +1704,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", - "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", + "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0" + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1721,9 +1721,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", - "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", + "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1734,13 +1734,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", - "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", + "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1762,17 +1762,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz", - "integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz", + "integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/typescript-estree": "7.4.0", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/typescript-estree": "7.5.0", "semver": "^7.5.4" }, "engines": { @@ -1787,12 +1787,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", - "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", + "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/types": "7.5.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1828,15 +1828,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.4.0.tgz", - "integrity": "sha512-ZvKHxHLusweEUVwrGRXXUVzFgnWhigo4JurEj0dGF1tbcGh6buL+ejDdjxOQxv6ytcY1uhun1p2sm8iWStlgLQ==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.5.0.tgz", + "integrity": "sha512-cj+XGhNujfD2/wzR1tabNsidnYRaFfEkcULdcIyVBYcXjBvBKOes+mpMBP7hMpOyk+gBcfXsrg4NBGAStQyxjQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/typescript-estree": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/typescript-estree": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4" }, "engines": { @@ -1856,13 +1856,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", - "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", + "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0" + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1873,9 +1873,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", - "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", + "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1886,13 +1886,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", - "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", + "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1914,12 +1914,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", - "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", + "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/types": "7.5.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1972,13 +1972,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.4.0.tgz", - "integrity": "sha512-247ETeHgr9WTRMqHbbQdzwzhuyaJ8dPTuyuUEMANqzMRB1rj/9qFIuIXK7l0FX9i9FXbHeBQl/4uz6mYuCE7Aw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz", + "integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.4.0", - "@typescript-eslint/utils": "7.4.0", + "@typescript-eslint/typescript-estree": "7.5.0", + "@typescript-eslint/utils": "7.5.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1999,13 +1999,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", - "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", + "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0" + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2016,9 +2016,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", - "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", + "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2029,13 +2029,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", - "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", + "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2057,17 +2057,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz", - "integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz", + "integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/typescript-estree": "7.4.0", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/typescript-estree": "7.5.0", "semver": "^7.5.4" }, "engines": { @@ -2082,12 +2082,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", - "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", + "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/types": "7.5.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -7570,16 +7570,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.4.0.tgz", - "integrity": "sha512-yHMQ/oFaM7HZdVrVm/M2WHaNPgyuJH4WelkSVEWSSsir34kxW2kDJCxlXRhhGWEsMN0WAW/vLpKfKVcm8k+MPw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.5.0.tgz", + "integrity": "sha512-HpqNTH8Du34nLxbKgVMGljZMG0rJd2O9ecvr2QLYp+7512ty1j42KnsFwspPXg1Vh8an9YImf6CokUBltisZFQ==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/type-utils": "7.4.0", - "@typescript-eslint/utils": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/type-utils": "7.5.0", + "@typescript-eslint/utils": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -7589,29 +7589,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", - "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", + "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0" + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0" } }, "@typescript-eslint/types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", - "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", + "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", - "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", + "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7621,27 +7621,27 @@ } }, "@typescript-eslint/utils": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz", - "integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz", + "integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/typescript-estree": "7.4.0", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/typescript-estree": "7.5.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", - "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", + "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/types": "7.5.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -7666,42 +7666,42 @@ } }, "@typescript-eslint/parser": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.4.0.tgz", - "integrity": "sha512-ZvKHxHLusweEUVwrGRXXUVzFgnWhigo4JurEj0dGF1tbcGh6buL+ejDdjxOQxv6ytcY1uhun1p2sm8iWStlgLQ==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.5.0.tgz", + "integrity": "sha512-cj+XGhNujfD2/wzR1tabNsidnYRaFfEkcULdcIyVBYcXjBvBKOes+mpMBP7hMpOyk+gBcfXsrg4NBGAStQyxjQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/typescript-estree": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/typescript-estree": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", - "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", + "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0" + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0" } }, "@typescript-eslint/types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", - "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", + "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", - "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", + "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7711,12 +7711,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", - "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", + "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/types": "7.5.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -7751,41 +7751,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.4.0.tgz", - "integrity": "sha512-247ETeHgr9WTRMqHbbQdzwzhuyaJ8dPTuyuUEMANqzMRB1rj/9qFIuIXK7l0FX9i9FXbHeBQl/4uz6mYuCE7Aw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz", + "integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.4.0", - "@typescript-eslint/utils": "7.4.0", + "@typescript-eslint/typescript-estree": "7.5.0", + "@typescript-eslint/utils": "7.5.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", - "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", + "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0" + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0" } }, "@typescript-eslint/types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", - "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", + "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", - "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", + "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/visitor-keys": "7.5.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7795,27 +7795,27 @@ } }, "@typescript-eslint/utils": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz", - "integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz", + "integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/typescript-estree": "7.4.0", + "@typescript-eslint/scope-manager": "7.5.0", + "@typescript-eslint/types": "7.5.0", + "@typescript-eslint/typescript-estree": "7.5.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", - "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", + "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/types": "7.5.0", "eslint-visitor-keys": "^3.4.1" } }, diff --git a/package.json b/package.json index 33596e6c28..ea960acec9 100644 --- a/package.json +++ b/package.json @@ -113,8 +113,8 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.12.2", - "@typescript-eslint/eslint-plugin": "^7.4.0", - "@typescript-eslint/parser": "^7.4.0", + "@typescript-eslint/eslint-plugin": "^7.5.0", + "@typescript-eslint/parser": "^7.5.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^27.9.0", From 8389947c3c6f1a3bbac75efa6285c81dd917ed65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 3 Apr 2024 11:46:40 +0200 Subject: [PATCH 05/28] Node tests: pass to utils.deepFreeze() --- node/src/test/test-ActiveSpeakerObserver.ts | 2 +- node/src/test/test-AudioLevelObserver.ts | 2 +- node/src/test/test-Consumer.ts | 182 ++++++++++---------- node/src/test/test-DataConsumer.ts | 2 +- node/src/test/test-DataProducer.ts | 4 +- node/src/test/test-PipeTransport.ts | 114 ++++++------ node/src/test/test-PlainTransport.ts | 2 +- node/src/test/test-Producer.ts | 6 +- node/src/test/test-Router.ts | 2 +- node/src/test/test-WebRtcTransport.ts | 2 +- node/src/test/test-multiopus.ts | 76 ++++---- 11 files changed, 200 insertions(+), 194 deletions(-) diff --git a/node/src/test/test-ActiveSpeakerObserver.ts b/node/src/test/test-ActiveSpeakerObserver.ts index 2f31ff5379..b4f2689fd0 100644 --- a/node/src/test/test-ActiveSpeakerObserver.ts +++ b/node/src/test/test-ActiveSpeakerObserver.ts @@ -8,7 +8,7 @@ type TestContext = { }; const ctx: TestContext = { - mediaCodecs: utils.deepFreeze([ + mediaCodecs: utils.deepFreeze([ { kind: 'audio', mimeType: 'audio/opus', diff --git a/node/src/test/test-AudioLevelObserver.ts b/node/src/test/test-AudioLevelObserver.ts index f981d59df9..7d4fe82592 100644 --- a/node/src/test/test-AudioLevelObserver.ts +++ b/node/src/test/test-AudioLevelObserver.ts @@ -8,7 +8,7 @@ type TestContext = { }; const ctx: TestContext = { - mediaCodecs: utils.deepFreeze([ + mediaCodecs: utils.deepFreeze([ { kind: 'audio', mimeType: 'audio/opus', diff --git a/node/src/test/test-Consumer.ts b/node/src/test/test-Consumer.ts index ee643c7a25..0d3a4a056e 100644 --- a/node/src/test/test-Consumer.ts +++ b/node/src/test/test-Consumer.ts @@ -24,7 +24,7 @@ type TestContext = { }; const ctx: TestContext = { - mediaCodecs: utils.deepFreeze([ + mediaCodecs: utils.deepFreeze([ { kind: 'audio', mimeType: 'audio/opus', @@ -51,7 +51,7 @@ const ctx: TestContext = { }, }, ]), - audioProducerOptions: utils.deepFreeze({ + audioProducerOptions: utils.deepFreeze({ kind: 'audio', rtpParameters: { mid: 'AUDIO', @@ -86,7 +86,7 @@ const ctx: TestContext = { }, appData: { foo: 1, bar: '2' }, }), - videoProducerOptions: utils.deepFreeze({ + videoProducerOptions: utils.deepFreeze({ kind: 'video', rtpParameters: { mid: 'VIDEO', @@ -134,95 +134,97 @@ const ctx: TestContext = { }, appData: { foo: 1, bar: '2' }, }), - consumerDeviceCapabilities: utils.deepFreeze({ - codecs: [ - { - mimeType: 'audio/opus', - kind: 'audio', - preferredPayloadType: 100, - clockRate: 48000, - channels: 2, - rtcpFeedback: [{ type: 'nack', parameter: '' }], - }, - { - mimeType: 'video/H264', - kind: 'video', - preferredPayloadType: 101, - clockRate: 90000, - parameters: { - 'level-asymmetry-allowed': 1, - 'packetization-mode': 1, - 'profile-level-id': '4d0032', + consumerDeviceCapabilities: utils.deepFreeze( + { + codecs: [ + { + mimeType: 'audio/opus', + kind: 'audio', + preferredPayloadType: 100, + clockRate: 48000, + channels: 2, + rtcpFeedback: [{ type: 'nack', parameter: '' }], }, - rtcpFeedback: [ - { type: 'nack', parameter: '' }, - { type: 'nack', parameter: 'pli' }, - { type: 'ccm', parameter: 'fir' }, - { type: 'goog-remb', parameter: '' }, - ], - }, - { - mimeType: 'video/rtx', - kind: 'video', - preferredPayloadType: 102, - clockRate: 90000, - parameters: { - apt: 101, + { + mimeType: 'video/H264', + kind: 'video', + preferredPayloadType: 101, + clockRate: 90000, + parameters: { + 'level-asymmetry-allowed': 1, + 'packetization-mode': 1, + 'profile-level-id': '4d0032', + }, + rtcpFeedback: [ + { type: 'nack', parameter: '' }, + { type: 'nack', parameter: 'pli' }, + { type: 'ccm', parameter: 'fir' }, + { type: 'goog-remb', parameter: '' }, + ], }, - rtcpFeedback: [], - }, - ], - headerExtensions: [ - { - kind: 'audio', - uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId: 1, - preferredEncrypt: false, - }, - { - kind: 'video', - uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId: 1, - preferredEncrypt: false, - }, - { - kind: 'video', - uri: 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id', - preferredId: 2, - preferredEncrypt: false, - }, - { - kind: 'audio', - uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len - preferredId: 4, - preferredEncrypt: false, - }, - { - kind: 'video', - uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len - preferredId: 4, - preferredEncrypt: false, - }, - { - kind: 'audio', - uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - preferredId: 10, - preferredEncrypt: false, - }, - { - kind: 'video', - uri: 'urn:3gpp:video-orientation', - preferredId: 11, - preferredEncrypt: false, - }, - { - kind: 'video', - uri: 'urn:ietf:params:rtp-hdrext:toffset', - preferredId: 12, - preferredEncrypt: false, - }, - ], - }), + { + mimeType: 'video/rtx', + kind: 'video', + preferredPayloadType: 102, + clockRate: 90000, + parameters: { + apt: 101, + }, + rtcpFeedback: [], + }, + ], + headerExtensions: [ + { + kind: 'audio', + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId: 1, + preferredEncrypt: false, + }, + { + kind: 'video', + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId: 1, + preferredEncrypt: false, + }, + { + kind: 'video', + uri: 'urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id', + preferredId: 2, + preferredEncrypt: false, + }, + { + kind: 'audio', + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len + preferredId: 4, + preferredEncrypt: false, + }, + { + kind: 'video', + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len + preferredId: 4, + preferredEncrypt: false, + }, + { + kind: 'audio', + uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + preferredId: 10, + preferredEncrypt: false, + }, + { + kind: 'video', + uri: 'urn:3gpp:video-orientation', + preferredId: 11, + preferredEncrypt: false, + }, + { + kind: 'video', + uri: 'urn:ietf:params:rtp-hdrext:toffset', + preferredId: 12, + preferredEncrypt: false, + }, + ], + } + ), }; beforeEach(async () => { diff --git a/node/src/test/test-DataConsumer.ts b/node/src/test/test-DataConsumer.ts index d37ab10c30..163f4d4e19 100644 --- a/node/src/test/test-DataConsumer.ts +++ b/node/src/test/test-DataConsumer.ts @@ -12,7 +12,7 @@ type TestContext = { }; const ctx: TestContext = { - dataProducerOptions: utils.deepFreeze({ + dataProducerOptions: utils.deepFreeze({ sctpStreamParameters: { streamId: 12345, ordered: false, diff --git a/node/src/test/test-DataProducer.ts b/node/src/test/test-DataProducer.ts index 54362f4381..c5dddaacba 100644 --- a/node/src/test/test-DataProducer.ts +++ b/node/src/test/test-DataProducer.ts @@ -11,7 +11,7 @@ type TestContext = { }; const ctx: TestContext = { - dataProducerOptions1: utils.deepFreeze({ + dataProducerOptions1: utils.deepFreeze({ sctpStreamParameters: { streamId: 666, }, @@ -19,7 +19,7 @@ const ctx: TestContext = { protocol: 'bar', appData: { foo: 1, bar: '2' }, }), - dataProducerOptions2: utils.deepFreeze({ + dataProducerOptions2: utils.deepFreeze({ sctpStreamParameters: { streamId: 777, maxRetransmits: 3, diff --git a/node/src/test/test-PipeTransport.ts b/node/src/test/test-PipeTransport.ts index 7be3294d07..3b9052374d 100644 --- a/node/src/test/test-PipeTransport.ts +++ b/node/src/test/test-PipeTransport.ts @@ -22,7 +22,7 @@ type TestContext = { }; const ctx: TestContext = { - mediaCodecs: utils.deepFreeze([ + mediaCodecs: utils.deepFreeze([ { kind: 'audio', mimeType: 'audio/opus', @@ -35,7 +35,7 @@ const ctx: TestContext = { clockRate: 90000, }, ]), - audioProducerOptions: utils.deepFreeze({ + audioProducerOptions: utils.deepFreeze({ kind: 'audio', rtpParameters: { mid: 'AUDIO', @@ -64,7 +64,7 @@ const ctx: TestContext = { }, appData: { foo: 'bar1' }, }), - videoProducerOptions: utils.deepFreeze({ + videoProducerOptions: utils.deepFreeze({ kind: 'video', rtpParameters: { mid: 'VIDEO', @@ -102,7 +102,7 @@ const ctx: TestContext = { }, appData: { foo: 'bar2' }, }), - dataProducerOptions: utils.deepFreeze({ + dataProducerOptions: utils.deepFreeze({ sctpStreamParameters: { streamId: 666, ordered: false, @@ -111,59 +111,61 @@ const ctx: TestContext = { label: 'foo', protocol: 'bar', }), - consumerDeviceCapabilities: utils.deepFreeze({ - codecs: [ - { - kind: 'audio', - mimeType: 'audio/opus', - preferredPayloadType: 100, - clockRate: 48000, - channels: 2, - }, - { - kind: 'video', - mimeType: 'video/VP8', - preferredPayloadType: 101, - clockRate: 90000, - rtcpFeedback: [ - { type: 'nack' }, - { type: 'ccm', parameter: 'fir' }, - { type: 'transport-cc' }, - ], - }, - { - kind: 'video', - mimeType: 'video/rtx', - preferredPayloadType: 102, - clockRate: 90000, - parameters: { - apt: 101, + consumerDeviceCapabilities: utils.deepFreeze( + { + codecs: [ + { + kind: 'audio', + mimeType: 'audio/opus', + preferredPayloadType: 100, + clockRate: 48000, + channels: 2, }, - rtcpFeedback: [], - }, - ], - headerExtensions: [ - { - kind: 'video', - uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', - preferredId: 4, - preferredEncrypt: false, - direction: 'sendrecv', - }, - { - kind: 'video', - uri: 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', - preferredId: 5, - preferredEncrypt: false, - }, - { - kind: 'audio', - uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - preferredId: 10, - preferredEncrypt: false, - }, - ], - }), + { + kind: 'video', + mimeType: 'video/VP8', + preferredPayloadType: 101, + clockRate: 90000, + rtcpFeedback: [ + { type: 'nack' }, + { type: 'ccm', parameter: 'fir' }, + { type: 'transport-cc' }, + ], + }, + { + kind: 'video', + mimeType: 'video/rtx', + preferredPayloadType: 102, + clockRate: 90000, + parameters: { + apt: 101, + }, + rtcpFeedback: [], + }, + ], + headerExtensions: [ + { + kind: 'video', + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', + preferredId: 4, + preferredEncrypt: false, + direction: 'sendrecv', + }, + { + kind: 'video', + uri: 'http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01', + preferredId: 5, + preferredEncrypt: false, + }, + { + kind: 'audio', + uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + preferredId: 10, + preferredEncrypt: false, + }, + ], + } + ), }; beforeEach(async () => { diff --git a/node/src/test/test-PlainTransport.ts b/node/src/test/test-PlainTransport.ts index 097cc2b91f..6588fe55cb 100644 --- a/node/src/test/test-PlainTransport.ts +++ b/node/src/test/test-PlainTransport.ts @@ -12,7 +12,7 @@ type TestContext = { }; const ctx: TestContext = { - mediaCodecs: utils.deepFreeze([ + mediaCodecs: utils.deepFreeze([ { kind: 'audio', mimeType: 'audio/opus', diff --git a/node/src/test/test-Producer.ts b/node/src/test/test-Producer.ts index 18cc7eaa90..d6fe900cf4 100644 --- a/node/src/test/test-Producer.ts +++ b/node/src/test/test-Producer.ts @@ -20,7 +20,7 @@ type TestContext = { }; const ctx: TestContext = { - mediaCodecs: utils.deepFreeze([ + mediaCodecs: utils.deepFreeze([ { kind: 'audio', mimeType: 'audio/opus', @@ -48,7 +48,7 @@ const ctx: TestContext = { rtcpFeedback: [], // Will be ignored. }, ]), - audioProducerOptions: utils.deepFreeze({ + audioProducerOptions: utils.deepFreeze({ kind: 'audio', rtpParameters: { mid: 'AUDIO', @@ -83,7 +83,7 @@ const ctx: TestContext = { }, appData: { foo: 1, bar: '2' }, }), - videoProducerOptions: utils.deepFreeze({ + videoProducerOptions: utils.deepFreeze({ kind: 'video', rtpParameters: { mid: 'VIDEO', diff --git a/node/src/test/test-Router.ts b/node/src/test/test-Router.ts index b5f989bfe4..d904883509 100644 --- a/node/src/test/test-Router.ts +++ b/node/src/test/test-Router.ts @@ -8,7 +8,7 @@ type TestContext = { }; const ctx: TestContext = { - mediaCodecs: utils.deepFreeze([ + mediaCodecs: utils.deepFreeze([ { kind: 'audio', mimeType: 'audio/opus', diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index c605c05cb5..129a33a19b 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -18,7 +18,7 @@ type TestContext = { }; const ctx: TestContext = { - mediaCodecs: utils.deepFreeze([ + mediaCodecs: utils.deepFreeze([ { kind: 'audio', mimeType: 'audio/opus', diff --git a/node/src/test/test-multiopus.ts b/node/src/test/test-multiopus.ts index cf7ea964f1..2b419271bf 100644 --- a/node/src/test/test-multiopus.ts +++ b/node/src/test/test-multiopus.ts @@ -12,7 +12,7 @@ type TestContext = { }; const ctx: TestContext = { - mediaCodecs: utils.deepFreeze([ + mediaCodecs: utils.deepFreeze([ { kind: 'audio', mimeType: 'audio/multiopus', @@ -27,7 +27,7 @@ const ctx: TestContext = { }, }, ]), - audioProducerOptions: utils.deepFreeze({ + audioProducerOptions: utils.deepFreeze({ kind: 'audio', rtpParameters: { mid: 'AUDIO', @@ -57,42 +57,44 @@ const ctx: TestContext = { ], }, }), - consumerDeviceCapabilities: utils.deepFreeze({ - codecs: [ - { - mimeType: 'audio/multiopus', - kind: 'audio', - preferredPayloadType: 100, - clockRate: 48000, - channels: 6, - parameters: { - channel_mapping: '0,4,1,2,3,5', - num_streams: 4, - coupled_streams: 2, + consumerDeviceCapabilities: utils.deepFreeze( + { + codecs: [ + { + mimeType: 'audio/multiopus', + kind: 'audio', + preferredPayloadType: 100, + clockRate: 48000, + channels: 6, + parameters: { + channel_mapping: '0,4,1,2,3,5', + num_streams: 4, + coupled_streams: 2, + }, }, - }, - ], - headerExtensions: [ - { - kind: 'audio', - uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', - preferredId: 1, - preferredEncrypt: false, - }, - { - kind: 'audio', - uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len - preferredId: 4, - preferredEncrypt: false, - }, - { - kind: 'audio', - uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', - preferredId: 10, - preferredEncrypt: false, - }, - ], - }), + ], + headerExtensions: [ + { + kind: 'audio', + uri: 'urn:ietf:params:rtp-hdrext:sdes:mid', + preferredId: 1, + preferredEncrypt: false, + }, + { + kind: 'audio', + uri: 'http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time', // eslint-disable-line max-len + preferredId: 4, + preferredEncrypt: false, + }, + { + kind: 'audio', + uri: 'urn:ietf:params:rtp-hdrext:ssrc-audio-level', + preferredId: 10, + preferredEncrypt: false, + }, + ], + } + ), }; beforeEach(async () => { From cd475ac36e409b43084a40fbe1a6889c8fc1b9e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 5 Apr 2024 11:01:17 +0200 Subject: [PATCH 06/28] cosmetic --- worker/src/Worker.cpp | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/worker/src/Worker.cpp b/worker/src/Worker.cpp index 1bd5468f88..2dd3cb2b6f 100644 --- a/worker/src/Worker.cpp +++ b/worker/src/Worker.cpp @@ -216,6 +216,18 @@ flatbuffers::Offset Worker::FillBufferResour uvRusage.ru_nivcsw); } +RTC::WebRtcServer* Worker::GetWebRtcServer(const std::string& webRtcServerId) const +{ + auto it = this->mapWebRtcServers.find(webRtcServerId); + + if (it == this->mapWebRtcServers.end()) + { + MS_THROW_ERROR("WebRtcServer not found"); + } + + return it->second; +} + RTC::Router* Worker::GetRouter(const std::string& routerId) const { MS_TRACE(); @@ -246,19 +258,7 @@ void Worker::CheckNoRouter(const std::string& routerId) const } } -RTC::WebRtcServer* Worker::GetWebRtcServer(const std::string& webRtcServerId) const -{ - auto it = this->mapWebRtcServers.find(webRtcServerId); - - if (it == this->mapWebRtcServers.end()) - { - MS_THROW_ERROR("WebRtcServer not found"); - } - - return it->second; -} - -inline void Worker::HandleRequest(Channel::ChannelRequest* request) +void Worker::HandleRequest(Channel::ChannelRequest* request) { MS_TRACE(); @@ -449,7 +449,7 @@ inline void Worker::HandleRequest(Channel::ChannelRequest* request) } } -inline void Worker::HandleNotification(Channel::ChannelNotification* notification) +void Worker::HandleNotification(Channel::ChannelNotification* notification) { MS_TRACE(); @@ -478,7 +478,7 @@ inline void Worker::HandleNotification(Channel::ChannelNotification* notificatio } } -inline void Worker::OnChannelClosed(Channel::ChannelSocket* /*socket*/) +void Worker::OnChannelClosed(Channel::ChannelSocket* /*socket*/) { MS_TRACE_STD(); @@ -492,7 +492,7 @@ inline void Worker::OnChannelClosed(Channel::ChannelSocket* /*socket*/) Close(); } -inline void Worker::OnSignal(SignalHandle* /*signalHandle*/, int signum) +void Worker::OnSignal(SignalHandle* /*signalHandle*/, int signum) { MS_TRACE(); @@ -538,8 +538,7 @@ inline void Worker::OnSignal(SignalHandle* /*signalHandle*/, int signum) } } -inline RTC::WebRtcServer* Worker::OnRouterNeedWebRtcServer( - RTC::Router* /*router*/, std::string& webRtcServerId) +RTC::WebRtcServer* Worker::OnRouterNeedWebRtcServer(RTC::Router* /*router*/, std::string& webRtcServerId) { MS_TRACE(); From f7b96b87f6462c614e48ea9e8d768fa7f27f2ee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 5 Apr 2024 11:50:51 +0200 Subject: [PATCH 07/28] cosmetic --- worker/include/Utils.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/worker/include/Utils.hpp b/worker/include/Utils.hpp index 4e2d0ba15f..53bb2d3cde 100644 --- a/worker/include/Utils.hpp +++ b/worker/include/Utils.hpp @@ -28,7 +28,10 @@ namespace Utils static bool CompareAddresses(const struct sockaddr* addr1, const struct sockaddr* addr2) { // Compare family. - if (addr1->sa_family != addr2->sa_family || (addr1->sa_family != AF_INET && addr1->sa_family != AF_INET6)) + if ( + addr1->sa_family != addr2->sa_family || + (addr1->sa_family != AF_INET && addr1->sa_family != AF_INET6) || + (addr2->sa_family != AF_INET && addr2->sa_family != AF_INET6)) { return false; } From dd691ff289fb3ef97bf96b9bb9cd5c4c31eab0e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 5 Apr 2024 14:42:02 +0200 Subject: [PATCH 08/28] cosmetic --- worker/include/RTC/TransportTuple.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index 9366ba5d54..19750caf99 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -130,7 +130,7 @@ namespace RTC { if (this->protocol == Protocol::UDP) { - return (const struct sockaddr*)this->udpRemoteAddr; + return static_cast(this->udpRemoteAddr); } else { From 16e430486dd331a8eb65385a0ec9f22a64639458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 8 Apr 2024 13:46:45 +0200 Subject: [PATCH 09/28] Require Node >= 18 (#1367) --- .github/workflows/mediasoup-node.yaml | 8 +- CHANGELOG.md | 4 + package-lock.json | 994 ++++++++++---------------- package.json | 10 +- worker/scripts/package-lock.json | 113 +-- worker/scripts/package.json | 2 +- 6 files changed, 409 insertions(+), 722 deletions(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index 0b5d7c420b..bf643d7caf 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -13,15 +13,10 @@ jobs: strategy: matrix: ci: - - os: ubuntu-20.04 - node: 16 - os: ubuntu-20.04 node: 18 - os: ubuntu-22.04 node: 20 - - os: ubuntu-20.04 - node: 16 - arch: arm64 - os: ubuntu-20.04 node: 18 arch: arm64 @@ -59,9 +54,8 @@ jobs: restore-keys: | ${{ matrix.ci.os }}-node- - # NOTE: Add --force since some dev dependencies require Node >= 18. - name: npm ci - run: npm ci --force --foreground-scripts + run: npm ci --foreground-scripts - name: npm run lint:node run: npm run lint:node diff --git a/CHANGELOG.md b/CHANGELOG.md index a22380b77f..8de44463fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### NEXT + +- Require Node.js >= 18 ([PR #1365](https://github.com/versatica/mediasoup/pull/1365)). + ### 3.13.24 - Node: Fix missing `bitrateByLayer` field in stats of `RtpRecvStream` in Node ([PR #1349](https://github.com/versatica/mediasoup/pull/1349)). diff --git a/package-lock.json b/package-lock.json index e65843070c..4531ca93d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,15 +20,15 @@ "tar": "^6.2.1" }, "devDependencies": { - "@octokit/rest": "^20.0.2", + "@octokit/rest": "^20.1.0", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.12.2", + "@types/node": "^20.12.5", "@typescript-eslint/eslint-plugin": "^7.5.0", "@typescript-eslint/parser": "^7.5.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^27.9.0", + "eslint-plugin-jest": "^28.2.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "marked": "^12.0.1", @@ -37,10 +37,10 @@ "prettier": "^3.2.5", "sctp": "^1.0.0", "ts-jest": "^29.1.2", - "typescript": "^5.4.3" + "typescript": "^5.4.4" }, "engines": { - "node": ">=16" + "node": ">=18" }, "funding": { "type": "opencollective", @@ -806,9 +806,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { @@ -1305,16 +1305,16 @@ } }, "node_modules/@octokit/core": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.0.tgz", - "integrity": "sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.0.tgz", + "integrity": "sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==", "dev": true, "dependencies": { "@octokit/auth-token": "^4.0.0", - "@octokit/graphql": "^7.0.0", - "@octokit/request": "^8.0.2", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^11.0.0", + "@octokit/graphql": "^7.1.0", + "@octokit/request": "^8.3.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" }, @@ -1323,13 +1323,12 @@ } }, "node_modules/@octokit/endpoint": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.0.tgz", - "integrity": "sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.5.tgz", + "integrity": "sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==", "dev": true, "dependencies": { - "@octokit/types": "^11.0.0", - "is-plain-object": "^5.0.0", + "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" }, "engines": { @@ -1337,13 +1336,13 @@ } }, "node_modules/@octokit/graphql": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.1.tgz", - "integrity": "sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.0.tgz", + "integrity": "sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==", "dev": true, "dependencies": { - "@octokit/request": "^8.0.1", - "@octokit/types": "^11.0.0", + "@octokit/request": "^8.3.0", + "@octokit/types": "^13.0.0", "universal-user-agent": "^6.0.0" }, "engines": { @@ -1351,39 +1350,39 @@ } }, "node_modules/@octokit/openapi-types": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", - "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==", + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-21.2.0.tgz", + "integrity": "sha512-xx+Xd6I7rYvul/hgUDqv6TeGX0IOGnhSg9IOeYgd/uI7IAqUy6DE2B6Ipv2M4mWoxaMcWjIzgTIcv8pMO3F3vw==", "dev": true }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.0.0.tgz", - "integrity": "sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz", + "integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==", "dev": true, "dependencies": { - "@octokit/types": "^12.0.0" + "@octokit/types": "^12.6.0" }, "engines": { "node": ">= 18" }, "peerDependencies": { - "@octokit/core": ">=5" + "@octokit/core": "5" } }, "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", - "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", "dev": true }, "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", - "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", "dev": true, "dependencies": { - "@octokit/openapi-types": "^19.0.0" + "@octokit/openapi-types": "^20.0.0" } }, "node_modules/@octokit/plugin-request-log": { @@ -1399,45 +1398,44 @@ } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.0.0.tgz", - "integrity": "sha512-16VkwE2v6rXU+/gBsYC62M8lKWOphY5Lg4wpjYnVE9Zbu0J6IwiT5kILoj1YOB53XLmcJR+Nqp8DmifOPY4H3g==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", + "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", "dev": true, "dependencies": { - "@octokit/types": "^12.0.0" + "@octokit/types": "^12.6.0" }, "engines": { "node": ">= 18" }, "peerDependencies": { - "@octokit/core": ">=5" + "@octokit/core": "5" } }, "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", - "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", "dev": true }, "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", - "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", "dev": true, "dependencies": { - "@octokit/openapi-types": "^19.0.0" + "@octokit/openapi-types": "^20.0.0" } }, "node_modules/@octokit/request": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.1.tgz", - "integrity": "sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.3.1.tgz", + "integrity": "sha512-fin4cl5eHN5Ybmb/gtn7YZ+ycyUlcyqqkg5lfxeSChqj7sUt6TNaJPehREi+0PABKLREYL8pfaUhH3TicEWNoA==", "dev": true, "dependencies": { - "@octokit/endpoint": "^9.0.0", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^11.1.0", - "is-plain-object": "^5.0.0", + "@octokit/endpoint": "^9.0.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.0.0", "universal-user-agent": "^6.0.0" }, "engines": { @@ -1445,12 +1443,12 @@ } }, "node_modules/@octokit/request-error": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.0.tgz", - "integrity": "sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.0.tgz", + "integrity": "sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==", "dev": true, "dependencies": { - "@octokit/types": "^11.0.0", + "@octokit/types": "^13.1.0", "deprecation": "^2.0.0", "once": "^1.4.0" }, @@ -1459,27 +1457,27 @@ } }, "node_modules/@octokit/rest": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.2.tgz", - "integrity": "sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==", + "version": "20.1.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.1.0.tgz", + "integrity": "sha512-STVO3itHQLrp80lvcYB2UIKoeil5Ctsgd2s1AM+du3HqZIR35ZH7WE9HLwUOLXH0myA0y3AGNPo8gZtcgIbw0g==", "dev": true, "dependencies": { - "@octokit/core": "^5.0.0", - "@octokit/plugin-paginate-rest": "^9.0.0", + "@octokit/core": "^5.0.2", + "@octokit/plugin-paginate-rest": "^9.1.5", "@octokit/plugin-request-log": "^4.0.0", - "@octokit/plugin-rest-endpoint-methods": "^10.0.0" + "@octokit/plugin-rest-endpoint-methods": "^10.2.0" }, "engines": { "node": ">= 18" } }, "node_modules/@octokit/types": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.1.0.tgz", - "integrity": "sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.1.0.tgz", + "integrity": "sha512-nBwAFOYqVUUJ2AZFK4ZzESQptaAVqdTDKk8gE0Xr0o99WuPDSrhUC38x0F40xD9OUxXhOOuZKWNNVVLPSHQDvQ==", "dev": true, "dependencies": { - "@octokit/openapi-types": "^18.0.0" + "@octokit/openapi-types": "^21.0.0" } }, "node_modules/@pkgr/core": { @@ -1633,9 +1631,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.12.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.2.tgz", - "integrity": "sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==", + "version": "20.12.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.5.tgz", + "integrity": "sha512-BD+BjQ9LS/D8ST9p5uqBxghlN+S42iuNxjsUGjeZobe/ciXzk2qb1B6IXc6AnRLS+yFJRpN2IPEHMzwspfDJNw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1720,6 +1718,33 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz", + "integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.5.0", + "@typescript-eslint/utils": "7.5.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", @@ -1955,87 +1980,43 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz", - "integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "7.5.0", - "@typescript-eslint/utils": "7.5.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", - "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", - "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", - "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2044,7 +2025,7 @@ "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", @@ -2056,49 +2037,7 @@ } } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz", - "integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.5.0", - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/typescript-estree": "7.5.0", - "semver": "^7.5.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", - "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.5.0", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", @@ -2107,7 +2046,7 @@ "balanced-match": "^1.0.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", @@ -2122,83 +2061,17 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", @@ -2212,9 +2085,9 @@ "dev": true }, "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -3010,19 +2883,19 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", - "integrity": "sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==", + "version": "28.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.2.0.tgz", + "integrity": "sha512-yRDti/a+f+SMSmNTiT9/M/MzXGkitl8CfzUxnpoQcTyfq8gUrXMriVcWU36W1X6BZSUoyUCJrDAWWUA2N4hE5g==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "^5.10.0" + "@typescript-eslint/utils": "^6.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.10.0 || ^18.12.0 || >=20.0.0" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0 || ^7.0.0", - "eslint": "^7.0.0 || ^8.0.0", + "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0", + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0", "jest": "*" }, "peerDependenciesMeta": { @@ -3034,6 +2907,31 @@ } } }, + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, "node_modules/eslint-plugin-prettier": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", @@ -3065,31 +2963,6 @@ } }, "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", @@ -3105,13 +2978,16 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "engines": { - "node": ">=4.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/espree": { @@ -3156,15 +3032,6 @@ "node": ">=0.10" } }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -3177,7 +3044,7 @@ "node": ">=4.0" } }, - "node_modules/esrecurse/node_modules/estraverse": { + "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", @@ -3186,15 +3053,6 @@ "node": ">=4.0" } }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -3402,12 +3260,13 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { @@ -3420,9 +3279,9 @@ "integrity": "sha512-3HDgPbgiwWMI9zVB7VYBHaMrbOO7Gm0v+yD2FV/sCKj+9NDeVL7BOBYUuhWAQGKWOzBo8S9WdMvV0eixO233XQ==" }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "node_modules/formdata-polyfill": { @@ -3568,9 +3427,9 @@ } }, "node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -3877,15 +3736,6 @@ "node": ">=8" } }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -4609,6 +4459,12 @@ "node": ">=4" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -4639,6 +4495,15 @@ "node": ">=6" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -5997,27 +5862,6 @@ } } }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -6052,9 +5896,9 @@ } }, "node_modules/typescript": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", - "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", + "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -6086,9 +5930,9 @@ } }, "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", "dev": true }, "node_modules/update-browserslist-db": { @@ -6849,9 +6693,9 @@ "dev": true }, "@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, "@istanbuljs/load-nyc-config": { @@ -7243,70 +7087,69 @@ "dev": true }, "@octokit/core": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.0.tgz", - "integrity": "sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.0.tgz", + "integrity": "sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==", "dev": true, "requires": { "@octokit/auth-token": "^4.0.0", - "@octokit/graphql": "^7.0.0", - "@octokit/request": "^8.0.2", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^11.0.0", + "@octokit/graphql": "^7.1.0", + "@octokit/request": "^8.3.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" } }, "@octokit/endpoint": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.0.tgz", - "integrity": "sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.5.tgz", + "integrity": "sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==", "dev": true, "requires": { - "@octokit/types": "^11.0.0", - "is-plain-object": "^5.0.0", + "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" } }, "@octokit/graphql": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.1.tgz", - "integrity": "sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.0.tgz", + "integrity": "sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==", "dev": true, "requires": { - "@octokit/request": "^8.0.1", - "@octokit/types": "^11.0.0", + "@octokit/request": "^8.3.0", + "@octokit/types": "^13.0.0", "universal-user-agent": "^6.0.0" } }, "@octokit/openapi-types": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", - "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==", + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-21.2.0.tgz", + "integrity": "sha512-xx+Xd6I7rYvul/hgUDqv6TeGX0IOGnhSg9IOeYgd/uI7IAqUy6DE2B6Ipv2M4mWoxaMcWjIzgTIcv8pMO3F3vw==", "dev": true }, "@octokit/plugin-paginate-rest": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.0.0.tgz", - "integrity": "sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz", + "integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==", "dev": true, "requires": { - "@octokit/types": "^12.0.0" + "@octokit/types": "^12.6.0" }, "dependencies": { "@octokit/openapi-types": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", - "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", "dev": true }, "@octokit/types": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", - "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", "dev": true, "requires": { - "@octokit/openapi-types": "^19.0.0" + "@octokit/openapi-types": "^20.0.0" } } } @@ -7319,74 +7162,73 @@ "requires": {} }, "@octokit/plugin-rest-endpoint-methods": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.0.0.tgz", - "integrity": "sha512-16VkwE2v6rXU+/gBsYC62M8lKWOphY5Lg4wpjYnVE9Zbu0J6IwiT5kILoj1YOB53XLmcJR+Nqp8DmifOPY4H3g==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", + "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", "dev": true, "requires": { - "@octokit/types": "^12.0.0" + "@octokit/types": "^12.6.0" }, "dependencies": { "@octokit/openapi-types": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", - "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", "dev": true }, "@octokit/types": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", - "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", "dev": true, "requires": { - "@octokit/openapi-types": "^19.0.0" + "@octokit/openapi-types": "^20.0.0" } } } }, "@octokit/request": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.1.tgz", - "integrity": "sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.3.1.tgz", + "integrity": "sha512-fin4cl5eHN5Ybmb/gtn7YZ+ycyUlcyqqkg5lfxeSChqj7sUt6TNaJPehREi+0PABKLREYL8pfaUhH3TicEWNoA==", "dev": true, "requires": { - "@octokit/endpoint": "^9.0.0", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^11.1.0", - "is-plain-object": "^5.0.0", + "@octokit/endpoint": "^9.0.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.0.0", "universal-user-agent": "^6.0.0" } }, "@octokit/request-error": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.0.tgz", - "integrity": "sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.0.tgz", + "integrity": "sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==", "dev": true, "requires": { - "@octokit/types": "^11.0.0", + "@octokit/types": "^13.1.0", "deprecation": "^2.0.0", "once": "^1.4.0" } }, "@octokit/rest": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.2.tgz", - "integrity": "sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==", + "version": "20.1.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.1.0.tgz", + "integrity": "sha512-STVO3itHQLrp80lvcYB2UIKoeil5Ctsgd2s1AM+du3HqZIR35ZH7WE9HLwUOLXH0myA0y3AGNPo8gZtcgIbw0g==", "dev": true, "requires": { - "@octokit/core": "^5.0.0", - "@octokit/plugin-paginate-rest": "^9.0.0", + "@octokit/core": "^5.0.2", + "@octokit/plugin-paginate-rest": "^9.1.5", "@octokit/plugin-request-log": "^4.0.0", - "@octokit/plugin-rest-endpoint-methods": "^10.0.0" + "@octokit/plugin-rest-endpoint-methods": "^10.2.0" } }, "@octokit/types": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.1.0.tgz", - "integrity": "sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.1.0.tgz", + "integrity": "sha512-nBwAFOYqVUUJ2AZFK4ZzESQptaAVqdTDKk8gE0Xr0o99WuPDSrhUC38x0F40xD9OUxXhOOuZKWNNVVLPSHQDvQ==", "dev": true, "requires": { - "@octokit/openapi-types": "^18.0.0" + "@octokit/openapi-types": "^21.0.0" } }, "@pkgr/core": { @@ -7534,9 +7376,9 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.12.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.2.tgz", - "integrity": "sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==", + "version": "20.12.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.5.tgz", + "integrity": "sha512-BD+BjQ9LS/D8ST9p5uqBxghlN+S42iuNxjsUGjeZobe/ciXzk2qb1B6IXc6AnRLS+yFJRpN2IPEHMzwspfDJNw==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -7598,6 +7440,18 @@ "@typescript-eslint/visitor-keys": "7.5.0" } }, + "@typescript-eslint/type-utils": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz", + "integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "7.5.0", + "@typescript-eslint/utils": "7.5.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + } + }, "@typescript-eslint/types": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", @@ -7741,84 +7595,37 @@ } }, "@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" } }, - "@typescript-eslint/type-utils": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz", - "integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==", + "@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.5.0", - "@typescript-eslint/utils": "7.5.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", - "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0" - } - }, - "@typescript-eslint/types": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", - "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", - "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - } - }, - "@typescript-eslint/utils": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz", - "integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.5.0", - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/typescript-estree": "7.5.0", - "semver": "^7.5.4" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", - "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.5.0", - "eslint-visitor-keys": "^3.4.1" - } - }, "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -7839,51 +7646,14 @@ } } }, - "@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - } - }, "@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "requires": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" } }, "@ungap/structured-clone": { @@ -7893,9 +7663,9 @@ "dev": true }, "acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true }, "acorn-jsx": { @@ -8451,24 +8221,6 @@ "optionator": "^0.9.3", "strip-ansi": "^6.0.1", "text-table": "^0.2.0" - }, - "dependencies": { - "eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } } }, "eslint-config-prettier": { @@ -8479,12 +8231,29 @@ "requires": {} }, "eslint-plugin-jest": { - "version": "27.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", - "integrity": "sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==", + "version": "28.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.2.0.tgz", + "integrity": "sha512-yRDti/a+f+SMSmNTiT9/M/MzXGkitl8CfzUxnpoQcTyfq8gUrXMriVcWU36W1X6BZSUoyUCJrDAWWUA2N4hE5g==", "dev": true, "requires": { - "@typescript-eslint/utils": "^5.10.0" + "@typescript-eslint/utils": "^6.0.0" + }, + "dependencies": { + "@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + } + } } }, "eslint-plugin-prettier": { @@ -8498,13 +8267,13 @@ } }, "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "requires": { "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "estraverse": "^5.2.0" } }, "eslint-visitor-keys": { @@ -8537,14 +8306,6 @@ "dev": true, "requires": { "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } } }, "esrecurse": { @@ -8554,20 +8315,12 @@ "dev": true, "requires": { "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } } }, "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true }, "esutils": { @@ -8727,12 +8480,13 @@ } }, "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "requires": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" } }, @@ -8742,9 +8496,9 @@ "integrity": "sha512-3HDgPbgiwWMI9zVB7VYBHaMrbOO7Gm0v+yD2FV/sCKj+9NDeVL7BOBYUuhWAQGKWOzBo8S9WdMvV0eixO233XQ==" }, "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "formdata-polyfill": { @@ -8846,9 +8600,9 @@ } }, "globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -9050,12 +8804,6 @@ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true }, - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true - }, "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -9606,6 +9354,12 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -9630,6 +9384,15 @@ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -10542,21 +10305,6 @@ "yargs-parser": "^21.0.1" } }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -10579,9 +10327,9 @@ "dev": true }, "typescript": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", - "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", + "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==", "dev": true }, "undici-types": { @@ -10600,9 +10348,9 @@ } }, "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", "dev": true }, "update-browserslist-db": { diff --git a/package.json b/package.json index ea960acec9..87fa1f789d 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "npm-scripts.mjs" ], "engines": { - "node": ">=16" + "node": ">=18" }, "keywords": [ "webrtc", @@ -109,15 +109,15 @@ "tar": "^6.2.1" }, "devDependencies": { - "@octokit/rest": "^20.0.2", + "@octokit/rest": "^20.1.0", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.12.2", + "@types/node": "^20.12.5", "@typescript-eslint/eslint-plugin": "^7.5.0", "@typescript-eslint/parser": "^7.5.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-jest": "^27.9.0", + "eslint-plugin-jest": "^28.2.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "marked": "^12.0.1", @@ -126,6 +126,6 @@ "prettier": "^3.2.5", "sctp": "^1.0.0", "ts-jest": "^29.1.2", - "typescript": "^5.4.3" + "typescript": "^5.4.4" } } diff --git a/worker/scripts/package-lock.json b/worker/scripts/package-lock.json index 9f468b26cc..71d690bdba 100644 --- a/worker/scripts/package-lock.json +++ b/worker/scripts/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.1", "dependencies": { "clang-format": "^1.8.0", - "glob": "^10.3.10" + "glob": "^10.3.12" } }, "node_modules/@isaacs/cliui": { @@ -277,15 +277,15 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.3.12", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", + "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", + "jackspeak": "^2.3.6", "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" }, "bin": { "glob": "dist/esm/bin.mjs" @@ -356,41 +356,13 @@ } }, "node_modules/lru-cache": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.2.tgz", - "integrity": "sha512-Yj9mA8fPiVgOUpByoTZO5pNrcl5Yk37FcSHsUINpAsaBIEZIuqcCclDZJCVxqQShDsmYX8QG63svJiTbOATZwg==", - "dependencies": { - "semver": "^7.3.5" - }, + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", "engines": { "node": "14 || >=16.14" } }, - "node_modules/lru-cache/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/lru-cache/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -443,11 +415,11 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", + "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { @@ -624,11 +596,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } }, "dependencies": { @@ -831,15 +798,15 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.3.12", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", + "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", "requires": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", + "jackspeak": "^2.3.6", "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" } }, "has": { @@ -887,30 +854,9 @@ } }, "lru-cache": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.2.tgz", - "integrity": "sha512-Yj9mA8fPiVgOUpByoTZO5pNrcl5Yk37FcSHsUINpAsaBIEZIuqcCclDZJCVxqQShDsmYX8QG63svJiTbOATZwg==", - "requires": { - "semver": "^7.3.5" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "requires": { - "lru-cache": "^6.0.0" - } - } - } + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==" }, "minimatch": { "version": "9.0.3", @@ -949,11 +895,11 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", + "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", "requires": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, @@ -1076,11 +1022,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/worker/scripts/package.json b/worker/scripts/package.json index eb4827cf34..2831c80c0d 100644 --- a/worker/scripts/package.json +++ b/worker/scripts/package.json @@ -8,6 +8,6 @@ }, "dependencies": { "clang-format": "^1.8.0", - "glob": "^10.3.10" + "glob": "^10.3.12" } } From 62d2731a933b79b2c391aa44b28e95d368da27d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 8 Apr 2024 16:24:07 +0200 Subject: [PATCH 10/28] TransportListenInfo: Add portRange (deprecate worker port range) (#1365) --- CHANGELOG.md | 7 +- node/src/Channel.ts | 7 +- node/src/Router.ts | 16 +- node/src/Transport.ts | 90 ++- node/src/WebRtcServer.ts | 3 +- node/src/Worker.ts | 6 +- node/src/test/test-WebRtcTransport.ts | 69 +- rust/benches/producer.rs | 1 + rust/examples/echo.rs | 1 + rust/examples/multiopus.rs | 2 + rust/examples/svc-simulcast.rs | 1 + rust/examples/videoroom.rs | 1 + rust/src/data_structures.rs | 14 +- rust/src/router.rs | 8 + rust/src/router/consumer/tests.rs | 1 + rust/src/router/data_consumer/tests.rs | 3 + rust/src/router/data_producer/tests.rs | 1 + rust/src/router/pipe_transport/tests.rs | 1 + rust/src/router/plain_transport/tests.rs | 1 + rust/src/router/producer/tests.rs | 1 + rust/src/router/webrtc_transport/tests.rs | 5 + rust/src/webrtc_server/tests.rs | 1 + rust/src/worker.rs | 18 +- rust/tests/integration/consumer.rs | 1 + rust/tests/integration/data_consumer.rs | 4 + rust/tests/integration/data_producer.rs | 2 + rust/tests/integration/multiopus.rs | 1 + rust/tests/integration/pipe_transport.rs | 7 + rust/tests/integration/plain_transport.rs | 16 + rust/tests/integration/producer.rs | 1 + rust/tests/integration/smoke.rs | 2 + rust/tests/integration/webrtc_server.rs | 11 + rust/tests/integration/webrtc_transport.rs | 81 ++ rust/tests/integration/worker.rs | 4 +- worker/fbs/transport.fbs | 6 + worker/include/RTC/PortManager.hpp | 69 +- .../include/RTC/RTCP/XrDelaySinceLastRr.hpp | 6 +- .../RTC/RTCP/XrReceiverReferenceTime.hpp | 6 +- worker/include/RTC/TcpServer.hpp | 8 +- worker/include/RTC/Transport.hpp | 7 + worker/include/RTC/TransportTuple.hpp | 74 +- worker/include/RTC/UdpSocket.hpp | 9 +- .../include/handles/TcpConnectionHandle.hpp | 2 +- worker/include/handles/TcpServerHandle.hpp | 2 +- worker/include/handles/UdpSocketHandle.hpp | 2 +- worker/src/RTC/PipeTransport.cpp | 30 +- worker/src/RTC/PlainTransport.cpp | 62 +- worker/src/RTC/PortManager.cpp | 711 ++++++++++-------- worker/src/RTC/TcpServer.cpp | 20 +- worker/src/RTC/TransportTuple.cpp | 73 ++ worker/src/RTC/UdpSocket.cpp | 22 +- worker/src/RTC/WebRtcServer.cpp | 57 +- worker/src/RTC/WebRtcTransport.cpp | 57 +- worker/src/Worker.cpp | 1 + 54 files changed, 1063 insertions(+), 549 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8de44463fa..a3462be0dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### NEXT +- `TransportListenInfo`: Add `portRange` (deprecate worker port range) ([PR #1365](https://github.com/versatica/mediasoup/pull/1365)). - Require Node.js >= 18 ([PR #1365](https://github.com/versatica/mediasoup/pull/1365)). ### 3.13.24 @@ -54,8 +55,8 @@ ### 3.13.14 - Avoid modification of user input data ([PR #1285](https://github.com/versatica/mediasoup/pull/1285)). -- `ListenInfo`: Add transport socket flags ([PR #1291](https://github.com/versatica/mediasoup/pull/1291)). -- `ListenInfo`: Ignore given socket flags if not suitable for given IP family or transport ([PR #1294](https://github.com/versatica/mediasoup/pull/1294)). +- `TransportListenInfo`: Add transport socket flags ([PR #1291](https://github.com/versatica/mediasoup/pull/1291)). +- `TransportListenInfo`: Ignore given socket flags if not suitable for given IP family or transport ([PR #1294](https://github.com/versatica/mediasoup/pull/1294)). - Meson: Remove `-Db_pie=true -Db_staticpic=true` args ([PR #1293](https://github.com/versatica/mediasoup/pull/1293)). - Add RTCP Sender Report trace event ([PR #1267](https://github.com/versatica/mediasoup/pull/1267) by @GithubUser8080). @@ -129,7 +130,7 @@ ### 3.13.0 - Switch from JSON based messages to FlatBuffers ([PR #1064](https://github.com/versatica/mediasoup/pull/1064)). -- Add `ListenInfo` in all transports and send/recv buffer size options ([PR #1084](https://github.com/versatica/mediasoup/pull/1084)). +- Add `TransportListenInfo` in all transports and send/recv buffer size options ([PR #1084](https://github.com/versatica/mediasoup/pull/1084)). - Add optional `rtcpListenInfo` in `PlainTransportOptions` ([PR #1099](https://github.com/versatica/mediasoup/pull/1099)). - Add pause/resume API in `DataProducer` and `DataConsumer` ([PR #1104](https://github.com/versatica/mediasoup/pull/1104)). - DataChannel subchannels feature ([PR #1152](https://github.com/versatica/mediasoup/pull/1152)). diff --git a/node/src/Channel.ts b/node/src/Channel.ts index fca87950f9..d0b9664707 100644 --- a/node/src/Channel.ts +++ b/node/src/Channel.ts @@ -1,5 +1,6 @@ import * as os from 'node:os'; import { Duplex } from 'node:stream'; +import { info, warn } from 'node:console'; import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; @@ -156,8 +157,7 @@ export class Channel extends EnhancedEventEmitter { } default: { - // eslint-disable-next-line no-console - console.warn( + warn( `worker[pid:${pid}] unexpected data: ${payload.toString( 'utf8', 1 @@ -482,8 +482,7 @@ export class Channel extends EnhancedEventEmitter { // 'X' (a dump log). case 'X': { - // eslint-disable-next-line no-console - console.log(logData.slice(1)); + info(logData.slice(1)); break; } diff --git a/node/src/Router.ts b/node/src/Router.ts index 56245fe877..e0d61f6f91 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -8,7 +8,8 @@ import { TransportListenInfo, TransportListenIp, TransportProtocol, - TransportSocketFlags, + portRangeToFbs, + socketFlagsToFbs, } from './Transport'; import { WebRtcTransport, @@ -560,6 +561,7 @@ export class Router< listenInfo.ip, listenInfo.announcedAddress ?? listenInfo.announcedIp, listenInfo.port, + portRangeToFbs(listenInfo.portRange), socketFlagsToFbs(listenInfo.flags), listenInfo.sendBufferSize, listenInfo.recvBufferSize @@ -748,6 +750,7 @@ export class Router< listenInfo!.ip, listenInfo!.announcedAddress ?? listenInfo!.announcedIp, listenInfo!.port, + portRangeToFbs(listenInfo!.portRange), socketFlagsToFbs(listenInfo!.flags), listenInfo!.sendBufferSize, listenInfo!.recvBufferSize @@ -760,6 +763,7 @@ export class Router< rtcpListenInfo.ip, rtcpListenInfo.announcedAddress ?? rtcpListenInfo.announcedIp, rtcpListenInfo.port, + portRangeToFbs(rtcpListenInfo.portRange), socketFlagsToFbs(rtcpListenInfo.flags), rtcpListenInfo.sendBufferSize, rtcpListenInfo.recvBufferSize @@ -900,6 +904,7 @@ export class Router< listenInfo!.ip, listenInfo!.announcedAddress ?? listenInfo!.announcedIp, listenInfo!.port, + portRangeToFbs(listenInfo!.portRange), socketFlagsToFbs(listenInfo!.flags), listenInfo!.sendBufferSize, listenInfo!.recvBufferSize @@ -1569,12 +1574,3 @@ export function parseRouterDumpResponse( ), }; } - -export function socketFlagsToFbs( - flags: TransportSocketFlags = {} -): FbsTransport.SocketFlagsT { - return new FbsTransport.SocketFlagsT( - Boolean(flags.ipv6Only), - Boolean(flags.udpReusePort) - ); -} diff --git a/node/src/Transport.ts b/node/src/Transport.ts index de25523662..64299f9ca2 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -90,6 +90,11 @@ export type TransportListenInfo = { */ port?: number; + /** + * Listening port range. If given then |port| will be ignored. + */ + portRange?: TransportPortRange; + /** * Socket flags. */ @@ -128,6 +133,20 @@ export type TransportListenIp = { */ export type TransportProtocol = 'udp' | 'tcp'; +/** + * Port range.. + */ +export type TransportPortRange = { + /** + * Lowest port in the range. + */ + min: number; + /** + * Highest port in the range. + */ + max: number; +}; + /** * UDP/TCP socket flags. */ @@ -1274,36 +1293,19 @@ export class Transport< } } -function transportTraceEventTypeToFbs( - eventType: TransportTraceEventType -): FbsTransport.TraceEventType { - switch (eventType) { - case 'probation': { - return FbsTransport.TraceEventType.PROBATION; - } - - case 'bwe': { - return FbsTransport.TraceEventType.BWE; - } - - default: { - throw new TypeError(`invalid TransportTraceEventType: ${eventType}`); - } - } +export function portRangeToFbs( + portRange: TransportPortRange = { min: 0, max: 0 } +): FbsTransport.PortRangeT { + return new FbsTransport.PortRangeT(portRange.min, portRange.max); } -function transportTraceEventTypeFromFbs( - eventType: FbsTransport.TraceEventType -): TransportTraceEventType { - switch (eventType) { - case FbsTransport.TraceEventType.PROBATION: { - return 'probation'; - } - - case FbsTransport.TraceEventType.BWE: { - return 'bwe'; - } - } +export function socketFlagsToFbs( + flags: TransportSocketFlags = {} +): FbsTransport.SocketFlagsT { + return new FbsTransport.SocketFlagsT( + Boolean(flags.ipv6Only), + Boolean(flags.udpReusePort) + ); } export function parseSctpState(fbsSctpState: FbsSctpState): SctpState { @@ -1527,6 +1529,38 @@ function parseRecvRtpHeaderExtensions( }; } +function transportTraceEventTypeToFbs( + eventType: TransportTraceEventType +): FbsTransport.TraceEventType { + switch (eventType) { + case 'probation': { + return FbsTransport.TraceEventType.PROBATION; + } + + case 'bwe': { + return FbsTransport.TraceEventType.BWE; + } + + default: { + throw new TypeError(`invalid TransportTraceEventType: ${eventType}`); + } + } +} + +function transportTraceEventTypeFromFbs( + eventType: FbsTransport.TraceEventType +): TransportTraceEventType { + switch (eventType) { + case FbsTransport.TraceEventType.PROBATION: { + return 'probation'; + } + + case FbsTransport.TraceEventType.BWE: { + return 'bwe'; + } + } +} + function parseBweTraceInfo(binary: FbsTransport.BweTraceInfo): { desiredBitrate: number; effectiveDesiredBitrate: number; diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index bfe2714007..c13f83c35d 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -23,8 +23,7 @@ export type WebRtcServerOptions = }; /** - * @deprecated - * Use TransportListenInfo instead. + * @deprecated Use TransportListenInfo instead. */ export type WebRtcServerListenInfo = TransportListenInfo; diff --git a/node/src/Worker.ts b/node/src/Worker.ts index ad9838ce4a..cce310e810 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -6,8 +6,9 @@ import { Logger } from './Logger'; import { EnhancedEventEmitter } from './EnhancedEventEmitter'; import * as ortc from './ortc'; import { Channel } from './Channel'; -import { Router, RouterOptions, socketFlagsToFbs } from './Router'; +import { Router, RouterOptions } from './Router'; import { WebRtcServer, WebRtcServerOptions } from './WebRtcServer'; +import { portRangeToFbs, socketFlagsToFbs } from './Transport'; import { RtpCodecCapability } from './RtpParameters'; import { AppData } from './types'; import * as utils from './utils'; @@ -50,11 +51,13 @@ export type WorkerSettings = { /** * Minimun RTC port for ICE, DTLS, RTP, etc. Default 10000. + * @deprecated Use |portRange| in TransportListenInfo object instead. */ rtcMinPort?: number; /** * Maximum RTC port for ICE, DTLS, RTP, etc. Default 59999. + * @deprecated Use |portRange| in TransportListenInfo object instead. */ rtcMaxPort?: number; @@ -701,6 +704,7 @@ export class Worker< listenInfo.ip, listenInfo.announcedAddress ?? listenInfo.announcedIp, listenInfo.port, + portRangeToFbs(listenInfo.portRange), socketFlagsToFbs(listenInfo.flags), listenInfo.sendBufferSize, listenInfo.recvBufferSize diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index 129a33a19b..109b15499b 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -197,6 +197,57 @@ test('router.createWebRtcTransport() with deprecated listenIps succeeds', async expect(iceCandidates[0].priority).toBeGreaterThan(iceCandidates[1].priority); }, 2000); +test('router.createWebRtcTransport() with fixed port succeeds', async () => { + const port = await pickPort({ + type: 'tcp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); + const webRtcTransport = await ctx.router!.createWebRtcTransport({ + listenInfos: [ + // NOTE: udpReusePort flag will be ignored since protocol is TCP. + { protocol: 'tcp', ip: '127.0.0.1', port, flags: { udpReusePort: true } }, + ], + }); + + expect(webRtcTransport.iceCandidates[0].port).toEqual(port); +}, 2000); + +test('router.createWebRtcTransport() with portRange succeeds', async () => { + const portRange = { min: 11111, max: 11112 }; + + const webRtcTransport1 = await ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1', portRange }], + }); + + const iceCandidate1 = webRtcTransport1.iceCandidates[0]; + + expect(iceCandidate1.ip).toBe('127.0.0.1'); + expect( + iceCandidate1.port >= portRange.min && iceCandidate1.port <= portRange.max + ).toBe(true); + expect(iceCandidate1.protocol).toBe('udp'); + + const webRtcTransport2 = await ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1', portRange }], + }); + + const iceCandidate2 = webRtcTransport2.iceCandidates[0]; + + expect(iceCandidate2.ip).toBe('127.0.0.1'); + expect( + iceCandidate1.port >= portRange.min && iceCandidate1.port <= portRange.max + ).toBe(true); + expect(iceCandidate2.protocol).toBe('udp'); + + // No more available ports so it must fail. + await expect( + ctx.router!.createWebRtcTransport({ + listenInfos: [{ protocol: 'udp', ip: '127.0.0.1', portRange }], + }) + ).rejects.toThrow(Error); +}, 2000); + test('router.createWebRtcTransport() with wrong arguments rejects with TypeError', async () => { // @ts-ignore await expect(ctx.router!.createWebRtcTransport({})).rejects.toThrow( @@ -701,24 +752,6 @@ test('WebRtcTransport methods reject if closed', async () => { await expect(webRtcTransport.restartIce()).rejects.toThrow(Error); }, 2000); -test('router.createWebRtcTransport() with fixed port succeeds', async () => { - const port = await pickPort({ - type: 'tcp', - ip: '127.0.0.1', - reserveTimeout: 0, - }); - const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [ - // NOTE: udpReusePort flag will be ignored since protocol is TCP. - { protocol: 'tcp', ip: '127.0.0.1', port, flags: { udpReusePort: true } }, - ], - }); - - expect(webRtcTransport.iceCandidates[0].port).toEqual(port); - - webRtcTransport.close(); -}, 2000); - test('WebRtcTransport emits "routerclose" if Router is closed', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ listenIps: ['127.0.0.1'], diff --git a/rust/benches/producer.rs b/rust/benches/producer.rs index 8d05625a26..260a00f189 100644 --- a/rust/benches/producer.rs +++ b/rust/benches/producer.rs @@ -67,6 +67,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/examples/echo.rs b/rust/examples/echo.rs index d8d751f55f..98a39e582d 100644 --- a/rust/examples/echo.rs +++ b/rust/examples/echo.rs @@ -187,6 +187,7 @@ impl EchoConnection { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/examples/multiopus.rs b/rust/examples/multiopus.rs index d78e8fd859..9f959c1999 100644 --- a/rust/examples/multiopus.rs +++ b/rust/examples/multiopus.rs @@ -150,6 +150,7 @@ impl EchoConnection { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -236,6 +237,7 @@ impl EchoConnection { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/examples/svc-simulcast.rs b/rust/examples/svc-simulcast.rs index 4bf34bbf6c..b33b4f095d 100644 --- a/rust/examples/svc-simulcast.rs +++ b/rust/examples/svc-simulcast.rs @@ -207,6 +207,7 @@ impl SvcSimulcastConnection { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/examples/videoroom.rs b/rust/examples/videoroom.rs index 379958534e..d475372735 100644 --- a/rust/examples/videoroom.rs +++ b/rust/examples/videoroom.rs @@ -501,6 +501,7 @@ mod participant { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/src/data_structures.rs b/rust/src/data_structures.rs index 807dee3990..3019b6ed1f 100644 --- a/rust/src/data_structures.rs +++ b/rust/src/data_structures.rs @@ -13,7 +13,7 @@ use std::any::Any; use std::borrow::Cow; use std::fmt; use std::net::IpAddr; -use std::ops::{Deref, DerefMut}; +use std::ops::{Deref, DerefMut, RangeInclusive}; use std::sync::Arc; /// Container for arbitrary data attached to mediasoup entities. @@ -52,7 +52,7 @@ impl AppData { /// # Notes on usage /// If you use "0.0.0.0" or "::" as ip value, then you need to also provide /// `announced_address`. -#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Deserialize, Serialize)] +#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct ListenInfo { /// Network protocol. @@ -66,6 +66,9 @@ pub struct ListenInfo { /// Listening port. #[serde(skip_serializing_if = "Option::is_none")] pub port: Option, + /// Listening port range. If given then |port| will be ignored. + #[serde(skip_serializing_if = "Option::is_none")] + pub port_range: Option>, /// Socket flags. #[serde(skip_serializing_if = "Option::is_none")] pub flags: Option, @@ -90,6 +93,13 @@ impl ListenInfo { .as_ref() .map(|address| address.to_string()), port: self.port.unwrap_or(0), + port_range: match &self.port_range { + Some(port_range) => Box::new(transport::PortRange { + min: *port_range.start(), + max: *port_range.end(), + }), + None => Box::new(transport::PortRange { min: 0, max: 0 }), + }, flags: Box::new(self.flags.unwrap_or_default().to_fbs()), send_buffer_size: self.send_buffer_size.unwrap_or(0), recv_buffer_size: self.recv_buffer_size.unwrap_or(0), diff --git a/rust/src/router.rs b/rust/src/router.rs index c1259c3174..95049e18fa 100644 --- a/rust/src/router.rs +++ b/rust/src/router.rs @@ -147,6 +147,7 @@ impl PipeToRouterOptions { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -610,6 +611,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_address: Some("9.9.9.1".to_string()), /// port: None, + /// port_range: None, /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, @@ -698,6 +700,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_address: Some("9.9.9.1".to_string()), /// port: None, + /// port_range: None, /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, @@ -764,6 +767,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_address: Some("9.9.9.1".to_string()), /// port: None, + /// port_range: None, /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, @@ -975,6 +979,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_address: Some("9.9.9.1".to_string()), /// port: None, + /// port_range: None, /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, @@ -1018,6 +1023,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_address: Some("9.9.9.1".to_string()), /// port: None, + /// port_range: None, /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, @@ -1204,6 +1210,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_address: Some("9.9.9.1".to_string()), /// port: None, + /// port_range: None, /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, @@ -1236,6 +1243,7 @@ impl Router { /// ip: IpAddr::V4(Ipv4Addr::LOCALHOST), /// announced_address: Some("9.9.9.1".to_string()), /// port: None, + /// port_range: None, /// flags: None, /// send_buffer_size: None, /// recv_buffer_size: None, diff --git a/rust/src/router/consumer/tests.rs b/rust/src/router/consumer/tests.rs index 0055fc3262..eaf36003db 100644 --- a/rust/src/router/consumer/tests.rs +++ b/rust/src/router/consumer/tests.rs @@ -87,6 +87,7 @@ async fn init() -> (Router, WebRtcTransport, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/src/router/data_consumer/tests.rs b/rust/src/router/data_consumer/tests.rs index b04a0a81b8..5edcb94537 100644 --- a/rust/src/router/data_consumer/tests.rs +++ b/rust/src/router/data_consumer/tests.rs @@ -41,6 +41,7 @@ async fn init() -> (Router, DataProducer) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -75,6 +76,7 @@ fn data_producer_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -129,6 +131,7 @@ fn transport_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/src/router/data_producer/tests.rs b/rust/src/router/data_producer/tests.rs index 349a0909d4..5b910f570e 100644 --- a/rust/src/router/data_producer/tests.rs +++ b/rust/src/router/data_producer/tests.rs @@ -41,6 +41,7 @@ async fn init() -> (Router, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/src/router/pipe_transport/tests.rs b/rust/src/router/pipe_transport/tests.rs index 7a3864cfd5..ef09da4a40 100644 --- a/rust/src/router/pipe_transport/tests.rs +++ b/rust/src/router/pipe_transport/tests.rs @@ -103,6 +103,7 @@ async fn init() -> (Router, Router, WebRtcTransport, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/src/router/plain_transport/tests.rs b/rust/src/router/plain_transport/tests.rs index e10654f8cf..496d25a9bd 100644 --- a/rust/src/router/plain_transport/tests.rs +++ b/rust/src/router/plain_transport/tests.rs @@ -42,6 +42,7 @@ fn router_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("4.4.4.4".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/src/router/producer/tests.rs b/rust/src/router/producer/tests.rs index 68b73f4292..c4941e4f58 100644 --- a/rust/src/router/producer/tests.rs +++ b/rust/src/router/producer/tests.rs @@ -72,6 +72,7 @@ async fn init() -> (Router, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/src/router/webrtc_transport/tests.rs b/rust/src/router/webrtc_transport/tests.rs index 75ea2726b1..86a7518797 100644 --- a/rust/src/router/webrtc_transport/tests.rs +++ b/rust/src/router/webrtc_transport/tests.rs @@ -57,6 +57,7 @@ fn create_with_webrtc_server_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port1), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -66,6 +67,7 @@ fn create_with_webrtc_server_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port2), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -235,6 +237,7 @@ fn router_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -277,6 +280,7 @@ fn webrtc_server_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port1), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -286,6 +290,7 @@ fn webrtc_server_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port2), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/src/webrtc_server/tests.rs b/rust/src/webrtc_server/tests.rs index 468be2ba85..63fb7d2c50 100644 --- a/rust/src/webrtc_server/tests.rs +++ b/rust/src/webrtc_server/tests.rs @@ -38,6 +38,7 @@ fn worker_close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/src/worker.rs b/rust/src/worker.rs index f233b72aa3..60a08b67f0 100644 --- a/rust/src/worker.rs +++ b/rust/src/worker.rs @@ -179,8 +179,8 @@ pub struct WorkerSettings { /// Log tags for debugging. Check the meaning of each available tag in the /// [Debugging](https://mediasoup.org/documentation/v3/mediasoup/debugging/) documentation. pub log_tags: Vec, - /// RTC ports range for ICE, DTLS, RTP, etc. Default 10000..=59999. - pub rtc_ports_range: RangeInclusive, + /// RTC port range for ICE, DTLS, RTP, etc. Default 10000..=59999. + pub rtc_port_range: RangeInclusive, /// DTLS certificate and private key. /// /// If `None`, a certificate is dynamically created. @@ -218,7 +218,7 @@ impl Default for WorkerSettings { WorkerLogTag::Sctp, WorkerLogTag::Message, ], - rtc_ports_range: 10000..=59999, + rtc_port_range: 10000..=59999, dtls_files: None, libwebrtc_field_trials: None, thread_initializer: None, @@ -232,7 +232,7 @@ impl fmt::Debug for WorkerSettings { let WorkerSettings { log_level, log_tags, - rtc_ports_range, + rtc_port_range, dtls_files, libwebrtc_field_trials, thread_initializer, @@ -242,7 +242,7 @@ impl fmt::Debug for WorkerSettings { f.debug_struct("WorkerSettings") .field("log_level", &log_level) .field("log_tags", &log_tags) - .field("rtc_ports_range", &rtc_ports_range) + .field("rtc_port_range", &rtc_port_range) .field("dtls_files", &dtls_files) .field("libwebrtc_field_trials", &libwebrtc_field_trials) .field( @@ -353,7 +353,7 @@ impl Inner { WorkerSettings { log_level, log_tags, - rtc_ports_range, + rtc_port_range, dtls_files, libwebrtc_field_trials, thread_initializer, @@ -371,14 +371,14 @@ impl Inner { spawn_args.push(format!("--logTag={}", log_tag.as_str())); } - if rtc_ports_range.is_empty() { + if rtc_port_range.is_empty() { return Err(io::Error::new( io::ErrorKind::InvalidInput, "Invalid RTC ports range", )); } - spawn_args.push(format!("--rtcMinPort={}", rtc_ports_range.start())); - spawn_args.push(format!("--rtcMaxPort={}", rtc_ports_range.end())); + spawn_args.push(format!("--rtcMinPort={}", rtc_port_range.start())); + spawn_args.push(format!("--rtcMaxPort={}", rtc_port_range.end())); if let Some(dtls_files) = dtls_files { spawn_args.push(format!( diff --git a/rust/tests/integration/consumer.rs b/rust/tests/integration/consumer.rs index ed2fdbc3b0..e1abdf88e6 100644 --- a/rust/tests/integration/consumer.rs +++ b/rust/tests/integration/consumer.rs @@ -356,6 +356,7 @@ async fn init() -> ( ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/data_consumer.rs b/rust/tests/integration/data_consumer.rs index 609837fd9e..1ded846105 100644 --- a/rust/tests/integration/data_consumer.rs +++ b/rust/tests/integration/data_consumer.rs @@ -68,6 +68,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, DataProducer) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -100,6 +101,7 @@ fn consume_data_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -210,6 +212,7 @@ fn weak() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -575,6 +578,7 @@ fn close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/data_producer.rs b/rust/tests/integration/data_producer.rs index 3fe27a394b..409a70eade 100644 --- a/rust/tests/integration/data_producer.rs +++ b/rust/tests/integration/data_producer.rs @@ -54,6 +54,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, PlainTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -73,6 +74,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, PlainTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/multiopus.rs b/rust/tests/integration/multiopus.rs index 0bcc1ea97d..5479be2077 100644 --- a/rust/tests/integration/multiopus.rs +++ b/rust/tests/integration/multiopus.rs @@ -135,6 +135,7 @@ async fn init() -> (Router, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/pipe_transport.rs b/rust/tests/integration/pipe_transport.rs index aff1990092..bf7bd01e80 100644 --- a/rust/tests/integration/pipe_transport.rs +++ b/rust/tests/integration/pipe_transport.rs @@ -261,6 +261,7 @@ async fn init() -> ( ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -606,6 +607,7 @@ fn weak() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -641,6 +643,7 @@ fn create_with_fixed_port_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -665,6 +668,7 @@ fn create_with_enable_rtx_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -778,6 +782,7 @@ fn create_with_enable_srtp_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -834,6 +839,7 @@ fn create_with_invalid_srtp_parameters_fails() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -1161,6 +1167,7 @@ fn pipe_to_router_called_twice_generates_single_pair() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/plain_transport.rs b/rust/tests/integration/plain_transport.rs index 2edadb74ee..3fe38ed4a8 100644 --- a/rust/tests/integration/plain_transport.rs +++ b/rust/tests/integration/plain_transport.rs @@ -96,6 +96,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("4.4.4.4".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -135,6 +136,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -211,6 +213,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -222,6 +225,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(rtcp_port), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -292,6 +296,7 @@ fn create_with_fixed_port_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("4.4.4.4".to_string()), port: Some(port), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -316,6 +321,7 @@ fn weak() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("4.4.4.4".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -350,6 +356,7 @@ fn create_enable_srtp_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -416,6 +423,7 @@ fn create_non_bindable_ip() { ip: "8.8.8.8".parse().unwrap(), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -442,6 +450,7 @@ fn create_two_transports_binding_to_same_ip_port_with_udp_reuse_port_flag_succee ip: multicast_ip, announced_address: None, port: Some(port), + port_range: None, // NOTE: ipv6Only flag will be ignored since ip is IPv4. flags: Some(SocketFlags { ipv6_only: true, @@ -461,6 +470,7 @@ fn create_two_transports_binding_to_same_ip_port_with_udp_reuse_port_flag_succee ip: multicast_ip, announced_address: None, port: Some(port), + port_range: None, flags: Some(SocketFlags { ipv6_only: false, udp_reuse_port: true, @@ -493,6 +503,7 @@ fn create_two_transports_binding_to_same_ip_port_without_udp_reuse_port_flag_fai ip: multicast_ip, announced_address: None, port: Some(port), + port_range: None, flags: Some(SocketFlags { ipv6_only: false, udp_reuse_port: false, @@ -511,6 +522,7 @@ fn create_two_transports_binding_to_same_ip_port_without_udp_reuse_port_flag_fai ip: multicast_ip, announced_address: None, port: Some(port), + port_range: None, flags: Some(SocketFlags { ipv6_only: false, udp_reuse_port: false, @@ -538,6 +550,7 @@ fn get_stats_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("4.4.4.4".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -598,6 +611,7 @@ fn connect_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("4.4.4.4".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -674,6 +688,7 @@ fn connect_wrong_arguments() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("4.4.4.4".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -715,6 +730,7 @@ fn close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("4.4.4.4".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/producer.rs b/rust/tests/integration/producer.rs index 44197df4e6..2fb6ac9276 100644 --- a/rust/tests/integration/producer.rs +++ b/rust/tests/integration/producer.rs @@ -207,6 +207,7 @@ async fn init() -> (Worker, Router, WebRtcTransport, WebRtcTransport) { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/smoke.rs b/rust/tests/integration/smoke.rs index 1c0c48890f..20f3bff81c 100644 --- a/rust/tests/integration/smoke.rs +++ b/rust/tests/integration/smoke.rs @@ -88,6 +88,7 @@ fn smoke() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -275,6 +276,7 @@ fn smoke() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/webrtc_server.rs b/rust/tests/integration/webrtc_server.rs index c647d8a9bd..a052d0653b 100644 --- a/rust/tests/integration/webrtc_server.rs +++ b/rust/tests/integration/webrtc_server.rs @@ -64,6 +64,7 @@ fn create_webrtc_server_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port1), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -73,6 +74,7 @@ fn create_webrtc_server_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("foo.bar.org".to_string()), port: Some(port2), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -160,6 +162,7 @@ fn create_webrtc_server_without_specifying_port_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -169,6 +172,7 @@ fn create_webrtc_server_without_specifying_port_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("1.2.3.4".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -243,6 +247,7 @@ fn unavailable_infos_fails() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port1), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -252,6 +257,7 @@ fn unavailable_infos_fails() { ip: IpAddr::V4(Ipv4Addr::new(1, 2, 3, 4)), announced_address: None, port: Some(port2), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -276,6 +282,7 @@ fn unavailable_infos_fails() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port1), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -285,6 +292,7 @@ fn unavailable_infos_fails() { ip: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), announced_address: Some("1.2.3.4".to_string()), port: Some(port1), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -309,6 +317,7 @@ fn unavailable_infos_fails() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port1), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -324,6 +333,7 @@ fn unavailable_infos_fails() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port1), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -353,6 +363,7 @@ fn close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: Some(port), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/webrtc_transport.rs b/rust/tests/integration/webrtc_transport.rs index c1e9b4bffb..e59caab44c 100644 --- a/rust/tests/integration/webrtc_transport.rs +++ b/rust/tests/integration/webrtc_transport.rs @@ -100,6 +100,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -138,6 +139,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -147,6 +149,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::UNSPECIFIED), announced_address: Some("foo1.bar.org".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -156,6 +159,7 @@ fn create_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -267,6 +271,7 @@ fn create_with_fixed_port_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: Some(port), + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -279,6 +284,70 @@ fn create_with_fixed_port_succeeds() { }); } +#[test] +fn create_with_port_range_succeeds() { + future::block_on(async move { + let (_worker, router) = init().await; + let port_range = 11111..=11112; + + let transport1 = router + .create_webrtc_transport({ + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_address: Some("9.9.9.1".to_string()), + port: None, + port_range: Some(port_range.clone()), + flags: None, + send_buffer_size: None, + recv_buffer_size: None, + })) + }) + .await + .expect("Failed to create WebRTC transport"); + + let port1 = transport1.ice_candidates().get(0).unwrap().port; + assert!(port1 >= *port_range.start() && port1 <= *port_range.end()); + + let transport2 = router + .create_webrtc_transport({ + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_address: Some("9.9.9.1".to_string()), + port: None, + port_range: Some(port_range.clone()), + flags: None, + send_buffer_size: None, + recv_buffer_size: None, + })) + }) + .await + .expect("Failed to create WebRTC transport"); + + let port2 = transport2.ice_candidates().get(0).unwrap().port; + assert!(port2 >= *port_range.start() && port2 <= *port_range.end()); + + assert!(matches!( + router + .create_webrtc_transport({ + WebRtcTransportOptions::new(WebRtcTransportListenInfos::new(ListenInfo { + protocol: Protocol::Udp, + ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + announced_address: Some("9.9.9.1".to_string()), + port: None, + port_range: Some(port_range.clone()), + flags: None, + send_buffer_size: None, + recv_buffer_size: None, + })) + }) + .await, + Err(RequestError::Response { .. }), + )); + }); +} + #[test] fn weak() { future::block_on(async move { @@ -291,6 +360,7 @@ fn weak() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -322,6 +392,7 @@ fn create_non_bindable_ip() { ip: "8.8.8.8".parse().unwrap(), announced_address: None, port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -345,6 +416,7 @@ fn get_stats_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -397,6 +469,7 @@ fn connect_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -447,6 +520,7 @@ fn set_max_incoming_bitrate_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -480,6 +554,7 @@ fn set_max_outgoing_bitrate_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -513,6 +588,7 @@ fn set_min_outgoing_bitrate_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -546,6 +622,7 @@ fn set_max_outgoing_bitrate_fails_if_value_is_lower_than_current_min_limit() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -584,6 +661,7 @@ fn set_min_outgoing_bitrate_fails_if_value_is_higher_than_current_max_limit() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -622,6 +700,7 @@ fn restart_ice_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -658,6 +737,7 @@ fn enable_trace_event_succeeds() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, @@ -734,6 +814,7 @@ fn close_event() { ip: IpAddr::V4(Ipv4Addr::LOCALHOST), announced_address: Some("9.9.9.1".to_string()), port: None, + port_range: None, flags: None, send_buffer_size: None, recv_buffer_size: None, diff --git a/rust/tests/integration/worker.rs b/rust/tests/integration/worker.rs index ad0a3d7d9a..9f905ae888 100644 --- a/rust/tests/integration/worker.rs +++ b/rust/tests/integration/worker.rs @@ -42,7 +42,7 @@ fn create_worker_succeeds() { settings.log_level = WorkerLogLevel::Debug; settings.log_tags = vec![WorkerLogTag::Info]; - settings.rtc_ports_range = 0..=9999; + settings.rtc_port_range = 0..=9999; settings.dtls_files = Some(WorkerDtlsFiles { certificate: "tests/integration/data/dtls-cert.pem".into(), private_key: "tests/integration/data/dtls-key.pem".into(), @@ -79,7 +79,7 @@ fn create_worker_wrong_settings() { // Intentionally incorrect range #[allow(clippy::reversed_empty_ranges)] { - settings.rtc_ports_range = 1000..=999; + settings.rtc_port_range = 1000..=999; } settings diff --git a/worker/fbs/transport.fbs b/worker/fbs/transport.fbs index fee932d964..655db6389e 100644 --- a/worker/fbs/transport.fbs +++ b/worker/fbs/transport.fbs @@ -13,6 +13,11 @@ enum Protocol: uint8 { TCP } +table PortRange { + min: uint16 = 0; + max: uint16 = 0; +} + table SocketFlags { ipv6_only: bool = false; udp_reuse_port: bool = false; @@ -23,6 +28,7 @@ table ListenInfo { ip: string (required); announced_address: string; port: uint16 = 0; + port_range: PortRange (required); flags: SocketFlags (required); send_buffer_size: uint32 = 0; recv_buffer_size: uint32 = 0; diff --git a/worker/include/RTC/PortManager.hpp b/worker/include/RTC/PortManager.hpp index f8c102b6b9..3e8c6aa9da 100644 --- a/worker/include/RTC/PortManager.hpp +++ b/worker/include/RTC/PortManager.hpp @@ -2,7 +2,6 @@ #define MS_RTC_PORT_MANAGER_HPP #include "common.hpp" -#include "Settings.hpp" #include "RTC/Transport.hpp" #include #include @@ -14,50 +13,72 @@ namespace RTC class PortManager { private: - enum class Transport : uint8_t + enum class Protocol : uint8_t { UDP = 1, TCP }; - public: - static uv_udp_t* BindUdp(std::string& ip, RTC::Transport::SocketFlags& flags) + private: + struct PortRange { - return reinterpret_cast(Bind(Transport::UDP, ip, flags)); - } + explicit PortRange(uint16_t numPorts, uint16_t minPort) + : ports(numPorts, false), minPort(minPort) + { + } + + std::vector ports; + uint16_t minPort{ 0u }; + uint16_t numUsedPorts{ 0u }; + }; + + public: static uv_udp_t* BindUdp(std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags) { - return reinterpret_cast(Bind(Transport::UDP, ip, port, flags)); + return reinterpret_cast(Bind(Protocol::UDP, ip, port, flags)); } - static uv_tcp_t* BindTcp(std::string& ip, RTC::Transport::SocketFlags& flags) + static uv_udp_t* BindUdp( + std::string& ip, + uint16_t minPort, + uint16_t maxPort, + RTC::Transport::SocketFlags& flags, + uint64_t& hash) { - return reinterpret_cast(Bind(Transport::TCP, ip, flags)); + return reinterpret_cast(Bind(Protocol::UDP, ip, minPort, maxPort, flags, hash)); } static uv_tcp_t* BindTcp(std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags) { - return reinterpret_cast(Bind(Transport::TCP, ip, port, flags)); + return reinterpret_cast(Bind(Protocol::TCP, ip, port, flags)); } - static void UnbindUdp(std::string& ip, uint16_t port) + static uv_tcp_t* BindTcp( + std::string& ip, + uint16_t minPort, + uint16_t maxPort, + RTC::Transport::SocketFlags& flags, + uint64_t& hash) { - return Unbind(Transport::UDP, ip, port); - } - static void UnbindTcp(std::string& ip, uint16_t port) - { - return Unbind(Transport::TCP, ip, port); + return reinterpret_cast(Bind(Protocol::TCP, ip, minPort, maxPort, flags, hash)); } + static void Unbind(uint64_t hash, uint16_t port); + static void Dump(); private: - static uv_handle_t* Bind(Transport transport, std::string& ip, RTC::Transport::SocketFlags& flags); static uv_handle_t* Bind( - Transport transport, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags); - static void Unbind(Transport transport, std::string& ip, uint16_t port); - static std::vector& GetPorts(Transport transport, const std::string& ip); - static uint8_t ConvertSocketFlags( - RTC::Transport::SocketFlags& flags, Transport transport, int family); + Protocol protocol, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags); + static uv_handle_t* Bind( + Protocol protocol, + std::string& ip, + uint16_t minPort, + uint16_t maxPort, + RTC::Transport::SocketFlags& flags, + uint64_t& hash); + static uint64_t GeneratePortRangeHash( + Protocol protocol, sockaddr_storage* bindAddr, uint16_t minPort, uint16_t maxPort); + static PortRange& GetOrCreatePortRange(uint64_t hash, uint16_t minPort, uint16_t maxPort); + static uint8_t ConvertSocketFlags(RTC::Transport::SocketFlags& flags, Protocol protocol, int family); private: - thread_local static absl::flat_hash_map> mapUdpIpPorts; - thread_local static absl::flat_hash_map> mapTcpIpPorts; + thread_local static absl::flat_hash_map mapPortRanges; }; } // namespace RTC diff --git a/worker/include/RTC/RTCP/XrDelaySinceLastRr.hpp b/worker/include/RTC/RTCP/XrDelaySinceLastRr.hpp index fa77eff277..eac430e28d 100644 --- a/worker/include/RTC/RTCP/XrDelaySinceLastRr.hpp +++ b/worker/include/RTC/RTCP/XrDelaySinceLastRr.hpp @@ -143,9 +143,9 @@ namespace RTC /* Pure virtual methods inherited from ExtendedReportBlock. */ public: - virtual void Dump() const override; - virtual size_t Serialize(uint8_t* buffer) override; - virtual size_t GetSize() const override + void Dump() const override; + size_t Serialize(uint8_t* buffer) override; + size_t GetSize() const override { size_t size{ 4u }; // Common header. diff --git a/worker/include/RTC/RTCP/XrReceiverReferenceTime.hpp b/worker/include/RTC/RTCP/XrReceiverReferenceTime.hpp index ecafaf1ad0..0083618588 100644 --- a/worker/include/RTC/RTCP/XrReceiverReferenceTime.hpp +++ b/worker/include/RTC/RTCP/XrReceiverReferenceTime.hpp @@ -68,9 +68,9 @@ namespace RTC /* Pure virtual methods inherited from ExtendedReportBlock. */ public: - virtual void Dump() const override; - virtual size_t Serialize(uint8_t* buffer) override; - virtual size_t GetSize() const override + void Dump() const override; + size_t Serialize(uint8_t* buffer) override; + size_t GetSize() const override { size_t size{ 4 }; // Common header. diff --git a/worker/include/RTC/TcpServer.hpp b/worker/include/RTC/TcpServer.hpp index 6d1aeb7376..383ae16ef4 100644 --- a/worker/include/RTC/TcpServer.hpp +++ b/worker/include/RTC/TcpServer.hpp @@ -28,13 +28,16 @@ namespace RTC Listener* listener, RTC::TcpConnection::Listener* connListener, std::string& ip, + uint16_t port, RTC::Transport::SocketFlags& flags); TcpServer( Listener* listener, RTC::TcpConnection::Listener* connListener, std::string& ip, - uint16_t port, - RTC::Transport::SocketFlags& flags); + uint16_t minPort, + uint16_t maxPort, + RTC::Transport::SocketFlags& flags, + uint64_t& portRangeHash); ~TcpServer() override; /* Pure virtual methods inherited from ::TcpServerHandle. */ @@ -47,6 +50,7 @@ namespace RTC Listener* listener{ nullptr }; RTC::TcpConnection::Listener* connListener{ nullptr }; bool fixedPort{ false }; + uint64_t portRangeHash{ 0u }; }; } // namespace RTC diff --git a/worker/include/RTC/Transport.hpp b/worker/include/RTC/Transport.hpp index 1b0baaa9c3..3448555a59 100644 --- a/worker/include/RTC/Transport.hpp +++ b/worker/include/RTC/Transport.hpp @@ -125,11 +125,18 @@ namespace RTC bool udpReusePort{ false }; }; + struct PortRange + { + uint16_t min{ 0u }; + uint16_t max{ 0u }; + }; + struct ListenInfo { std::string ip; std::string announcedAddress; uint16_t port{ 0u }; + PortRange portRange; SocketFlags flags; uint32_t sendBufferSize{ 0u }; uint32_t recvBufferSize{ 0u }; diff --git a/worker/include/RTC/TransportTuple.hpp b/worker/include/RTC/TransportTuple.hpp index 19750caf99..8df96d10ce 100644 --- a/worker/include/RTC/TransportTuple.hpp +++ b/worker/include/RTC/TransportTuple.hpp @@ -17,7 +17,7 @@ namespace RTC using onSendCallback = const std::function; public: - enum class Protocol + enum class Protocol : uint8_t { UDP = 1, TCP @@ -163,77 +163,7 @@ namespace RTC } private: - /* - * Hash for IPv4 - * - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | PORT | IP | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | IP | |F|P| - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * Hash for IPv6 - * - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | PORT | IP[0] ^ IP[1] ^ IP[2] ^ IP[3]| - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |IP[0] ^ IP[1] ^ IP[2] ^ IP[3] | IP[0] >> 16 |F|P| - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - void SetHash() - { - const struct sockaddr* remoteSockAddr = GetRemoteAddress(); - - switch (remoteSockAddr->sa_family) - { - case AF_INET: - { - const auto* remoteSockAddrIn = reinterpret_cast(remoteSockAddr); - - const uint64_t address = ntohl(remoteSockAddrIn->sin_addr.s_addr); - const uint64_t port = (ntohs(remoteSockAddrIn->sin_port)); - - this->hash = port << 48; - this->hash |= address << 16; - this->hash |= 0x0000; // AF_INET. - - break; - } - - case AF_INET6: - { - const auto* remoteSockAddrIn6 = - reinterpret_cast(remoteSockAddr); - const auto* a = - reinterpret_cast(std::addressof(remoteSockAddrIn6->sin6_addr)); - - const auto address1 = a[0] ^ a[1] ^ a[2] ^ a[3]; - const auto address2 = a[0]; - const uint64_t port = ntohs(remoteSockAddrIn6->sin6_port); - - this->hash = port << 48; - this->hash |= static_cast(address1) << 16; - this->hash |= address2 >> 16 & 0xFFFC; - this->hash |= 0x0002; // AF_INET6. - - break; - } - } - - // Override least significant bit with protocol information: - // - If UDP, start with 0. - // - If TCP, start with 1. - if (this->protocol == Protocol::UDP) - { - this->hash |= 0x0000; - } - else - { - this->hash |= 0x0001; - } - } + void SetHash(); public: uint64_t hash{ 0u }; diff --git a/worker/include/RTC/UdpSocket.hpp b/worker/include/RTC/UdpSocket.hpp index ad9bde10d6..3a15f9cc0b 100644 --- a/worker/include/RTC/UdpSocket.hpp +++ b/worker/include/RTC/UdpSocket.hpp @@ -22,8 +22,14 @@ namespace RTC }; public: - UdpSocket(Listener* listener, std::string& ip, RTC::Transport::SocketFlags& flags); UdpSocket(Listener* listener, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags); + UdpSocket( + Listener* listener, + std::string& ip, + uint16_t minPort, + uint16_t maxPort, + RTC::Transport::SocketFlags& flags, + uint64_t& portRangeHash); ~UdpSocket() override; /* Pure virtual methods inherited from ::UdpSocketHandle. */ @@ -34,6 +40,7 @@ namespace RTC // Passed by argument. Listener* listener{ nullptr }; bool fixedPort{ false }; + uint64_t portRangeHash{ 0u }; }; } // namespace RTC diff --git a/worker/include/handles/TcpConnectionHandle.hpp b/worker/include/handles/TcpConnectionHandle.hpp index 073602d305..76c92e3512 100644 --- a/worker/include/handles/TcpConnectionHandle.hpp +++ b/worker/include/handles/TcpConnectionHandle.hpp @@ -54,7 +54,7 @@ class TcpConnectionHandle { return this->closed; } - virtual void Dump() const; + void Dump() const; void Setup( Listener* listener, struct sockaddr_storage* localAddr, diff --git a/worker/include/handles/TcpServerHandle.hpp b/worker/include/handles/TcpServerHandle.hpp index 6d0fa9d1f9..e82c92a9a5 100644 --- a/worker/include/handles/TcpServerHandle.hpp +++ b/worker/include/handles/TcpServerHandle.hpp @@ -18,7 +18,7 @@ class TcpServerHandle : public TcpConnectionHandle::Listener public: void Close(); - virtual void Dump() const; + void Dump() const; const struct sockaddr* GetLocalAddress() const { return reinterpret_cast(&this->localAddr); diff --git a/worker/include/handles/UdpSocketHandle.hpp b/worker/include/handles/UdpSocketHandle.hpp index 2b7a708105..084690e76e 100644 --- a/worker/include/handles/UdpSocketHandle.hpp +++ b/worker/include/handles/UdpSocketHandle.hpp @@ -47,7 +47,7 @@ class UdpSocketHandle { return this->closed; } - virtual void Dump() const; + void Dump() const; void Send( const uint8_t* data, size_t len, const struct sockaddr* addr, UdpSocketHandle::onSendCallback* cb); const struct sockaddr* GetLocalAddress() const diff --git a/worker/src/RTC/PipeTransport.cpp b/worker/src/RTC/PipeTransport.cpp index 07fc5b538b..257b328ef1 100644 --- a/worker/src/RTC/PipeTransport.cpp +++ b/worker/src/RTC/PipeTransport.cpp @@ -53,6 +53,8 @@ namespace RTC } this->listenInfo.port = options->listenInfo()->port(); + this->listenInfo.portRange.min = options->listenInfo()->portRange()->min(); + this->listenInfo.portRange.max = options->listenInfo()->portRange()->max(); this->listenInfo.sendBufferSize = options->listenInfo()->sendBufferSize(); this->listenInfo.recvBufferSize = options->listenInfo()->recvBufferSize(); this->listenInfo.flags.ipv6Only = options->listenInfo()->flags()->ipv6Only(); @@ -68,15 +70,37 @@ namespace RTC try { - // This may throw. - if (this->listenInfo.port != 0) + if (this->listenInfo.portRange.min != 0 && this->listenInfo.portRange.max != 0) + { + uint64_t portRangeHash{ 0u }; + + this->udpSocket = new RTC::UdpSocket( + this, + this->listenInfo.ip, + this->listenInfo.portRange.min, + this->listenInfo.portRange.max, + this->listenInfo.flags, + portRangeHash); + } + else if (this->listenInfo.port != 0) { this->udpSocket = new RTC::UdpSocket( this, this->listenInfo.ip, this->listenInfo.port, this->listenInfo.flags); } + // NOTE: This is temporal to allow deprecated usage of worker port range. + // In the future this should throw since |port| or |portRange| will be + // required. else { - this->udpSocket = new RTC::UdpSocket(this, this->listenInfo.ip, this->listenInfo.flags); + uint64_t portRangeHash{ 0u }; + + this->udpSocket = new RTC::UdpSocket( + this, + this->listenInfo.ip, + Settings::configuration.rtcMinPort, + Settings::configuration.rtcMaxPort, + this->listenInfo.flags, + portRangeHash); } if (this->listenInfo.sendBufferSize != 0) diff --git a/worker/src/RTC/PlainTransport.cpp b/worker/src/RTC/PlainTransport.cpp index 2c8c14dfc4..3cb5a5b676 100644 --- a/worker/src/RTC/PlainTransport.cpp +++ b/worker/src/RTC/PlainTransport.cpp @@ -4,6 +4,7 @@ #include "RTC/PlainTransport.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Settings.hpp" #include "Utils.hpp" namespace RTC @@ -54,6 +55,8 @@ namespace RTC } this->listenInfo.port = options->listenInfo()->port(); + this->listenInfo.portRange.min = options->listenInfo()->portRange()->min(); + this->listenInfo.portRange.max = options->listenInfo()->portRange()->max(); this->listenInfo.sendBufferSize = options->listenInfo()->sendBufferSize(); this->listenInfo.recvBufferSize = options->listenInfo()->recvBufferSize(); this->listenInfo.flags.ipv6Only = options->listenInfo()->flags()->ipv6Only(); @@ -85,6 +88,8 @@ namespace RTC } this->rtcpListenInfo.port = options->rtcpListenInfo()->port(); + this->rtcpListenInfo.portRange.min = options->rtcpListenInfo()->portRange()->min(); + this->rtcpListenInfo.portRange.max = options->rtcpListenInfo()->portRange()->max(); this->rtcpListenInfo.sendBufferSize = options->rtcpListenInfo()->sendBufferSize(); this->rtcpListenInfo.recvBufferSize = options->rtcpListenInfo()->recvBufferSize(); this->rtcpListenInfo.flags.ipv6Only = options->rtcpListenInfo()->flags()->ipv6Only(); @@ -143,15 +148,37 @@ namespace RTC try { - // This may throw. - if (this->listenInfo.port != 0) + if (this->listenInfo.portRange.min != 0 && this->listenInfo.portRange.max != 0) + { + uint64_t portRangeHash{ 0u }; + + this->udpSocket = new RTC::UdpSocket( + this, + this->listenInfo.ip, + this->listenInfo.portRange.min, + this->listenInfo.portRange.max, + this->listenInfo.flags, + portRangeHash); + } + else if (this->listenInfo.port != 0) { this->udpSocket = new RTC::UdpSocket( this, this->listenInfo.ip, this->listenInfo.port, this->listenInfo.flags); } + // NOTE: This is temporal to allow deprecated usage of worker port range. + // In the future this should throw since |port| or |portRange| will be + // required. else { - this->udpSocket = new RTC::UdpSocket(this, this->listenInfo.ip, this->listenInfo.flags); + uint64_t portRangeHash{ 0u }; + + this->udpSocket = new RTC::UdpSocket( + this, + this->listenInfo.ip, + Settings::configuration.rtcMinPort, + Settings::configuration.rtcMaxPort, + this->listenInfo.flags, + portRangeHash); } if (this->listenInfo.sendBufferSize != 0) @@ -168,16 +195,37 @@ namespace RTC if (!this->rtcpMux) { - // This may throw. - if (this->rtcpListenInfo.port != 0) + if (this->rtcpListenInfo.portRange.min != 0 && this->rtcpListenInfo.portRange.max != 0) + { + uint64_t portRangeHash{ 0u }; + + this->rtcpUdpSocket = new RTC::UdpSocket( + this, + this->rtcpListenInfo.ip, + this->rtcpListenInfo.portRange.min, + this->rtcpListenInfo.portRange.max, + this->rtcpListenInfo.flags, + portRangeHash); + } + else if (this->rtcpListenInfo.port != 0) { this->rtcpUdpSocket = new RTC::UdpSocket( this, this->rtcpListenInfo.ip, this->rtcpListenInfo.port, this->rtcpListenInfo.flags); } + // NOTE: This is temporal to allow deprecated usage of worker port range. + // In the future this should throw since |port| or |portRange| will be + // required. else { - this->rtcpUdpSocket = - new RTC::UdpSocket(this, this->rtcpListenInfo.ip, this->rtcpListenInfo.flags); + uint64_t portRangeHash{ 0u }; + + this->rtcpUdpSocket = new RTC::UdpSocket( + this, + this->rtcpListenInfo.ip, + Settings::configuration.rtcMinPort, + Settings::configuration.rtcMaxPort, + this->rtcpListenInfo.flags, + portRangeHash); } if (this->rtcpListenInfo.sendBufferSize != 0) diff --git a/worker/src/RTC/PortManager.cpp b/worker/src/RTC/PortManager.cpp index a2247bf256..557596dc04 100644 --- a/worker/src/RTC/PortManager.cpp +++ b/worker/src/RTC/PortManager.cpp @@ -33,12 +33,12 @@ namespace RTC { /* Class variables. */ - thread_local absl::flat_hash_map> PortManager::mapUdpIpPorts; - thread_local absl::flat_hash_map> PortManager::mapTcpIpPorts; + thread_local absl::flat_hash_map PortManager::mapPortRanges; /* Class methods. */ - uv_handle_t* PortManager::Bind(Transport transport, std::string& ip, RTC::Transport::SocketFlags& flags) + uv_handle_t* PortManager::Bind( + Protocol protocol, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags) { MS_TRACE(); @@ -50,27 +50,22 @@ namespace RTC struct sockaddr_storage bindAddr { }; - size_t portIdx; - std::vector& ports = PortManager::GetPorts(transport, ip); - size_t attempt{ 0u }; - const size_t numAttempts = ports.size(); uv_handle_t* uvHandle{ nullptr }; - uint16_t port; - std::string transportStr; - const uint8_t bitFlags = ConvertSocketFlags(flags, transport, family); + std::string protocolStr; + const uint8_t bitFlags = ConvertSocketFlags(flags, protocol, family); - switch (transport) + switch (protocol) { - case Transport::UDP: + case Protocol::UDP: { - transportStr.assign("udp"); + protocolStr.assign("udp"); break; } - case Transport::TCP: + case Protocol::TCP: { - transportStr.assign("tcp"); + protocolStr.assign("tcp"); break; } @@ -109,9 +104,233 @@ namespace RTC } } + // Set the port into the sockaddr struct. + switch (family) + { + case AF_INET: + { + (reinterpret_cast(&bindAddr))->sin_port = htons(port); + + break; + } + + case AF_INET6: + { + (reinterpret_cast(&bindAddr))->sin6_port = htons(port); + + break; + } + } + + // Try to bind on it. + switch (protocol) + { + case Protocol::UDP: + { + uvHandle = reinterpret_cast(new uv_udp_t()); + err = uv_udp_init_ex( + DepLibUV::GetLoop(), reinterpret_cast(uvHandle), UV_UDP_RECVMMSG); + + break; + } + + case Protocol::TCP: + { + uvHandle = reinterpret_cast(new uv_tcp_t()); + err = uv_tcp_init(DepLibUV::GetLoop(), reinterpret_cast(uvHandle)); + + break; + } + } + + if (err != 0) + { + switch (protocol) + { + case Protocol::UDP: + { + delete reinterpret_cast(uvHandle); + + MS_THROW_ERROR("uv_udp_init_ex() failed: %s", uv_strerror(err)); + + break; + } + + case Protocol::TCP: + { + delete reinterpret_cast(uvHandle); + + MS_THROW_ERROR("uv_tcp_init() failed: %s", uv_strerror(err)); + + break; + } + } + } + + switch (protocol) + { + case Protocol::UDP: + { + err = uv_udp_bind( + reinterpret_cast(uvHandle), + reinterpret_cast(&bindAddr), + bitFlags); + + if (err != 0) + { + // If it failed, close the handle and check the reason. + uv_close(reinterpret_cast(uvHandle), static_cast(onCloseUdp)); + + MS_THROW_ERROR( + "uv_udp_bind() failed [protocol:%s, ip:'%s', port:%" PRIu16 "]: %s", + protocolStr.c_str(), + ip.c_str(), + port, + uv_strerror(err)); + } + + break; + } + + case Protocol::TCP: + { + err = uv_tcp_bind( + reinterpret_cast(uvHandle), + reinterpret_cast(&bindAddr), + bitFlags); + + if (err != 0) + { + // If it failed, close the handle and check the reason. + uv_close(reinterpret_cast(uvHandle), static_cast(onCloseTcp)); + + MS_THROW_ERROR( + "uv_tcp_bind() failed [protocol:%s, ip:'%s', port:%" PRIu16 "]: %s", + protocolStr.c_str(), + ip.c_str(), + port, + uv_strerror(err)); + } + + // uv_tcp_bind() may succeed even if later uv_listen() fails, so + // double check it. + err = uv_listen( + reinterpret_cast(uvHandle), + 256, + static_cast(onFakeConnection)); + + if (err != 0) + { + // If it failed, close the handle and check the reason. + uv_close(reinterpret_cast(uvHandle), static_cast(onCloseTcp)); + + MS_THROW_ERROR( + "uv_listen() failed [protocol:%s, ip:'%s', port:%" PRIu16 "]: %s", + protocolStr.c_str(), + ip.c_str(), + port, + uv_strerror(err)); + } + + break; + } + } + + MS_DEBUG_DEV( + "bind succeeded [protocol:%s, ip:'%s', port:%" PRIu16 "]", protocolStr.c_str(), ip.c_str(), port); + + return static_cast(uvHandle); + } + + uv_handle_t* PortManager::Bind( + Protocol protocol, + std::string& ip, + uint16_t minPort, + uint16_t maxPort, + RTC::Transport::SocketFlags& flags, + uint64_t& hash) + { + MS_TRACE(); + + if (maxPort < minPort) + { + MS_THROW_TYPE_ERROR("maxPort cannot be less than minPort"); + } + + // First normalize the IP. This may throw if invalid IP. + Utils::IP::NormalizeIp(ip); + + int err; + const int family = Utils::IP::GetFamily(ip); + struct sockaddr_storage bindAddr + { + }; + std::string protocolStr; + + switch (protocol) + { + case Protocol::UDP: + { + protocolStr.assign("udp"); + + break; + } + + case Protocol::TCP: + { + protocolStr.assign("tcp"); + + break; + } + } + + switch (family) + { + case AF_INET: + { + err = uv_ip4_addr(ip.c_str(), 0, reinterpret_cast(&bindAddr)); + + if (err != 0) + { + MS_THROW_ERROR("uv_ip4_addr() failed: %s", uv_strerror(err)); + } + + break; + } + + case AF_INET6: + { + err = uv_ip6_addr(ip.c_str(), 0, reinterpret_cast(&bindAddr)); + + if (err != 0) + { + MS_THROW_ERROR("uv_ip6_addr() failed: %s", uv_strerror(err)); + } + + break; + } + + // This cannot happen. + default: + { + MS_THROW_ERROR("unknown IP family"); + } + } + + hash = GeneratePortRangeHash(protocol, std::addressof(bindAddr), minPort, maxPort); + + auto& portRange = PortManager::GetOrCreatePortRange(hash, minPort, maxPort); + const size_t numPorts = portRange.ports.size(); + const size_t numAttempts = numPorts; + size_t attempt{ 0u }; + size_t portIdx; + uint16_t port; + uv_handle_t* uvHandle{ nullptr }; + const uint8_t bitFlags = ConvertSocketFlags(flags, protocol, family); + // Choose a random port index to start from. - portIdx = static_cast(Utils::Crypto::GetRandomUInt( - static_cast(0), static_cast(ports.size() - 1))); + portIdx = static_cast( + Utils::Crypto::GetRandomUInt(static_cast(0), static_cast(numPorts - 1))); // Iterate all ports until getting one available. Fail if none found and also // if bind() fails N times in theoretically available ports. @@ -124,32 +343,32 @@ namespace RTC if (attempt > numAttempts) { MS_THROW_ERROR( - "no more available ports [transport:%s, ip:'%s', numAttempt:%zu]", - transportStr.c_str(), + "no more available ports [protocol:%s, ip:'%s', numAttempt:%zu]", + protocolStr.c_str(), ip.c_str(), numAttempts); } // Increase current port index. - portIdx = (portIdx + 1) % ports.size(); + portIdx = (portIdx + 1) % numPorts; // So the corresponding port is the vector position plus the RTC minimum port. - port = static_cast(portIdx + Settings::configuration.rtcMinPort); + port = static_cast(portIdx + minPort); MS_DEBUG_DEV( - "testing port [transport:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]", - transportStr.c_str(), + "testing port [protocol:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]", + protocolStr.c_str(), ip.c_str(), port, attempt, numAttempts); // Check whether this port is not available. - if (ports[portIdx]) + if (portRange.ports[portIdx]) { MS_DEBUG_DEV( - "port in use, trying again [transport:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]", - transportStr.c_str(), + "port in use, trying again [protocol:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]", + protocolStr.c_str(), ip.c_str(), port, attempt, @@ -180,9 +399,9 @@ namespace RTC } // Try to bind on it. - switch (transport) + switch (protocol) { - case Transport::UDP: + case Protocol::UDP: { uvHandle = reinterpret_cast(new uv_udp_t()); err = uv_udp_init_ex( @@ -191,7 +410,7 @@ namespace RTC break; } - case Transport::TCP: + case Protocol::TCP: { uvHandle = reinterpret_cast(new uv_tcp_t()); err = uv_tcp_init(DepLibUV::GetLoop(), reinterpret_cast(uvHandle)); @@ -202,9 +421,9 @@ namespace RTC if (err != 0) { - switch (transport) + switch (protocol) { - case Transport::UDP: + case Protocol::UDP: { delete reinterpret_cast(uvHandle); @@ -213,7 +432,7 @@ namespace RTC break; } - case Transport::TCP: + case Protocol::TCP: { delete reinterpret_cast(uvHandle); @@ -224,9 +443,9 @@ namespace RTC } } - switch (transport) + switch (protocol) { - case Transport::UDP: + case Protocol::UDP: { err = uv_udp_bind( reinterpret_cast(uvHandle), @@ -236,8 +455,8 @@ namespace RTC if (err != 0) { MS_WARN_DEV( - "uv_udp_bind() failed [transport:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]: %s", - transportStr.c_str(), + "uv_udp_bind() failed [protocol:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]: %s", + protocolStr.c_str(), ip.c_str(), port, attempt, @@ -248,7 +467,7 @@ namespace RTC break; } - case Transport::TCP: + case Protocol::TCP: { err = uv_tcp_bind( reinterpret_cast(uvHandle), @@ -258,8 +477,8 @@ namespace RTC if (err != 0) { MS_WARN_DEV( - "uv_tcp_bind() failed [transport:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]: %s", - transportStr.c_str(), + "uv_tcp_bind() failed [protocol:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]: %s", + protocolStr.c_str(), ip.c_str(), port, attempt, @@ -277,8 +496,8 @@ namespace RTC static_cast(onFakeConnection)); MS_WARN_DEV( - "uv_listen() failed [transport:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]: %s", - transportStr.c_str(), + "uv_listen() failed [protocol:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]: %s", + protocolStr.c_str(), ip.c_str(), port, attempt, @@ -297,16 +516,16 @@ namespace RTC } // If it failed, close the handle and check the reason. - switch (transport) + switch (protocol) { - case Transport::UDP: + case Protocol::UDP: { uv_close(reinterpret_cast(uvHandle), static_cast(onCloseUdp)); break; }; - case Transport::TCP: + case Protocol::TCP: { uv_close(reinterpret_cast(uvHandle), static_cast(onCloseTcp)); @@ -320,9 +539,9 @@ namespace RTC case UV_EMFILE: { MS_THROW_ERROR( - "port bind failed due to too many open files [transport:%s, ip:'%s', port:%" PRIu16 + "port bind failed due to too many open files [protocol:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]", - transportStr.c_str(), + protocolStr.c_str(), ip.c_str(), port, attempt, @@ -335,9 +554,9 @@ namespace RTC case UV_EADDRNOTAVAIL: { MS_THROW_ERROR( - "port bind failed due to address not available [transport:%s, ip:'%s', port:%" PRIu16 + "port bind failed due to address not available [protocol:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]", - transportStr.c_str(), + protocolStr.c_str(), ip.c_str(), port, attempt, @@ -354,11 +573,14 @@ namespace RTC } // If here, we got an available port. Mark it as unavailable. - ports[portIdx] = true; + portRange.ports[portIdx] = true; + + // Increase number of used ports in the range. + portRange.numUsedPorts++; MS_DEBUG_DEV( - "bind succeeded [transport:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]", - transportStr.c_str(), + "bind succeeded [protocol:%s, ip:'%s', port:%" PRIu16 ", attempt:%zu/%zu]", + protocolStr.c_str(), ip.c_str(), port, attempt, @@ -367,337 +589,164 @@ namespace RTC return static_cast(uvHandle); } - uv_handle_t* PortManager::Bind( - Transport transport, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags) + void PortManager::Unbind(uint64_t hash, uint16_t port) { MS_TRACE(); - // First normalize the IP. This may throw if invalid IP. - Utils::IP::NormalizeIp(ip); - - int err; - const int family = Utils::IP::GetFamily(ip); - struct sockaddr_storage bindAddr - { - }; - uv_handle_t* uvHandle{ nullptr }; - std::string transportStr; - const uint8_t bitFlags = ConvertSocketFlags(flags, transport, family); + auto it = PortManager::mapPortRanges.find(hash); - switch (transport) + // This should not happen. + if (it == PortManager::mapPortRanges.end()) { - case Transport::UDP: - { - transportStr.assign("udp"); - - break; - } - - case Transport::TCP: - { - transportStr.assign("tcp"); + MS_ERROR("hash %" PRIu64 " doesn't exist in the map", hash); - break; - } + return; } - switch (family) - { - case AF_INET: - { - err = uv_ip4_addr(ip.c_str(), 0, reinterpret_cast(&bindAddr)); - - if (err != 0) - { - MS_THROW_ERROR("uv_ip4_addr() failed: %s", uv_strerror(err)); - } - - break; - } + auto& portRange = it->second; + const auto portIdx = static_cast(port - portRange.minPort); - case AF_INET6: - { - err = uv_ip6_addr(ip.c_str(), 0, reinterpret_cast(&bindAddr)); + // This should not happen. + MS_ASSERT(portRange.ports.at(portIdx) == true, "port %" PRIu16 " is not used", port); + MS_ASSERT(portRange.numUsedPorts > 0u, "number of used ports is 0"); - if (err != 0) - { - MS_THROW_ERROR("uv_ip6_addr() failed: %s", uv_strerror(err)); - } + // Mark the port as available. + portRange.ports[portIdx] = false; - break; - } + // Decrease number of used ports in the range. + portRange.numUsedPorts--; - // This cannot happen. - default: - { - MS_THROW_ERROR("unknown IP family"); - } - } - - // Set the port into the sockaddr struct. - switch (family) + // Remove vector if there are no used ports. + if (portRange.numUsedPorts == 0u) { - case AF_INET: - { - (reinterpret_cast(&bindAddr))->sin_port = htons(port); - - break; - } - - case AF_INET6: - { - (reinterpret_cast(&bindAddr))->sin6_port = htons(port); - - break; - } + PortManager::mapPortRanges.erase(it); } + } - // Try to bind on it. - switch (transport) - { - case Transport::UDP: - { - uvHandle = reinterpret_cast(new uv_udp_t()); - err = uv_udp_init_ex( - DepLibUV::GetLoop(), reinterpret_cast(uvHandle), UV_UDP_RECVMMSG); - - break; - } - - case Transport::TCP: - { - uvHandle = reinterpret_cast(new uv_tcp_t()); - err = uv_tcp_init(DepLibUV::GetLoop(), reinterpret_cast(uvHandle)); - - break; - } - } + void PortManager::Dump() + { + MS_DUMP(""); - if (err != 0) + for (auto& kv : PortManager::mapPortRanges) { - switch (transport) - { - case Transport::UDP: - { - delete reinterpret_cast(uvHandle); - - MS_THROW_ERROR("uv_udp_init_ex() failed: %s", uv_strerror(err)); - - break; - } + auto hash = kv.first; + auto portRange = kv.second; + + MS_DUMP(" "); + MS_DUMP(" hash: %" PRIu64, hash); + MS_DUMP(" minPort: %" PRIu16, portRange.minPort); + MS_DUMP(" maxPort: %zu", portRange.minPort + portRange.ports.size() - 1); + MS_DUMP(" numUsedPorts: %" PRIu16, portRange.numUsedPorts); + MS_DUMP(" "); + } - case Transport::TCP: - { - delete reinterpret_cast(uvHandle); + MS_DUMP(""); + } - MS_THROW_ERROR("uv_tcp_init() failed: %s", uv_strerror(err)); + /* + * Hash for IPv4. + * + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | MIN PORT | MAX PORT | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | IP | IP >> 2 |F|P| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Hash for IPv6. + * + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | MIN PORT | MAX PORT | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |IP[0] ^ IP[1] ^ IP[2] ^ IP[3] | same >> 2 |F|P| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + uint64_t PortManager::GeneratePortRangeHash( + Protocol protocol, sockaddr_storage* bindAddr, uint16_t minPort, uint16_t maxPort) + { + MS_TRACE(); - break; - } - } - } + uint64_t hash{ 0u }; - switch (transport) + switch (bindAddr->ss_family) { - case Transport::UDP: + case AF_INET: { - err = uv_udp_bind( - reinterpret_cast(uvHandle), - reinterpret_cast(&bindAddr), - bitFlags); + auto* bindAddrIn = reinterpret_cast(bindAddr); - if (err != 0) - { - // If it failed, close the handle and check the reason. - uv_close(reinterpret_cast(uvHandle), static_cast(onCloseUdp)); + // We want it in network order. + const uint64_t address = bindAddrIn->sin_addr.s_addr; - MS_THROW_ERROR( - "uv_udp_bind() failed [transport:%s, ip:'%s', port:%" PRIu16 "]: %s", - transportStr.c_str(), - ip.c_str(), - port, - uv_strerror(err)); - } + hash = static_cast(minPort) << 48; + hash = static_cast(maxPort) << 32; + hash |= (address >> 2) << 2; + hash |= 0x0000; // AF_INET. break; } - case Transport::TCP: + case AF_INET6: { - err = uv_tcp_bind( - reinterpret_cast(uvHandle), - reinterpret_cast(&bindAddr), - bitFlags); + auto* bindAddrIn6 = reinterpret_cast(bindAddr); + auto* a = reinterpret_cast(std::addressof(bindAddrIn6->sin6_addr)); - if (err != 0) - { - // If it failed, close the handle and check the reason. - uv_close(reinterpret_cast(uvHandle), static_cast(onCloseTcp)); + const auto address = a[0] ^ a[1] ^ a[2] ^ a[3]; - MS_THROW_ERROR( - "uv_tcp_bind() failed [transport:%s, ip:'%s', port:%" PRIu16 "]: %s", - transportStr.c_str(), - ip.c_str(), - port, - uv_strerror(err)); - } - - // uv_tcp_bind() may succeed even if later uv_listen() fails, so - // double check it. - err = uv_listen( - reinterpret_cast(uvHandle), - 256, - static_cast(onFakeConnection)); - - if (err != 0) - { - // If it failed, close the handle and check the reason. - uv_close(reinterpret_cast(uvHandle), static_cast(onCloseTcp)); - - MS_THROW_ERROR( - "uv_listen() failed [transport:%s, ip:'%s', port:%" PRIu16 "]: %s", - transportStr.c_str(), - ip.c_str(), - port, - uv_strerror(err)); - } + hash = static_cast(minPort) << 48; + hash = static_cast(maxPort) << 32; + hash |= static_cast(address) << 16; + hash |= (static_cast(address) >> 2) << 2; + hash |= 0x0002; // AF_INET6. break; } } - MS_DEBUG_DEV( - "bind succeeded [transport:%s, ip:'%s', port:%" PRIu16 "]", - transportStr.c_str(), - ip.c_str(), - port); - - return static_cast(uvHandle); - } - - void PortManager::Unbind(Transport transport, std::string& ip, uint16_t port) - { - MS_TRACE(); - - if ( - (static_cast(port) < Settings::configuration.rtcMinPort) || - (static_cast(port) > Settings::configuration.rtcMaxPort)) + // Override least significant bit with protocol information: + // - If UDP, start with 0. + // - If TCP, start with 1. + if (protocol == Protocol::UDP) { - MS_ERROR("given port %" PRIu16 " is out of range", port); - - return; + hash |= 0x0000; } - - const size_t portIdx = static_cast(port) - Settings::configuration.rtcMinPort; - - switch (transport) + else { - case Transport::UDP: - { - auto it = PortManager::mapUdpIpPorts.find(ip); - - if (it == PortManager::mapUdpIpPorts.end()) - { - return; - } - - auto& ports = it->second; - - // Mark the port as available. - ports[portIdx] = false; - - break; - } - - case Transport::TCP: - { - auto it = PortManager::mapTcpIpPorts.find(ip); - - if (it == PortManager::mapTcpIpPorts.end()) - { - return; - } - - auto& ports = it->second; - - // Mark the port as available. - ports[portIdx] = false; - - break; - } + hash |= 0x0001; } + + return hash; } - std::vector& PortManager::GetPorts(Transport transport, const std::string& ip) + PortManager::PortRange& PortManager::GetOrCreatePortRange( + uint64_t hash, uint16_t minPort, uint16_t maxPort) { MS_TRACE(); - // Make GCC happy so it does not print: - // "control reaches end of non-void function [-Wreturn-type]" - static std::vector emptyPorts; + auto it = PortManager::mapPortRanges.find(hash); - switch (transport) + // If the hash is already handled, return its port range. + if (it != PortManager::mapPortRanges.end()) { - case Transport::UDP: - { - auto it = PortManager::mapUdpIpPorts.find(ip); - - // If the IP is already handled, return its ports vector. - if (it != PortManager::mapUdpIpPorts.end()) - { - auto& ports = it->second; - - return ports; - } - - // Otherwise add an entry in the map and return it. - const uint16_t numPorts = - Settings::configuration.rtcMaxPort - Settings::configuration.rtcMinPort + 1; - - // Emplace a new vector filled with numPorts false values, meaning that - // all ports are available. - auto pair = PortManager::mapUdpIpPorts.emplace( - std::piecewise_construct, std::make_tuple(ip), std::make_tuple(numPorts, false)); + auto& portRange = it->second; - // pair.first is an iterator to the inserted value. - auto& ports = pair.first->second; - - return ports; - } - - case Transport::TCP: - { - auto it = PortManager::mapTcpIpPorts.find(ip); - - // If the IP is already handled, return its ports vector. - if (it != PortManager::mapTcpIpPorts.end()) - { - auto& ports = it->second; - - return ports; - } - - // Otherwise add an entry in the map and return it. - const uint16_t numPorts = - Settings::configuration.rtcMaxPort - Settings::configuration.rtcMinPort + 1; + return portRange; + } - // Emplace a new vector filled with numPorts false values, meaning that - // all ports are available. - auto pair = PortManager::mapTcpIpPorts.emplace( - std::piecewise_construct, std::make_tuple(ip), std::make_tuple(numPorts, false)); + const uint16_t numPorts = maxPort - minPort + 1; - // pair.first is an iterator to the inserted value. - auto& ports = pair.first->second; + // Emplace a new vector filled with numPorts false values, meaning that + // all ports are available. + auto pair = PortManager::mapPortRanges.emplace( + std::piecewise_construct, std::make_tuple(hash), std::make_tuple(numPorts, minPort)); - return ports; - } - } + // pair.first is an iterator to the inserted value. + auto& portRange = pair.first->second; - return emptyPorts; + return portRange; } - uint8_t PortManager::ConvertSocketFlags( - RTC::Transport::SocketFlags& flags, Transport transport, int family) + uint8_t PortManager::ConvertSocketFlags(RTC::Transport::SocketFlags& flags, Protocol protocol, int family) { MS_TRACE(); @@ -706,16 +755,16 @@ namespace RTC // Ignore ipv6Only in IPv4, otherwise libuv will throw. if (flags.ipv6Only && family == AF_INET6) { - switch (transport) + switch (protocol) { - case Transport::UDP: + case Protocol::UDP: { bitFlags |= UV_UDP_IPV6ONLY; break; } - case Transport::TCP: + case Protocol::TCP: { bitFlags |= UV_TCP_IPV6ONLY; @@ -725,7 +774,7 @@ namespace RTC } // Ignore udpReusePort in TCP, otherwise libuv will throw. - if (flags.udpReusePort && transport == Transport::UDP) + if (flags.udpReusePort && protocol == Protocol::UDP) { bitFlags |= UV_UDP_REUSEADDR; } diff --git a/worker/src/RTC/TcpServer.cpp b/worker/src/RTC/TcpServer.cpp index 685c0b1118..9ae9b49dfe 100644 --- a/worker/src/RTC/TcpServer.cpp +++ b/worker/src/RTC/TcpServer.cpp @@ -14,10 +14,11 @@ namespace RTC Listener* listener, RTC::TcpConnection::Listener* connListener, std::string& ip, + uint16_t port, RTC::Transport::SocketFlags& flags) : // This may throw. - ::TcpServerHandle::TcpServerHandle(RTC::PortManager::BindTcp(ip, flags)), listener(listener), - connListener(connListener) + ::TcpServerHandle::TcpServerHandle(RTC::PortManager::BindTcp(ip, port, flags)), + listener(listener), connListener(connListener), fixedPort(true) { MS_TRACE(); } @@ -26,13 +27,18 @@ namespace RTC Listener* listener, RTC::TcpConnection::Listener* connListener, std::string& ip, - uint16_t port, - RTC::Transport::SocketFlags& flags) + uint16_t minPort, + uint16_t maxPort, + RTC::Transport::SocketFlags& flags, + uint64_t& portRangeHash) : // This may throw. - ::TcpServerHandle::TcpServerHandle(RTC::PortManager::BindTcp(ip, port, flags)), - listener(listener), connListener(connListener), fixedPort(true) + ::TcpServerHandle::TcpServerHandle( + RTC::PortManager::BindTcp(ip, minPort, maxPort, flags, portRangeHash)), + listener(listener), connListener(connListener), fixedPort(false) { MS_TRACE(); + + this->portRangeHash = portRangeHash; } TcpServer::~TcpServer() @@ -41,7 +47,7 @@ namespace RTC if (!this->fixedPort) { - RTC::PortManager::UnbindTcp(this->localIp, this->localPort); + RTC::PortManager::Unbind(this->portRangeHash, this->localPort); } } diff --git a/worker/src/RTC/TransportTuple.cpp b/worker/src/RTC/TransportTuple.cpp index 33720bf689..68d14d0bd5 100644 --- a/worker/src/RTC/TransportTuple.cpp +++ b/worker/src/RTC/TransportTuple.cpp @@ -95,4 +95,77 @@ namespace RTC MS_DUMP(""); } + + /* + * Hash for IPv4. + * + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PORT | IP | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | IP | |F|P| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Hash for IPv6. + * + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PORT | IP[0] ^ IP[1] ^ IP[2] ^ IP[3]| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |IP[0] ^ IP[1] ^ IP[2] ^ IP[3] | IP[0] >> 16 |F|P| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + void TransportTuple::SetHash() + { + MS_TRACE(); + + const struct sockaddr* remoteSockAddr = GetRemoteAddress(); + + switch (remoteSockAddr->sa_family) + { + case AF_INET: + { + const auto* remoteSockAddrIn = reinterpret_cast(remoteSockAddr); + + const uint64_t address = ntohl(remoteSockAddrIn->sin_addr.s_addr); + const uint64_t port = ntohs(remoteSockAddrIn->sin_port); + + this->hash = port << 48; + this->hash |= address << 16; + this->hash |= 0x0000; // AF_INET. + + break; + } + + case AF_INET6: + { + const auto* remoteSockAddrIn6 = reinterpret_cast(remoteSockAddr); + const auto* a = + reinterpret_cast(std::addressof(remoteSockAddrIn6->sin6_addr)); + + const auto address1 = a[0] ^ a[1] ^ a[2] ^ a[3]; + const auto address2 = a[0]; + const uint64_t port = ntohs(remoteSockAddrIn6->sin6_port); + + this->hash = port << 48; + this->hash |= static_cast(address1) << 16; + this->hash |= address2 >> 16 & 0xFFFC; + this->hash |= 0x0002; // AF_INET6. + + break; + } + } + + // Override least significant bit with protocol information: + // - If UDP, start with 0. + // - If TCP, start with 1. + if (this->protocol == Protocol::UDP) + { + this->hash |= 0x0000; + } + else + { + this->hash |= 0x0001; + } + } } // namespace RTC diff --git a/worker/src/RTC/UdpSocket.cpp b/worker/src/RTC/UdpSocket.cpp index c6d4ff5500..5069688baf 100644 --- a/worker/src/RTC/UdpSocket.cpp +++ b/worker/src/RTC/UdpSocket.cpp @@ -10,20 +10,30 @@ namespace RTC { /* Instance methods. */ - UdpSocket::UdpSocket(Listener* listener, std::string& ip, RTC::Transport::SocketFlags& flags) + UdpSocket::UdpSocket( + Listener* listener, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags) : // This may throw. - ::UdpSocketHandle::UdpSocketHandle(PortManager::BindUdp(ip, flags)), listener(listener) + ::UdpSocketHandle::UdpSocketHandle(RTC::PortManager::BindUdp(ip, port, flags)), + listener(listener), fixedPort(true) { MS_TRACE(); } UdpSocket::UdpSocket( - Listener* listener, std::string& ip, uint16_t port, RTC::Transport::SocketFlags& flags) + Listener* listener, + std::string& ip, + uint16_t minPort, + uint16_t maxPort, + RTC::Transport::SocketFlags& flags, + uint64_t& portRangeHash) : // This may throw. - ::UdpSocketHandle::UdpSocketHandle(PortManager::BindUdp(ip, port, flags)), listener(listener), - fixedPort(true) + ::UdpSocketHandle::UdpSocketHandle( + RTC::PortManager::BindUdp(ip, minPort, maxPort, flags, portRangeHash)), + listener(listener), fixedPort(false) { MS_TRACE(); + + this->portRangeHash = portRangeHash; } UdpSocket::~UdpSocket() @@ -32,7 +42,7 @@ namespace RTC if (!this->fixedPort) { - PortManager::UnbindUdp(this->localIp, this->localPort); + RTC::PortManager::Unbind(this->portRangeHash, this->localPort); } } diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 362b43d455..1cd27188b5 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -4,6 +4,7 @@ #include "RTC/WebRtcServer.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Settings.hpp" #include "Utils.hpp" #include // std::pow() @@ -94,13 +95,36 @@ namespace RTC // This may throw. RTC::UdpSocket* udpSocket; - if (listenInfo->port() != 0) + if (listenInfo->portRange()->min() != 0 && listenInfo->portRange()->max() != 0) + { + uint64_t portRangeHash{ 0u }; + + udpSocket = new RTC::UdpSocket( + this, + ip, + listenInfo->portRange()->min(), + listenInfo->portRange()->max(), + flags, + portRangeHash); + } + else if (listenInfo->port() != 0) { udpSocket = new RTC::UdpSocket(this, ip, listenInfo->port(), flags); } + // NOTE: This is temporal to allow deprecated usage of worker port range. + // In the future this should throw since |port| or |portRange| will be + // required. else { - udpSocket = new RTC::UdpSocket(this, ip, flags); + uint64_t portRangeHash{ 0u }; + + udpSocket = new RTC::UdpSocket( + this, + ip, + Settings::configuration.rtcMinPort, + Settings::configuration.rtcMaxPort, + flags, + portRangeHash); } this->udpSocketOrTcpServers.emplace_back(udpSocket, nullptr, announcedAddress); @@ -126,13 +150,38 @@ namespace RTC // This may throw. RTC::TcpServer* tcpServer; - if (listenInfo->port() != 0) + if (listenInfo->portRange()->min() != 0 && listenInfo->portRange()->max() != 0) + { + uint64_t portRangeHash{ 0u }; + + tcpServer = new RTC::TcpServer( + this, + this, + ip, + listenInfo->portRange()->min(), + listenInfo->portRange()->max(), + flags, + portRangeHash); + } + else if (listenInfo->port() != 0) { tcpServer = new RTC::TcpServer(this, this, ip, listenInfo->port(), flags); } + // NOTE: This is temporal to allow deprecated usage of worker port range. + // In the future this should throw since |port| or |portRange| will be + // required. else { - tcpServer = new RTC::TcpServer(this, this, ip, flags); + uint64_t portRangeHash{ 0u }; + + tcpServer = new RTC::TcpServer( + this, + this, + ip, + Settings::configuration.rtcMinPort, + Settings::configuration.rtcMaxPort, + flags, + portRangeHash); } this->udpSocketOrTcpServers.emplace_back(nullptr, tcpServer, announcedAddress); diff --git a/worker/src/RTC/WebRtcTransport.cpp b/worker/src/RTC/WebRtcTransport.cpp index a5deb26fe0..c5d0bc5673 100644 --- a/worker/src/RTC/WebRtcTransport.cpp +++ b/worker/src/RTC/WebRtcTransport.cpp @@ -4,6 +4,7 @@ #include "RTC/WebRtcTransport.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Settings.hpp" #include "Utils.hpp" #include "FBS/webRtcTransport.h" #include // std::pow() @@ -75,13 +76,36 @@ namespace RTC { RTC::UdpSocket* udpSocket; - if (listenInfo->port() != 0) + if (listenInfo->portRange()->min() != 0 && listenInfo->portRange()->max() != 0) + { + uint64_t portRangeHash{ 0u }; + + udpSocket = new RTC::UdpSocket( + this, + ip, + listenInfo->portRange()->min(), + listenInfo->portRange()->max(), + flags, + portRangeHash); + } + else if (listenInfo->port() != 0) { udpSocket = new RTC::UdpSocket(this, ip, listenInfo->port(), flags); } + // NOTE: This is temporal to allow deprecated usage of worker port range. + // In the future this should throw since |port| or |portRange| will be + // required. else { - udpSocket = new RTC::UdpSocket(this, ip, flags); + uint64_t portRangeHash{ 0u }; + + udpSocket = new RTC::UdpSocket( + this, + ip, + Settings::configuration.rtcMinPort, + Settings::configuration.rtcMaxPort, + flags, + portRangeHash); } this->udpSockets[udpSocket] = announcedAddress; @@ -117,13 +141,38 @@ namespace RTC { RTC::TcpServer* tcpServer; - if (listenInfo->port() != 0) + if (listenInfo->portRange()->min() != 0 && listenInfo->portRange()->max() != 0) + { + uint64_t portRangeHash{ 0u }; + + tcpServer = new RTC::TcpServer( + this, + this, + ip, + listenInfo->portRange()->min(), + listenInfo->portRange()->max(), + flags, + portRangeHash); + } + else if (listenInfo->port() != 0) { tcpServer = new RTC::TcpServer(this, this, ip, listenInfo->port(), flags); } + // NOTE: This is temporal to allow deprecated usage of worker port range. + // In the future this should throw since |port| or |portRange| will be + // required. else { - tcpServer = new RTC::TcpServer(this, this, ip, flags); + uint64_t portRangeHash{ 0u }; + + tcpServer = new RTC::TcpServer( + this, + this, + ip, + Settings::configuration.rtcMinPort, + Settings::configuration.rtcMaxPort, + flags, + portRangeHash); } this->tcpServers[tcpServer] = announcedAddress; diff --git a/worker/src/Worker.cpp b/worker/src/Worker.cpp index 2dd3cb2b6f..5a3e7f4670 100644 --- a/worker/src/Worker.cpp +++ b/worker/src/Worker.cpp @@ -139,6 +139,7 @@ flatbuffers::Offset Worker::FillBuffer( routerIds.push_back(builder.CreateString(routerId)); } + // Add channelMessageHandlers. auto channelMessageHandlers = this->shared->channelMessageRegistrator->FillBuffer(builder); return FBS::Worker::CreateDumpResponseDirect( From 1d71e4b69e35e3b4c059f0b8270ee0e0993f051b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 8 Apr 2024 16:32:26 +0200 Subject: [PATCH 11/28] 3.14.0 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3462be0dc..5cec4f7c36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -### NEXT +### 3.14.0 - `TransportListenInfo`: Add `portRange` (deprecate worker port range) ([PR #1365](https://github.com/versatica/mediasoup/pull/1365)). - Require Node.js >= 18 ([PR #1365](https://github.com/versatica/mediasoup/pull/1365)). diff --git a/package-lock.json b/package-lock.json index 4531ca93d3..c3799da215 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.13.24", + "version": "3.14.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.13.24", + "version": "3.14.0", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 87fa1f789d..aaf9dd46e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.13.24", + "version": "3.14.0", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "IƱaki Baz Castillo (https://inakibaz.me)", From 1a507ecc2da2ce6886a26ead0adf59243519f73c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 8 Apr 2024 16:51:38 +0200 Subject: [PATCH 12/28] Node: update tests to use portRange --- node/src/test/test-PipeTransport.ts | 22 ++++- node/src/test/test-PlainTransport.ts | 17 +++- node/src/test/test-WebRtcServer.ts | 71 ++++++++++++++- node/src/test/test-WebRtcTransport.ts | 126 +++++++++++++++++++++----- 4 files changed, 211 insertions(+), 25 deletions(-) diff --git a/node/src/test/test-PipeTransport.ts b/node/src/test/test-PipeTransport.ts index 3b9052374d..bfa17f9c18 100644 --- a/node/src/test/test-PipeTransport.ts +++ b/node/src/test/test-PipeTransport.ts @@ -453,6 +453,16 @@ test('router.createPipeTransport() with wrong arguments rejects with TypeError', // @ts-ignore await expect(ctx.router1!.createPipeTransport({})).rejects.toThrow(TypeError); + await expect( + ctx.router1!.createPipeTransport({ + listenInfo: { + protocol: 'udp', + ip: '127.0.0.1', + portRange: { min: 4000, max: 3000 }, + }, + }) + ).rejects.toThrow(TypeError); + await expect( ctx.router1!.createPipeTransport({ listenIp: '123' }) ).rejects.toThrow(TypeError); @@ -479,7 +489,11 @@ test('router.createPipeTransport() with wrong arguments rejects with TypeError', test('router.createPipeTransport() with enableRtx succeeds', async () => { const pipeTransport = await ctx.router1!.createPipeTransport({ - listenInfo: { protocol: 'udp', ip: '127.0.0.1' }, + listenInfo: { + protocol: 'udp', + ip: '127.0.0.1', + portRange: { min: 2000, max: 3000 }, + }, enableRtx: true, }); @@ -583,7 +597,11 @@ test('pipeTransport.connect() with valid SRTP parameters succeeds', async () => test('pipeTransport.connect() with srtpParameters fails if enableSrtp is unset', async () => { const pipeTransport = await ctx.router1!.createPipeTransport({ - listenInfo: { protocol: 'udp', ip: '127.0.0.1' }, + listenInfo: { + protocol: 'udp', + ip: '127.0.0.1', + portRange: { min: 2000, max: 3000 }, + }, enableRtx: true, }); diff --git a/node/src/test/test-PlainTransport.ts b/node/src/test/test-PlainTransport.ts index 6588fe55cb..c0e1a0afc1 100644 --- a/node/src/test/test-PlainTransport.ts +++ b/node/src/test/test-PlainTransport.ts @@ -60,7 +60,11 @@ afterEach(async () => { test('router.createPlainTransport() succeeds', async () => { const plainTransport = await ctx.router!.createPlainTransport({ - listenInfo: { protocol: 'udp', ip: '127.0.0.1' }, + listenInfo: { + protocol: 'udp', + ip: '127.0.0.1', + portRange: { min: 2000, max: 3000 }, + }, }); await expect(ctx.router!.dump()).resolves.toMatchObject({ @@ -77,6 +81,7 @@ test('router.createPlainTransport() succeeds', async () => { protocol: 'udp', ip: '127.0.0.1', announcedAddress: '9.9.9.1', + portRange: { min: 2000, max: 3000 }, }, enableSctp: true, appData: { foo: 'bar' }, @@ -171,6 +176,16 @@ test('router.createPlainTransport() with wrong arguments rejects with TypeError' // @ts-ignore await expect(ctx.router!.createPlainTransport({})).rejects.toThrow(TypeError); + await expect( + ctx.router!.createPlainTransport({ + listenInfo: { + protocol: 'udp', + ip: '127.0.0.1', + portRange: { min: 4000, max: 3000 }, + }, + }) + ).rejects.toThrow(TypeError); + await expect( ctx.router!.createPlainTransport({ listenIp: '123' }) ).rejects.toThrow(TypeError); diff --git a/node/src/test/test-WebRtcServer.ts b/node/src/test/test-WebRtcServer.ts index e5e2e2b703..4641f7415a 100644 --- a/node/src/test/test-WebRtcServer.ts +++ b/node/src/test/test-WebRtcServer.ts @@ -91,7 +91,76 @@ test('worker.createWebRtcServer() succeeds', async () => { expect(ctx.worker!.webRtcServersForTesting.size).toBe(0); }, 2000); -test('worker.createWebRtcServer() without specifying port succeeds', async () => { +test('worker.createWebRtcServer() with portRange succeeds', async () => { + const onObserverNewWebRtcServer = jest.fn(); + + ctx.worker!.observer.once('newwebrtcserver', onObserverNewWebRtcServer); + + const port1 = await pickPort({ + type: 'udp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); + const port2 = await pickPort({ + type: 'udp', + ip: '127.0.0.1', + reserveTimeout: 0, + }); + + const webRtcServer = await ctx.worker!.createWebRtcServer({ + listenInfos: [ + { + protocol: 'udp', + ip: '127.0.0.1', + portRange: { min: port1, max: port1 }, + }, + { + protocol: 'tcp', + ip: '127.0.0.1', + announcedAddress: '1.2.3.4', + portRange: { min: port2, max: port2 }, + }, + ], + appData: { foo: 123 }, + }); + + expect(onObserverNewWebRtcServer).toHaveBeenCalledTimes(1); + expect(onObserverNewWebRtcServer).toHaveBeenCalledWith(webRtcServer); + expect(typeof webRtcServer.id).toBe('string'); + expect(webRtcServer.closed).toBe(false); + expect(webRtcServer.appData).toEqual({ foo: 123 }); + + await expect(ctx.worker!.dump()).resolves.toMatchObject({ + pid: ctx.worker!.pid, + webRtcServerIds: [webRtcServer.id], + routerIds: [], + channelMessageHandlers: { + channelRequestHandlers: [webRtcServer.id], + channelNotificationHandlers: [], + }, + }); + + await expect(webRtcServer.dump()).resolves.toMatchObject({ + id: webRtcServer.id, + udpSockets: [{ ip: '127.0.0.1', port: port1 }], + tcpServers: [{ ip: '127.0.0.1', port: port2 }], + webRtcTransportIds: [], + localIceUsernameFragments: [], + tupleHashes: [], + }); + + // Private API. + expect(ctx.worker!.webRtcServersForTesting.size).toBe(1); + + ctx.worker!.close(); + + expect(webRtcServer.closed).toBe(true); + + // Private API. + expect(ctx.worker!.webRtcServersForTesting.size).toBe(0); +}, 2000); + +test('worker.createWebRtcServer() without specifying port/portRange succeeds', async () => { const onObserverNewWebRtcServer = jest.fn(); ctx.worker!.observer.once('newwebrtcserver', onObserverNewWebRtcServer); diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index 109b15499b..c069b54c0c 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -70,12 +70,42 @@ test('router.createWebRtcTransport() succeeds', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ listenInfos: [ - { protocol: 'udp', ip: '127.0.0.1', announcedAddress: '9.9.9.1' }, - { protocol: 'tcp', ip: '127.0.0.1', announcedAddress: '9.9.9.1' }, - { protocol: 'udp', ip: '0.0.0.0', announcedAddress: 'foo1.bar.org' }, - { protocol: 'tcp', ip: '0.0.0.0', announcedAddress: 'foo2.bar.org' }, - { protocol: 'udp', ip: '127.0.0.1', announcedAddress: undefined }, - { protocol: 'tcp', ip: '127.0.0.1', announcedAddress: undefined }, + { + protocol: 'udp', + ip: '127.0.0.1', + announcedAddress: '9.9.9.1', + portRange: { min: 2000, max: 3000 }, + }, + { + protocol: 'tcp', + ip: '127.0.0.1', + announcedAddress: '9.9.9.1', + portRange: { min: 2000, max: 3000 }, + }, + { + protocol: 'udp', + ip: '0.0.0.0', + announcedAddress: 'foo1.bar.org', + portRange: { min: 2000, max: 3000 }, + }, + { + protocol: 'tcp', + ip: '0.0.0.0', + announcedAddress: 'foo2.bar.org', + portRange: { min: 2000, max: 3000 }, + }, + { + protocol: 'udp', + ip: '127.0.0.1', + announcedAddress: undefined, + portRange: { min: 2000, max: 3000 }, + }, + { + protocol: 'tcp', + ip: '127.0.0.1', + announcedAddress: undefined, + portRange: { min: 2000, max: 3000 }, + }, ], enableTcp: true, preferUdp: true, @@ -254,6 +284,18 @@ test('router.createWebRtcTransport() with wrong arguments rejects with TypeError TypeError ); + await expect( + ctx.router!.createWebRtcTransport({ + listenInfos: [ + { + protocol: 'udp', + ip: '127.0.0.1', + portRange: { min: 4000, max: 3000 }, + }, + ], + }) + ).rejects.toThrow(TypeError); + await expect( // @ts-ignore ctx.router!.createWebRtcTransport({ listenIps: [123] }) @@ -290,7 +332,9 @@ test('router.createWebRtcTransport() with wrong arguments rejects with TypeError test('router.createWebRtcTransport() with non bindable IP rejects with Error', async () => { await expect( ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '8.8.8.8' }], + listenInfos: [ + { protocol: 'udp', ip: '8.8.8.8', portRange: { min: 2000, max: 3000 } }, + ], }) ).rejects.toThrow(Error); }, 2000); @@ -298,7 +342,12 @@ test('router.createWebRtcTransport() with non bindable IP rejects with Error', a test('webRtcTransport.getStats() succeeds', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ listenInfos: [ - { protocol: 'udp', ip: '127.0.0.1', announcedAddress: '9.9.9.1' }, + { + protocol: 'udp', + ip: '127.0.0.1', + announcedAddress: '9.9.9.1', + portRange: { min: 2000, max: 3000 }, + }, ], }); @@ -334,7 +383,12 @@ test('webRtcTransport.getStats() succeeds', async () => { test('webRtcTransport.connect() succeeds', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ listenInfos: [ - { protocol: 'udp', ip: '127.0.0.1', announcedAddress: '9.9.9.1' }, + { + protocol: 'udp', + ip: '127.0.0.1', + announcedAddress: '9.9.9.1', + portRange: { min: 2000, max: 3000 }, + }, ], }); @@ -368,7 +422,12 @@ test('webRtcTransport.connect() succeeds', async () => { test('webRtcTransport.connect() with wrong arguments rejects with TypeError', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ listenInfos: [ - { protocol: 'udp', ip: '127.0.0.1', announcedAddress: '9.9.9.1' }, + { + protocol: 'udp', + ip: '127.0.0.1', + announcedAddress: '9.9.9.1', + portRange: { min: 2000, max: 3000 }, + }, ], }); @@ -428,7 +487,12 @@ test('webRtcTransport.connect() with wrong arguments rejects with TypeError', as test('webRtcTransport.setMaxIncomingBitrate() succeeds', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ listenInfos: [ - { protocol: 'udp', ip: '127.0.0.1', announcedAddress: '9.9.9.1' }, + { + protocol: 'udp', + ip: '127.0.0.1', + announcedAddress: '9.9.9.1', + portRange: { min: 2000, max: 3000 }, + }, ], }); @@ -444,7 +508,9 @@ test('webRtcTransport.setMaxIncomingBitrate() succeeds', async () => { test('webRtcTransport.setMaxOutgoingBitrate() succeeds', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); await expect( @@ -459,7 +525,9 @@ test('webRtcTransport.setMaxOutgoingBitrate() succeeds', async () => { test('webRtcTransport.setMinOutgoingBitrate() succeeds', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); await expect( @@ -474,7 +542,9 @@ test('webRtcTransport.setMinOutgoingBitrate() succeeds', async () => { test('webRtcTransport.setMaxOutgoingBitrate() fails if value is lower than current min limit', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); await expect( @@ -493,7 +563,9 @@ test('webRtcTransport.setMaxOutgoingBitrate() fails if value is lower than curre test('webRtcTransport.setMinOutgoingBitrate() fails if value is higher than current max limit', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); await expect( @@ -512,7 +584,9 @@ test('webRtcTransport.setMinOutgoingBitrate() fails if value is higher than curr test('webRtcTransport.restartIce() succeeds', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); const previousIceUsernameFragment = @@ -535,7 +609,9 @@ test('webRtcTransport.restartIce() succeeds', async () => { test('transport.enableTraceEvent() succeed', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); // @ts-ignore @@ -563,7 +639,9 @@ test('transport.enableTraceEvent() succeed', async () => { test('transport.enableTraceEvent() with wrong arguments rejects with TypeError', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); // @ts-ignore @@ -584,7 +662,9 @@ test('transport.enableTraceEvent() with wrong arguments rejects with TypeError', test('WebRtcTransport events succeed', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); // Private API. @@ -715,7 +795,9 @@ test('WebRtcTransport events succeed', async () => { test('WebRtcTransport methods reject if closed', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); const onObserverClose = jest.fn(); @@ -778,7 +860,9 @@ test('WebRtcTransport emits "routerclose" if Router is closed', async () => { test('WebRtcTransport emits "routerclose" if Worker is closed', async () => { const webRtcTransport = await ctx.router!.createWebRtcTransport({ - listenInfos: [{ protocol: 'udp', ip: '127.0.0.1' }], + listenInfos: [ + { protocol: 'udp', ip: '127.0.0.1', portRange: { min: 2000, max: 3000 } }, + ], }); const onObserverClose = jest.fn(); From c0e3a62342bb718871ff5ab4efd699257e52f833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 9 Apr 2024 15:16:35 +0200 Subject: [PATCH 13/28] Avoid abseil containers with SeqManager compare functions (#1369) --- .github/workflows/codeql.yaml | 1 + .github/workflows/mediasoup-node.yaml | 4 ++++ .github/workflows/mediasoup-rust.yaml | 6 +++++- .github/workflows/mediasoup-worker-fuzzer.yaml | 4 ++++ .github/workflows/mediasoup-worker-prebuild.yaml | 1 + .github/workflows/mediasoup-worker.yaml | 4 ++++ worker/include/RTC/NackGenerator.hpp | 8 +++----- worker/include/RTC/SenderBandwidthEstimator.hpp | 3 +-- worker/include/RTC/WebRtcServer.hpp | 2 ++ worker/src/RTC/AudioLevelObserver.cpp | 1 + worker/src/RTC/WebRtcServer.cpp | 11 ++++++++++- 11 files changed, 36 insertions(+), 9 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 16712fe8d3..331661b59c 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -42,6 +42,7 @@ jobs: env: MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' MEDIASOUP_LOCAL_DEV: 'true' + MEDIASOUP_BUILDTYPE: 'Release' steps: - name: Checkout repository diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index bf643d7caf..a8436e5e0f 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -29,12 +29,16 @@ jobs: node: 20 - os: windows-2022 node: 20 + build-type: + - Release + - Debug runs-on: ${{ matrix.ci.os }} env: MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' MEDIASOUP_LOCAL_DEV: 'true' + MEDIASOUP_BUILDTYPE: ${{ matrix.build-type }} steps: - name: Checkout diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index c2f449c010..a6605fa8d7 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -49,8 +49,12 @@ jobs: - name: cargo clippy run: cargo clippy --all-targets -- -D warnings + # NOTE: In Windows this will build and test libmediasoupworker in release + # mode twice since build.rs doesn't allow debug mode for Windows. - name: cargo test - run: cargo test --verbose + run: | + cargo test --verbose + cargo test --release --verbose - name: cargo doc run: cargo doc --locked --all --no-deps --lib diff --git a/.github/workflows/mediasoup-worker-fuzzer.yaml b/.github/workflows/mediasoup-worker-fuzzer.yaml index 6662e144ac..97b2b0cfb5 100644 --- a/.github/workflows/mediasoup-worker-fuzzer.yaml +++ b/.github/workflows/mediasoup-worker-fuzzer.yaml @@ -20,6 +20,9 @@ jobs: cc: clang cxx: clang++ arch: arm64 + build-type: + - Release + - Debug runs-on: ${{ matrix.build.os }} @@ -28,6 +31,7 @@ jobs: CXX: ${{ matrix.build.cxx }} MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' MEDIASOUP_LOCAL_DEV: 'true' + MEDIASOUP_BUILDTYPE: ${{ matrix.build-type }} steps: - name: Checkout diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index e6616f033d..35cc8466cc 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -51,6 +51,7 @@ jobs: CXX: ${{ matrix.build.cxx }} MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' MEDIASOUP_LOCAL_DEV: 'true' + MEDIASOUP_BUILDTYPE: 'Release' steps: - name: Checkout diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 6851658a8f..0b05cd9dc1 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -53,6 +53,9 @@ jobs: # A single Node.js version should be fine for C++. node: - 20 + build-type: + - Release + - Debug runs-on: ${{ matrix.build.os }} @@ -61,6 +64,7 @@ jobs: CXX: ${{ matrix.build.cxx }} MEDIASOUP_SKIP_WORKER_PREBUILT_DOWNLOAD: 'true' MEDIASOUP_LOCAL_DEV: 'true' + MEDIASOUP_BUILDTYPE: ${{ matrix.build-type }} steps: - name: Checkout diff --git a/worker/include/RTC/NackGenerator.hpp b/worker/include/RTC/NackGenerator.hpp index 3195267729..f46ab43fe7 100644 --- a/worker/include/RTC/NackGenerator.hpp +++ b/worker/include/RTC/NackGenerator.hpp @@ -5,8 +5,6 @@ #include "RTC/RtpPacket.hpp" #include "RTC/SeqManager.hpp" #include "handles/TimerHandle.hpp" -#include -#include #include #include #include @@ -80,9 +78,9 @@ namespace RTC // Allocated by this. TimerHandle* timer{ nullptr }; // Others. - absl::btree_map::SeqLowerThan> nackList; - absl::btree_set::SeqLowerThan> keyFrameList; - absl::btree_set::SeqLowerThan> recoveredList; + std::map::SeqLowerThan> nackList; + std::set::SeqLowerThan> keyFrameList; + std::set::SeqLowerThan> recoveredList; bool started{ false }; uint16_t lastSeq{ 0u }; // Seq number of last valid packet. uint32_t rtt{ 0u }; // Round trip time (ms). diff --git a/worker/include/RTC/SenderBandwidthEstimator.hpp b/worker/include/RTC/SenderBandwidthEstimator.hpp index 208b188f93..7b715deee9 100644 --- a/worker/include/RTC/SenderBandwidthEstimator.hpp +++ b/worker/include/RTC/SenderBandwidthEstimator.hpp @@ -6,7 +6,6 @@ #include "RTC/RateCalculator.hpp" #include "RTC/SeqManager.hpp" #include "RTC/TrendCalculator.hpp" -#include #include namespace RTC @@ -103,7 +102,7 @@ namespace RTC uint32_t initialAvailableBitrate{ 0u }; uint32_t availableBitrate{ 0u }; uint64_t lastAvailableBitrateEventAtMs{ 0u }; - absl::btree_map::SeqLowerThan> sentInfos; + std::map::SeqLowerThan> sentInfos; float rtt{ 0 }; // Round trip time in ms. CummulativeResult cummulativeResult; CummulativeResult probationCummulativeResult; diff --git a/worker/include/RTC/WebRtcServer.hpp b/worker/include/RTC/WebRtcServer.hpp index 96bde6e277..11f3901dfb 100644 --- a/worker/include/RTC/WebRtcServer.hpp +++ b/worker/include/RTC/WebRtcServer.hpp @@ -106,6 +106,8 @@ namespace RTC absl::flat_hash_map mapLocalIceUsernameFragmentWebRtcTransport; // Map of WebRtcTransports indexed by TransportTuple.hash. absl::flat_hash_map mapTupleWebRtcTransport; + // Whether the destructor has been called. + bool closing{ false }; }; } // namespace RTC diff --git a/worker/src/RTC/AudioLevelObserver.cpp b/worker/src/RTC/AudioLevelObserver.cpp index 0b880d88af..ef40fa26e1 100644 --- a/worker/src/RTC/AudioLevelObserver.cpp +++ b/worker/src/RTC/AudioLevelObserver.cpp @@ -5,6 +5,7 @@ #include "Logger.hpp" #include "MediaSoupErrors.hpp" #include "RTC/RtpDictionaries.hpp" +#include #include // std::lround() namespace RTC diff --git a/worker/src/RTC/WebRtcServer.cpp b/worker/src/RTC/WebRtcServer.cpp index 1cd27188b5..274391d922 100644 --- a/worker/src/RTC/WebRtcServer.cpp +++ b/worker/src/RTC/WebRtcServer.cpp @@ -232,6 +232,8 @@ namespace RTC { MS_TRACE(); + this->closing = true; + this->shared->channelMessageRegistrator->UnregisterHandler(this->id); for (auto& item : this->udpSocketOrTcpServers) @@ -497,7 +499,14 @@ namespace RTC this->webRtcTransports.find(webRtcTransport) != this->webRtcTransports.end(), "WebRtcTransport not handled"); - this->webRtcTransports.erase(webRtcTransport); + // NOTE: If WebRtcServer is closing then do not remove the transport from + // the set since it would modify the set while the WebRtcServer destructor + // is iterating it. + // See: https://github.com/versatica/mediasoup/pull/1369#issuecomment-2044672247 + if (!this->closing) + { + this->webRtcTransports.erase(webRtcTransport); + } } inline void WebRtcServer::OnWebRtcTransportLocalIceUsernameFragmentAdded( From 35057305b7574ad641572a64ca62080494d69e67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 9 Apr 2024 18:42:26 +0200 Subject: [PATCH 14/28] [Node] Bring transport rtpPacketLossReceived and rtpPacketLossSent stats back (#1371) --- CHANGELOG.md | 4 ++++ node/src/Transport.ts | 37 +++++++++++++++++++++++++++++++----- worker/src/RTC/Transport.cpp | 4 ++-- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cec4f7c36..3fcb84ad71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### NEXT + +- Node: Bring transport `rtpPacketLossReceived` and `rtpPacketLossSent` stats back ([PR #XXXX](https://github.com/versatica/mediasoup/pull/XXXX)). + ### 3.14.0 - `TransportListenInfo`: Add `portRange` (deprecate worker port range) ([PR #1365](https://github.com/versatica/mediasoup/pull/1365)). diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 64299f9ca2..ca330b6c54 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -285,6 +285,10 @@ export type BaseTransportStats = { availableOutgoingBitrate?: number; availableIncomingBitrate?: number; maxIncomingBitrate?: number; + maxOutgoingBitrate?: number; + minOutgoingBitrate?: number; + rtpPacketLossReceived?: number; + rtpPacketLossSent?: number; }; type TransportData = @@ -1475,11 +1479,34 @@ export function parseBaseTransportStats( rtxSendBitrate: Number(binary.rtxSendBitrate()), probationBytesSent: Number(binary.probationBytesSent()), probationSendBitrate: Number(binary.probationSendBitrate()), - availableOutgoingBitrate: Number(binary.availableOutgoingBitrate()), - availableIncomingBitrate: Number(binary.availableIncomingBitrate()), - maxIncomingBitrate: binary.maxIncomingBitrate() - ? Number(binary.maxIncomingBitrate()) - : undefined, + availableOutgoingBitrate: + typeof binary.availableOutgoingBitrate() === 'number' + ? Number(binary.availableOutgoingBitrate()) + : undefined, + availableIncomingBitrate: + typeof binary.availableIncomingBitrate() === 'number' + ? Number(binary.availableIncomingBitrate()) + : undefined, + maxIncomingBitrate: + typeof binary.maxIncomingBitrate() === 'number' + ? Number(binary.maxIncomingBitrate()) + : undefined, + maxOutgoingBitrate: + typeof binary.maxOutgoingBitrate() === 'number' + ? Number(binary.maxOutgoingBitrate()) + : undefined, + minOutgoingBitrate: + typeof binary.minOutgoingBitrate() === 'number' + ? Number(binary.minOutgoingBitrate()) + : undefined, + rtpPacketLossReceived: + typeof binary.rtpPacketLossReceived() === 'number' + ? Number(binary.rtpPacketLossReceived()) + : undefined, + rtpPacketLossSent: + typeof binary.rtpPacketLossSent() === 'number' + ? Number(binary.rtpPacketLossSent()) + : undefined, }; } diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index ea5426970f..89f5800ea3 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -502,10 +502,10 @@ namespace RTC // minOutgoingBitrate. this->minOutgoingBitrate ? flatbuffers::Optional(this->minOutgoingBitrate) : flatbuffers::nullopt, - // packetLossReceived. + // rtpPacketLossReceived. this->tccServer ? flatbuffers::Optional(this->tccServer->GetPacketLoss()) : flatbuffers::nullopt, - // packetLossSent. + // rtpPacketLossSent. this->tccClient ? flatbuffers::Optional(this->tccClient->GetPacketLoss()) : flatbuffers::nullopt); } From 09c1ba5bdc47ce489ded3f7c5e7d3d76191f0a78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 9 Apr 2024 18:58:32 +0200 Subject: [PATCH 15/28] 3.14.1 --- CHANGELOG.md | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fcb84ad71..31badafe81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ # Changelog -### NEXT +### 3.14.1 -- Node: Bring transport `rtpPacketLossReceived` and `rtpPacketLossSent` stats back ([PR #XXXX](https://github.com/versatica/mediasoup/pull/XXXX)). +- Node: Bring transport `rtpPacketLossReceived` and `rtpPacketLossSent` stats back ([PR #1371](https://github.com/versatica/mediasoup/pull/1371)). ### 3.14.0 diff --git a/package-lock.json b/package-lock.json index c3799da215..59f4478ff1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.14.0", + "version": "3.14.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.14.0", + "version": "3.14.1", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index aaf9dd46e3..925f1ca850 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.14.0", + "version": "3.14.1", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "IƱaki Baz Castillo (https://inakibaz.me)", From 8be8493091a42d54ed6d6b4c0731795894984c94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 10 Apr 2024 10:18:27 +0200 Subject: [PATCH 16/28] CI: Remove machines with arch arm64 (#1373) --- .github/workflows/mediasoup-node.yaml | 6 ------ .github/workflows/mediasoup-rust.yaml | 4 ---- .github/workflows/mediasoup-worker-fuzzer.yaml | 4 ---- .github/workflows/mediasoup-worker-prebuild.yaml | 10 ---------- .github/workflows/mediasoup-worker.yaml | 16 ---------------- 5 files changed, 40 deletions(-) diff --git a/.github/workflows/mediasoup-node.yaml b/.github/workflows/mediasoup-node.yaml index a8436e5e0f..b035e0c56f 100644 --- a/.github/workflows/mediasoup-node.yaml +++ b/.github/workflows/mediasoup-node.yaml @@ -17,12 +17,6 @@ jobs: node: 18 - os: ubuntu-22.04 node: 20 - - os: ubuntu-20.04 - node: 18 - arch: arm64 - - os: ubuntu-22.04 - node: 20 - arch: arm64 - os: macos-12 node: 18 - os: macos-14 diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index a6605fa8d7..9b76ffcb22 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -18,10 +18,6 @@ jobs: ci: - os: ubuntu-20.04 - os: ubuntu-22.04 - - os: ubuntu-20.04 - arch: arm64 - - os: ubuntu-22.04 - arch: arm64 - os: macos-12 - os: macos-14 - os: windows-2022 diff --git a/.github/workflows/mediasoup-worker-fuzzer.yaml b/.github/workflows/mediasoup-worker-fuzzer.yaml index 97b2b0cfb5..60798016db 100644 --- a/.github/workflows/mediasoup-worker-fuzzer.yaml +++ b/.github/workflows/mediasoup-worker-fuzzer.yaml @@ -16,10 +16,6 @@ jobs: - os: ubuntu-22.04 cc: clang cxx: clang++ - - os: ubuntu-22.04 - cc: clang - cxx: clang++ - arch: arm64 build-type: - Release - Debug diff --git a/.github/workflows/mediasoup-worker-prebuild.yaml b/.github/workflows/mediasoup-worker-prebuild.yaml index 35cc8466cc..762361367b 100644 --- a/.github/workflows/mediasoup-worker-prebuild.yaml +++ b/.github/workflows/mediasoup-worker-prebuild.yaml @@ -22,16 +22,6 @@ jobs: - os: ubuntu-22.04 cc: gcc cxx: g++ - # Worker prebuild for Linux on arm64. - - os: ubuntu-20.04 - cc: gcc - cxx: g++ - arch: arm64 - # Worker prebuild for Linux on arm64. - - os: ubuntu-22.04 - cc: gcc - cxx: g++ - arch: arm64 - os: macos-12 cc: clang cxx: clang++ diff --git a/.github/workflows/mediasoup-worker.yaml b/.github/workflows/mediasoup-worker.yaml index 0b05cd9dc1..584d4c47e4 100644 --- a/.github/workflows/mediasoup-worker.yaml +++ b/.github/workflows/mediasoup-worker.yaml @@ -25,22 +25,6 @@ jobs: - os: ubuntu-22.04 cc: clang cxx: clang++ - - os: ubuntu-20.04 - cc: gcc - cxx: g++ - arch: arm64 - - os: ubuntu-20.04 - cc: clang - cxx: clang++ - arch: arm64 - - os: ubuntu-22.04 - cc: gcc - cxx: g++ - arch: arm64 - - os: ubuntu-22.04 - cc: clang - cxx: clang++ - arch: arm64 - os: macos-12 cc: gcc cxx: g++ From e516ebc2de5aa4f7af4ae05702756f45484daf2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Wed, 10 Apr 2024 12:46:46 +0200 Subject: [PATCH 17/28] Node: add enhancedOnce() typed function (#1375) ### Details - Same as [events.once(emmiter, eventName)](https://nodejs.org/api/events.html#eventsonceemitter-name-options) but with TypeScript typed events. - Rename `EnhancedEventEmitter.ts` file to `enhancedEvents.ts` for consistency with the Node `events` module. --- node/src/ActiveSpeakerObserver.ts | 2 +- node/src/AudioLevelObserver.ts | 2 +- node/src/Channel.ts | 2 +- node/src/Consumer.ts | 2 +- node/src/DataConsumer.ts | 2 +- node/src/DataProducer.ts | 2 +- node/src/Producer.ts | 2 +- node/src/Router.ts | 2 +- node/src/RtpObserver.ts | 2 +- node/src/Transport.ts | 2 +- node/src/WebRtcServer.ts | 2 +- node/src/Worker.ts | 2 +- ...ancedEventEmitter.ts => enhancedEvents.ts} | 23 +++++++++++++-- node/src/index.ts | 2 +- node/src/test/test-ActiveSpeakerObserver.ts | 28 +++++++++++-------- node/src/test/test-AudioLevelObserver.ts | 28 +++++++++++-------- node/src/test/test-Consumer.ts | 27 +++++++++--------- node/src/test/test-DataConsumer.ts | 26 +++++++++-------- node/src/test/test-DataProducer.ts | 16 ++++++----- node/src/test/test-DirectTransport.ts | 26 +++++++++-------- node/src/test/test-PipeTransport.ts | 27 +++++++----------- node/src/test/test-PlainTransport.ts | 26 +++++++++-------- node/src/test/test-Producer.ts | 14 +++++----- node/src/test/test-Router.ts | 13 ++++----- node/src/test/test-WebRtcServer.ts | 14 +++++----- node/src/test/test-WebRtcTransport.ts | 26 +++++++++-------- node/src/test/test-Worker.ts | 24 ++++++++-------- node/src/test/test-multiopus.ts | 6 ++-- node/src/test/test-node-sctp.ts | 8 +++--- 29 files changed, 199 insertions(+), 159 deletions(-) rename node/src/{EnhancedEventEmitter.ts => enhancedEvents.ts} (81%) diff --git a/node/src/ActiveSpeakerObserver.ts b/node/src/ActiveSpeakerObserver.ts index 4cdd1d675e..88229731dc 100644 --- a/node/src/ActiveSpeakerObserver.ts +++ b/node/src/ActiveSpeakerObserver.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { RtpObserver, RtpObserverEvents, diff --git a/node/src/AudioLevelObserver.ts b/node/src/AudioLevelObserver.ts index b6a725ae39..f24e5d6b16 100644 --- a/node/src/AudioLevelObserver.ts +++ b/node/src/AudioLevelObserver.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { RtpObserver, RtpObserverEvents, diff --git a/node/src/Channel.ts b/node/src/Channel.ts index d0b9664707..a2fa6b3a6c 100644 --- a/node/src/Channel.ts +++ b/node/src/Channel.ts @@ -3,7 +3,7 @@ import { Duplex } from 'node:stream'; import { info, warn } from 'node:console'; import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { InvalidStateError } from './errors'; import { Body as RequestBody, Method, Request } from './fbs/request'; import { Response } from './fbs/response'; diff --git a/node/src/Consumer.ts b/node/src/Consumer.ts index 6b70025d18..8ada889603 100644 --- a/node/src/Consumer.ts +++ b/node/src/Consumer.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { Channel } from './Channel'; import { TransportInternal } from './Transport'; import { ProducerStat } from './Producer'; diff --git a/node/src/DataConsumer.ts b/node/src/DataConsumer.ts index 202b5d32f4..d0ff2ace7c 100644 --- a/node/src/DataConsumer.ts +++ b/node/src/DataConsumer.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { Channel } from './Channel'; import { TransportInternal } from './Transport'; import { diff --git a/node/src/DataProducer.ts b/node/src/DataProducer.ts index 2763e4fbfa..af7ef5c716 100644 --- a/node/src/DataProducer.ts +++ b/node/src/DataProducer.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { Channel } from './Channel'; import { TransportInternal } from './Transport'; import { diff --git a/node/src/Producer.ts b/node/src/Producer.ts index a36f7c5a75..afadbc8255 100644 --- a/node/src/Producer.ts +++ b/node/src/Producer.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { Channel } from './Channel'; import { TransportInternal } from './Transport'; import { MediaKind, RtpParameters, parseRtpParameters } from './RtpParameters'; diff --git a/node/src/Router.ts b/node/src/Router.ts index e0d61f6f91..c604768053 100644 --- a/node/src/Router.ts +++ b/node/src/Router.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import * as ortc from './ortc'; import { InvalidStateError } from './errors'; import { Channel } from './Channel'; diff --git a/node/src/RtpObserver.ts b/node/src/RtpObserver.ts index 705488f0d4..1756880755 100644 --- a/node/src/RtpObserver.ts +++ b/node/src/RtpObserver.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { Channel } from './Channel'; import { RouterInternal } from './Router'; import { Producer } from './Producer'; diff --git a/node/src/Transport.ts b/node/src/Transport.ts index ca330b6c54..30812e6dfa 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -1,6 +1,6 @@ import * as flatbuffers from 'flatbuffers'; import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import * as ortc from './ortc'; import { Channel } from './Channel'; import { RouterInternal } from './Router'; diff --git a/node/src/WebRtcServer.ts b/node/src/WebRtcServer.ts index c13f83c35d..a820bfda3d 100644 --- a/node/src/WebRtcServer.ts +++ b/node/src/WebRtcServer.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { Channel } from './Channel'; import { TransportListenInfo } from './Transport'; import { WebRtcTransport } from './WebRtcTransport'; diff --git a/node/src/Worker.ts b/node/src/Worker.ts index cce310e810..b69d2c9c29 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -3,7 +3,7 @@ import * as path from 'node:path'; import { spawn, ChildProcess } from 'node:child_process'; import { version } from './'; import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import * as ortc from './ortc'; import { Channel } from './Channel'; import { Router, RouterOptions } from './Router'; diff --git a/node/src/EnhancedEventEmitter.ts b/node/src/enhancedEvents.ts similarity index 81% rename from node/src/EnhancedEventEmitter.ts rename to node/src/enhancedEvents.ts index f5d1f688a3..a5458d3a08 100644 --- a/node/src/EnhancedEventEmitter.ts +++ b/node/src/enhancedEvents.ts @@ -1,7 +1,7 @@ -import { EventEmitter } from 'node:events'; +import { EventEmitter, once } from 'node:events'; import { Logger } from './Logger'; -const logger = new Logger('EnhancedEventEmitter'); +const enhancedEventEmitterLogger = new Logger('EnhancedEventEmitter'); type Events = Record; @@ -24,7 +24,7 @@ export class EnhancedEventEmitter< try { return super.emit(eventName, ...args); } catch (error) { - logger.error( + enhancedEventEmitterLogger.error( 'safeEmit() | event listener threw an error [eventName:%s]:%o', eventName, error @@ -121,3 +121,20 @@ export class EnhancedEventEmitter< return super.rawListeners(eventName); } } + +/** + * TypeScript version of events.once(): + * https://nodejs.org/api/events.html#eventsonceemitter-name-options + * + * Usage example: + * ```ts + * await enhancedOnce(videoConsumer, 'producerpause'); + * ```` + */ +export async function enhancedOnce( + emmiter: EnhancedEventEmitter, + eventName: keyof E & string, + options?: any +): Promise { + return once(emmiter, eventName, options); +} diff --git a/node/src/index.ts b/node/src/index.ts index b2efb864b2..28c41f361d 100644 --- a/node/src/index.ts +++ b/node/src/index.ts @@ -1,5 +1,5 @@ import { Logger } from './Logger'; -import { EnhancedEventEmitter } from './EnhancedEventEmitter'; +import { EnhancedEventEmitter } from './enhancedEvents'; import { workerBin, Worker, WorkerSettings } from './Worker'; import * as utils from './utils'; import { supportedRtpCapabilities } from './supportedRtpCapabilities'; diff --git a/node/src/test/test-ActiveSpeakerObserver.ts b/node/src/test/test-ActiveSpeakerObserver.ts index b4f2689fd0..f957a727c2 100644 --- a/node/src/test/test-ActiveSpeakerObserver.ts +++ b/node/src/test/test-ActiveSpeakerObserver.ts @@ -1,4 +1,6 @@ import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, ActiveSpeakerObserverEvents } from '../types'; import * as utils from '../utils'; type TestContext = { @@ -31,9 +33,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -105,10 +105,13 @@ test('activeSpeakerObserver.close() succeeds', async () => { test('ActiveSpeakerObserver emits "routerclose" if Router is closed', async () => { const activeSpeakerObserver = await ctx.router!.createAudioLevelObserver(); - await new Promise(resolve => { - activeSpeakerObserver.on('routerclose', resolve); - ctx.router!.close(); - }); + const promise = enhancedOnce( + activeSpeakerObserver, + 'routerclose' + ); + + ctx.router!.close(); + await promise; expect(activeSpeakerObserver.closed).toBe(true); }, 2000); @@ -116,10 +119,13 @@ test('ActiveSpeakerObserver emits "routerclose" if Router is closed', async () = test('ActiveSpeakerObserver emits "routerclose" if Worker is closed', async () => { const activeSpeakerObserver = await ctx.router!.createAudioLevelObserver(); - await new Promise(resolve => { - activeSpeakerObserver.on('routerclose', resolve); - ctx.worker!.close(); - }); + const promise = enhancedOnce( + activeSpeakerObserver, + 'routerclose' + ); + + ctx.worker!.close(); + await promise; expect(activeSpeakerObserver.closed).toBe(true); }, 2000); diff --git a/node/src/test/test-AudioLevelObserver.ts b/node/src/test/test-AudioLevelObserver.ts index 7d4fe82592..f6d6f61723 100644 --- a/node/src/test/test-AudioLevelObserver.ts +++ b/node/src/test/test-AudioLevelObserver.ts @@ -1,4 +1,6 @@ import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, AudioLevelObserverEvents } from '../types'; import * as utils from '../utils'; type TestContext = { @@ -31,9 +33,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -114,10 +114,13 @@ test('audioLevelObserver.close() succeeds', async () => { test('AudioLevelObserver emits "routerclose" if Router is closed', async () => { const audioLevelObserver = await ctx.router!.createAudioLevelObserver(); - await new Promise(resolve => { - audioLevelObserver.on('routerclose', resolve); - ctx.router!.close(); - }); + const promise = enhancedOnce( + audioLevelObserver, + 'routerclose' + ); + + ctx.router!.close(); + await promise; expect(audioLevelObserver.closed).toBe(true); }, 2000); @@ -125,10 +128,13 @@ test('AudioLevelObserver emits "routerclose" if Router is closed', async () => { test('AudioLevelObserver emits "routerclose" if Worker is closed', async () => { const audioLevelObserver = await ctx.router!.createAudioLevelObserver(); - await new Promise(resolve => { - audioLevelObserver.on('routerclose', resolve); - ctx.worker!.close(); - }); + const promise = enhancedOnce( + audioLevelObserver, + 'routerclose' + ); + + ctx.worker!.close(); + await promise; expect(audioLevelObserver.closed).toBe(true); }, 2000); diff --git a/node/src/test/test-Consumer.ts b/node/src/test/test-Consumer.ts index 0d3a4a056e..436145fbc2 100644 --- a/node/src/test/test-Consumer.ts +++ b/node/src/test/test-Consumer.ts @@ -1,6 +1,7 @@ -import { once } from 'node:events'; import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, ConsumerEvents } from '../types'; import { UnsupportedError } from '../errors'; import * as utils from '../utils'; import { @@ -248,9 +249,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -1025,7 +1024,7 @@ test('Consumer emits "producerpause" and "producerresume"', async () => { }); await Promise.all([ - once(audioConsumer, 'producerpause'), + enhancedOnce(audioConsumer, 'producerpause'), // Let's await for pause() to resolve to avoid aborted channel requests // due to worker closure. @@ -1036,7 +1035,7 @@ test('Consumer emits "producerpause" and "producerresume"', async () => { expect(audioConsumer.producerPaused).toBe(true); await Promise.all([ - once(audioConsumer, 'producerresume'), + enhancedOnce(audioConsumer, 'producerresume'), // Let's await for resume() to resolve to avoid aborted channel requests // due to worker closure. @@ -1162,10 +1161,10 @@ test('Consumer emits "producerclose" if Producer is closed', async () => { audioConsumer.observer.once('close', onObserverClose); - await new Promise(resolve => { - audioConsumer.on('producerclose', resolve); - ctx.audioProducer!.close(); - }); + const promise = enhancedOnce(audioConsumer, 'producerclose'); + + ctx.audioProducer!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(audioConsumer.closed).toBe(true); @@ -1181,10 +1180,10 @@ test('Consumer emits "transportclose" if Transport is closed', async () => { videoConsumer.observer.once('close', onObserverClose); - await new Promise(resolve => { - videoConsumer.on('transportclose', resolve); - ctx.webRtcTransport2!.close(); - }); + const promise = enhancedOnce(videoConsumer, 'transportclose'); + + ctx.webRtcTransport2!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(videoConsumer.closed).toBe(true); diff --git a/node/src/test/test-DataConsumer.ts b/node/src/test/test-DataConsumer.ts index 163f4d4e19..e51a718095 100644 --- a/node/src/test/test-DataConsumer.ts +++ b/node/src/test/test-DataConsumer.ts @@ -1,4 +1,6 @@ import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, DataConsumerEvents } from '../types'; import * as utils from '../utils'; type TestContext = { @@ -44,9 +46,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -374,11 +374,13 @@ test('DataConsumer emits "dataproducerclose" if DataProducer is closed', async ( dataConsumer.observer.once('close', onObserverClose); - await new Promise(resolve => { - dataConsumer.on('dataproducerclose', resolve); + const promise = enhancedOnce( + dataConsumer, + 'dataproducerclose' + ); - ctx.dataProducer!.close(); - }); + ctx.dataProducer!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(dataConsumer.closed).toBe(true); @@ -392,11 +394,13 @@ test('DataConsumer emits "transportclose" if Transport is closed', async () => { dataConsumer.observer.once('close', onObserverClose); - await new Promise(resolve => { - dataConsumer.on('transportclose', resolve); + const promise = enhancedOnce( + dataConsumer, + 'transportclose' + ); - ctx.webRtcTransport2!.close(); - }); + ctx.webRtcTransport2!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(dataConsumer.closed).toBe(true); diff --git a/node/src/test/test-DataProducer.ts b/node/src/test/test-DataProducer.ts index c5dddaacba..ad1457caea 100644 --- a/node/src/test/test-DataProducer.ts +++ b/node/src/test/test-DataProducer.ts @@ -1,4 +1,6 @@ import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, DataProducerEvents } from '../types'; import * as utils from '../utils'; type TestContext = { @@ -48,9 +50,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -353,11 +353,13 @@ test('DataProducer emits "transportclose" if Transport is closed', async () => { dataProducer2.observer.once('close', onObserverClose); - await new Promise(resolve => { - dataProducer2.on('transportclose', resolve); + const promise = enhancedOnce( + dataProducer2, + 'transportclose' + ); - ctx.webRtcTransport2!.close(); - }); + ctx.webRtcTransport2!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(dataProducer2.closed).toBe(true); diff --git a/node/src/test/test-DirectTransport.ts b/node/src/test/test-DirectTransport.ts index ac2f6ff8e8..3b7689acc1 100644 --- a/node/src/test/test-DirectTransport.ts +++ b/node/src/test/test-DirectTransport.ts @@ -1,4 +1,6 @@ import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, DirectTransportEvents } from '../types'; type TestContext = { worker?: mediasoup.types.Worker; @@ -16,9 +18,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -397,11 +397,13 @@ test('DirectTransport emits "routerclose" if Router is closed', async () => { directTransport.observer.once('close', onObserverClose); - await new Promise(resolve => { - directTransport.on('routerclose', resolve); + const promise = enhancedOnce( + directTransport, + 'routerclose' + ); - ctx.router!.close(); - }); + ctx.router!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(directTransport.closed).toBe(true); @@ -413,11 +415,13 @@ test('DirectTransport emits "routerclose" if Worker is closed', async () => { directTransport.observer.once('close', onObserverClose); - await new Promise(resolve => { - directTransport.on('routerclose', resolve); + const promise = enhancedOnce( + directTransport, + 'routerclose' + ); - ctx.worker!.close(); - }); + ctx.worker!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(directTransport.closed).toBe(true); diff --git a/node/src/test/test-PipeTransport.ts b/node/src/test/test-PipeTransport.ts index bfa17f9c18..0ded5cab8a 100644 --- a/node/src/test/test-PipeTransport.ts +++ b/node/src/test/test-PipeTransport.ts @@ -1,5 +1,7 @@ import { pickPort } from 'pick-port'; import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, ConsumerEvents, DataConsumerEvents } from '../types'; import * as utils from '../utils'; type TestContext = { @@ -201,15 +203,11 @@ afterEach(async () => { ctx.worker2?.close(); if (ctx.worker1?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker1?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker1, 'subprocessclose'); } if (ctx.worker2?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker2?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker2, 'subprocessclose'); } }); @@ -827,8 +825,9 @@ test('producer.pause() and producer.resume() are transmitted to pipe Consumer', // NOTE: Let's use a Promise since otherwise there may be race conditions // between events and await lines below. - const promise1 = new Promise(resolve => - videoConsumer.once('producerresume', resolve) + const promise1 = enhancedOnce( + videoConsumer, + 'producerresume' ); await ctx.videoProducer!.resume(); @@ -837,9 +836,7 @@ test('producer.pause() and producer.resume() are transmitted to pipe Consumer', expect(videoConsumer.producerPaused).toBe(false); expect(videoConsumer.paused).toBe(false); - const promise2 = new Promise(resolve => - videoConsumer.once('producerpause', resolve) - ); + const promise2 = enhancedOnce(videoConsumer, 'producerpause'); await ctx.videoProducer!.pause(); await promise2; @@ -864,9 +861,7 @@ test('producer.close() is transmitted to pipe Consumer', async () => { expect(ctx.videoProducer!.closed).toBe(true); if (!videoConsumer.closed) { - await new Promise(resolve => - videoConsumer.once('producerclose', resolve) - ); + await enhancedOnce(videoConsumer, 'producerclose'); } expect(videoConsumer.closed).toBe(true); @@ -969,9 +964,7 @@ test('dataProducer.close() is transmitted to pipe DataConsumer', async () => { expect(ctx.dataProducer!.closed).toBe(true); if (!dataConsumer.closed) { - await new Promise(resolve => - dataConsumer.once('dataproducerclose', resolve) - ); + await enhancedOnce(dataConsumer, 'dataproducerclose'); } expect(dataConsumer.closed).toBe(true); diff --git a/node/src/test/test-PlainTransport.ts b/node/src/test/test-PlainTransport.ts index c0e1a0afc1..31508bbddf 100644 --- a/node/src/test/test-PlainTransport.ts +++ b/node/src/test/test-PlainTransport.ts @@ -1,6 +1,8 @@ import * as os from 'node:os'; import { pickPort } from 'pick-port'; import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, PlainTransportEvents } from '../types'; import * as utils from '../utils'; const IS_WINDOWS = os.platform() === 'win32'; @@ -52,9 +54,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -539,11 +539,13 @@ test('PlainTransport emits "routerclose" if Router is closed', async () => { plainTransport.observer.once('close', onObserverClose); - await new Promise(resolve => { - plainTransport.on('routerclose', resolve); + const promise = enhancedOnce( + plainTransport, + 'routerclose' + ); - ctx.router!.close(); - }); + ctx.router!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(plainTransport.closed).toBe(true); @@ -558,11 +560,13 @@ test('PlainTransport emits "routerclose" if Worker is closed', async () => { plainTransport.observer.once('close', onObserverClose); - await new Promise(resolve => { - plainTransport.on('routerclose', resolve); + const promise = enhancedOnce( + plainTransport, + 'routerclose' + ); - ctx.worker!.close(); - }); + ctx.worker!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(plainTransport.closed).toBe(true); diff --git a/node/src/test/test-Producer.ts b/node/src/test/test-Producer.ts index d6fe900cf4..fbf2cef5c1 100644 --- a/node/src/test/test-Producer.ts +++ b/node/src/test/test-Producer.ts @@ -1,5 +1,7 @@ import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, ProducerEvents } from '../types'; import { UnsupportedError } from '../errors'; import * as utils from '../utils'; import { @@ -148,9 +150,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -823,10 +823,10 @@ test('Producer emits "transportclose" if Transport is closed', async () => { videoProducer.observer.once('close', onObserverClose); - await new Promise(resolve => { - videoProducer.on('transportclose', resolve); - ctx.webRtcTransport2!.close(); - }); + const promise = enhancedOnce(videoProducer, 'transportclose'); + + ctx.webRtcTransport2!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(videoProducer.closed).toBe(true); diff --git a/node/src/test/test-Router.ts b/node/src/test/test-Router.ts index d904883509..50602aec32 100644 --- a/node/src/test/test-Router.ts +++ b/node/src/test/test-Router.ts @@ -1,4 +1,6 @@ import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, RouterEvents } from '../types'; import { InvalidStateError } from '../errors'; import * as utils from '../utils'; @@ -46,9 +48,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -148,11 +148,10 @@ test('Router emits "workerclose" if Worker is closed', async () => { router.observer.once('close', onObserverClose); - await new Promise(resolve => { - router.on('workerclose', resolve); + const promise = enhancedOnce(router, 'workerclose'); - ctx.worker!.close(); - }); + ctx.worker!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(router.closed).toBe(true); diff --git a/node/src/test/test-WebRtcServer.ts b/node/src/test/test-WebRtcServer.ts index 4641f7415a..8297941723 100644 --- a/node/src/test/test-WebRtcServer.ts +++ b/node/src/test/test-WebRtcServer.ts @@ -1,5 +1,7 @@ import { pickPort } from 'pick-port'; import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, WebRtcServerEvents } from '../types'; import { InvalidStateError } from '../errors'; type TestContext = { @@ -16,9 +18,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -359,10 +359,10 @@ test('WebRtcServer emits "workerclose" if Worker is closed', async () => { webRtcServer.observer.once('close', onObserverClose); - await new Promise(resolve => { - webRtcServer.on('workerclose', resolve); - ctx.worker!.close(); - }); + const promise = enhancedOnce(webRtcServer, 'workerclose'); + + ctx.worker!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(webRtcServer.closed).toBe(true); diff --git a/node/src/test/test-WebRtcTransport.ts b/node/src/test/test-WebRtcTransport.ts index c069b54c0c..601073d209 100644 --- a/node/src/test/test-WebRtcTransport.ts +++ b/node/src/test/test-WebRtcTransport.ts @@ -1,6 +1,8 @@ import { pickPort } from 'pick-port'; import * as flatbuffers from 'flatbuffers'; import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents, WebRtcTransportEvents } from '../types'; import * as utils from '../utils'; import { serializeProtocol, TransportTuple } from '../Transport'; import { @@ -57,9 +59,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); @@ -844,11 +844,13 @@ test('WebRtcTransport emits "routerclose" if Router is closed', async () => { webRtcTransport.observer.once('close', onObserverClose); - await new Promise(resolve => { - webRtcTransport.on('routerclose', resolve); + const promise = enhancedOnce( + webRtcTransport, + 'routerclose' + ); - ctx.router!.close(); - }); + ctx.router!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(webRtcTransport.closed).toBe(true); @@ -869,11 +871,13 @@ test('WebRtcTransport emits "routerclose" if Worker is closed', async () => { webRtcTransport.observer.once('close', onObserverClose); - await new Promise(resolve => { - webRtcTransport.on('routerclose', resolve); + const promise = enhancedOnce( + webRtcTransport, + 'routerclose' + ); - ctx.worker!.close(); - }); + ctx.worker!.close(); + await promise; expect(onObserverClose).toHaveBeenCalledTimes(1); expect(webRtcTransport.closed).toBe(true); diff --git a/node/src/test/test-Worker.ts b/node/src/test/test-Worker.ts index a29fa5e457..6f1b28dedc 100644 --- a/node/src/test/test-Worker.ts +++ b/node/src/test/test-Worker.ts @@ -2,6 +2,8 @@ import * as os from 'node:os'; import * as process from 'node:process'; import * as path from 'node:path'; import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents } from '../types'; import { InvalidStateError } from '../errors'; test('Worker.workerBin matches mediasoup-worker absolute path', () => { @@ -48,7 +50,7 @@ test('createWorker() succeeds', async () => { worker1.close(); - await new Promise(resolve => worker1.on('subprocessclose', resolve)); + await enhancedOnce(worker1, 'subprocessclose'); expect(worker1.closed).toBe(true); expect(worker1.died).toBe(false); @@ -72,7 +74,7 @@ test('createWorker() succeeds', async () => { worker2.close(); - await new Promise(resolve => worker2.on('subprocessclose', resolve)); + await enhancedOnce(worker2, 'subprocessclose'); expect(worker2.closed).toBe(true); expect(worker2.died).toBe(false); @@ -116,7 +118,7 @@ test('worker.updateSettings() succeeds', async () => { worker.close(); - await new Promise(resolve => worker.on('subprocessclose', resolve)); + await enhancedOnce(worker, 'subprocessclose'); }, 2000); test('worker.updateSettings() with wrong settings rejects with TypeError', async () => { @@ -129,7 +131,7 @@ test('worker.updateSettings() with wrong settings rejects with TypeError', async worker.close(); - await new Promise(resolve => worker.on('subprocessclose', resolve)); + await enhancedOnce(worker, 'subprocessclose'); }, 2000); test('worker.updateSettings() rejects with InvalidStateError if closed', async () => { @@ -137,7 +139,7 @@ test('worker.updateSettings() rejects with InvalidStateError if closed', async ( worker.close(); - await new Promise(resolve => worker.on('subprocessclose', resolve)); + await enhancedOnce(worker, 'subprocessclose'); await expect(worker.updateSettings({ logLevel: 'error' })).rejects.toThrow( InvalidStateError @@ -165,7 +167,7 @@ test('worker.dump() rejects with InvalidStateError if closed', async () => { worker.close(); - await new Promise(resolve => worker.on('subprocessclose', resolve)); + await enhancedOnce(worker, 'subprocessclose'); await expect(worker.dump()).rejects.toThrow(InvalidStateError); }, 2000); @@ -177,7 +179,7 @@ test('worker.getResourceUsage() succeeds', async () => { worker.close(); - await new Promise(resolve => worker.on('subprocessclose', resolve)); + await enhancedOnce(worker, 'subprocessclose'); }, 2000); test('worker.close() succeeds', async () => { @@ -187,7 +189,7 @@ test('worker.close() succeeds', async () => { worker.observer.once('close', onObserverClose); worker.close(); - await new Promise(resolve => worker.on('subprocessclose', resolve)); + await enhancedOnce(worker, 'subprocessclose'); expect(onObserverClose).toHaveBeenCalledTimes(1); expect(worker.closed).toBe(true); @@ -224,7 +226,7 @@ test('Worker emits "died" if worker process died unexpectedly', async () => { }); if (!worker1.subprocessClosed) { - await new Promise(resolve => worker1.on('subprocessclose', resolve)); + await enhancedOnce(worker1, 'subprocessclose'); } expect(onDied).toHaveBeenCalledTimes(1); @@ -258,7 +260,7 @@ test('Worker emits "died" if worker process died unexpectedly', async () => { }); if (!worker2.subprocessClosed) { - await new Promise(resolve => worker2.on('subprocessclose', resolve)); + await enhancedOnce(worker2, 'subprocessclose'); } expect(onDied).toHaveBeenCalledTimes(1); @@ -292,7 +294,7 @@ test('Worker emits "died" if worker process died unexpectedly', async () => { }); if (!worker3.subprocessClosed) { - await new Promise(resolve => worker3.on('subprocessclose', resolve)); + await enhancedOnce(worker3, 'subprocessclose'); } expect(onDied).toHaveBeenCalledTimes(1); diff --git a/node/src/test/test-multiopus.ts b/node/src/test/test-multiopus.ts index 2b419271bf..d6542fb391 100644 --- a/node/src/test/test-multiopus.ts +++ b/node/src/test/test-multiopus.ts @@ -1,4 +1,6 @@ import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents } from '../types'; import { UnsupportedError } from '../errors'; import * as utils from '../utils'; @@ -109,9 +111,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } }); diff --git a/node/src/test/test-node-sctp.ts b/node/src/test/test-node-sctp.ts index f5e402f082..46b2f93036 100644 --- a/node/src/test/test-node-sctp.ts +++ b/node/src/test/test-node-sctp.ts @@ -2,6 +2,8 @@ import * as dgram from 'node:dgram'; // @ts-ignore import * as sctp from 'sctp'; import * as mediasoup from '../'; +import { enhancedOnce } from '../enhancedEvents'; +import { WorkerEvents } from '../types'; type TestContext = { worker?: mediasoup.types.Worker; @@ -66,7 +68,7 @@ beforeEach(async () => { // Wait for the SCTP association to be open. await Promise.race([ - new Promise(resolve => ctx.sctpSocket.on('connect', resolve)), + enhancedOnce(ctx.sctpSocket, 'connect'), new Promise((resolve, reject) => setTimeout(() => reject(new Error('SCTP connection timeout')), 3000) ), @@ -100,9 +102,7 @@ afterEach(async () => { ctx.worker?.close(); if (ctx.worker?.subprocessClosed === false) { - await new Promise(resolve => - ctx.worker?.on('subprocessclose', resolve) - ); + await enhancedOnce(ctx.worker, 'subprocessclose'); } // NOTE: For some reason we have to wait a bit for the SCTP stuff to release From b1b5ad4a17f24d7fe17aed45f493c3ce714f9dad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 15 Apr 2024 10:59:48 +0200 Subject: [PATCH 18/28] Update Node deps --- npm-scripts.mjs | 2 +- package-lock.json | 1501 ++++++++++++++++++++++++++++++++------------- package.json | 10 +- 3 files changed, 1073 insertions(+), 440 deletions(-) diff --git a/npm-scripts.mjs b/npm-scripts.mjs index 7cdffa32e4..280f68c270 100644 --- a/npm-scripts.mjs +++ b/npm-scripts.mjs @@ -4,7 +4,7 @@ import * as fs from 'node:fs'; import * as path from 'node:path'; import { execSync } from 'node:child_process'; import fetch from 'node-fetch'; -import tar from 'tar'; +import * as tar from 'tar'; import * as ini from 'ini'; const PKG = JSON.parse( diff --git a/package-lock.json b/package-lock.json index 59f4478ff1..723424671e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,15 +17,15 @@ "ini": "^4.1.2", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", - "tar": "^6.2.1" + "tar": "^7.0.1" }, "devDependencies": { "@octokit/rest": "^20.1.0", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.12.5", - "@typescript-eslint/eslint-plugin": "^7.5.0", - "@typescript-eslint/parser": "^7.5.0", + "@types/node": "^20.12.7", + "@typescript-eslint/eslint-plugin": "^7.6.0", + "@typescript-eslint/parser": "^7.6.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.2.0", @@ -37,7 +37,7 @@ "prettier": "^3.2.5", "sctp": "^1.0.0", "ts-jest": "^29.1.2", - "typescript": "^5.4.4" + "typescript": "^5.4.5" }, "engines": { "node": ">=18" @@ -738,9 +738,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", - "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -811,6 +811,114 @@ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.0.tgz", + "integrity": "sha512-S00nN1Qt3z3dSP6Db45fj/mksrAq5XWNIJ/SWXGP8XPT2jrzEuYRCSEx08JpJwBcG2F1xgiOtBMGDU0AZHmxew==", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@isaacs/fs-minipass/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1480,6 +1588,15 @@ "@octokit/openapi-types": "^21.0.0" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@pkgr/core": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", @@ -1620,9 +1737,9 @@ } }, "node_modules/@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "node_modules/@types/ms": { @@ -1631,18 +1748,18 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "node_modules/@types/node": { - "version": "20.12.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.5.tgz", - "integrity": "sha512-BD+BjQ9LS/D8ST9p5uqBxghlN+S42iuNxjsUGjeZobe/ciXzk2qb1B6IXc6AnRLS+yFJRpN2IPEHMzwspfDJNw==", + "version": "20.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", + "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, "node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, "node_modules/@types/stack-utils": { @@ -1667,22 +1784,22 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.5.0.tgz", - "integrity": "sha512-HpqNTH8Du34nLxbKgVMGljZMG0rJd2O9ecvr2QLYp+7512ty1j42KnsFwspPXg1Vh8an9YImf6CokUBltisZFQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.6.0.tgz", + "integrity": "sha512-gKmTNwZnblUdnTIJu3e9kmeRRzV2j1a/LUO27KNNAnIC5zjy1aSvXSRp4rVNlmAoHlQ7HzX42NbKpcSr4jF80A==", "dev": true, "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.5.0", - "@typescript-eslint/type-utils": "7.5.0", - "@typescript-eslint/utils": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.6.0", + "@typescript-eslint/type-utils": "7.6.0", + "@typescript-eslint/utils": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", "debug": "^4.3.4", "graphemer": "^1.4.0", - "ignore": "^5.2.4", + "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1702,14 +1819,27 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", - "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", + "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0" + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", + "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" }, @@ -1718,16 +1848,34 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz", - "integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", + "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.5.0", - "@typescript-eslint/utils": "7.5.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "@typescript-eslint/types": "7.6.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.6.0.tgz", + "integrity": "sha512-usPMPHcwX3ZoPWnBnhhorc14NJw9J4HpSXQX4urF2TPKG0au0XhJoZyX62fmvdHONUkmyUe74Hzm1//XA+BoYg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.6.0", + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/typescript-estree": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", + "debug": "^4.3.4" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1745,11 +1893,15 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", - "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", + "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0" + }, "engines": { "node": "^18.18.0 || >=20.0.0" }, @@ -1758,47 +1910,33 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", - "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", + "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, "engines": { "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz", - "integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", + "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.5.0", - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/typescript-estree": "7.5.0", - "semver": "^7.5.4" + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1807,18 +1945,20 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependencies": { - "eslint": "^8.56.0" + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", - "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", + "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.5.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "7.6.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1828,7 +1968,7 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/brace-expansion": { + "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", @@ -1837,10 +1977,10 @@ "balanced-match": "^1.0.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/@typescript-eslint/parser/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -1852,42 +1992,33 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@typescript-eslint/parser": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.5.0.tgz", - "integrity": "sha512-cj+XGhNujfD2/wzR1tabNsidnYRaFfEkcULdcIyVBYcXjBvBKOes+mpMBP7hMpOyk+gBcfXsrg4NBGAStQyxjQ==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.5.0", - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/typescript-estree": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", - "debug": "^4.3.4" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", - "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", + "node_modules/@typescript-eslint/type-utils": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.6.0.tgz", + "integrity": "sha512-NxAfqAPNLG6LTmy7uZgpK8KcuiS2NZD/HlThPXQRGwz6u7MDBWRVliEEl1Gj6U7++kVJTpehkhZzCJLMK66Scw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0" + "@typescript-eslint/typescript-estree": "7.6.0", + "@typescript-eslint/utils": "7.6.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1895,12 +2026,20 @@ "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", - "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", + "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1910,20 +2049,20 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", - "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", + "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1938,14 +2077,14 @@ } } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", - "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", + "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.5.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "7.6.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1955,7 +2094,7 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { + "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", @@ -1964,10 +2103,10 @@ "balanced-match": "^1.0.0" } }, - "node_modules/@typescript-eslint/parser/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -1979,23 +2118,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", @@ -2061,6 +2183,130 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@typescript-eslint/utils": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.6.0.tgz", + "integrity": "sha512-x54gaSsRRI+Nwz59TXpCsr6harB98qjXYzsRxGqvA5Ue3kQH+FxS7FYU81g/omn22ML2pZJkisy6Q+ElK8pBCA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.15", + "@types/semver": "^7.5.8", + "@typescript-eslint/scope-manager": "7.6.0", + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/typescript-estree": "7.6.0", + "semver": "^7.6.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", + "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", + "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", + "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", + "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.6.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@typescript-eslint/visitor-keys": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", @@ -2152,7 +2398,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -2161,7 +2406,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" }, @@ -2294,8 +2538,7 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/before-after-hook": { "version": "2.2.3", @@ -2476,11 +2719,11 @@ } }, "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/ci-info": { @@ -2532,7 +2775,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" }, @@ -2543,8 +2785,7 @@ "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/concat-map": { "version": "0.0.1", @@ -2583,7 +2824,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2761,6 +3001,11 @@ "node": ">=6.0.0" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, "node_modules/electron-to-chromium": { "version": "1.4.284", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", @@ -2782,8 +3027,7 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/error-ex": { "version": "1.3.2", @@ -3284,37 +3528,41 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", "dependencies": { - "fetch-blob": "^3.1.2" + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">=12.20.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dependencies": { - "minipass": "^3.0.0" - }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "engines": { - "node": ">= 8" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", "dependencies": { - "yallist": "^4.0.0" + "fetch-blob": "^3.1.2" }, "engines": { - "node": ">=8" + "node": ">=12.20.0" } }, "node_modules/fs.realpath": { @@ -3546,9 +3794,9 @@ ] }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" @@ -3674,7 +3922,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -3766,8 +4013,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", @@ -3865,6 +4111,23 @@ "node": ">=8" } }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -4692,37 +4955,97 @@ } }, "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz", + "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==", "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" + "minipass": "^7.0.4", + "rimraf": "^5.0.5" }, "engines": { - "node": ">= 8" + "node": ">= 18" + } + }, + "node_modules/minizlib/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/minizlib/node_modules/glob": { + "version": "10.3.12", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", + "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.6", + "minimatch": "^9.0.1", + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minizlib/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib/node_modules/rimraf": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", + "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", "dependencies": { - "yallist": "^4.0.0" + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" }, "engines": { - "node": ">=8" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", "bin": { - "mkdirp": "bin/cmd.js" + "mkdirp": "dist/cjs/src/bin.js" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/ms": { @@ -4976,7 +5299,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -4987,6 +5309,29 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-scurry": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", + "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "engines": { + "node": "14 || >=16.14" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -5434,9 +5779,9 @@ } }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -5452,7 +5797,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -5464,7 +5808,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -5562,7 +5905,20 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -5576,7 +5932,18 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -5677,19 +6044,27 @@ "dev": true }, "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.0.1.tgz", + "integrity": "sha512-IjMhdQMZFpKsHEQT3woZVxBtCQY+0wk3CVxdRkGXEgyGa0dNS/ehPvOMr2nmfC7x5Zj2N+l6yZUpmICjLGS35w==", "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "engines": { + "node": ">=18" } }, "node_modules/temp-dir": { @@ -5808,9 +6183,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", - "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "engines": { "node": ">=16" @@ -5896,9 +6271,9 @@ } }, "node_modules/typescript": { - "version": "5.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", - "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -6017,22 +6392,38 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">= 8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi": { + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -6076,7 +6467,8 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/yargs": { "version": "17.7.2", @@ -6647,9 +7039,9 @@ } }, "@eslint-community/regexpp": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", - "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true }, "@eslint/eslintrc": { @@ -6698,6 +7090,79 @@ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, + "@isaacs/fs-minipass": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.0.tgz", + "integrity": "sha512-S00nN1Qt3z3dSP6Db45fj/mksrAq5XWNIJ/SWXGP8XPT2jrzEuYRCSEx08JpJwBcG2F1xgiOtBMGDU0AZHmxew==", + "requires": { + "minipass": "^7.0.4" + }, + "dependencies": { + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" + } + } + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -7231,6 +7696,12 @@ "@octokit/openapi-types": "^21.0.0" } }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true + }, "@pkgr/core": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", @@ -7365,9 +7836,9 @@ } }, "@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "@types/ms": { @@ -7376,18 +7847,18 @@ "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" }, "@types/node": { - "version": "20.12.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.5.tgz", - "integrity": "sha512-BD+BjQ9LS/D8ST9p5uqBxghlN+S42iuNxjsUGjeZobe/ciXzk2qb1B6IXc6AnRLS+yFJRpN2IPEHMzwspfDJNw==", + "version": "20.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", + "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", "dev": true, "requires": { "undici-types": "~5.26.4" } }, "@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, "@types/stack-utils": { @@ -7412,91 +7883,105 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.5.0.tgz", - "integrity": "sha512-HpqNTH8Du34nLxbKgVMGljZMG0rJd2O9ecvr2QLYp+7512ty1j42KnsFwspPXg1Vh8an9YImf6CokUBltisZFQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.6.0.tgz", + "integrity": "sha512-gKmTNwZnblUdnTIJu3e9kmeRRzV2j1a/LUO27KNNAnIC5zjy1aSvXSRp4rVNlmAoHlQ7HzX42NbKpcSr4jF80A==", "dev": true, "requires": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.5.0", - "@typescript-eslint/type-utils": "7.5.0", - "@typescript-eslint/utils": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.6.0", + "@typescript-eslint/type-utils": "7.6.0", + "@typescript-eslint/utils": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", "debug": "^4.3.4", "graphemer": "^1.4.0", - "ignore": "^5.2.4", + "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", - "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", + "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", "dev": true, "requires": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0" + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0" } }, - "@typescript-eslint/type-utils": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz", - "integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==", + "@typescript-eslint/types": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", + "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "dev": true + }, + "@typescript-eslint/visitor-keys": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", + "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.5.0", - "@typescript-eslint/utils": "7.5.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "@typescript-eslint/types": "7.6.0", + "eslint-visitor-keys": "^3.4.3" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.6.0.tgz", + "integrity": "sha512-usPMPHcwX3ZoPWnBnhhorc14NJw9J4HpSXQX4urF2TPKG0au0XhJoZyX62fmvdHONUkmyUe74Hzm1//XA+BoYg==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "7.6.0", + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/typescript-estree": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", + "debug": "^4.3.4" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", + "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0" } }, "@typescript-eslint/types": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", - "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", + "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", - "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", + "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - } - }, - "@typescript-eslint/utils": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz", - "integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.5.0", - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/typescript-estree": "7.5.0", - "semver": "^7.5.4" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/visitor-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", - "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", + "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.5.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "7.6.0", + "eslint-visitor-keys": "^3.4.3" } }, "brace-expansion": { @@ -7509,9 +7994,9 @@ } }, "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -7519,59 +8004,58 @@ } } }, - "@typescript-eslint/parser": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.5.0.tgz", - "integrity": "sha512-cj+XGhNujfD2/wzR1tabNsidnYRaFfEkcULdcIyVBYcXjBvBKOes+mpMBP7hMpOyk+gBcfXsrg4NBGAStQyxjQ==", + "@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.5.0", - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/typescript-estree": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", - "debug": "^4.3.4" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.6.0.tgz", + "integrity": "sha512-NxAfqAPNLG6LTmy7uZgpK8KcuiS2NZD/HlThPXQRGwz6u7MDBWRVliEEl1Gj6U7++kVJTpehkhZzCJLMK66Scw==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "7.6.0", + "@typescript-eslint/utils": "7.6.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" }, "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz", - "integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0" - } - }, "@typescript-eslint/types": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz", - "integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", + "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz", - "integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", + "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.5.0", - "@typescript-eslint/visitor-keys": "7.5.0", + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" } }, "@typescript-eslint/visitor-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz", - "integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", + "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.5.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "7.6.0", + "eslint-visitor-keys": "^3.4.3" } }, "brace-expansion": { @@ -7584,9 +8068,9 @@ } }, "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -7594,16 +8078,6 @@ } } }, - "@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" - } - }, "@typescript-eslint/types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", @@ -7646,6 +8120,83 @@ } } }, + "@typescript-eslint/utils": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.6.0.tgz", + "integrity": "sha512-x54gaSsRRI+Nwz59TXpCsr6harB98qjXYzsRxGqvA5Ue3kQH+FxS7FYU81g/omn22ML2pZJkisy6Q+ElK8pBCA==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.15", + "@types/semver": "^7.5.8", + "@typescript-eslint/scope-manager": "7.6.0", + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/typescript-estree": "7.6.0", + "semver": "^7.6.0" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", + "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0" + } + }, + "@typescript-eslint/types": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", + "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", + "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/visitor-keys": "7.6.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", + "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.6.0", + "eslint-visitor-keys": "^3.4.3" + } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "@typescript-eslint/visitor-keys": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", @@ -7707,14 +8258,12 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { "color-convert": "^2.0.1" } @@ -7814,8 +8363,7 @@ "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "before-after-hook": { "version": "2.2.3", @@ -7939,9 +8487,9 @@ "dev": true }, "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==" }, "ci-info": { "version": "3.6.1", @@ -7982,7 +8530,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, "requires": { "color-name": "~1.1.4" } @@ -7990,8 +8537,7 @@ "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==" }, "concat-map": { "version": "0.0.1", @@ -8024,7 +8570,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -8138,6 +8683,11 @@ "esutils": "^2.0.2" } }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, "electron-to-chromium": { "version": "1.4.284", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", @@ -8153,8 +8703,7 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "error-ex": { "version": "1.3.2", @@ -8501,6 +9050,22 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, + "foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" + } + } + }, "formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", @@ -8509,24 +9074,6 @@ "fetch-blob": "^3.1.2" } }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - } - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -8677,9 +9224,9 @@ "dev": true }, "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true }, "import-fresh": { @@ -8765,8 +9312,7 @@ "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-generator-fn": { "version": "2.1.0", @@ -8822,8 +9368,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "istanbul-lib-coverage": { "version": "3.2.0", @@ -8901,6 +9446,15 @@ "istanbul-lib-report": "^3.0.0" } }, + "jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, "jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -9530,28 +10084,61 @@ "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" }, "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz", + "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==", "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" + "minipass": "^7.0.4", + "rimraf": "^5.0.5" }, "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "10.3.12", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", + "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.6", + "minimatch": "^9.0.1", + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" + } + }, + "minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "requires": { + "brace-expansion": "^2.0.1" + } + }, "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" + }, + "rimraf": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", + "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", "requires": { - "yallist": "^4.0.0" + "glob": "^10.3.7" } } } }, "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==" }, "ms": { "version": "2.1.2", @@ -9723,8 +10310,7 @@ "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, "path-parse": { "version": "1.0.7", @@ -9732,6 +10318,22 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "path-scurry": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", + "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", + "requires": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==" + } + } + }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -10013,9 +10615,9 @@ } }, "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -10025,7 +10627,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "requires": { "shebang-regex": "^3.0.0" } @@ -10033,8 +10634,7 @@ "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "signal-exit": { "version": "3.0.7", @@ -10116,7 +10716,16 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -10127,7 +10736,14 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "requires": { "ansi-regex": "^5.0.1" } @@ -10190,16 +10806,23 @@ } }, "tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.0.1.tgz", + "integrity": "sha512-IjMhdQMZFpKsHEQT3woZVxBtCQY+0wk3CVxdRkGXEgyGa0dNS/ehPvOMr2nmfC7x5Zj2N+l6yZUpmICjLGS35w==", "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "dependencies": { + "yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==" + } } }, "temp-dir": { @@ -10283,9 +10906,9 @@ } }, "ts-api-utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", - "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "requires": {} }, @@ -10327,9 +10950,9 @@ "dev": true }, "typescript": { - "version": "5.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", - "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true }, "undici-types": { @@ -10415,7 +11038,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "requires": { "isexe": "^2.0.0" } @@ -10431,6 +11053,16 @@ "strip-ansi": "^6.0.0" } }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -10456,7 +11088,8 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "yargs": { "version": "17.7.2", diff --git a/package.json b/package.json index 925f1ca850..395182b1ed 100644 --- a/package.json +++ b/package.json @@ -106,15 +106,15 @@ "ini": "^4.1.2", "node-fetch": "^3.3.2", "supports-color": "^9.4.0", - "tar": "^6.2.1" + "tar": "^7.0.1" }, "devDependencies": { "@octokit/rest": "^20.1.0", "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", - "@types/node": "^20.12.5", - "@typescript-eslint/eslint-plugin": "^7.5.0", - "@typescript-eslint/parser": "^7.5.0", + "@types/node": "^20.12.7", + "@typescript-eslint/eslint-plugin": "^7.6.0", + "@typescript-eslint/parser": "^7.6.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.2.0", @@ -126,6 +126,6 @@ "prettier": "^3.2.5", "sctp": "^1.0.0", "ts-jest": "^29.1.2", - "typescript": "^5.4.4" + "typescript": "^5.4.5" } } From 80960abfb7f9915a79dd6c9562aa0e5f3e179894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 15 Apr 2024 14:46:32 +0200 Subject: [PATCH 19/28] Update worker subprojects (#1376) ### Details - Update `openssl` from 3.0.8-2 to 3.0.8-3 - Update `abseil-cpp` from 20230802.0-3 to 20230802.1-2 - Update `Catch2` from 3.4.0-1 to 3.5.3-1 - Update `usrsctp` from commit ebb18adac6501bad4501b1f6dccb67a1c85cc299 to latest commit d45b53f5dfa79533f5c5e7aefa5d7570405afb39, diff: https://github.com/sctplab/usrsctp/compare/ebb18adac6501bad4501b1f6dccb67a1c85cc299...master --- worker/subprojects/abseil-cpp.wrap | 24 +++++++++++++++--------- worker/subprojects/catch2.wrap | 12 ++++++------ worker/subprojects/openssl.wrap | 10 +++++----- worker/subprojects/usrsctp.wrap | 8 ++++---- 4 files changed, 30 insertions(+), 24 deletions(-) diff --git a/worker/subprojects/abseil-cpp.wrap b/worker/subprojects/abseil-cpp.wrap index 61e2e4a4f6..4e62885650 100644 --- a/worker/subprojects/abseil-cpp.wrap +++ b/worker/subprojects/abseil-cpp.wrap @@ -1,13 +1,13 @@ [wrap-file] -directory = abseil-cpp-20230802.0 -source_url = https://github.com/abseil/abseil-cpp/archive/20230802.0.tar.gz -source_filename = abseil-cpp-20230802.0.tar.gz -source_hash = 59d2976af9d6ecf001a81a35749a6e551a335b949d34918cfade07737b9d93c5 -patch_filename = abseil-cpp_20230802.0-3_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/abseil-cpp_20230802.0-3/get_patch -patch_hash = 1bcd502774c0cd7ad2f3b310bb6bffaa440a290e7300d7df79557b6be20b5daf -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/abseil-cpp_20230802.0-3/abseil-cpp-20230802.0.tar.gz -wrapdb_version = 20230802.0-3 +directory = abseil-cpp-20230802.1 +source_url = https://github.com/abseil/abseil-cpp/archive/20230802.1.tar.gz +source_filename = abseil-cpp-20230802.1.tar.gz +source_hash = 987ce98f02eefbaf930d6e38ab16aa05737234d7afbab2d5c4ea7adbe50c28ed +patch_filename = abseil-cpp_20230802.1-2_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/abseil-cpp_20230802.1-2/get_patch +patch_hash = f6ceb55ca4b0995d826cbdefc0a37e0f8b6202d3e7ecb3436298f54d3a23942b +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/abseil-cpp_20230802.1-2/abseil-cpp-20230802.1.tar.gz +wrapdb_version = 20230802.1-2 [provide] absl_base = absl_base_dep @@ -41,8 +41,10 @@ absl_cordz_handle = absl_strings_dep absl_cordz_info = absl_strings_dep absl_cordz_sample_token = absl_strings_dep absl_core_headers = absl_base_dep +absl_crc32c = absl_crc_dep absl_debugging_internal = absl_debugging_dep absl_demangle_internal = absl_debugging_dep +absl_die_if_null = absl_log_dep absl_examine_stack = absl_debugging_dep absl_exponential_biased = absl_profiling_dep absl_failure_signal_handler = absl_debugging_dep @@ -65,6 +67,9 @@ absl_hashtablez_sampler = absl_container_dep absl_inlined_vector = absl_container_dep absl_int128 = absl_numeric_dep absl_leak_check = absl_debugging_dep +absl_log_initialize = absl_log_dep +absl_log_internal_check_op = absl_log_dep +absl_log_internal_message = absl_log_dep absl_log_severity = absl_base_dep absl_low_level_hash = absl_hash_dep absl_memory = absl_base_dep @@ -93,6 +98,7 @@ absl_statusor = absl_status_dep absl_str_format = absl_strings_dep absl_str_format_internal = absl_strings_dep absl_strerror = absl_base_dep +absl_string_view = absl_strings_dep absl_strings_internal = absl_strings_dep absl_symbolize = absl_debugging_dep absl_throw_delegate = absl_base_dep diff --git a/worker/subprojects/catch2.wrap b/worker/subprojects/catch2.wrap index 691d39c858..9566401a2d 100644 --- a/worker/subprojects/catch2.wrap +++ b/worker/subprojects/catch2.wrap @@ -1,10 +1,10 @@ [wrap-file] -directory = Catch2-3.4.0 -source_url = https://github.com/catchorg/Catch2/archive/v3.4.0.tar.gz -source_filename = Catch2-3.4.0.tar.gz -source_hash = 122928b814b75717316c71af69bd2b43387643ba076a6ec16e7882bfb2dfacbb -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/catch2_3.4.0-1/Catch2-3.4.0.tar.gz -wrapdb_version = 3.4.0-1 +directory = Catch2-3.5.3 +source_url = https://github.com/catchorg/Catch2/archive/v3.5.3.tar.gz +source_filename = Catch2-3.5.3.tar.gz +source_hash = 8d723b0535c94860ef8cf6231580fa47d67a3416757ecb10639e40d748ab6c71 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/catch2_3.5.3-1/Catch2-3.5.3.tar.gz +wrapdb_version = 3.5.3-1 [provide] catch2 = catch2_dep diff --git a/worker/subprojects/openssl.wrap b/worker/subprojects/openssl.wrap index b69462f53e..873d55106e 100644 --- a/worker/subprojects/openssl.wrap +++ b/worker/subprojects/openssl.wrap @@ -3,11 +3,11 @@ directory = openssl-3.0.8 source_url = https://www.openssl.org/source/openssl-3.0.8.tar.gz source_filename = openssl-3.0.8.tar.gz source_hash = 6c13d2bf38fdf31eac3ce2a347073673f5d63263398f1f69d0df4a41253e4b3e -patch_filename = openssl_3.0.8-2_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/openssl_3.0.8-2/get_patch -patch_hash = e84b5fe469e681e3318184157a0c7c43d4cbacd078bb88f506e31569f8f75072 -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/openssl_3.0.8-2/openssl-3.0.8.tar.gz -wrapdb_version = 3.0.8-2 +patch_filename = openssl_3.0.8-3_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/openssl_3.0.8-3/get_patch +patch_hash = 300da189e106942347d61a4a4295aa2edbcf06184f8d13b4cee0bed9fb936963 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/openssl_3.0.8-3/openssl-3.0.8.tar.gz +wrapdb_version = 3.0.8-3 [provide] libcrypto = libcrypto_dep diff --git a/worker/subprojects/usrsctp.wrap b/worker/subprojects/usrsctp.wrap index 3cd7061b98..469f66291b 100644 --- a/worker/subprojects/usrsctp.wrap +++ b/worker/subprojects/usrsctp.wrap @@ -1,8 +1,8 @@ [wrap-file] -directory = usrsctp-ebb18adac6501bad4501b1f6dccb67a1c85cc299 -source_url = https://github.com/sctplab/usrsctp/archive/ebb18adac6501bad4501b1f6dccb67a1c85cc299.zip -source_filename = ebb18adac6501bad4501b1f6dccb67a1c85cc299.zip -source_hash = e77a855ce395b877e9f2aa7ebe070dfaf5cb11cfecdeb424cc876fc0d98e5d11 +directory = usrsctp-d45b53f5dfa79533f5c5e7aefa5d7570405afb39 +source_url = https://github.com/sctplab/usrsctp/archive/d45b53f5dfa79533f5c5e7aefa5d7570405afb39.zip +source_filename = d45b53f5dfa79533f5c5e7aefa5d7570405afb39.zip +source_hash = da5f9adafc48fb5451f8355fee06508db52a3fca11138852c73ecb844f3b8647 [provide] usrsctp = usrsctp_dep From d534be0cf3a90a7199435deb601dba73401bd767 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 15 Apr 2024 14:47:32 +0200 Subject: [PATCH 20/28] Update CHANGELOG --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31badafe81..d1a851dc1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### NEXT + +- Update worker subprojects ([PR #1376](https://github.com/versatica/mediasoup/pull/1376)). + ### 3.14.1 - Node: Bring transport `rtpPacketLossReceived` and `rtpPacketLossSent` stats back ([PR #1371](https://github.com/versatica/mediasoup/pull/1371)). From d6373d540751c06b7fb96f0e7e26ad56f50f25bd Mon Sep 17 00:00:00 2001 From: satoren Date: Tue, 16 Apr 2024 21:12:26 +0900 Subject: [PATCH 21/28] Rust: fix panic with normal errors (#1377) --- rust/src/router/consumer.rs | 4 ++-- rust/src/router/producer.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rust/src/router/consumer.rs b/rust/src/router/consumer.rs index 3914d40b2d..8d58811aea 100644 --- a/rust/src/router/consumer.rs +++ b/rust/src/router/consumer.rs @@ -1020,9 +1020,9 @@ impl Consumer { .inner .channel .request(self.id(), ConsumerGetStatsRequest {}) - .await; + .await?; - if let Ok(response::Body::ConsumerGetStatsResponse(data)) = response { + if let response::Body::ConsumerGetStatsResponse(data) = response { match data.stats.len() { 0 => panic!("Empty stats response from worker"), 1 => { diff --git a/rust/src/router/producer.rs b/rust/src/router/producer.rs index 8b1a952e37..ec60283239 100644 --- a/rust/src/router/producer.rs +++ b/rust/src/router/producer.rs @@ -899,9 +899,9 @@ impl Producer { .inner() .channel .request(self.id(), ProducerGetStatsRequest {}) - .await; + .await?; - if let Ok(response::Body::ProducerGetStatsResponse(data)) = response { + if let response::Body::ProducerGetStatsResponse(data) = response { Ok(data.stats.iter().map(ProducerStat::from_fbs).collect()) } else { panic!("Wrong message from worker"); From 2854761ff1dc984d1d3f31cbf216319c085b2e12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 22 Apr 2024 12:25:32 +0200 Subject: [PATCH 22/28] CHANGELOG: Add a note about the behavior change due to flags.ipv6Only --- CHANGELOG.md | 1 + node/src/Transport.ts | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1a851dc1f..3b67364665 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ - Avoid modification of user input data ([PR #1285](https://github.com/versatica/mediasoup/pull/1285)). - `TransportListenInfo`: Add transport socket flags ([PR #1291](https://github.com/versatica/mediasoup/pull/1291)). + - Note that `flags.ipv6Only` is `false` by default. - `TransportListenInfo`: Ignore given socket flags if not suitable for given IP family or transport ([PR #1294](https://github.com/versatica/mediasoup/pull/1294)). - Meson: Remove `-Db_pie=true -Db_staticpic=true` args ([PR #1293](https://github.com/versatica/mediasoup/pull/1293)). - Add RTCP Sender Report trace event ([PR #1267](https://github.com/versatica/mediasoup/pull/1267) by @GithubUser8080). diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 30812e6dfa..f748b9e9c1 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -152,11 +152,11 @@ export type TransportPortRange = { */ export type TransportSocketFlags = { /** - * Disable dual-stack support so only IPv6 is used (only if ip is IPv6). + * Disable dual-stack support so only IPv6 is used (only if |ip| is IPv6). */ ipv6Only?: boolean; /** - * Make different transports bind to the same ip and port (only for UDP). + * Make different transports bind to the same IP and port (only for UDP). * Useful for multicast scenarios with plain transport. Use with caution. */ udpReusePort?: boolean; From 3c012fe643474587fce03edae69a52ab0d0bfa32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 22 Apr 2024 20:31:22 +0200 Subject: [PATCH 23/28] fix typo in fuzzer script --- worker/scripts/run-fuzzer.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/scripts/run-fuzzer.sh b/worker/scripts/run-fuzzer.sh index bc9c5321b6..ffe0d8ac87 100755 --- a/worker/scripts/run-fuzzer.sh +++ b/worker/scripts/run-fuzzer.sh @@ -10,7 +10,7 @@ if [ "${current_dir_name}" != "worker" ] ; then fi if [ "$#" -eq 0 ] ; then - echo "run-fuzzer.sh [ERROR] duration (in seconds) must be fiven as argument" >&2 + echo "run-fuzzer.sh [ERROR] duration (in seconds) must be given as argument" >&2 exit 1 fi From 3d5fd7614607ce6e6314992535e04230983f2a8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 22 Apr 2024 20:42:34 +0200 Subject: [PATCH 24/28] RtpPacket: Make (almost) all methods remove payload padding if present (#1380) --- worker/src/RTC/RtpPacket.cpp | 52 ++++++++++++++++++++------- worker/test/src/RTC/TestRtpPacket.cpp | 32 ++++++++++++----- 2 files changed, 63 insertions(+), 21 deletions(-) diff --git a/worker/src/RTC/RtpPacket.cpp b/worker/src/RTC/RtpPacket.cpp index c38f1eefd4..8bf92ed232 100644 --- a/worker/src/RTC/RtpPacket.cpp +++ b/worker/src/RTC/RtpPacket.cpp @@ -96,6 +96,7 @@ namespace RTC } payloadPadding = data[len - 1]; + if (payloadPadding == 0) { MS_WARN_TAG(rtp, "padding byte cannot be 0, packet discarded"); @@ -112,6 +113,7 @@ namespace RTC return nullptr; } + payloadLength -= size_t{ payloadPadding }; } @@ -650,20 +652,25 @@ namespace RTC } } + /** + * NOTE: This method automatically removes payload padding if present. + */ void RtpPacket::SetPayloadLength(size_t length) { MS_TRACE(); - // Pad desired length to 4 bytes. - length = static_cast(Utils::Byte::PadTo4Bytes(static_cast(length))); - this->size -= this->payloadLength; - this->size -= size_t{ this->payloadPadding }; - this->payloadLength = length; - this->payloadPadding = 0u; - this->size += length; + this->payloadLength = length; + this->size += this->payloadLength; + + // Remove padding if present. + if (this->payloadPadding != 0u) + { + SetPayloadPaddingFlag(false); - SetPayloadPaddingFlag(false); + this->size -= size_t{ this->payloadPadding }; + this->payloadPadding = 0u; + } } RtpPacket* RtpPacket::Clone() const @@ -749,8 +756,12 @@ namespace RTC return packet; } - // NOTE: The caller must ensure that the buffer/memmory of the packet has - // space enough for adding 2 extra bytes. + /** + * NOTE: The caller must ensure that the buffer/memmory of the packet has + * space enough for adding 2 extra bytes. + * + * NOTE: This method automatically removes payload padding if present. + */ void RtpPacket::RtxEncode(uint8_t payloadType, uint32_t ssrc, uint16_t seq) { MS_TRACE(); @@ -784,6 +795,9 @@ namespace RTC } } + /** + * NOTE: This method automatically removes payload padding if present. + */ bool RtpPacket::RtxDecode(uint8_t payloadType, uint32_t ssrc) { MS_TRACE(); @@ -849,6 +863,11 @@ namespace RTC this->payloadDescriptorHandler->Restore(this->payload); } + /** + * Shifts the payload given offset (to right or to left). + * + * NOTE: This method automatically removes payload padding if present. + */ void RtpPacket::ShiftPayload(size_t payloadOffset, size_t shift, bool expand) { MS_TRACE(); @@ -870,7 +889,7 @@ namespace RTC if (expand) { - shiftedLen = this->payloadLength + size_t{ this->payloadPadding } - payloadOffset; + shiftedLen = this->payloadLength - payloadOffset; std::memmove(payloadOffsetPtr + shift, payloadOffsetPtr, shiftedLen); @@ -879,13 +898,22 @@ namespace RTC } else { - shiftedLen = this->payloadLength + size_t{ this->payloadPadding } - payloadOffset - shift; + shiftedLen = this->payloadLength - payloadOffset - shift; std::memmove(payloadOffsetPtr, payloadOffsetPtr + shift, shiftedLen); this->payloadLength -= shift; this->size -= shift; } + + // Remove padding if present. + if (this->payloadPadding != 0u) + { + SetPayloadPaddingFlag(false); + + this->size -= size_t{ this->payloadPadding }; + this->payloadPadding = 0u; + } } void RtpPacket::ParseExtensions() diff --git a/worker/test/src/RTC/TestRtpPacket.cpp b/worker/test/src/RTC/TestRtpPacket.cpp index ade9004564..699cd14bbd 100644 --- a/worker/test/src/RTC/TestRtpPacket.cpp +++ b/worker/test/src/RTC/TestRtpPacket.cpp @@ -435,6 +435,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasTwoBytesExtensions() == false); REQUIRE(packet->GetPayloadLength() == 8); REQUIRE(packet->GetPayloadPadding() == 4); + REQUIRE(packet->GetPayload()[packet->GetPayloadLength() + packet->GetPayloadPadding() - 1] == 4); REQUIRE(packet->GetSize() == 40); auto* payload = packet->GetPayload(); @@ -448,11 +449,12 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(payload[6] == 0x06); REQUIRE(payload[7] == 0x07); + // NOTE: This will remove padding. packet->ShiftPayload(0, 2, true); REQUIRE(packet->GetPayloadLength() == 10); - REQUIRE(packet->GetPayloadPadding() == 4); - REQUIRE(packet->GetSize() == 42); + REQUIRE(packet->GetPayloadPadding() == 0); + REQUIRE(packet->GetSize() == 38); REQUIRE(payload[2] == 0x00); REQUIRE(payload[3] == 0x01); REQUIRE(payload[4] == 0x02); @@ -465,8 +467,8 @@ SCENARIO("parse RTP packets", "[parser][rtp]") packet->ShiftPayload(0, 2, false); REQUIRE(packet->GetPayloadLength() == 8); - REQUIRE(packet->GetPayloadPadding() == 4); - REQUIRE(packet->GetSize() == 40); + REQUIRE(packet->GetPayloadPadding() == 0); + REQUIRE(packet->GetSize() == 36); REQUIRE(payload[0] == 0x00); REQUIRE(payload[1] == 0x01); REQUIRE(payload[2] == 0x02); @@ -476,18 +478,18 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(payload[6] == 0x06); REQUIRE(payload[7] == 0x07); - // NOTE: This will require padding to 4 bytes. + // NOTE: This will remove padding. packet->SetPayloadLength(14); - REQUIRE(packet->GetPayloadLength() == 16); + REQUIRE(packet->GetPayloadLength() == 14); REQUIRE(packet->GetPayloadPadding() == 0); - REQUIRE(packet->GetSize() == 44); + REQUIRE(packet->GetSize() == 42); packet->ShiftPayload(4, 4, true); - REQUIRE(packet->GetPayloadLength() == 20); + REQUIRE(packet->GetPayloadLength() == 18); REQUIRE(packet->GetPayloadPadding() == 0); - REQUIRE(packet->GetSize() == 48); + REQUIRE(packet->GetSize() == 46); REQUIRE(payload[0] == 0x00); REQUIRE(payload[1] == 0x01); REQUIRE(payload[2] == 0x02); @@ -545,6 +547,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasTwoBytesExtensions() == false); REQUIRE(packet->GetPayloadLength() == 12); REQUIRE(packet->GetPayloadPadding() == 4); + REQUIRE(packet->GetPayload()[packet->GetPayloadLength() + packet->GetPayloadPadding() - 1] == 4); REQUIRE(packet->GetPayload()[0] == 0x11); REQUIRE(packet->GetPayload()[packet->GetPayloadLength() - 1] == 0xCC); @@ -560,6 +563,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasTwoBytesExtensions() == false); REQUIRE(packet->GetPayloadLength() == 12); REQUIRE(packet->GetPayloadPadding() == 4); + REQUIRE(packet->GetPayload()[packet->GetPayloadLength() + packet->GetPayloadPadding() - 1] == 4); REQUIRE(packet->GetPayload()[0] == 0x11); REQUIRE(packet->GetPayload()[packet->GetPayloadLength() - 1] == 0xCC); @@ -612,6 +616,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasTwoBytesExtensions() == false); REQUIRE(packet->GetPayloadLength() == 12); REQUIRE(packet->GetPayloadPadding() == 4); + REQUIRE(packet->GetPayload()[packet->GetPayloadLength() + packet->GetPayloadPadding() - 1] == 4); REQUIRE(packet->GetPayload()[0] == 0x11); REQUIRE(packet->GetPayload()[packet->GetPayloadLength() - 1] == 0xCC); REQUIRE(packet->GetExtension(0, extenLen) == nullptr); @@ -647,6 +652,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasTwoBytesExtensions() == false); REQUIRE(packet->GetPayloadLength() == 12); REQUIRE(packet->GetPayloadPadding() == 4); + REQUIRE(packet->GetPayload()[packet->GetPayloadLength() + packet->GetPayloadPadding() - 1] == 4); REQUIRE(packet->GetPayload()[0] == 0x11); REQUIRE(packet->GetPayload()[packet->GetPayloadLength() - 1] == 0xCC); REQUIRE(packet->GetExtension(1, extenLen) == nullptr); @@ -689,6 +695,10 @@ SCENARIO("parse RTP packets", "[parser][rtp]") 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; // clang-format on @@ -710,6 +720,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasTwoBytesExtensions() == false); REQUIRE(packet->GetPayloadLength() == 12); REQUIRE(packet->GetPayloadPadding() == 4); + REQUIRE(packet->GetPayload()[packet->GetPayloadLength() + packet->GetPayloadPadding() - 1] == 4); REQUIRE(packet->GetPayload()[0] == 0x11); REQUIRE(packet->GetPayload()[packet->GetPayloadLength() - 1] == 0xCC); @@ -725,6 +736,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasTwoBytesExtensions() == true); REQUIRE(packet->GetPayloadLength() == 12); REQUIRE(packet->GetPayloadPadding() == 4); + REQUIRE(packet->GetPayload()[packet->GetPayloadLength() + packet->GetPayloadPadding() - 1] == 4); REQUIRE(packet->GetPayload()[0] == 0x11); REQUIRE(packet->GetPayload()[packet->GetPayloadLength() - 1] == 0xCC); @@ -763,6 +775,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasTwoBytesExtensions() == true); REQUIRE(packet->GetPayloadLength() == 12); REQUIRE(packet->GetPayloadPadding() == 4); + REQUIRE(packet->GetPayload()[packet->GetPayloadLength() + packet->GetPayloadPadding() - 1] == 4); REQUIRE(packet->GetPayload()[0] == 0x11); REQUIRE(packet->GetPayload()[packet->GetPayloadLength() - 1] == 0xCC); REQUIRE(packet->GetExtension(0, extenLen) == nullptr); @@ -806,6 +819,7 @@ SCENARIO("parse RTP packets", "[parser][rtp]") REQUIRE(packet->HasTwoBytesExtensions() == true); REQUIRE(packet->GetPayloadLength() == 12); REQUIRE(packet->GetPayloadPadding() == 4); + REQUIRE(packet->GetPayload()[packet->GetPayloadLength() + packet->GetPayloadPadding() - 1] == 4); REQUIRE(packet->GetPayload()[0] == 0x11); REQUIRE(packet->GetPayload()[packet->GetPayloadLength() - 1] == 0xCC); REQUIRE(packet->GetExtension(1, extenLen) == nullptr); From f0a0a5b3b7379290261d433f6e3a6ee7cbd87648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 22 Apr 2024 20:48:46 +0200 Subject: [PATCH 25/28] update NPM deps --- package-lock.json | 350 +++++++++++++++++++++++----------------------- package.json | 6 +- 2 files changed, 178 insertions(+), 178 deletions(-) diff --git a/package-lock.json b/package-lock.json index 723424671e..f914ae513b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,14 +24,14 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.12.7", - "@typescript-eslint/eslint-plugin": "^7.6.0", - "@typescript-eslint/parser": "^7.6.0", + "@typescript-eslint/eslint-plugin": "^7.7.1", + "@typescript-eslint/parser": "^7.7.1", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.2.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", - "marked": "^12.0.1", + "marked": "^12.0.2", "open-cli": "^8.0.0", "pick-port": "^2.0.1", "prettier": "^3.2.5", @@ -1784,16 +1784,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.6.0.tgz", - "integrity": "sha512-gKmTNwZnblUdnTIJu3e9kmeRRzV2j1a/LUO27KNNAnIC5zjy1aSvXSRp4rVNlmAoHlQ7HzX42NbKpcSr4jF80A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.7.1.tgz", + "integrity": "sha512-KwfdWXJBOviaBVhxO3p5TJiLpNuh2iyXyjmWN0f1nU87pwyvfS0EmjC6ukQVYVFJd/K1+0NWGPDXiyEyQorn0Q==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.6.0", - "@typescript-eslint/type-utils": "7.6.0", - "@typescript-eslint/utils": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/scope-manager": "7.7.1", + "@typescript-eslint/type-utils": "7.7.1", + "@typescript-eslint/utils": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.3.1", @@ -1819,13 +1819,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", - "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", + "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0" + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1836,9 +1836,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", - "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", + "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1849,12 +1849,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", - "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", + "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/types": "7.7.1", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -1866,15 +1866,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.6.0.tgz", - "integrity": "sha512-usPMPHcwX3ZoPWnBnhhorc14NJw9J4HpSXQX4urF2TPKG0au0XhJoZyX62fmvdHONUkmyUe74Hzm1//XA+BoYg==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.7.1.tgz", + "integrity": "sha512-vmPzBOOtz48F6JAGVS/kZYk4EkXao6iGrD838sp1w3NQQC0W8ry/q641KU4PrG7AKNAf56NOcR8GOpH8l9FPCw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.6.0", - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/typescript-estree": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/scope-manager": "7.7.1", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/typescript-estree": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4" }, "engines": { @@ -1894,13 +1894,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", - "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", + "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0" + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1911,9 +1911,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", - "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", + "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -1924,13 +1924,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", - "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", + "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1952,12 +1952,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", - "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", + "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/types": "7.7.1", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2010,13 +2010,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.6.0.tgz", - "integrity": "sha512-NxAfqAPNLG6LTmy7uZgpK8KcuiS2NZD/HlThPXQRGwz6u7MDBWRVliEEl1Gj6U7++kVJTpehkhZzCJLMK66Scw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.7.1.tgz", + "integrity": "sha512-ZksJLW3WF7o75zaBPScdW1Gbkwhd/lyeXGf1kQCxJaOeITscoSl0MjynVvCzuV5boUz/3fOI06Lz8La55mu29Q==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.6.0", - "@typescript-eslint/utils": "7.6.0", + "@typescript-eslint/typescript-estree": "7.7.1", + "@typescript-eslint/utils": "7.7.1", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2037,9 +2037,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", - "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", + "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2050,13 +2050,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", - "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", + "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2078,12 +2078,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", - "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", + "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/types": "7.7.1", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2184,17 +2184,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.6.0.tgz", - "integrity": "sha512-x54gaSsRRI+Nwz59TXpCsr6harB98qjXYzsRxGqvA5Ue3kQH+FxS7FYU81g/omn22ML2pZJkisy6Q+ElK8pBCA==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.7.1.tgz", + "integrity": "sha512-QUvBxPEaBXf41ZBbaidKICgVL8Hin0p6prQDu6bbetWo39BKbWJxRsErOzMNT1rXvTll+J7ChrbmMCXM9rsvOQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.15", "@types/semver": "^7.5.8", - "@typescript-eslint/scope-manager": "7.6.0", - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/typescript-estree": "7.6.0", + "@typescript-eslint/scope-manager": "7.7.1", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/typescript-estree": "7.7.1", "semver": "^7.6.0" }, "engines": { @@ -2209,13 +2209,13 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", - "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", + "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0" + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2226,9 +2226,9 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", - "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", + "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2239,13 +2239,13 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", - "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", + "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2267,12 +2267,12 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", - "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", + "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/types": "7.7.1", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -4874,9 +4874,9 @@ } }, "node_modules/marked": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.1.tgz", - "integrity": "sha512-Y1/V2yafOcOdWQCX0XpAKXzDakPOpn6U0YLxTJs3cww6VxOzZV1BTOOYWLvH3gX38cq+iLwljHHTnMtlDfg01Q==", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", + "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -7883,16 +7883,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.6.0.tgz", - "integrity": "sha512-gKmTNwZnblUdnTIJu3e9kmeRRzV2j1a/LUO27KNNAnIC5zjy1aSvXSRp4rVNlmAoHlQ7HzX42NbKpcSr4jF80A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.7.1.tgz", + "integrity": "sha512-KwfdWXJBOviaBVhxO3p5TJiLpNuh2iyXyjmWN0f1nU87pwyvfS0EmjC6ukQVYVFJd/K1+0NWGPDXiyEyQorn0Q==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.6.0", - "@typescript-eslint/type-utils": "7.6.0", - "@typescript-eslint/utils": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/scope-manager": "7.7.1", + "@typescript-eslint/type-utils": "7.7.1", + "@typescript-eslint/utils": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.3.1", @@ -7902,70 +7902,70 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", - "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", + "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0" + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1" } }, "@typescript-eslint/types": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", - "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", + "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", "dev": true }, "@typescript-eslint/visitor-keys": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", - "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", + "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/types": "7.7.1", "eslint-visitor-keys": "^3.4.3" } } } }, "@typescript-eslint/parser": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.6.0.tgz", - "integrity": "sha512-usPMPHcwX3ZoPWnBnhhorc14NJw9J4HpSXQX4urF2TPKG0au0XhJoZyX62fmvdHONUkmyUe74Hzm1//XA+BoYg==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.7.1.tgz", + "integrity": "sha512-vmPzBOOtz48F6JAGVS/kZYk4EkXao6iGrD838sp1w3NQQC0W8ry/q641KU4PrG7AKNAf56NOcR8GOpH8l9FPCw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.6.0", - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/typescript-estree": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/scope-manager": "7.7.1", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/typescript-estree": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", - "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", + "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0" + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1" } }, "@typescript-eslint/types": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", - "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", + "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", - "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", + "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7975,12 +7975,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", - "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", + "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/types": "7.7.1", "eslint-visitor-keys": "^3.4.3" } }, @@ -8015,31 +8015,31 @@ } }, "@typescript-eslint/type-utils": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.6.0.tgz", - "integrity": "sha512-NxAfqAPNLG6LTmy7uZgpK8KcuiS2NZD/HlThPXQRGwz6u7MDBWRVliEEl1Gj6U7++kVJTpehkhZzCJLMK66Scw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.7.1.tgz", + "integrity": "sha512-ZksJLW3WF7o75zaBPScdW1Gbkwhd/lyeXGf1kQCxJaOeITscoSl0MjynVvCzuV5boUz/3fOI06Lz8La55mu29Q==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.6.0", - "@typescript-eslint/utils": "7.6.0", + "@typescript-eslint/typescript-estree": "7.7.1", + "@typescript-eslint/utils": "7.7.1", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, "dependencies": { "@typescript-eslint/types": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", - "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", + "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", - "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", + "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8049,12 +8049,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", - "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", + "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/types": "7.7.1", "eslint-visitor-keys": "^3.4.3" } }, @@ -8121,44 +8121,44 @@ } }, "@typescript-eslint/utils": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.6.0.tgz", - "integrity": "sha512-x54gaSsRRI+Nwz59TXpCsr6harB98qjXYzsRxGqvA5Ue3kQH+FxS7FYU81g/omn22ML2pZJkisy6Q+ElK8pBCA==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.7.1.tgz", + "integrity": "sha512-QUvBxPEaBXf41ZBbaidKICgVL8Hin0p6prQDu6bbetWo39BKbWJxRsErOzMNT1rXvTll+J7ChrbmMCXM9rsvOQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.15", "@types/semver": "^7.5.8", - "@typescript-eslint/scope-manager": "7.6.0", - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/typescript-estree": "7.6.0", + "@typescript-eslint/scope-manager": "7.7.1", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/typescript-estree": "7.7.1", "semver": "^7.6.0" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz", - "integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz", + "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0" + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1" } }, "@typescript-eslint/types": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz", - "integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz", + "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz", - "integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz", + "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", - "@typescript-eslint/visitor-keys": "7.6.0", + "@typescript-eslint/types": "7.7.1", + "@typescript-eslint/visitor-keys": "7.7.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -8168,12 +8168,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz", - "integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz", + "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==", "dev": true, "requires": { - "@typescript-eslint/types": "7.6.0", + "@typescript-eslint/types": "7.7.1", "eslint-visitor-keys": "^3.4.3" } }, @@ -10030,9 +10030,9 @@ } }, "marked": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.1.tgz", - "integrity": "sha512-Y1/V2yafOcOdWQCX0XpAKXzDakPOpn6U0YLxTJs3cww6VxOzZV1BTOOYWLvH3gX38cq+iLwljHHTnMtlDfg01Q==", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", + "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==", "dev": true }, "meow": { diff --git a/package.json b/package.json index 395182b1ed..b33e8412c7 100644 --- a/package.json +++ b/package.json @@ -113,14 +113,14 @@ "@types/debug": "^4.1.12", "@types/jest": "^29.5.12", "@types/node": "^20.12.7", - "@typescript-eslint/eslint-plugin": "^7.6.0", - "@typescript-eslint/parser": "^7.6.0", + "@typescript-eslint/eslint-plugin": "^7.7.1", + "@typescript-eslint/parser": "^7.7.1", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.2.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", - "marked": "^12.0.1", + "marked": "^12.0.2", "open-cli": "^8.0.0", "pick-port": "^2.0.1", "prettier": "^3.2.5", From d4204c6e80132789b8b1b4828bd8679688dd6653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Tue, 23 Apr 2024 18:35:03 +0200 Subject: [PATCH 26/28] OPUS: Fix DTX detection (#1357) --- CHANGELOG.md | 1 + worker/include/RTC/Codecs/Opus.hpp | 3 ++ worker/src/RTC/Codecs/H264.cpp | 2 + worker/src/RTC/Codecs/H264_SVC.cpp | 17 +++++-- worker/src/RTC/Codecs/Opus.cpp | 73 ++++++++++++++++++++++++++++-- worker/src/RTC/Codecs/VP8.cpp | 14 ++++++ worker/src/RTC/Codecs/VP9.cpp | 10 ++++ 7 files changed, 113 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b67364665..022325c673 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### NEXT - Update worker subprojects ([PR #1376](https://github.com/versatica/mediasoup/pull/1376)). +- OPUS: Fix DTX detection #1357 ([PR #1357](https://github.com/versatica/mediasoup/pull/1357)). ### 3.14.1 diff --git a/worker/include/RTC/Codecs/Opus.hpp b/worker/include/RTC/Codecs/Opus.hpp index a703e224de..ac889e149c 100644 --- a/worker/include/RTC/Codecs/Opus.hpp +++ b/worker/include/RTC/Codecs/Opus.hpp @@ -20,6 +20,9 @@ namespace RTC void Dump() const override; + // Mandatory fields. + uint8_t stereo : 1; + uint8_t code : 2; // Parsed values. bool isDtx{ false }; }; diff --git a/worker/src/RTC/Codecs/H264.cpp b/worker/src/RTC/Codecs/H264.cpp index 63bff4dcab..b2dd988e65 100644 --- a/worker/src/RTC/Codecs/H264.cpp +++ b/worker/src/RTC/Codecs/H264.cpp @@ -18,6 +18,8 @@ namespace RTC if (len < 2) { + MS_WARN_DEV("ignoring payload with length < 2"); + return nullptr; } diff --git a/worker/src/RTC/Codecs/H264_SVC.cpp b/worker/src/RTC/Codecs/H264_SVC.cpp index 05e43ec318..9214094ffb 100644 --- a/worker/src/RTC/Codecs/H264_SVC.cpp +++ b/worker/src/RTC/Codecs/H264_SVC.cpp @@ -17,6 +17,8 @@ namespace RTC if (len < 2) { + MS_WARN_DEV("ignoring payload with length < 2"); + return nullptr; } @@ -54,12 +56,13 @@ namespace RTC } } - // NOTE: Unfortunately libwebrtc produces wrong Frame-Marking (without i=1 in - // keyframes) when it uses H264 hardware encoder (at least in Mac): + // NOTE: Unfortunately libwebrtc produces wrong Frame-Marking (without i=1 + // in keyframes) when it uses H264 hardware encoder (at least in Mac): // https://bugs.chromium.org/p/webrtc/issues/detail?id=10746 // - // As a temporal workaround, always do payload parsing to detect keyframes if - // there is no frame-marking or if there is but keyframe was not detected above. + // As a temporal workaround, always do payload parsing to detect keyframes + // if there is no frame-marking or if there is but keyframe was not + // detected above. if (!frameMarking || !payloadDescriptor->isKeyFrame) { const uint8_t nal = *data & 0x1F; @@ -79,6 +82,8 @@ namespace RTC if (payloadDescriptor == nullptr) { + MS_WARN_DEV("ignoring invalid payload (1)"); + return nullptr; } @@ -106,6 +111,8 @@ namespace RTC if (payloadDescriptor == nullptr) { + MS_WARN_DEV("ignoring invalid payload (2)"); + return nullptr; } @@ -142,6 +149,8 @@ namespace RTC if (payloadDescriptor == nullptr) { + MS_WARN_DEV("ignoring invalid payload (3)"); + return nullptr; } diff --git a/worker/src/RTC/Codecs/Opus.cpp b/worker/src/RTC/Codecs/Opus.cpp index 4ff265ec1b..0fa4dff95e 100644 --- a/worker/src/RTC/Codecs/Opus.cpp +++ b/worker/src/RTC/Codecs/Opus.cpp @@ -14,12 +14,72 @@ namespace RTC { MS_TRACE(); + if (len < 1) + { + MS_WARN_DEV("ignoring empty payload"); + + return nullptr; + } + std::unique_ptr payloadDescriptor(new PayloadDescriptor()); - // libopus generates a single byte payload (TOC, no frames) to generate DTX. - if (len == 1) + uint8_t byte = data[0]; + + payloadDescriptor->stereo = (byte >> 2) & 0x01; + payloadDescriptor->code = byte & 0x03; + + switch (payloadDescriptor->code) { - payloadDescriptor->isDtx = true; + case 0: + case 1: + { + // In code 0 and 1 packets, DTX is determined by total length = 1 (TOC + // byte only). + if (len == 1) + { + payloadDescriptor->isDtx = true; + } + + break; + } + + case 2: + { + // As per spec, a 1-byte code 2 packet is always invalid. + if (len == 1) + { + MS_WARN_DEV("ignoring invalid payload (1)"); + + return nullptr; + } + + // In code 2 packets, DTX is determined by total length = 2 (TOC byte + // only). Per spec, the only valid 2-byte code 2 packet is one where + // the length of both frames is zero. + if (len == 2) + { + payloadDescriptor->isDtx = true; + } + + break; + } + + case 3: + { + // As per spec, a 1-byte code 3 packet is always invalid. + if (len == 1) + { + MS_WARN_DEV("ignoring invalid payload (2)"); + + return nullptr; + } + + // A code 3 packet can never be DTX. + + break; + } + + default:; } return payloadDescriptor.release(); @@ -34,6 +94,11 @@ namespace RTC PayloadDescriptor* payloadDescriptor = Opus::Parse(data, len); + if (!payloadDescriptor) + { + return; + } + auto* payloadDescriptorHandler = new PayloadDescriptorHandler(payloadDescriptor); packet->SetPayloadDescriptorHandler(payloadDescriptorHandler); @@ -46,6 +111,8 @@ namespace RTC MS_TRACE(); MS_DUMP(""); + MS_DUMP(" stereo: %" PRIu8, this->stereo); + MS_DUMP(" code: %" PRIu8, this->code); MS_DUMP(" isDtx: %s", this->isDtx ? "true" : "false"); MS_DUMP(""); } diff --git a/worker/src/RTC/Codecs/VP8.cpp b/worker/src/RTC/Codecs/VP8.cpp index 0c336ce1b3..4dd9bc5127 100644 --- a/worker/src/RTC/Codecs/VP8.cpp +++ b/worker/src/RTC/Codecs/VP8.cpp @@ -21,6 +21,8 @@ namespace RTC if (len < 1) { + MS_WARN_DEV("ignoring empty payload"); + return nullptr; } @@ -36,12 +38,16 @@ namespace RTC if (!payloadDescriptor->extended) { + MS_WARN_DEV("ignoring invalid payload (1)"); + return nullptr; } else { if (len < ++offset + 1) { + MS_WARN_DEV("ignoring invalid payload (2)"); + return nullptr; } @@ -57,6 +63,8 @@ namespace RTC { if (len < ++offset + 1) { + MS_WARN_DEV("ignoring invalid payload (3)"); + return nullptr; } @@ -66,6 +74,8 @@ namespace RTC { if (len < ++offset + 1) { + MS_WARN_DEV("ignoring invalid payload (4)"); + return nullptr; } @@ -86,6 +96,8 @@ namespace RTC { if (len < ++offset + 1) { + MS_WARN_DEV("ignoring invalid payload (5)"); + return nullptr; } @@ -97,6 +109,8 @@ namespace RTC { if (len < ++offset + 1) { + MS_WARN_DEV("ignoring invalid payload (6)"); + return nullptr; } diff --git a/worker/src/RTC/Codecs/VP9.cpp b/worker/src/RTC/Codecs/VP9.cpp index 646ca8d72a..dea55d37c3 100644 --- a/worker/src/RTC/Codecs/VP9.cpp +++ b/worker/src/RTC/Codecs/VP9.cpp @@ -20,6 +20,8 @@ namespace RTC if (len < 1) { + MS_WARN_DEV("ignoring empty payload"); + return nullptr; } @@ -40,6 +42,8 @@ namespace RTC { if (len < ++offset + 1) { + MS_WARN_DEV("ignoring invalid payload (1)"); + return nullptr; } @@ -49,6 +53,8 @@ namespace RTC { if (len < ++offset + 1) { + MS_WARN_DEV("ignoring invalid payload (2)"); + return nullptr; } @@ -69,6 +75,8 @@ namespace RTC { if (len < ++offset + 1) { + MS_WARN_DEV("ignoring invalid payload (3)"); + return nullptr; } @@ -83,6 +91,8 @@ namespace RTC if (len < ++offset + 1) { + MS_WARN_DEV("ignoring invalid payload (4)"); + return nullptr; } From c7e05eff0e870182c8f97252fb957ce55a1e428c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sun, 28 Apr 2024 13:21:13 +0200 Subject: [PATCH 27/28] Worker: Fix sending callback leaks (#1383) --- CHANGELOG.md | 21 +++++++++++---------- worker/src/RTC/DataConsumer.cpp | 24 ++++++++++++++++++++++++ worker/src/RTC/DirectTransport.cpp | 18 +++++++++++++----- 3 files changed, 48 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 022325c673..28b2a97ae3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ ### NEXT - Update worker subprojects ([PR #1376](https://github.com/versatica/mediasoup/pull/1376)). -- OPUS: Fix DTX detection #1357 ([PR #1357](https://github.com/versatica/mediasoup/pull/1357)). +- OPUS: Fix DTX detection ([PR #1357](https://github.com/versatica/mediasoup/pull/1357)). +- Worker: Fix sending callback leaks ([PR #1383](https://github.com/versatica/mediasoup/pull/1383), credits to @Lynnworld). ### 3.14.1 @@ -72,13 +73,13 @@ ### 3.13.13 -- worker: Do not use references for async callbacks ([PR #1274](https://github.com/versatica/mediasoup/pull/1274)). +- Worker: Do not use references for async callbacks ([PR #1274](https://github.com/versatica/mediasoup/pull/1274)). - liburing: Enable zero copy ([PR #1273](https://github.com/versatica/mediasoup/pull/1273)). - Fix build on musl based systems (such as Alpine Linux) ([PR #1279](https://github.com/versatica/mediasoup/pull/1279)). ### 3.13.12 -- worker: Disable `RtcLogger` usage if not enabled ([PR #1264](https://github.com/versatica/mediasoup/pull/1264)). +- Worker: Disable `RtcLogger` usage if not enabled ([PR #1264](https://github.com/versatica/mediasoup/pull/1264)). - npm installation: Don't require Python if valid worker prebuilt binary is fetched ([PR #1265](https://github.com/versatica/mediasoup/pull/1265)). - Update h264-profile-level-id NPM dependency to 1.1.0. @@ -144,7 +145,7 @@ - Add optional `rtcpListenInfo` in `PlainTransportOptions` ([PR #1099](https://github.com/versatica/mediasoup/pull/1099)). - Add pause/resume API in `DataProducer` and `DataConsumer` ([PR #1104](https://github.com/versatica/mediasoup/pull/1104)). - DataChannel subchannels feature ([PR #1152](https://github.com/versatica/mediasoup/pull/1152)). -- `Worker`: Make DTLS fragment stay within MTU size range ([PR #1156](https://github.com/versatica/mediasoup/pull/1156), based on [PR #1143](https://github.com/versatica/mediasoup/pull/1143) by @vpnts-se). +- Worker: Make DTLS fragment stay within MTU size range ([PR #1156](https://github.com/versatica/mediasoup/pull/1156), based on [PR #1143](https://github.com/versatica/mediasoup/pull/1143) by @vpnts-se). ### 3.12.16 @@ -189,7 +190,7 @@ ### 3.12.6 -- `Worker`: Add `Transport::Destroying()` protected method ([PR #1114](https://github.com/versatica/mediasoup/pull/1114)). +- Worker: Add `Transport::Destroying()` protected method ([PR #1114](https://github.com/versatica/mediasoup/pull/1114)). - `RtpStreamRecv`: Fix jitter calculation ([PR #1117](https://github.com/versatica/mediasoup/pull/1117), thanks to @penguinol). - Revert "Node: make types.ts only export types rather than the entire class/code" ([PR #1109](https://github.com/versatica/mediasoup/pull/1109)) because it requires `typescript` >= 5 in the apps that import mediasoup and we don't want to be that strict yet. @@ -219,11 +220,11 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi ### 3.11.26 -- `Worker`: Fix NACK timer and avoid negative RTT ([PR #1082](https://github.com/versatica/mediasoup/pull/1082), thanks to @o-u-p for his work in ([PR #1076](https://github.com/versatica/mediasoup/pull/1076)). +- Worker: Fix NACK timer and avoid negative RTT ([PR #1082](https://github.com/versatica/mediasoup/pull/1082), thanks to @o-u-p for his work in ([PR #1076](https://github.com/versatica/mediasoup/pull/1076)). ### 3.11.25 -- `Worker`: Require C++17, Meson >= 1.1.0 and update subprojects ([PR #1081](https://github.com/versatica/mediasoup/pull/1081)). +- Worker: Require C++17, Meson >= 1.1.0 and update subprojects ([PR #1081](https://github.com/versatica/mediasoup/pull/1081)). ### 3.11.24 @@ -323,7 +324,7 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi - Node: Migrate tests to TypeScript ([PR #958](https://github.com/versatica/mediasoup/pull/958)). - Node: Remove compiled JavaScript from repository and compile TypeScript code on NPM `prepare` script on demand when installed via git ([PR #954](https://github.com/versatica/mediasoup/pull/954)). -- `Worker`: Add `RTC::Shared` singleton for RTC entities ([PR #953](https://github.com/versatica/mediasoup/pull/953)). +- Worker: Add `RTC::Shared` singleton for RTC entities ([PR #953](https://github.com/versatica/mediasoup/pull/953)). - Update OpenSSL to 3.0.7. ### 3.11.3 @@ -499,7 +500,7 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi ### 3.9.4 -- `Worker`: Fix bad printing of error messages from Worker ([PR #750](https://github.com/versatica/mediasoup/pull/750) by @j1elo). +- Worker: Fix bad printing of error messages from Worker ([PR #750](https://github.com/versatica/mediasoup/pull/750) by @j1elo). ### 3.9.3 @@ -517,7 +518,7 @@ Migrate `npm-scripts.js` to `npm-scripts.mjs` (ES Module) ([PR #1093](https://gi ### 3.9.1 - NixOS friendly build process ([PR #683](https://github.com/versatica/mediasoup/pull/683)). -- `Worker`: Emit "died" event before observer "close" ([PR #684](https://github.com/versatica/mediasoup/pull/684)). +- Worker: Emit "died" event before observer "close" ([PR #684](https://github.com/versatica/mediasoup/pull/684)). - Transport: Hide debug message for RTX RTCP-RR packets ([PR #688](https://github.com/versatica/mediasoup/pull/688)). - Update `libuv` to 1.42.0. - Improve Windows support ([PR #692](https://github.com/versatica/mediasoup/pull/692)). diff --git a/worker/src/RTC/DataConsumer.cpp b/worker/src/RTC/DataConsumer.cpp index 1aaf97df12..c9034cdf0f 100644 --- a/worker/src/RTC/DataConsumer.cpp +++ b/worker/src/RTC/DataConsumer.cpp @@ -527,6 +527,12 @@ namespace RTC if (!IsActive()) { + if (cb) + { + (*cb)(false, false); + delete cb; + } + return; } @@ -536,6 +542,12 @@ namespace RTC requiredSubchannel.has_value() && this->subchannels.find(requiredSubchannel.value()) == this->subchannels.end()) { + if (cb) + { + (*cb)(false, false); + delete cb; + } + return; } @@ -557,6 +569,12 @@ namespace RTC if (!subchannelMatched) { + if (cb) + { + (*cb)(false, false); + delete cb; + } + return; } } @@ -569,6 +587,12 @@ namespace RTC len, this->maxMessageSize); + if (cb) + { + (*cb)(false, false); + delete cb; + } + return; } diff --git a/worker/src/RTC/DirectTransport.cpp b/worker/src/RTC/DirectTransport.cpp index 435c4b406b..f3af041e0f 100644 --- a/worker/src/RTC/DirectTransport.cpp +++ b/worker/src/RTC/DirectTransport.cpp @@ -146,6 +146,12 @@ namespace RTC { MS_WARN_TAG(rtp, "cannot send RTP packet not associated to a Consumer"); + if (cb) + { + (*cb)(false); + delete cb; + } + return; } @@ -212,11 +218,7 @@ namespace RTC } void DirectTransport::SendMessage( - RTC::DataConsumer* dataConsumer, - const uint8_t* msg, - size_t len, - uint32_t ppid, - onQueuedCallback* /*cb*/) + RTC::DataConsumer* dataConsumer, const uint8_t* msg, size_t len, uint32_t ppid, onQueuedCallback* cb) { MS_TRACE(); @@ -232,6 +234,12 @@ namespace RTC FBS::Notification::Body::DataConsumer_MessageNotification, notification); + if (cb) + { + (*cb)(true, false); + delete cb; + } + // Increase send transmission. RTC::Transport::DataSent(len); } From d3f1402f79755d07fdcd46e01144da843ae128be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Sun, 28 Apr 2024 13:24:37 +0200 Subject: [PATCH 28/28] 3.14.2 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28b2a97ae3..ef5a7f78de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -### NEXT +### 3.14.2 - Update worker subprojects ([PR #1376](https://github.com/versatica/mediasoup/pull/1376)). - OPUS: Fix DTX detection ([PR #1357](https://github.com/versatica/mediasoup/pull/1357)). diff --git a/package-lock.json b/package-lock.json index f914ae513b..93c17522b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mediasoup", - "version": "3.14.1", + "version": "3.14.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediasoup", - "version": "3.14.1", + "version": "3.14.2", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index b33e8412c7..b371d96fe1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mediasoup", - "version": "3.14.1", + "version": "3.14.2", "description": "Cutting Edge WebRTC Video Conferencing", "contributors": [ "IƱaki Baz Castillo (https://inakibaz.me)",