diff --git a/.ci-config/rippled.cfg b/.ci-config/rippled.cfg index 05d5753eea..ce092a1520 100644 --- a/.ci-config/rippled.cfg +++ b/.ci-config/rippled.cfg @@ -101,7 +101,6 @@ online_delete=256 # Devnet amendments as of June 28th, 2023 NegativeUNL fixRemoveNFTokenAutoTrustLine -NonFungibleTokensV1 CheckCashMakesTrustLine fixRmSmallIncreasedQOffers fixSTAmountCanonicalize @@ -144,10 +143,8 @@ fix1512 fix1373 MultiSign Checks -NonFungibleTokensV1_1 # 1.10.0 Amendments DisallowIncoming -fixNonFungibleTokensV1_2 fixTrustLinesToSelf fixUniversalNumber ImmediateOfferKilled @@ -158,7 +155,6 @@ ExpandedSignerList AMM Clawback fixReducedOffersV1 -fixNFTokenRemint # 2.0.0 Amendments XChainBridge DID @@ -188,11 +184,12 @@ PermissionedDomains fixFrozenLPTokenTransfer fixInvalidTxFlags # 2.5.0 Amendments -PermissionDelegation Batch PermissionedDEX TokenEscrow SingleAssetVault +LendingProtocol +PermissionDelegationV1_1 # This section can be used to simulate various FeeSettings scenarios for rippled node in standalone mode [voting] diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 0c33596aec..216a653043 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,6 +3,6 @@ updates: - package-ecosystem: npm directory: "/" schedule: - interval: weekly + interval: quarterly time: "15:00" - open-pull-requests-limit: 10 + open-pull-requests-limit: 30 diff --git a/.github/workflows/faucet_test.yml b/.github/workflows/faucet_test.yml index 9ee0af3e2b..df2938c5b9 100644 --- a/.github/workflows/faucet_test.yml +++ b/.github/workflows/faucet_test.yml @@ -10,10 +10,16 @@ on: description: 'Git ref to checkout (branch, tag, or commit SHA)' required: true type: string + run_faucet_tests: + description: 'Run faucet tests job' + required: false + type: boolean + default: true jobs: faucet-test: + if: ${{ github.event_name != 'workflow_dispatch' || inputs.run_faucet_tests != false }} runs-on: ubuntu-latest timeout-minutes: 15 diff --git a/.github/workflows/generate-documentation.yml b/.github/workflows/generate-documentation.yml new file mode 100644 index 0000000000..edf760884d --- /dev/null +++ b/.github/workflows/generate-documentation.yml @@ -0,0 +1,77 @@ +name: Generate Documentation + +on: + workflow_call: + inputs: + git_ref: + description: 'Git ref to checkout (branch, tag, or commit SHA)' + required: true + type: string + +env: + GIT_REF: ${{ inputs.git_ref }} + +jobs: + generate-documentation: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [22.x] + + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ env.GIT_REF }} + fetch-depth: 0 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + + - name: Setup npm version 10 + run: | + npm i -g npm@10 --registry=https://registry.npmjs.org + - name: Cache node modules + id: cache-nodemodules + uses: actions/cache@v4 + env: + cache-name: cache-node-modules + with: + # caching node_modules + path: | + node_modules + */*/node_modules + key: ${{ runner.os }}-deps-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-deps-${{ matrix.node-version }}- + - name: Install Dependencies + if: steps.cache-nodemodules.outputs.cache-hit != 'true' + run: npm ci + + - run: npm run build + + - name: Generate Documentation + run: npm run docgen + + - name: Upload documentation files as artifact + id: docs-artifact + uses: actions/upload-pages-artifact@v3 + with: + path: docs/ + retention-days: 10 + + deploy-docs-pages: + permissions: + id-token: write # Needed for OIDC authentication + pages: write # this permission is needed for deploying into Github Pages + environment: + name: github-pages + url: ${{ steps.docs-artifact.outputs.page_url }} + runs-on: ubuntu-latest + needs: generate-documentation + steps: + - name: Deploy to Documentation to GitHub Pages + id: docs-artifact + uses: actions/deploy-pages@v4 diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 8a2f528c1d..5624ee8014 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -11,15 +11,31 @@ on: push: branches: [main] tags: - - '**' + - "**" pull_request: + types: [opened, synchronize, reopened, ready_for_review] workflow_dispatch: workflow_call: inputs: git_ref: - description: 'Git ref to checkout (branch, tag, or commit SHA)' + description: "Git ref to checkout (branch, tag, or commit SHA)" required: true type: string + run_unit_tests: + description: "Run unit tests job" + required: false + type: boolean + default: true + run_integration_tests: + description: "Run integration tests job" + required: false + type: boolean + default: true + run_browser_tests: + description: "Run browser tests job" + required: false + type: boolean + default: true jobs: build-and-lint: @@ -27,7 +43,7 @@ jobs: timeout-minutes: 10 strategy: matrix: - node-version: [22.x] + node-version: [24.x] steps: - uses: actions/checkout@v4 @@ -65,12 +81,13 @@ jobs: - run: npm run lint unit: + if: ${{ github.event_name != 'workflow_dispatch' || inputs.run_unit_tests != false }} runs-on: ubuntu-latest timeout-minutes: 10 strategy: matrix: - node-version: [20.x, 22.x] + node-version: [20.x, 22.x, 24.x] steps: - uses: actions/checkout@v4 @@ -108,12 +125,13 @@ jobs: - run: npm test integration: + if: ${{ github.event_name != 'workflow_dispatch' || inputs.run_integration_tests != false }} runs-on: ubuntu-latest timeout-minutes: 10 strategy: matrix: - node-version: [20.x, 22.x] + node-version: [20.x, 22.x, 24.x] steps: - uses: actions/checkout@v4 @@ -123,7 +141,7 @@ jobs: - name: Run docker in background run: | - docker run --detach --rm -p 6006:6006 --volume "${{ github.workspace }}/.ci-config/":"/etc/opt/ripple/" --name rippled-service --health-cmd="rippled server_info || exit 1" --health-interval=5s --health-retries=10 --health-timeout=2s --env GITHUB_ACTIONS=true --env CI=true --entrypoint bash ${{ env.RIPPLED_DOCKER_IMAGE }} -c "rippled -a" + docker run --detach --rm -p 6006:6006 --volume "${{ github.workspace }}/.ci-config/":"/etc/opt/ripple/" --name rippled-service --health-cmd="rippled server_info || exit 1" --health-interval=5s --health-retries=10 --health-timeout=2s --env GITHUB_ACTIONS=true --env CI=true --entrypoint bash ${{ env.RIPPLED_DOCKER_IMAGE }} -c "mkdir -p /var/lib/rippled/db/ && rippled -a" - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 @@ -162,12 +180,13 @@ jobs: run: docker stop rippled-service browser: + if: ${{ github.event_name != 'workflow_dispatch' || inputs.run_browser_tests != false }} runs-on: ubuntu-latest timeout-minutes: 10 strategy: matrix: - node-version: [22.x] + node-version: [24.x] steps: - uses: actions/checkout@v4 @@ -182,7 +201,7 @@ jobs: - name: Run docker in background run: | - docker run --detach --rm -p 6006:6006 --volume "${{ github.workspace }}/.ci-config/":"/etc/opt/ripple/" --name rippled-service --health-cmd="rippled server_info || exit 1" --health-interval=5s --health-retries=10 --health-timeout=2s --env GITHUB_ACTIONS=true --env CI=true --entrypoint bash ${{ env.RIPPLED_DOCKER_IMAGE }} -c "rippled -a" + docker run --detach --rm -p 6006:6006 --volume "${{ github.workspace }}/.ci-config/":"/etc/opt/ripple/" --name rippled-service --health-cmd="rippled server_info || exit 1" --health-interval=5s --health-retries=10 --health-timeout=2s --env GITHUB_ACTIONS=true --env CI=true --entrypoint bash ${{ env.RIPPLED_DOCKER_IMAGE }} -c "mkdir -p /var/lib/rippled/db/ && rippled -a" - name: Setup npm version 10 run: | @@ -214,79 +233,3 @@ jobs: - name: Stop docker container if: always() run: docker stop rippled-service - - generate-documentation: - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [22.x] - - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ env.GIT_REF }} - fetch-depth: 0 - - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - - - name: Setup npm version 10 - run: | - npm i -g npm@10 --registry=https://registry.npmjs.org - - - name: Cache node modules - id: cache-nodemodules - uses: actions/cache@v4 - env: - cache-name: cache-node-modules - with: - # caching node_modules - path: | - node_modules - */*/node_modules - key: ${{ runner.os }}-deps-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-deps-${{ matrix.node-version }}- - - - name: Install Dependencies - if: steps.cache-nodemodules.outputs.cache-hit != 'true' - run: npm ci - - - run: npm run build - - - name: Generate Documentation - run: npm run docgen - - - name: Upload documentation files as artifact - id: docs-artifact - uses: actions/upload-pages-artifact@v3 - with: - path: docs/ - retention-days: 10 - - deploy-docs-pages: - permissions: - id-token: write # Needed for OIDC authentication - pages: write # this permission is needed for deploying into Github Pages - environment: - name: github-pages - url: ${{ steps.docs-artifact.outputs.page_url }} - runs-on: ubuntu-latest - needs: generate-documentation - # Deploy docs only pushes into the main branch - if: success() && github.ref == 'refs/heads/main' - steps: - - name: Detect (non-beta) version tag - id: check-tag - run: | - if [[ ${{ github.event.ref }} =~ ^refs/tags/v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "published_version_tag=true" >> $GITHUB_OUTPUT - fi - - - name: Deploy to Documentation to GitHub Pages - id: docs-artifact - if: steps.check-tag.outputs.published_version_tag == 'true' - uses: actions/deploy-pages@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 016893d350..ccacc432c2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,52 +7,68 @@ on: workflow_dispatch: inputs: package_name: - description: 'Package folder (Name of the package directory under packages/ folder. e.g., xrpl, ripple-address-codec)' + description: "Package folder (Name of the package directory under packages/ folder. e.g., xrpl, ripple-address-codec)" required: true - release_branch: - description: 'Release branch the release is generated from' + release_branch_name: + description: 'Name of the release branch to be used' required: true npmjs_dist_tag: - description: 'npm distribution tag(Read more https://docs.npmjs.com/adding-dist-tags-to-packages)' - default: 'latest' + description: "npm distribution tag(Read more https://docs.npmjs.com/adding-dist-tags-to-packages)" + default: "latest" concurrency: group: release cancel-in-progress: true +defaults: + run: + shell: bash + jobs: get_version: runs-on: ubuntu-latest + permissions: + contents: read name: Get release version from package.json outputs: - package_version: ${{ steps.get_version.outputs.version }} + package_version: ${{ steps.get_version.outputs.package_version }} + dist_tag: ${{ steps.validate_inputs.outputs.dist_tag }} + release_branch: ${{ steps.validate_inputs.outputs.release_branch }} + is_beta: ${{ steps.validate_inputs.outputs.is_beta }} steps: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ github.event.inputs.release_branch }} fetch-depth: 0 + ref: ${{ github.event.inputs.release_branch_name }} - name: Validate inputs + id: validate_inputs + env: + GH_TOKEN: ${{ github.token }} + PKG_NAME: ${{ github.event.inputs.package_name }} + REPO: ${{ github.repository }} + RELEASE_BRANCH: ${{ github.event.inputs.release_branch_name }} + TRIGGER_BRANCH: ${{ github.ref_name }} + NPM_DIST_TAG: ${{ github.event.inputs.npmjs_dist_tag }} run: | set -euo pipefail + + if [[ -z "$RELEASE_BRANCH" ]]; then + echo "❌ Unable to determine branch name." >&2 + exit 1 + fi + # Validate package_name - PKG_NAME="${{ github.event.inputs.package_name }}" - if ! [[ "$PKG_NAME" =~ ^[a-z0-9][a-z0-9-]*$ ]]; then - echo "❌ Invalid package_name '$PKG_NAME' (allowed: [a-z0-9-], must start with alnum)." >&2 + if ! [[ "${PKG_NAME}" =~ ^[a-z0-9][a-z0-9-]*$ ]]; then + echo "❌ Invalid package_name '${PKG_NAME}' (allowed: [a-z0-9-], must start with alnum)." >&2 exit 1 fi # Guard against path traversal - if [[ "$PKG_NAME" == *".."* || "$PKG_NAME" == *"/"* ]]; then + if [[ "${PKG_NAME}" == *".."* || "${PKG_NAME}" == *"/"* ]]; then echo "❌ package_name must be a single directory under packages/." >&2 exit 1 fi - if git ls-remote --exit-code origin "refs/heads/${{ github.event.inputs.release_branch }}" > /dev/null; then - echo "✅ Found release branch: ${{ github.event.inputs.release_branch }}" - else - echo "❌ Release branch ${{ github.event.inputs.release_branch }} not found in remote. Failing workflow." - exit 1 - fi if grep -R --exclude-dir=.git --exclude-dir=.github "artifactory.ops.ripple.com" .; then echo "❌ Internal Artifactory URL found" @@ -61,107 +77,181 @@ jobs: echo "✅ No Internal Artifactory URL found" fi - # validate dist tag - NPM_DIST_TAG="${{ github.event.inputs.npmjs_dist_tag }}" - - # Empty → default to 'latest' if [ -z "$NPM_DIST_TAG" ]; then NPM_DIST_TAG="latest" echo "ℹ️ npmjs_dist_tag empty → defaulting to 'latest'." + else + NPM_DIST_TAG="$(printf '%s' "$NPM_DIST_TAG" | tr -d '[:space:]')" fi - # Must start with a lowercase letter; then [a-z0-9._-]; max 128 chars if ! [[ "$NPM_DIST_TAG" =~ ^[a-z][a-z0-9._-]{0,127}$ ]]; then echo "❌ Invalid npm dist-tag '$NPM_DIST_TAG'. Must start with a lowercase letter and contain only [a-z0-9._-], max 128 chars." >&2 exit 1 fi - - # Disallow version-like prefixes (avoid semver/range confusion) if [[ "$NPM_DIST_TAG" =~ ^v[0-9] || "$NPM_DIST_TAG" =~ ^[0-9] ]]; then echo "❌ Invalid npm dist-tag '$NPM_DIST_TAG'. Must not start with 'v' + digit or a digit (e.g., 'v1', '1.2.3')." >&2 exit 1 fi - echo "✅ npmjs_dist_tag '$NPM_DIST_TAG' is valid." + if [ "$NPM_DIST_TAG" = "latest" ]; then + IS_BETA="false" + else + IS_BETA="true" + NPM_DIST_TAG="${NPM_DIST_TAG}-experimental" + fi + + if [ "$IS_BETA" != "true" ] && [[ ! "${RELEASE_BRANCH}" =~ ^[Rr][Ee][Ll][Ee][Aa][Ss][Ee][-/] ]]; then + echo "❌ Release branch '$RELEASE_BRANCH' must start with 'release-' or 'release/' for stable releases." >&2 + exit 1 + fi + + if [[ "$TRIGGER_BRANCH" != "main" ]]; then + echo "❌ Release pipeline can only be triggered from the 'main' branch. Current branch: '$TRIGGER_BRANCH'." >&2 + exit 1 + fi + + { + echo "NPM_DIST_TAG=$NPM_DIST_TAG" + echo "RELEASE_BRANCH=$RELEASE_BRANCH" + } >> "$GITHUB_ENV" + + PR_NUMBER="" + PR_URL="" + + { + echo "release_branch=$RELEASE_BRANCH" + echo "is_beta=$IS_BETA" + echo "dist_tag=$NPM_DIST_TAG" + } >> "$GITHUB_OUTPUT" + - name: Get package version from package.json id: get_version + env: + IS_BETA: ${{ steps.validate_inputs.outputs.is_beta }} + PKG_NAME: ${{ github.event.inputs.package_name }} run: | set -euo pipefail - PACKAGE_NAME="${{ github.event.inputs.package_name }}" - PKG_JSON="packages/${PACKAGE_NAME}/package.json" - if [[ ! -f "$PKG_JSON" ]]; then - echo "package.json not found at $PKG_JSON. Check 'package_name' input." >&2 + PKG_JSON="packages/${PKG_NAME}/package.json" + if [[ ! -f "${PKG_JSON}" ]]; then + echo "package.json not found at ${PKG_JSON}. Check 'package_name' input." >&2 exit 1 fi - VERSION=$(jq -er .version "$PKG_JSON") - if [[ -z "$VERSION" || "$VERSION" == "null" ]]; then - echo "Version is empty or missing in $PKG_JSON" >&2 + VERSION=$(jq -er .version "${PKG_JSON}") + if [[ -z "${VERSION}" || "${VERSION}" == "null" ]]; then + echo "Version is empty or missing in ${PKG_JSON}" >&2 exit 1 fi - NPM_DIST_TAG="${{ github.event.inputs.npmjs_dist_tag }}" - if [ -z "$NPM_DIST_TAG" ]; then - NPM_DIST_TAG="latest" - fi - if [[ "$NPM_DIST_TAG" == "latest" ]] && ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + + if [[ "${IS_BETA:-false}" != "true" ]] && ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "With npmjs_dist_tag 'latest', version must be of the form x.y.z. Found '$VERSION'." >&2 exit 1 fi - echo "PACKAGE_VERSION=$VERSION" >> "$GITHUB_ENV" - echo "version=$VERSION" >> "$GITHUB_OUTPUT" + echo "package_version=$VERSION" >> "$GITHUB_OUTPUT" run_faucet_test: name: Run faucet tests ${{ needs.get_version.outputs.package_version }} needs: [get_version] uses: ./.github/workflows/faucet_test.yml with: - git_ref: ${{ github.event.inputs.release_branch }} + git_ref: ${{ needs.get_version.outputs.release_branch }} + run_faucet_tests: ${{ needs.get_version.outputs.is_beta != 'true' }} secrets: inherit run_tests: name: Run unit/integration tests ${{ needs.get_version.outputs.package_version }} - permissions: - contents: read - id-token: write - pages: write needs: [get_version] uses: ./.github/workflows/nodejs.yml with: - git_ref: ${{ github.event.inputs.release_branch }} + git_ref: ${{ needs.get_version.outputs.release_branch }} + run_unit_tests: true + run_integration_tests: ${{ needs.get_version.outputs.is_beta != 'true' }} + run_browser_tests: ${{ needs.get_version.outputs.is_beta != 'true' }} secrets: inherit pre_release: runs-on: ubuntu-latest + if: ${{ always() && needs.get_version.result == 'success' && (needs.run_faucet_test.result == 'success' || needs.run_faucet_test.result == 'skipped') && needs.run_tests.result == 'success' }} needs: [get_version, run_faucet_test, run_tests] name: Pre Release Pipeline for ${{ needs.get_version.outputs.package_version }} permissions: issues: write + pull-requests: write env: - PACKAGE_VERSION: "${{ needs.get_version.outputs.package_version }}" - PACKAGE_NAME: "${{ github.event.inputs.package_name }}" + PKG_VERSION: "${{ needs.get_version.outputs.package_version }}" + PKG_NAME: "${{ github.event.inputs.package_name }}" + outputs: + release_pr_number: ${{ steps.ensure_pr.outputs.pr_number }} + release_pr_url: ${{ steps.ensure_pr.outputs.pr_url }} steps: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ github.event.inputs.release_branch }} fetch-depth: 0 + ref: ${{ needs.get_version.outputs.release_branch }} + + - name: Create PR from release branch to main (skips for rc/beta) + id: ensure_pr + if: ${{ github.event.inputs.npmjs_dist_tag == '' || github.event.inputs.npmjs_dist_tag == 'latest' }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO: ${{ github.repository }} + RELEASE_BRANCH: ${{ needs.get_version.outputs.release_branch }} + VERSION: ${{ needs.get_version.outputs.package_version }} + RUN_ID: ${{ github.run_id }} + run: | + set -euo pipefail + + echo "🔎 Checking if a PR already exists for $RELEASE_BRANCH → main…" + OWNER="${REPO%%/*}" + # Find existing OPEN PR: base=main, head=OWNER:RELEASE_BRANCH + PRS_JSON="$(gh api -H 'Accept: application/vnd.github+json' \ + "/repos/$REPO/pulls?state=open&base=main&head=${OWNER}:${RELEASE_BRANCH}")" + PR_NUMBER="$(printf '%s' "$PRS_JSON" | jq -r '.[0].number // empty')" + PR_URL="$(printf '%s' "$PRS_JSON" | jq -r '.[0].html_url // empty')" + if [ -n "${PR_NUMBER:-}" ]; then + echo "ℹ️ Found existing PR: #$PR_NUMBER ($PR_URL)" + echo "🛑 Closing existing PR #$PR_NUMBER before opening a draft…" + CLOSE_JSON="$(jq -n --arg state "closed" '{state:$state}')" + if ! gh api -H 'Accept: application/vnd.github+json' \ + --method PATCH \ + "/repos/$REPO/pulls/$PR_NUMBER" \ + --input <(printf '%s' "$CLOSE_JSON"); then + echo "⚠️ Unable to close PR #$PR_NUMBER automatically. You may need to close it manually." >&2 + fi + fi + + echo "📝 Creating PR for release $VERSION from $RELEASE_BRANCH → main (as draft)" + CREATE_JSON="$(jq -n \ + --arg title "Release $VERSION: $RELEASE_BRANCH → main" \ + --arg head "$RELEASE_BRANCH" \ + --arg base "main" \ + --arg body "Automated PR for release **$VERSION** from **$RELEASE_BRANCH** → **main**. Workflow Run: https://github.com/$REPO/actions/runs/$RUN_ID" \ + '{title:$title, head:$head, base:$base, body:$body, draft:true}')" + RESP="$(gh api -H 'Accept: application/vnd.github+json' \ + --method POST /repos/$REPO/pulls --input <(printf '%s' "$CREATE_JSON"))" + PR_NUMBER="$(printf '%s' "$RESP" | jq -r '.number')" + PR_URL="$(printf '%s' "$RESP" | jq -r '.html_url')" + # Expose as step outputs (use these in later steps) + echo "pr_url=$PR_URL" >> "$GITHUB_OUTPUT" + echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT" - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: 20 - registry-url: 'https://registry.npmjs.org' + registry-url: "https://registry.npmjs.org" - name: Build package run: | - # dubugging info + # debugging info npm i -g npm@11.6.0 npm --version node --version ls -l pwd - #build + # build npm ci npm run build @@ -169,14 +259,16 @@ jobs: if: failure() env: SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }} + REPO: ${{ github.repository }} + RUN_ID: ${{ github.run_id }} run: | - MESSAGE="❌ Build failed for xrpl.js ${{ env.PACKAGE_VERSION }}. Check the logs: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + MESSAGE="❌ Build failed for xrpl.js ${PKG_VERSION}. Check the logs: https://github.com/${REPO}/actions/runs/${RUN_ID}" curl -X POST https://slack.com/api/chat.postMessage \ - -H "Authorization: Bearer $SLACK_TOKEN" \ + -H "Authorization: Bearer ${SLACK_TOKEN}" \ -H "Content-Type: application/json" \ -d "$(jq -n \ --arg channel "#xrpl-js" \ - --arg text "$MESSAGE" \ + --arg text "${MESSAGE}" \ '{channel: $channel, text: $text}')" - name: Install cyclonedx-npm @@ -196,10 +288,14 @@ jobs: severity: CRITICAL,HIGH - name: Upload sbom to OWASP + env: + OWASP_TOKEN: ${{ secrets.OWASP_TOKEN }} run: | curl -X POST \ - -H "X-Api-Key: ${{ secrets.OWASP_TOKEN }}" \ - -F "project=7c40c8ea-ea0f-4a5f-9b9f-368e53232397" \ + -H "X-Api-Key: ${OWASP_TOKEN}" \ + -F "autoCreate=true" \ + -F "projectName=xrpl-js" \ + -F "projectVersion=${PKG_VERSION}" \ -F "bom=@sbom.json" \ https://owasp-dt-api.prod.ripplex.io/api/v1/bom @@ -221,14 +317,18 @@ jobs: - name: Build vuln artifact URL id: vuln_art + env: + REPO: ${{ github.repository }} + RUN_ID: ${{ github.run_id }} + ARTIFACT_ID: ${{ steps.upload_vuln.outputs.artifact-id }} run: | - echo "art_url=https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts/${{ steps.upload_vuln.outputs.artifact-id }}" >> "$GITHUB_OUTPUT" + echo "art_url=https://github.com/${REPO}/actions/runs/${RUN_ID}/artifacts/${ARTIFACT_ID}" >> "$GITHUB_OUTPUT" - name: Check vulnerabilities in report id: check_vulns shell: bash env: - REPORT_PATH: vuln-report.txt # change if different + REPORT_PATH: vuln-report.txt # change if different run: | set -euo pipefail if grep -qE "CRITICAL|HIGH" "$REPORT_PATH"; then @@ -243,20 +343,18 @@ jobs: env: GH_TOKEN: ${{ github.token }} REPO: ${{ github.repository }} - PKG_NAME: ${{ env.PACKAGE_NAME }} - PKG_VER: ${{ env.PACKAGE_VERSION }} - REL_BRANCH: ${{ github.event.inputs.release_branch }} + REL_BRANCH: ${{ github.ref_name }} VULN_ART_URL: ${{ steps.vuln_art.outputs.art_url }} LABELS: security run: | set -euo pipefail - TITLE="🔒 Security vulnerabilities in ${PKG_NAME}@${PKG_VER}" + TITLE="🔒 Security vulnerabilities in ${PKG_NAME}@${PKG_VERSION}" : > issue_body.md - echo "The vulnerability scan has detected **CRITICAL/HIGH** vulnerabilities for \`${PKG_NAME}@${PKG_VER}\` on branch \`${REL_BRANCH}\`." >> issue_body.md + echo "The vulnerability scan has detected **CRITICAL/HIGH** vulnerabilities for \`${PKG_NAME}@${PKG_VERSION}\` on branch \`${REL_BRANCH}\`." >> issue_body.md echo "" >> issue_body.md echo "**Release Branch:** \`${REL_BRANCH}\`" >> issue_body.md - echo "**Package Version:** \`${PKG_VER}\`" >> issue_body.md + echo "**Package Version:** \`${PKG_VERSION}\`" >> issue_body.md echo "" >> issue_body.md echo "**Full vulnerability report:** ${VULN_ART_URL}" >> issue_body.md echo "" >> issue_body.md @@ -264,24 +362,24 @@ jobs: echo "" >> issue_body.md echo "---" >> issue_body.md echo "_This issue was automatically generated by the Release Pipeline._" >> issue_body.md - gh issue create --title "$TITLE" --body-file issue_body.md --label "$LABELS" + gh issue create --title "${TITLE}" --body-file issue_body.md --label "${LABELS}" - name: Generate lerna.json for choosen the package run: | - echo "🔧 Updating lerna.json to include only packages/${{ env.PACKAGE_NAME }}" + echo "🔧 Updating lerna.json to include only packages/${PKG_NAME}" # Use jq to update the packages field safely - jq --arg pkg "packages/${{ env.PACKAGE_NAME }}" '.packages = [$pkg]' lerna.json > lerna.tmp.json && mv lerna.tmp.json lerna.json + jq --arg pkg "packages/${PKG_NAME}" '.packages = [$pkg]' lerna.json > lerna.tmp.json && mv lerna.tmp.json lerna.json echo "✅ lerna.json updated:" cat lerna.json - name: Pack tarball run: | set -euo pipefail - echo "Packaging ${{ env.PACKAGE_NAME }}" - find "packages/${{ env.PACKAGE_NAME }}" -maxdepth 1 -name '*.tgz' -delete || true - FULL_PACKAGE_NAME="$(jq -er '.name' packages/${{ env.PACKAGE_NAME }}/package.json)" - TARBALL=$(npx lerna exec --scope "$FULL_PACKAGE_NAME" -- npm pack --json | jq -r '.[0].filename') - echo "TARBALL=packages/${{ env.PACKAGE_NAME }}/${TARBALL}" >> "$GITHUB_ENV" + echo "Packaging ${PKG_NAME}" + find "packages/${PKG_NAME}" -maxdepth 1 -name '*.tgz' -delete || true + FULL_PKG_NAME="$(jq -er '.name' packages/${PKG_NAME}/package.json)" + TARBALL=$(npx lerna exec --scope "${FULL_PKG_NAME}" -- npm pack --json | jq -r '.[0].filename') + echo "TARBALL=packages/${PKG_NAME}/${TARBALL}" >> "$GITHUB_ENV" - name: Upload tarball as artifact uses: actions/upload-artifact@v4 @@ -291,13 +389,15 @@ jobs: ask_for_dev_team_review: runs-on: ubuntu-latest + if: ${{ always() && needs.pre_release.result == 'success' && needs.run_tests.result == 'success' && (needs.run_faucet_test.result == 'success' || needs.run_faucet_test.result == 'skipped') }} needs: [get_version, run_faucet_test, run_tests, pre_release] permissions: pull-requests: write - name: Review test and security scan result -- Dev team + name: Print Test/Security scan result and invite Dev team to review env: - PACKAGE_VERSION: "${{ needs.get_version.outputs.package_version }}" - PACKAGE_NAME: "${{ github.event.inputs.package_name }}" + PKG_VERSION: "${{ needs.get_version.outputs.package_version }}" + PKG_NAME: "${{ github.event.inputs.package_name }}" + RELEASE_BRANCH: "${{ github.event.inputs.release_branch_name }}" outputs: reviewers_dev: ${{ steps.get_reviewers.outputs.reviewers_dev }} reviewers_sec: ${{ steps.get_reviewers.outputs.reviewers_sec }} @@ -306,50 +406,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ github.event.inputs.release_branch }} fetch-depth: 0 - - name: Create PR from release branch to main (skips for rc/beta) - id: ensure_pr - if: ${{ github.event.inputs.npmjs_dist_tag == '' || github.event.inputs.npmjs_dist_tag == 'latest' }} - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - REPO: ${{ github.repository }} - RELEASE_BRANCH: ${{ github.event.inputs.release_branch }} - VERSION: ${{ needs.get_version.outputs.package_version }} - run: | - set -euo pipefail - - echo "🔎 Checking if a PR already exists for $RELEASE_BRANCH → main…" - OWNER="${REPO%%/*}" - - # Find existing OPEN PR: base=main, head=OWNER:RELEASE_BRANCH - PRS_JSON="$(gh api -H 'Accept: application/vnd.github+json' \ - "/repos/$REPO/pulls?state=open&base=main&head=${OWNER}:${RELEASE_BRANCH}")" - - PR_NUMBER="$(printf '%s' "$PRS_JSON" | jq -r '.[0].number // empty')" - PR_URL="$(printf '%s' "$PRS_JSON" | jq -r '.[0].html_url // empty')" - - if [ -n "${PR_NUMBER:-}" ]; then - echo "ℹ️ Found existing PR: #$PR_NUMBER ($PR_URL)" - else - echo "📝 Creating PR for release $VERSION from $RELEASE_BRANCH → main" - CREATE_JSON="$(jq -n \ - --arg title "Release $VERSION: $RELEASE_BRANCH → main" \ - --arg head "$RELEASE_BRANCH" \ - --arg base "main" \ - --arg body "Automated PR for release **$VERSION** from **$RELEASE_BRANCH** → **main**. Workflow Run: https://github.com/$REPO/actions/runs/${{ github.run_id }}" \ - '{title:$title, head:$head, base:$base, body:$body}')" - - RESP="$(gh api -H 'Accept: application/vnd.github+json' \ - --method POST /repos/$REPO/pulls --input <(printf '%s' "$CREATE_JSON"))" - - PR_NUMBER="$(printf '%s' "$RESP" | jq -r '.number')" - PR_URL="$(printf '%s' "$RESP" | jq -r '.html_url')" - fi - - # Expose as step outputs (use these in later steps) - echo "pr_url=$PR_URL" >> "$GITHUB_OUTPUT" - echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT" - name: Get reviewers id: get_reviewers @@ -358,13 +415,8 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} REPO: ${{ github.repository }} RUN_ID: ${{ github.run_id }} - RUN_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} ENV_DEV_NAME: first-review ENV_SEC_NAME: official-release - PACKAGE_NAME: ${{ env.PACKAGE_NAME }} - PACKAGE_VERSION: ${{ env.PACKAGE_VERSION }} - NPMJS_DIST_TAG: ${{ github.event.inputs.npmjs_dist_tag }} - PR_URL: ${{ steps.ensure_pr.outputs.pr_url }} GITHUB_ACTOR: ${{ github.actor }} GITHUB_TRIGGERING_ACTOR: ${{ github.triggering_actor }} run: | @@ -412,26 +464,22 @@ jobs: REPO: ${{ github.repository }} RUN_ID: ${{ github.run_id }} ENV_NAME: official-release - PACKAGE_NAME: ${{ env.PACKAGE_NAME }} - PACKAGE_VERSION: ${{ env.PACKAGE_VERSION }} - NPMJS_DIST_TAG: ${{ github.event.inputs.npmjs_dist_tag }} GITHUB_ACTOR: ${{ github.actor }} GITHUB_TRIGGERING_ACTOR: ${{ github.triggering_actor }} RUN_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} - PR_URL: ${{ steps.ensure_pr.outputs.pr_url }} + PR_URL: ${{ needs.pre_release.outputs.release_pr_url }} run: | set -euo pipefail ARTIFACT_NAME="vulnerability-report" - RELEASE_BRANCH="${{ github.event.inputs.release_branch }}" COMMIT_SHA="$(git rev-parse --short HEAD)" echo "Fetching artifact ID for ${ARTIFACT_NAME}..." - ARTIFACTS=$(curl -s -H "Authorization: Bearer $GH_TOKEN" \ + ARTIFACTS=$(curl -s -H "Authorization: Bearer ${GH_TOKEN}" \ -H "Accept: application/vnd.github+json" \ - "https://api.github.com/repos/$REPO/actions/runs/$RUN_ID/artifacts") + "https://api.github.com/repos/${REPO}/actions/runs/${RUN_ID}/artifacts") - ARTIFACT_ID=$(echo "$ARTIFACTS" | jq -r ".artifacts[] | select(.name == \"$ARTIFACT_NAME\") | .id") + ARTIFACT_ID=$(echo "${ARTIFACTS}" | jq -r ".artifacts[] | select(.name == \"${ARTIFACT_NAME}\") | .id") if [ -z "${ARTIFACT_ID:-}" ]; then echo "❌ Artifact not found." @@ -439,11 +487,11 @@ jobs: fi echo "🔍 Please review the following details before proceeding:" - echo "📦 Package Name: $PACKAGE_NAME" - echo "🔖 Package Version: $PACKAGE_VERSION" - echo "🌿 Release Branch: $RELEASE_BRANCH" - echo "🔢 Commit SHA: $COMMIT_SHA" - echo "🔗 Vulnerabilities: https://github.com/$REPO/actions/runs/$RUN_ID/artifacts/$ARTIFACT_ID" + echo "📦 Package Name: ${PKG_NAME}" + echo "🔖 Package Version: ${PKG_VERSION}" + echo "🌿 Release Branch: ${RELEASE_BRANCH}" + echo "🔢 Commit SHA: ${COMMIT_SHA}" + echo "🔗 Vulnerabilities: https://github.com/${REPO}/actions/runs/${RUN_ID}/artifacts/${ARTIFACT_ID}" - name: Send Dev review message to Slack if: always() @@ -452,30 +500,39 @@ jobs: SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }} CHANNEL: "#xrpl-js" EXECUTOR: ${{ github.triggering_actor || github.actor }} - PACKAGE_NAME: ${{ env.PACKAGE_NAME }} - PACKAGE_VERSION: ${{ env.PACKAGE_VERSION }} RUN_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} + REPO: ${{ github.repository }} + RUN_ID: ${{ github.run_id }} DEV_REVIEWERS: ${{ steps.get_reviewers.outputs.reviewers_dev }} - PR_URL: ${{ steps.ensure_pr.outputs.pr_url }} + PR_URL: ${{ needs.pre_release.outputs.release_pr_url }} run: | set -euo pipefail + RUN_URL="https://github.com/${REPO}/actions/runs/${RUN_ID}" - MSG="${EXECUTOR} is releasing ${PACKAGE_NAME}@${PACKAGE_VERSION}. A member from the dev team (${DEV_REVIEWERS}) needs to take the following actions: \n1) Review the release artifacts and approve/reject the release. (${RUN_URL})" + MSG="${EXECUTOR} is releasing ${PKG_NAME}@${PKG_VERSION}. A member from the dev team (${DEV_REVIEWERS}) needs to take the following actions: \n1) Review the release artifacts and approve/reject the release. (${RUN_URL})" - if [ -n "${PR_URL:-}" ]; then + if [ -n "${PR_URL}" ]; then MSG="${MSG} \n2) Review the package update PR and provide two approvals. DO NOT MERGE — ${EXECUTOR} will verify the package on npm and merge the approved PR. (${PR_URL})" fi - MSG=$(printf '%b' "$MSG") + MSG=$(printf '%b' "${MSG}") # Post once curl -sS -X POST https://slack.com/api/chat.postMessage \ - -H "Authorization: Bearer $SLACK_TOKEN" \ + -H "Authorization: Bearer ${SLACK_TOKEN}" \ -H "Content-Type: application/json; charset=utf-8" \ - -d "$(jq -n --arg channel "$CHANNEL" --arg text "$MSG" '{channel:$channel, text:$text}')" \ + -d "$(jq -n --arg channel "${CHANNEL}" --arg text "${MSG}" '{channel:$channel, text:$text}')" \ | jq -er '.ok' >/dev/null first_review: runs-on: ubuntu-latest - needs: [get_version, run_faucet_test, run_tests, pre_release, ask_for_dev_team_review] + if: ${{ always() && needs.ask_for_dev_team_review.result == 'success' && needs.run_tests.result == 'success' && (needs.run_faucet_test.result == 'success' || needs.run_faucet_test.result == 'skipped') }} + needs: + [ + get_version, + run_faucet_test, + run_tests, + pre_release, + ask_for_dev_team_review + ] name: First approval (dev team) environment: name: first-review @@ -486,29 +543,39 @@ jobs: ask_for_sec_team_review: runs-on: ubuntu-latest - needs: [get_version, run_faucet_test, run_tests, pre_release, ask_for_dev_team_review, first_review] - name: Review test and security scan result — Sec team + if: ${{ always() && needs.first_review.result == 'success' && needs.run_tests.result == 'success' && (needs.run_faucet_test.result == 'success' || needs.run_faucet_test.result == 'skipped') }} + needs: + [ + get_version, + run_faucet_test, + run_tests, + pre_release, + ask_for_dev_team_review, + first_review + ] + name: Invite sec team to review steps: - name: Send Sec team review request to Slack shell: bash env: - SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }} - CHANNEL: "#xrpl-js" - - EXECUTOR: ${{ github.triggering_actor || github.actor }} - PACKAGE_NAME: ${{ needs.get_version.outputs.package_version && github.event.inputs.package_name }} - PACKAGE_VERSION: ${{ needs.get_version.outputs.package_version }} - RUN_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} - SEC_REVIEWERS: ${{ needs.ask_for_dev_team_review.outputs.reviewers_sec }} + SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }} + CHANNEL: "#ripplex-security" + EXECUTOR: ${{ github.triggering_actor || github.actor }} + PKG_NAME: ${{ github.event.inputs.package_name }} + PKG_VERSION: ${{ needs.get_version.outputs.package_version }} + REPO: ${{ github.repository }} + RUN_ID: ${{ github.run_id }} + SEC_REVIEWERS: ${{ needs.ask_for_dev_team_review.outputs.reviewers_sec }} run: | set -euo pipefail + RUN_URL="https://github.com/${REPO}/actions/runs/${RUN_ID}" - MSG="${EXECUTOR} is releasing ${PACKAGE_NAME}@${PACKAGE_VERSION}. A member from the infosec team (${SEC_REVIEWERS}) needs to take the following action:\n Review the release artifacts and approve/reject the release. (${RUN_URL})" + MSG="${EXECUTOR} is releasing ${PKG_NAME}@${PKG_VERSION}. A sec reviewer from (${SEC_REVIEWERS}) needs to take the following action:\nReview the release artifacts and approve/reject the release. (${RUN_URL})" MSG=$(printf '%b' "$MSG") curl -sS -X POST https://slack.com/api/chat.postMessage \ - -H "Authorization: Bearer $SLACK_TOKEN" \ + -H "Authorization: Bearer ${SLACK_TOKEN}" \ -H "Content-Type: application/json; charset=utf-8" \ - -d "$(jq -n --arg channel "$CHANNEL" --arg text "$MSG" '{channel:$channel, text:$text}')" \ + -d "$(jq -n --arg channel "${CHANNEL}" --arg text "${MSG}" '{channel:$channel, text:$text}')" \ | jq -er '.ok' >/dev/null release: @@ -516,11 +583,22 @@ jobs: permissions: id-token: write contents: write - needs: [get_version, run_faucet_test, run_tests, pre_release, ask_for_dev_team_review, first_review, ask_for_sec_team_review] - name: Release Pipeline for ${{ needs.get_version.outputs.package_version }} + if: ${{ always() && needs.ask_for_sec_team_review.result == 'success' && needs.run_tests.result == 'success' && (needs.run_faucet_test.result == 'success' || needs.run_faucet_test.result == 'skipped') }} + needs: + [ + get_version, + run_faucet_test, + run_tests, + pre_release, + ask_for_dev_team_review, + first_review, + ask_for_sec_team_review + ] + + name: Release for ${{ needs.get_version.outputs.package_version }} env: - PACKAGE_VERSION: "${{ needs.get_version.outputs.package_version }}" - PACKAGE_NAME: "${{ github.event.inputs.package_name }}" + PKG_VERSION: "${{ needs.get_version.outputs.package_version }}" + PKG_NAME: "${{ github.event.inputs.package_name }}" environment: name: official-release url: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} @@ -531,11 +609,17 @@ jobs: echo "❌ Workflow rerun (attempt ${GITHUB_RUN_ATTEMPT}). Second attempts are not allowed." exit 1 fi - - name: Checkout code + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + registry-url: 'https://registry.npmjs.org/' + - name: Checkout release branch uses: actions/checkout@v4 with: - ref: ${{ github.event.inputs.release_branch }} fetch-depth: 0 + ref: ${{ needs.get_version.outputs.release_branch }} - name: Download artifact uses: actions/download-artifact@v4 @@ -543,46 +627,55 @@ jobs: name: npm-package-tarball path: dist - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - registry-url: 'https://registry.npmjs.org/' - - name: Publish to npm + env: + NPM_DIST_TAG: ${{ needs.get_version.outputs.dist_tag }} + IS_BETA: ${{ needs.get_version.outputs.is_beta }} run: | + set -euo pipefail + REPO_ROOT="$PWD" + PACKAGE_JSON_PATH="$REPO_ROOT/packages/${PKG_NAME}/package.json" + if [ ! -f "$PACKAGE_JSON_PATH" ]; then + echo "❌ package.json not found at $PACKAGE_JSON_PATH" >&2 + exit 1 + fi + FULL_PACKAGE_NAME=$(jq -er '.name' "$PACKAGE_JSON_PATH") + cd dist PKG=$(ls *.tgz) - echo $PKG - NPM_DIST_TAG="${{ github.event.inputs.npmjs_dist_tag }}" - if [ -z "$NPM_DIST_TAG" ]; then - NPM_DIST_TAG="latest" + echo "$PKG" + + if [ -z "${NPM_DIST_TAG:-}" ]; then + echo "❌ Primary npm dist-tag is not set." >&2 + exit 1 fi - if [[ "$NPM_DIST_TAG" == "latest" ]] && ! [[ "${{ env.PACKAGE_VERSION }}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "With npmjs_dist_tag 'latest', version must be of the form x.y.z. Found '${{ env.PACKAGE_VERSION }}'." >&2 + + if [[ "${IS_BETA}" != "true" ]] && ! [[ "${PKG_VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Stable releases (tagged with 'latest') must use x.y.z SemVer. Found '${PKG_VERSION}'." >&2 exit 1 fi + npm i -g npm@11.6.0 - npm publish "$PKG" --provenance --access public --registry=https://registry.npmjs.org/ --tag "$NPM_DIST_TAG" + npm publish "${PKG}" --provenance --access public --registry=https://registry.npmjs.org/ --tag "$NPM_DIST_TAG" - name: Ensure Git tag exists id: create_tag run: | set -euo pipefail - TAG="${{ env.PACKAGE_NAME }}@${{ env.PACKAGE_VERSION }}" + TAG="${PKG_NAME}@${PKG_VERSION}" git fetch --tags origin - if git rev-parse "$TAG" >/dev/null 2>&1 ; then - echo "❌ Tag $TAG already exists (not a draft). Failing." + if git rev-parse "${TAG}" >/dev/null 2>&1 ; then + echo "❌ Tag ${TAG} already exists (not a draft). Failing." exit 1 fi - echo "🔖 Tagging $TAG" - git tag -f "$TAG" - git push origin -f "$TAG" + echo "🔖 Tagging ${TAG}" + git tag -f "${TAG}" + git push origin -f "${TAG}" - echo "tag_name=$TAG" >> "$GITHUB_OUTPUT" + echo "tag_name=${TAG}" >> "$GITHUB_OUTPUT" - name: Create GitHub release uses: softprops/action-gh-release@v2 @@ -591,42 +684,92 @@ jobs: name: "${{ steps.create_tag.outputs.tag_name }}" draft: false generate_release_notes: true - prerelease: ${{ github.event.inputs.npmjs_dist_tag != '' && github.event.inputs.npmjs_dist_tag != 'latest' }} - make_latest: ${{ github.event.inputs.npmjs_dist_tag == '' || github.event.inputs.npmjs_dist_tag == 'latest' }} + prerelease: ${{ needs.get_version.outputs.is_beta == 'true' }} + make_latest: ${{ needs.get_version.outputs.is_beta != 'true' }} - name: Notify Slack success (single-line) if: success() env: SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }} - REPO: ${{ github.repository }} - PACKAGE_NAME: ${{ env.PACKAGE_NAME }} - PACKAGE_VERSION: ${{ env.PACKAGE_VERSION }} - TAG: ${{ steps.create_tag.outputs.tag_name }} + REPO: ${{ github.repository }} + TAG: ${{ steps.create_tag.outputs.tag_name }} run: | set -euo pipefail # Build release URL from tag (URL-encoded to handle '@' etc.) - enc_tag="$(printf '%s' "$TAG" | jq -sRr @uri)" - RELEASE_URL="https://github.com/$REPO/releases/tag/$enc_tag" + enc_tag="$(printf '%s' "${TAG}" | jq -sRr @uri)" + RELEASE_URL="https://github.com/${REPO}/releases/tag/${enc_tag}" - text="${PACKAGE_NAME} ${PACKAGE_VERSION} has been succesfully released and published to npm.js. Release URL: ${RELEASE_URL}" + text="${PKG_NAME} ${PKG_VERSION} has been succesfully released and published to npm.js. Release URL: ${RELEASE_URL}" text="${text//\\n/ }" curl -sS -X POST https://slack.com/api/chat.postMessage \ - -H "Authorization: Bearer $SLACK_TOKEN" \ + -H "Authorization: Bearer ${SLACK_TOKEN}" \ -H "Content-Type: application/json; charset=utf-8" \ - -d "$(jq -n --arg channel "#xrpl-js" --arg text "$text" '{channel:$channel, text:$text}')" + -d "$(jq -n --arg channel '#xrpl-js' --arg text "${text}" '{channel:$channel, text:$text}')" - - name: Notify Slack if tests fail - if: failure() + generate-documentation: + name: Generate and Publish documentation for ${{ needs.get_version.outputs.package_version }} + if: ${{ needs.get_version.outputs.is_beta != 'true' }} + uses: ./.github/workflows/generate-documentation.yml + needs: [get_version, release] + permissions: + contents: read + pages: write + id-token: write + with: + git_ref: ${{ needs.get_version.outputs.release_branch }} + + notify_failures: + runs-on: ubuntu-latest + needs: + [ + get_version, + run_faucet_test, + run_tests, + pre_release, + ask_for_dev_team_review, + first_review, + ask_for_sec_team_review, + release, + generate-documentation + ] + if: >- + ${{ always() && ( + needs.get_version.result == 'failure' || + (needs.run_faucet_test.result == 'failure' && needs.get_version.outputs.is_beta != 'true') || + (needs.run_tests.result == 'failure' && needs.get_version.outputs.is_beta != 'true') || + needs.pre_release.result == 'failure' || + needs.ask_for_dev_team_review.result == 'failure' || + needs.first_review.result == 'failure' || + needs.ask_for_sec_team_review.result == 'failure' || + needs.release.result == 'failure' || + needs.generate-documentation.result == 'failure' + ) }} + steps: + - name: Notify Slack about workflow failure env: SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }} + PKG_NAME: ${{ github.event.inputs.package_name }} + PKG_VERSION: ${{ needs.get_version.outputs.package_version }} + NEEDS_JSON: ${{ toJson(needs) }} run: | - MESSAGE="❌ Tests failed for xrpl.js ${{ env.PACKAGE_VERSION }}. Check the logs: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - curl -X POST https://slack.com/api/chat.postMessage \ + set -euo pipefail + FAILED_JOBS=$(printf '%s' "$NEEDS_JSON" | jq -r ' + to_entries + | map(select(.value.result=="failure") | .key) + | join(", ") + ') + if [ -z "$FAILED_JOBS" ]; then + echo "No failed jobs detected; skipping notification." + exit 0 + fi + + MESSAGE="❌ Workflow failure for ${PKG_NAME}@${PKG_VERSION}. Release failed at ${FAILED_JOBS}. For details: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + curl -sS -X POST https://slack.com/api/chat.postMessage \ -H "Authorization: Bearer $SLACK_TOKEN" \ -H "Content-Type: application/json" \ -d "$(jq -n \ - --arg channel "#xrpl-js" \ - --arg text "$MESSAGE" \ + --arg channel '#xrpl-js' \ + --arg text "${MESSAGE}" \ '{channel: $channel, text: $text}')" diff --git a/.prettierignore b/.prettierignore index dd449725e1..dd767b8e97 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1 +1,3 @@ *.md + +/.nx/workspace-data \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6bda0fb2b2..6d4917ce73 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -64,7 +64,7 @@ From the top-level xrpl.js folder (one level above `packages`), run the followin ```bash npm install # sets up the rippled standalone Docker container - you can skip this step if you already have it set up -docker run -p 6006:6006 --rm -it --name rippled_standalone --volume $PWD/.ci-config:/etc/opt/ripple/ --entrypoint bash rippleci/rippled:develop -c 'rippled -a' +docker run -p 6006:6006 --rm -it --name rippled_standalone --volume $PWD/.ci-config:/etc/opt/ripple/ --entrypoint bash rippleci/rippled:develop -c 'mkdir -p /var/lib/rippled/db/ && rippled -a' npm run build npm run test:integration ``` @@ -241,7 +241,6 @@ Note: The same updated config can be used to update xrpl-py's CI as well. - [ ] Update the version number and release date, and ensure it lists the changes since the previous release. -4. Run `npm run docgen` if the docs were modified in this release to update them (skip this step for a beta). 5. Run `npm run clean` to delete previously generated artifacts. 6. Run `npm run build` to triple check the build still works 7. Run `npx lerna version --no-git-tag-version` - This bumps the package versions. @@ -265,6 +264,7 @@ Note: The same updated config can be used to update xrpl-py's CI as well. 13. Run `git tag -m `, where `` is the new package and version (e.g. `xrpl@2.1.1`), for each version released. 14. Run `git push --follow-tags`, to push the tags to Github. + 15. On GitHub, click the "Releases" link on the right-hand side of the page. 16. Repeat for each release: diff --git a/README.md b/README.md index 17a3c299de..9148cab4fc 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ You are also welcome to create an [issue](https://github.com/XRPLF/xrpl.js/issue - [xrpl.js Reference Docs](https://js.xrpl.org/) - [xrpl.org (Detailed docs on how the XRPL works)](https://xrpl.org/references.html) -- [XRPL Code Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples) +- [XRPL Code Samples](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples) - [#javascript in the XRPL Developer Discord for questions & support](https://xrpldevs.org) - [xrpl-announce (The mailing list for new xrpl.js versions)](https://groups.google.com/g/xrpl-announce) - [Applications that use xrpl.js](https://github.com/XRPLF/xrpl.js/blob/main/APPLICATIONS.md) (You can open a PR to add your project!) diff --git a/RELEASE.md b/RELEASE.md index 5a40eadde3..7c1c09e878 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -10,39 +10,53 @@ You can manually trigger the release workflow from the [GitHub Actions UI](https ### **Before triggering a release** -1. Create a release branch and update the **`version`** field in `packages//package.json` to the intended release version. +**Stable release ** +1. Create a release branch. A qualified branch name should start with "release-" or "release/", **case-insensitive**. e.g: `release/xrpl@4.3.8`, `release-xrpl-4.3.8`, `Release/xrpl@4.3.8`. +2. Update the **`version`** field in `packages//package.json` to the intended release version. ```json { "name": "", "version": "x.y.z" } ``` -2. Run npm i to update the package-lock with the updated versions and commit the lock file to the releaes branch +3. Run npm i to refresh package-lock.json and commit it. + +**Beta release ** +1. Create a release branch. There is no restriction for branch name. +2. Update the **`version`** field in `packages//package.json` to the intended beta release version. + ```json + { + "name": "", + "version": "x.y.z-.a" + } + ``` +3. Run `npm i` to refresh `package-lock.json` and commit it. ### **Triggering a Release** -1. Go to **GitHub → Actions → Release Pipeline → Run workflow** -2. Fill in these fields: - - **package_name** → The folder name under `packages/`, e.g., `xrpl` or `ripple-address-codec`. - - **release_branch** → The Git branch the release is generated from, e.g., `release/xrpl@4.3.8`. - - **npmjs_dist_tag** → The npm distribution tag to publish under. Defaults to `latest`. - - Examples: - - `latest` → Standard production release - - `beta` → Pre-release for testing - - `rc` → Release candidate +1. Go to **GitHub → Actions → Release Pipeline → Run workflow** (must be triggered from `main`). + +2. Triggering the workflow with following requied inputs: + + - **Stable release** + - `release_branch_name`: e.g., `release/xrpl@4.3.8` or `release-xrpl-4.3.8` (must start with `release-`/`release/`, **case-insensitive**). + - `package_name`: e.g., `xrpl`. + - `npmjs_dist_tag`: `latest`. -➡️ Example: + Example: `release_branch_name=release/xrpl@4.3.8`, `package_name=xrpl`, `npmjs_dist_tag=latest`. -| Field | Example | -|------------------|-----------------------| -| package_name | xrpl | -| release_branch | release/xrpl@4.3.8 | -| npmjs_dist_tag | latest | + - **Beta release** (publishes as `-experimental`) + - `release_branch_name`: e.g., `feature/xrpl-beta` (no naming restriction). + - `package_name`: e.g., `xrpl`. + - `npmjs_dist_tag`: a non-`latest` tag like `beta` or `rc` (must match `[a-z][a-z0-9._-]{0,127}` and not start with `v` + digit or a digit). + Example: `release_branch_name=feature/xrpl-beta`, `package_name=xrpl`, `npmjs_dist_tag=feature-a` (will be published as `feature-a-experimental`, `-experimental` will be automatically appended by the workflow). + +3. For stable release, after `Pre Release Pipeline` has been executed, update the PR automatically created by the release pipeline (release branch → main branch) from Draft to Ready for Review, and ensure all CI tests have passed. ### **Reviewing the release details and scan result** -1. The pipeline will pause at the "Review test and security scan result" step, at least 2 approvers are required to review and approve the release. +The pipeline will pause at the "Print Test/Security scan result and invite Dev team to review" step and also before the final release step, relevant team should review the release details and scan result. Stable release will be reviewed by infosec team as Sec reviewer. Beta release will be reviewed by security champions from Dev team. --- @@ -51,13 +65,13 @@ You can manually trigger the release workflow from the [GitHub Actions UI](https ### 1. **Get Package Version** - Extracts the version from `packages//package.json`. -- No manual version input is required. +- Validate inputs. --- ### 2. **Run Tests** -- Triggers the `faucet_test.yml` and `nodejs.yml` workflows to run unit, integration, and faucet tests against the specified Git ref. -- Ensures the code at the given Git ref passes all tests. +- Triggers the `faucet_test.yml` and `nodejs.yml` workflows to run unit, integration, and faucet tests against the specified Git ref. Integration and taucet tests are skipped for beta release. +- Ensures the code at the given Git ref passes required tests. --- @@ -69,6 +83,7 @@ You can manually trigger the release workflow from the [GitHub Actions UI](https - Packages the module with Lerna and uploads the tarball as an artifact. - Posts failure notifications to Slack.. - Create a Github issue for detected vulnerabilities. +- Automatically raise a PR from relase branch to main branch for stable release --- @@ -109,3 +124,5 @@ xrpl@2.3.1 - The release workflow does not overwrite existing tags. If the same version tag already exists, the workflow will fail. - Vulnerability scanning does not block the release, but it is the approvers' responsibility to review the scan results in the Review stage. + +- For stable release, after `Pre Release Pipeline` has been executed, update the PR automatically created by the release pipeline (release branch → main branch) from Draft to Ready for Review, and ensure all CI tests have passed. diff --git a/UNIQUE_SETUPS.md b/UNIQUE_SETUPS.md index c64ecd8250..5333e92386 100644 --- a/UNIQUE_SETUPS.md +++ b/UNIQUE_SETUPS.md @@ -56,26 +56,3 @@ import './polyfills' ### Using xrpl.js with Vite React Starting in 3.0 xrpl and all the packages in this repo no longer require custom configurations (ex. polyfills) to run. - -### Using xrpl.js with Deno - -Until official support for [Deno](https://deno.land) is added, you can use the following work-around to use `xrpl.js` with Deno: - -> [!NOTE] -> The following is currently broken due to https://github.com/denoland/deno/issues/20516. -> Once that is fixed there could be other issues as well. - -```javascript -import xrpl from 'https://dev.jspm.io/npm:xrpl'; - -(async () => { - const api = new (xrpl as any).Client('wss://s.altnet.rippletest.net:51233'); - const address = 'rH8NxV12EuV...khfJ5uw9kT'; - - api.connect().then(() => { - api.getBalances(address).then((balances: any) => { - console.log(JSON.stringify(balances, null, 2)); - }); - }); -})(); -``` diff --git a/jest.config.base.js b/jest.config.base.js index 4665c96bb7..21d202494b 100644 --- a/jest.config.base.js +++ b/jest.config.base.js @@ -4,7 +4,11 @@ module.exports = { roots: ["/src"], transform: { "^.+\\.ts$": "ts-jest", + "node_modules/chai/.+\\.js$": "ts-jest", }, + transformIgnorePatterns: [ + "/node_modules/(?!(chai)/)", + ], moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], collectCoverage: true, verbose: true, diff --git a/lerna.json b/lerna.json index dd76c3fa77..e127f42786 100644 --- a/lerna.json +++ b/lerna.json @@ -1,10 +1,13 @@ { "version": "independent", - "useWorkspaces": true, + "packages": [ + "packages/xrpl", + "packages/ripple-binary-codec", + "packages/ripple-keypairs", + "packages/ripple-address-codec", + "packages/isomorphic", + "packages/secret-numbers" + ], "npmClient": "npm", - "command": { - "publish": { - "access": "public" - } - } + "$schema": "node_modules/lerna/schemas/lerna-schema.json" } diff --git a/package-lock.json b/package-lock.json index 20c20c47bc..bc013f1bc0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,24 +24,24 @@ "@types/lodash": "^4.14.136", "@types/node": "^18.19.29", "@types/ws": "^8.2.0", - "@xrplf/eslint-config": "^2.0.0", + "@xrplf/eslint-config": "^3.0.0", "@xrplf/prettier-config": "^1.9.1", - "chai": "^4.3.4", + "chai": "^6.2.2", "copyfiles": "^2.4.1", "eslint": "^9.32.0", "eslint-config-prettier": "^10.1.8", "eslint-import-resolver-typescript": "^4.4.4", - "eslint-plugin-array-func": "^4.0.0", + "eslint-plugin-array-func": "^5.0.0", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsdoc": "^52.0.4", "eslint-plugin-n": "^17.21.3", "eslint-plugin-prettier": "^5.5.4", - "eslint-plugin-tsdoc": "^0.4.0", - "expect": "^29.3.1", + "eslint-plugin-tsdoc": "^0.5.0", + "expect": "^30.2.0", "globals": "^16.3.0", "jest": "^29.3.1", - "jest-mock": "^29.3.1", - "lerna": "^4.0.0", + "jest-mock": "^30.2.0", + "lerna": "^9.0.4", "lodash": "^4.17.21", "npm-run-all": "^4.1.5", "prettier": "^3.6.2", @@ -52,9 +52,9 @@ "ts-loader": "^9.2.5", "ts-node": "^10.2.1", "typescript": "^5.1.6", - "typescript-eslint": "^8.39.0", + "typescript-eslint": "^8.52.0", "webpack": "^5.81.0", - "webpack-bundle-analyzer": "^4.1.0", + "webpack-bundle-analyzer": "^5.1.1", "webpack-cli": "^6.0.1" }, "engines": { @@ -552,6 +552,37 @@ "node": ">=10.0.0" } }, + "node_modules/@emnapi/core": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz", + "integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", + "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@es-joy/jsdoccomment": { "version": "0.52.0", "dev": true, @@ -586,9 +617,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -605,7 +636,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", "engines": { @@ -613,11 +646,13 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.21.0", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.6", + "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -627,6 +662,8 @@ }, "node_modules/@eslint/config-array/node_modules/brace-expansion": { "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -636,6 +673,8 @@ }, "node_modules/@eslint/config-array/node_modules/minimatch": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", "dependencies": { @@ -646,19 +685,22 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", - "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/core": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", - "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -722,9 +764,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.35.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.35.0.tgz", - "integrity": "sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw==", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", "dev": true, "license": "MIT", "engines": { @@ -735,7 +777,9 @@ } }, "node_modules/@eslint/object-schema": { - "version": "2.1.6", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -743,33 +787,30 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", - "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.15.2", + "@eslint/core": "^0.17.0", "levn": "^0.4.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "dev": true, - "license": "MIT" - }, "node_modules/@gerrit0/mini-shiki": { - "version": "3.9.2", + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.19.0.tgz", + "integrity": "sha512-ZSlWfLvr8Nl0T4iA3FF/8VH8HivYF82xQts2DY0tJxZd4wtXJ8AA0nmdW9lmO4hlrh3f9xNwEPtOgqETPqKwDA==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/engine-oniguruma": "^3.9.2", - "@shikijs/langs": "^3.9.2", - "@shikijs/themes": "^3.9.2", - "@shikijs/types": "^3.9.2", + "@shikijs/engine-oniguruma": "^3.19.0", + "@shikijs/langs": "^3.19.0", + "@shikijs/themes": "^3.19.0", + "@shikijs/types": "^3.19.0", "@shikijs/vscode-textmate": "^10.0.2" } }, @@ -831,231 +872,745 @@ }, "node_modules/@hutson/parse-repository-url": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", + "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", "dev": true, "license": "Apache-2.0", "engines": { "node": ">=6.9.0" } }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", + "node_modules/@inquirer/ansi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", + "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", + "node_modules/@inquirer/checkbox": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.2.tgz", + "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==", "dev": true, "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", + "node_modules/@inquirer/confirm": { + "version": "5.1.21", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", + "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", + "node_modules/@inquirer/core": { + "version": "10.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", + "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "@inquirer/ansi": "^1.0.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.3" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", + "node_modules/@inquirer/editor": { + "version": "4.2.23", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.23.tgz", + "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==", "dev": true, "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "@inquirer/core": "^10.3.2", + "@inquirer/external-editor": "^1.0.3", + "@inquirer/type": "^3.0.10" }, "engines": { - "node": ">=6" + "node": ">=18" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", + "node_modules/@inquirer/expand": { + "version": "4.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.23.tgz", + "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==", "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", + "node_modules/@inquirer/external-editor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", + "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", "dev": true, "license": "MIT", + "dependencies": { + "chardet": "^2.1.1", + "iconv-lite": "^0.7.0" + }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { - "version": "1.0.3", + "node_modules/@inquirer/external-editor/node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", "dev": true, - "license": "BSD-3-Clause" + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", + "node_modules/@inquirer/figures": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", + "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/@jest/console": { - "version": "29.7.0", + "node_modules/@inquirer/input": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.3.1.tgz", + "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@jest/core": { - "version": "29.7.0", + "node_modules/@inquirer/number": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.23.tgz", + "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" }, "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "@types/node": ">=18" }, "peerDependenciesMeta": { - "node-notifier": { + "@types/node": { "optional": true } } }, - "node_modules/@jest/environment": { - "version": "29.7.0", + "node_modules/@inquirer/password": { + "version": "4.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.23.tgz", + "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@jest/expect": { - "version": "29.7.0", + "node_modules/@inquirer/prompts": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.10.1.tgz", + "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", "dev": true, "license": "MIT", "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" + "@inquirer/checkbox": "^4.3.2", + "@inquirer/confirm": "^5.1.21", + "@inquirer/editor": "^4.2.23", + "@inquirer/expand": "^4.0.23", + "@inquirer/input": "^4.3.1", + "@inquirer/number": "^3.0.23", + "@inquirer/password": "^4.0.23", + "@inquirer/rawlist": "^4.1.11", + "@inquirer/search": "^3.2.2", + "@inquirer/select": "^4.4.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", + "node_modules/@inquirer/rawlist": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.11.tgz", + "integrity": "sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==", "dev": true, "license": "MIT", "dependencies": { - "jest-get-type": "^29.6.3" + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", + "node_modules/@inquirer/search": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.2.tgz", + "integrity": "sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", + "@inquirer/core": "^10.3.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/select": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.2.tgz", + "integrity": "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz", + "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.1.tgz", + "integrity": "sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/cliui": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz", + "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@isaacs/string-locale-compare": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz", + "integrity": "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/diff-sequences": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", + "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/environment/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect/node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/get-type": { + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz", + "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, "node_modules/@jest/globals": { "version": "29.7.0", "dev": true, @@ -1070,6 +1625,45 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/globals/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/pattern": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", + "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-regex-util": "30.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/pattern/node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, "node_modules/@jest/reporters": { "version": "29.7.0", "dev": true, @@ -1223,7 +1817,9 @@ } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.10", + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "dev": true, "license": "MIT", "dependencies": { @@ -1245,184 +1841,272 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@lerna/add": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@lerna/bootstrap": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/filter-options": "4.0.0", - "@lerna/npm-conf": "4.0.0", - "@lerna/validation-error": "4.0.0", - "dedent": "^0.7.0", - "npm-package-arg": "^8.1.0", - "p-map": "^4.0.0", - "pacote": "^11.2.6", - "semver": "^7.3.4" + "node_modules/@lerna/create": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@lerna/create/-/create-9.0.4.tgz", + "integrity": "sha512-WxedGD98G8/a6HztCXNWquaM0x17oSvfvuqDsLxNNX1qXGyrzmMUmd1mQikF/47uy80X6qyWdaRtaAHlwkvEUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@npmcli/arborist": "9.1.6", + "@npmcli/package-json": "7.0.2", + "@npmcli/run-script": "10.0.3", + "@nx/devkit": ">=21.5.2 < 23.0.0", + "@octokit/plugin-enterprise-rest": "6.0.1", + "@octokit/rest": "20.1.2", + "aproba": "2.0.0", + "byte-size": "8.1.1", + "chalk": "4.1.0", + "cmd-shim": "6.0.3", + "color-support": "1.1.3", + "columnify": "1.6.0", + "console-control-strings": "^1.1.0", + "conventional-changelog-core": "5.0.1", + "conventional-recommended-bump": "7.0.1", + "cosmiconfig": "9.0.0", + "dedent": "1.5.3", + "execa": "5.0.0", + "fs-extra": "^11.2.0", + "get-stream": "6.0.0", + "git-url-parse": "14.0.0", + "glob-parent": "6.0.2", + "has-unicode": "2.0.1", + "ini": "^1.3.8", + "init-package-json": "8.2.2", + "inquirer": "12.9.6", + "is-ci": "3.0.1", + "is-stream": "2.0.0", + "js-yaml": "4.1.1", + "libnpmpublish": "11.1.2", + "load-json-file": "6.2.0", + "make-dir": "4.0.0", + "make-fetch-happen": "15.0.2", + "minimatch": "3.0.5", + "multimatch": "5.0.0", + "npm-package-arg": "13.0.1", + "npm-packlist": "10.0.3", + "npm-registry-fetch": "19.1.0", + "nx": ">=21.5.3 < 23.0.0", + "p-map": "4.0.0", + "p-map-series": "2.1.0", + "p-queue": "6.6.2", + "p-reduce": "^2.1.0", + "pacote": "21.0.1", + "pify": "5.0.0", + "read-cmd-shim": "4.0.0", + "resolve-from": "5.0.0", + "rimraf": "^6.1.2", + "semver": "7.7.2", + "set-blocking": "^2.0.0", + "signal-exit": "3.0.7", + "slash": "^3.0.0", + "ssri": "12.0.0", + "string-width": "^4.2.3", + "tar": "7.5.7", + "temp-dir": "1.0.0", + "through": "2.3.8", + "tinyglobby": "0.2.12", + "upath": "2.0.1", + "uuid": "^11.1.0", + "validate-npm-package-license": "3.0.4", + "validate-npm-package-name": "6.0.2", + "wide-align": "1.1.5", + "write-file-atomic": "5.0.1", + "write-pkg": "4.0.0", + "yargs": "17.7.2", + "yargs-parser": "21.1.1" }, "engines": { - "node": ">= 10.18.0" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, - "node_modules/@lerna/add/node_modules/dedent": { - "version": "0.7.0", + "node_modules/@lerna/create/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, - "node_modules/@lerna/bootstrap": { - "version": "4.0.0", + "node_modules/@lerna/create/node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "dev": true, "license": "MIT", "dependencies": { - "@lerna/command": "4.0.0", - "@lerna/filter-options": "4.0.0", - "@lerna/has-npm-version": "4.0.0", - "@lerna/npm-install": "4.0.0", - "@lerna/package-graph": "4.0.0", - "@lerna/pulse-till-done": "4.0.0", - "@lerna/rimraf-dir": "4.0.0", - "@lerna/run-lifecycle": "4.0.0", - "@lerna/run-topologically": "4.0.0", - "@lerna/symlink-binary": "4.0.0", - "@lerna/symlink-dependencies": "4.0.0", - "@lerna/validation-error": "4.0.0", - "dedent": "^0.7.0", - "get-port": "^5.1.1", - "multimatch": "^5.0.0", - "npm-package-arg": "^8.1.0", - "npmlog": "^4.1.2", - "p-map": "^4.0.0", - "p-map-series": "^2.1.0", - "p-waterfall": "^2.1.1", - "read-package-tree": "^5.3.1", - "semver": "^7.3.4" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 10.18.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@lerna/bootstrap/node_modules/dedent": { - "version": "0.7.0", + "node_modules/@lerna/create/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, - "license": "MIT" + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } }, - "node_modules/@lerna/changed": { - "version": "4.0.0", + "node_modules/@lerna/create/node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/@lerna/create/node_modules/execa": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", + "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", "dev": true, "license": "MIT", "dependencies": { - "@lerna/collect-updates": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/listable": "4.0.0", - "@lerna/output": "4.0.0" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">= 10.18.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/@lerna/check-working-tree": { - "version": "4.0.0", + "node_modules/@lerna/create/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", - "dependencies": { - "@lerna/collect-uncommitted": "4.0.0", - "@lerna/describe-ref": "4.0.0", - "@lerna/validation-error": "4.0.0" + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" }, - "engines": { - "node": ">= 10.18.0" + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/@lerna/child-process": { - "version": "4.0.0", + "node_modules/@lerna/create/node_modules/get-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", + "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", "dev": true, "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "execa": "^5.0.0", - "strong-log-transformer": "^2.1.0" - }, "engines": { - "node": ">= 10.18.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@lerna/clean": { - "version": "4.0.0", + "node_modules/@lerna/create/node_modules/glob": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.5.tgz", + "integrity": "sha512-BzXxZg24Ibra1pbQ/zE7Kys4Ua1ks7Bn6pKLkVPZ9FZe4JQS6/Q7ef3LG1H+k7lUf5l4T3PLSyYyYJVYUvfgTw==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "@lerna/command": "4.0.0", - "@lerna/filter-options": "4.0.0", - "@lerna/prompt": "4.0.0", - "@lerna/pulse-till-done": "4.0.0", - "@lerna/rimraf-dir": "4.0.0", - "p-map": "^4.0.0", - "p-map-series": "^2.1.0", - "p-waterfall": "^2.1.1" + "minimatch": "^10.2.1", + "minipass": "^7.1.2", + "path-scurry": "^2.0.0" }, "engines": { - "node": ">= 10.18.0" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@lerna/cli": { - "version": "4.0.0", + "node_modules/@lerna/create/node_modules/glob/node_modules/balanced-match": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.2.tgz", + "integrity": "sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==", "dev": true, "license": "MIT", "dependencies": { - "@lerna/global-options": "4.0.0", - "dedent": "^0.7.0", - "npmlog": "^4.1.2", - "yargs": "^16.2.0" + "jackspeak": "^4.2.3" }, "engines": { - "node": ">= 10.18.0" + "node": "20 || >=22" } }, - "node_modules/@lerna/cli/node_modules/dedent": { - "version": "0.7.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@lerna/collect-uncommitted": { - "version": "4.0.0", + "node_modules/@lerna/create/node_modules/glob/node_modules/brace-expansion": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", + "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", "dev": true, "license": "MIT", "dependencies": { - "@lerna/child-process": "4.0.0", - "chalk": "^4.1.0", - "npmlog": "^4.1.2" + "balanced-match": "^4.0.2" }, "engines": { - "node": ">= 10.18.0" + "node": "20 || >=22" } }, - "node_modules/@lerna/collect-updates": { - "version": "4.0.0", + "node_modules/@lerna/create/node_modules/glob/node_modules/minimatch": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.1.tgz", + "integrity": "sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "@lerna/child-process": "4.0.0", - "@lerna/describe-ref": "4.0.0", - "minimatch": "^3.0.4", - "npmlog": "^4.1.2", - "slash": "^3.0.0" + "brace-expansion": "^5.0.2" }, "engines": { - "node": ">= 10.18.0" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@lerna/collect-updates/node_modules/brace-expansion": { - "version": "1.1.12", + "node_modules/@lerna/create/node_modules/is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">=8" } }, - "node_modules/@lerna/collect-updates/node_modules/minimatch": { - "version": "3.1.2", + "node_modules/@lerna/create/node_modules/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", "dev": true, "license": "ISC", "dependencies": { @@ -1432,1196 +2116,1323 @@ "node": "*" } }, - "node_modules/@lerna/command": { - "version": "4.0.0", + "node_modules/@lerna/create/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "dependencies": { - "@lerna/child-process": "4.0.0", - "@lerna/package-graph": "4.0.0", - "@lerna/project": "4.0.0", - "@lerna/validation-error": "4.0.0", - "@lerna/write-log-file": "4.0.0", - "clone-deep": "^4.0.1", - "dedent": "^0.7.0", - "execa": "^5.0.0", - "is-ci": "^2.0.0", - "npmlog": "^4.1.2" - }, "engines": { - "node": ">= 10.18.0" - } - }, - "node_modules/@lerna/command/node_modules/dedent": { - "version": "0.7.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@lerna/conventional-commits": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@lerna/validation-error": "4.0.0", - "conventional-changelog-angular": "^5.0.12", - "conventional-changelog-core": "^4.2.2", - "conventional-recommended-bump": "^6.1.0", - "fs-extra": "^9.1.0", - "get-stream": "^6.0.0", - "lodash.template": "^4.5.0", - "npm-package-arg": "^8.1.0", - "npmlog": "^4.1.2", - "pify": "^5.0.0", - "semver": "^7.3.4" + "node": ">=12" }, - "engines": { - "node": ">= 10.18.0" + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/@lerna/create": { - "version": "4.0.0", + "node_modules/@lerna/create/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "license": "MIT", - "dependencies": { - "@lerna/child-process": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/npm-conf": "4.0.0", - "@lerna/validation-error": "4.0.0", - "dedent": "^0.7.0", - "fs-extra": "^9.1.0", - "globby": "^11.0.2", - "init-package-json": "^2.0.2", - "npm-package-arg": "^8.1.0", - "p-reduce": "^2.1.0", - "pacote": "^11.2.6", - "pify": "^5.0.0", - "semver": "^7.3.4", - "slash": "^3.0.0", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^3.0.0", - "whatwg-url": "^8.4.0", - "yargs-parser": "20.2.4" - }, "engines": { - "node": ">= 10.18.0" + "node": ">=8" } }, - "node_modules/@lerna/create-symlink": { - "version": "4.0.0", + "node_modules/@lerna/create/node_modules/rimraf": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", + "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "cmd-shim": "^4.1.0", - "fs-extra": "^9.1.0", - "npmlog": "^4.1.2" + "glob": "^13.0.3", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" }, "engines": { - "node": ">= 10.18.0" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@lerna/create/node_modules/dedent": { - "version": "0.7.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@lerna/describe-ref": { - "version": "4.0.0", + "node_modules/@lerna/create/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, - "license": "MIT", - "dependencies": { - "@lerna/child-process": "4.0.0", - "npmlog": "^4.1.2" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">= 10.18.0" + "node": ">=10" } }, - "node_modules/@lerna/diff": { - "version": "4.0.0", + "node_modules/@lerna/create/node_modules/tinyglobby": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", + "integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==", "dev": true, "license": "MIT", "dependencies": { - "@lerna/child-process": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/validation-error": "4.0.0", - "npmlog": "^4.1.2" + "fdir": "^6.4.3", + "picomatch": "^4.0.2" }, "engines": { - "node": ">= 10.18.0" + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/@lerna/exec": { - "version": "4.0.0", + "node_modules/@lerna/create/node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@lerna/child-process": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/filter-options": "4.0.0", - "@lerna/profiler": "4.0.0", - "@lerna/run-topologically": "4.0.0", - "@lerna/validation-error": "4.0.0", - "p-map": "^4.0.0" + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">= 10.18.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@lerna/filter-options": { - "version": "4.0.0", + "node_modules/@lerna/create/node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "license": "MIT", - "dependencies": { - "@lerna/collect-updates": "4.0.0", - "@lerna/filter-packages": "4.0.0", - "dedent": "^0.7.0", - "npmlog": "^4.1.2" - }, + "license": "ISC", "engines": { - "node": ">= 10.18.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@lerna/filter-options/node_modules/dedent": { - "version": "0.7.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@lerna/filter-packages": { - "version": "4.0.0", + "node_modules/@lerna/create/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "license": "MIT", "dependencies": { - "@lerna/validation-error": "4.0.0", - "multimatch": "^5.0.0", - "npmlog": "^4.1.2" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">= 10.18.0" + "node": ">=12" } }, - "node_modules/@lerna/get-npm-exec-opts": { - "version": "4.0.0", + "node_modules/@lerna/create/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, - "license": "MIT", - "dependencies": { - "npmlog": "^4.1.2" - }, + "license": "ISC", "engines": { - "node": ">= 10.18.0" + "node": ">=12" } }, - "node_modules/@lerna/get-packed": { - "version": "4.0.0", + "node_modules/@microsoft/tsdoc": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.16.0.tgz", + "integrity": "sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==", "dev": true, - "license": "MIT", - "dependencies": { - "fs-extra": "^9.1.0", - "ssri": "^8.0.1", - "tar": "^6.1.0" - }, - "engines": { - "node": ">= 10.18.0" - } + "license": "MIT" }, - "node_modules/@lerna/github-client": { - "version": "4.0.0", + "node_modules/@microsoft/tsdoc-config": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.18.0.tgz", + "integrity": "sha512-8N/vClYyfOH+l4fLkkr9+myAoR6M7akc8ntBJ4DJdWH2b09uVfr71+LTMpNyG19fNqWDg8KEDZhx5wxuqHyGjw==", "dev": true, "license": "MIT", "dependencies": { - "@lerna/child-process": "4.0.0", - "@octokit/plugin-enterprise-rest": "^6.0.1", - "@octokit/rest": "^18.1.0", - "git-url-parse": "^11.4.4", - "npmlog": "^4.1.2" - }, - "engines": { - "node": ">= 10.18.0" + "@microsoft/tsdoc": "0.16.0", + "ajv": "~8.12.0", + "jju": "~1.4.0", + "resolve": "~1.22.2" } }, - "node_modules/@lerna/gitlab-client": { - "version": "4.0.0", + "node_modules/@microsoft/tsdoc-config/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, "license": "MIT", "dependencies": { - "node-fetch": "^2.6.1", - "npmlog": "^4.1.2", - "whatwg-url": "^8.4.0" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">= 10.18.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@lerna/global-options": { - "version": "4.0.0", + "node_modules/@microsoft/tsdoc-config/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.18.0" - } + "license": "MIT" }, - "node_modules/@lerna/has-npm-version": { - "version": "4.0.0", + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "@lerna/child-process": "4.0.0", - "semver": "^7.3.4" - }, - "engines": { - "node": ">= 10.18.0" + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" } }, - "node_modules/@lerna/import": { - "version": "4.0.0", - "dev": true, + "node_modules/@noble/curves": { + "version": "1.8.1", "license": "MIT", "dependencies": { - "@lerna/child-process": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/prompt": "4.0.0", - "@lerna/pulse-till-done": "4.0.0", - "@lerna/validation-error": "4.0.0", - "dedent": "^0.7.0", - "fs-extra": "^9.1.0", - "p-map-series": "^2.1.0" + "@noble/hashes": "1.7.1" }, "engines": { - "node": ">= 10.18.0" + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@lerna/import/node_modules/dedent": { - "version": "0.7.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@lerna/info": { - "version": "4.0.0", - "dev": true, + "node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.7.1", "license": "MIT", - "dependencies": { - "@lerna/command": "4.0.0", - "@lerna/output": "4.0.0", - "envinfo": "^7.7.4" - }, "engines": { - "node": ">= 10.18.0" + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@lerna/init": { - "version": "4.0.0", - "dev": true, + "node_modules/@noble/hashes": { + "version": "1.8.0", "license": "MIT", - "dependencies": { - "@lerna/child-process": "4.0.0", - "@lerna/command": "4.0.0", - "fs-extra": "^9.1.0", - "p-map": "^4.0.0", - "write-json-file": "^4.3.0" - }, "engines": { - "node": ">= 10.18.0" + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@lerna/link": { - "version": "4.0.0", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "license": "MIT", "dependencies": { - "@lerna/command": "4.0.0", - "@lerna/package-graph": "4.0.0", - "@lerna/symlink-dependencies": "4.0.0", - "p-map": "^4.0.0", - "slash": "^3.0.0" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">= 10.18.0" + "node": ">= 8" } }, - "node_modules/@lerna/list": { - "version": "4.0.0", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, "license": "MIT", - "dependencies": { - "@lerna/command": "4.0.0", - "@lerna/filter-options": "4.0.0", - "@lerna/listable": "4.0.0", - "@lerna/output": "4.0.0" - }, "engines": { - "node": ">= 10.18.0" + "node": ">= 8" } }, - "node_modules/@lerna/listable": { - "version": "4.0.0", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "license": "MIT", "dependencies": { - "@lerna/query-graph": "4.0.0", - "chalk": "^4.1.0", - "columnify": "^1.5.4" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": ">= 10.18.0" + "node": ">= 8" } }, - "node_modules/@lerna/log-packed": { + "node_modules/@npmcli/agent": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-4.0.0.tgz", + "integrity": "sha512-kAQTcEN9E8ERLVg5AsGwLNoFb+oEG6engbqAU2P43gD4JEIkNGMHdVQ096FsOAAYpZPB0RSt0zgInKIAS1l5QA==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "byte-size": "^7.0.0", - "columnify": "^1.5.4", - "has-unicode": "^2.0.1", - "npmlog": "^4.1.2" + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^11.2.1", + "socks-proxy-agent": "^8.0.3" }, "engines": { - "node": ">= 10.18.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@lerna/npm-conf": { - "version": "4.0.0", + "node_modules/@npmcli/agent/node_modules/lru-cache": { + "version": "11.2.6", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", + "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", "dev": true, - "license": "MIT", - "dependencies": { - "config-chain": "^1.1.12", - "pify": "^5.0.0" - }, + "license": "BlueOak-1.0.0", "engines": { - "node": ">= 10.18.0" + "node": "20 || >=22" } }, - "node_modules/@lerna/npm-dist-tag": { - "version": "4.0.0", + "node_modules/@npmcli/arborist": { + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-9.1.6.tgz", + "integrity": "sha512-c5Pr3EG8UP5ollkJy2x+UdEQC5sEHe3H9whYn6hb2HJimAKS4zmoJkx5acCiR/g4P38RnCSMlsYQyyHnKYeLvQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@lerna/otplease": "4.0.0", - "npm-package-arg": "^8.1.0", - "npm-registry-fetch": "^9.0.0", - "npmlog": "^4.1.2" + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/fs": "^4.0.0", + "@npmcli/installed-package-contents": "^3.0.0", + "@npmcli/map-workspaces": "^5.0.0", + "@npmcli/metavuln-calculator": "^9.0.2", + "@npmcli/name-from-folder": "^3.0.0", + "@npmcli/node-gyp": "^4.0.0", + "@npmcli/package-json": "^7.0.0", + "@npmcli/query": "^4.0.0", + "@npmcli/redact": "^3.0.0", + "@npmcli/run-script": "^10.0.0", + "bin-links": "^5.0.0", + "cacache": "^20.0.1", + "common-ancestor-path": "^1.0.1", + "hosted-git-info": "^9.0.0", + "json-stringify-nice": "^1.1.4", + "lru-cache": "^11.2.1", + "minimatch": "^10.0.3", + "nopt": "^8.0.0", + "npm-install-checks": "^7.1.0", + "npm-package-arg": "^13.0.0", + "npm-pick-manifest": "^11.0.1", + "npm-registry-fetch": "^19.0.0", + "pacote": "^21.0.2", + "parse-conflict-json": "^4.0.0", + "proc-log": "^5.0.0", + "proggy": "^3.0.0", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^3.0.1", + "semver": "^7.3.7", + "ssri": "^12.0.0", + "treeverse": "^3.0.0", + "walk-up-path": "^4.0.0" + }, + "bin": { + "arborist": "bin/index.js" }, "engines": { - "node": ">= 10.18.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@lerna/npm-install": { - "version": "4.0.0", + "node_modules/@npmcli/arborist/node_modules/balanced-match": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.2.tgz", + "integrity": "sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==", "dev": true, "license": "MIT", "dependencies": { - "@lerna/child-process": "4.0.0", - "@lerna/get-npm-exec-opts": "4.0.0", - "fs-extra": "^9.1.0", - "npm-package-arg": "^8.1.0", - "npmlog": "^4.1.2", - "signal-exit": "^3.0.3", - "write-pkg": "^4.0.0" + "jackspeak": "^4.2.3" }, "engines": { - "node": ">= 10.18.0" + "node": "20 || >=22" } }, - "node_modules/@lerna/npm-publish": { - "version": "4.0.0", + "node_modules/@npmcli/arborist/node_modules/brace-expansion": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", + "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", "dev": true, "license": "MIT", "dependencies": { - "@lerna/otplease": "4.0.0", - "@lerna/run-lifecycle": "4.0.0", - "fs-extra": "^9.1.0", - "libnpmpublish": "^4.0.0", - "npm-package-arg": "^8.1.0", - "npmlog": "^4.1.2", - "pify": "^5.0.0", - "read-package-json": "^3.0.0" + "balanced-match": "^4.0.2" }, "engines": { - "node": ">= 10.18.0" + "node": "20 || >=22" } }, - "node_modules/@lerna/npm-run-script": { - "version": "4.0.0", + "node_modules/@npmcli/arborist/node_modules/lru-cache": { + "version": "11.2.6", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", + "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", "dev": true, - "license": "MIT", - "dependencies": { - "@lerna/child-process": "4.0.0", - "@lerna/get-npm-exec-opts": "4.0.0", - "npmlog": "^4.1.2" - }, + "license": "BlueOak-1.0.0", "engines": { - "node": ">= 10.18.0" + "node": "20 || >=22" } }, - "node_modules/@lerna/otplease": { - "version": "4.0.0", + "node_modules/@npmcli/arborist/node_modules/minimatch": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.1.tgz", + "integrity": "sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "@lerna/prompt": "4.0.0" + "brace-expansion": "^5.0.2" }, "engines": { - "node": ">= 10.18.0" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@lerna/output": { - "version": "4.0.0", + "node_modules/@npmcli/arborist/node_modules/npm-bundled": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-5.0.0.tgz", + "integrity": "sha512-JLSpbzh6UUXIEoqPsYBvVNVmyrjVZ1fzEFbqxKkTJQkWBO3xFzFT+KDnSKQWwOQNbuWRwt5LSD6HOTLGIWzfrw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "npmlog": "^4.1.2" + "npm-normalize-package-bin": "^5.0.0" }, "engines": { - "node": ">= 10.18.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@lerna/pack-directory": { - "version": "4.0.0", + "node_modules/@npmcli/arborist/node_modules/npm-normalize-package-bin": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", + "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==", "dev": true, - "license": "MIT", - "dependencies": { - "@lerna/get-packed": "4.0.0", - "@lerna/package": "4.0.0", - "@lerna/run-lifecycle": "4.0.0", - "npm-packlist": "^2.1.4", - "npmlog": "^4.1.2", - "tar": "^6.1.0", - "temp-write": "^4.0.0" - }, + "license": "ISC", "engines": { - "node": ">= 10.18.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@lerna/package": { - "version": "4.0.0", + "node_modules/@npmcli/arborist/node_modules/pacote": { + "version": "21.3.1", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-21.3.1.tgz", + "integrity": "sha512-O0EDXi85LF4AzdjG74GUwEArhdvawi/YOHcsW6IijKNj7wm8IvEWNF5GnfuxNpQ/ZpO3L37+v8hqdVh8GgWYhg==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "load-json-file": "^6.2.0", - "npm-package-arg": "^8.1.0", - "write-pkg": "^4.0.0" + "@npmcli/git": "^7.0.0", + "@npmcli/installed-package-contents": "^4.0.0", + "@npmcli/package-json": "^7.0.0", + "@npmcli/promise-spawn": "^9.0.0", + "@npmcli/run-script": "^10.0.0", + "cacache": "^20.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^13.0.0", + "npm-packlist": "^10.0.1", + "npm-pick-manifest": "^11.0.1", + "npm-registry-fetch": "^19.0.0", + "proc-log": "^6.0.0", + "promise-retry": "^2.0.1", + "sigstore": "^4.0.0", + "ssri": "^13.0.0", + "tar": "^7.4.3" + }, + "bin": { + "pacote": "bin/index.js" }, "engines": { - "node": ">= 10.18.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@lerna/package-graph": { + "node_modules/@npmcli/arborist/node_modules/pacote/node_modules/@npmcli/installed-package-contents": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-4.0.0.tgz", + "integrity": "sha512-yNyAdkBxB72gtZ4GrwXCM0ZUedo9nIbOMKfGjt6Cu6DXf0p8y1PViZAKDC8q8kv/fufx0WTjRBdSlyrvnP7hmA==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@lerna/prerelease-id-from-version": "4.0.0", - "@lerna/validation-error": "4.0.0", - "npm-package-arg": "^8.1.0", - "npmlog": "^4.1.2", - "semver": "^7.3.4" + "npm-bundled": "^5.0.0", + "npm-normalize-package-bin": "^5.0.0" + }, + "bin": { + "installed-package-contents": "bin/index.js" }, "engines": { - "node": ">= 10.18.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@lerna/prerelease-id-from-version": { - "version": "4.0.0", + "node_modules/@npmcli/arborist/node_modules/pacote/node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.3.4" - }, + "license": "ISC", "engines": { - "node": ">= 10.18.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@lerna/profiler": { - "version": "4.0.0", + "node_modules/@npmcli/arborist/node_modules/pacote/node_modules/ssri": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-13.0.1.tgz", + "integrity": "sha512-QUiRf1+u9wPTL/76GTYlKttDEBWV1ga9ZXW8BG6kfdeyyM8LGPix9gROyg9V2+P0xNyF3X2Go526xKFdMZrHSQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "fs-extra": "^9.1.0", - "npmlog": "^4.1.2", - "upath": "^2.0.1" + "minipass": "^7.0.3" }, "engines": { - "node": ">= 10.18.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@lerna/project": { + "node_modules/@npmcli/fs": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz", + "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@lerna/package": "4.0.0", - "@lerna/validation-error": "4.0.0", - "cosmiconfig": "^7.0.0", - "dedent": "^0.7.0", - "dot-prop": "^6.0.1", - "glob-parent": "^5.1.1", - "globby": "^11.0.2", - "load-json-file": "^6.2.0", - "npmlog": "^4.1.2", - "p-map": "^4.0.0", - "resolve-from": "^5.0.0", - "write-json-file": "^4.3.0" + "semver": "^7.3.5" }, "engines": { - "node": ">= 10.18.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@lerna/project/node_modules/dedent": { - "version": "0.7.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@lerna/project/node_modules/glob-parent": { - "version": "5.1.2", + "node_modules/@npmcli/git": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-7.0.1.tgz", + "integrity": "sha512-+XTFxK2jJF/EJJ5SoAzXk3qwIDfvFc5/g+bD274LZ7uY7LE8sTfG6Z8rOanPl2ZEvZWqNvmEdtXC25cE54VcoA==", "dev": true, "license": "ISC", "dependencies": { - "is-glob": "^4.0.1" + "@npmcli/promise-spawn": "^9.0.0", + "ini": "^6.0.0", + "lru-cache": "^11.2.1", + "npm-pick-manifest": "^11.0.1", + "proc-log": "^6.0.0", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^6.0.0" }, "engines": { - "node": ">= 6" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@lerna/project/node_modules/resolve-from": { - "version": "5.0.0", + "node_modules/@npmcli/git/node_modules/ini": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz", + "integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==", "dev": true, - "license": "MIT", + "license": "ISC", "engines": { - "node": ">=8" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@lerna/prompt": { + "node_modules/@npmcli/git/node_modules/isexe": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", "dev": true, - "license": "MIT", - "dependencies": { - "inquirer": "^7.3.3", - "npmlog": "^4.1.2" - }, + "license": "BlueOak-1.0.0", "engines": { - "node": ">= 10.18.0" + "node": ">=20" } }, - "node_modules/@lerna/publish": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@lerna/check-working-tree": "4.0.0", - "@lerna/child-process": "4.0.0", - "@lerna/collect-updates": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/describe-ref": "4.0.0", - "@lerna/log-packed": "4.0.0", - "@lerna/npm-conf": "4.0.0", - "@lerna/npm-dist-tag": "4.0.0", - "@lerna/npm-publish": "4.0.0", - "@lerna/otplease": "4.0.0", - "@lerna/output": "4.0.0", - "@lerna/pack-directory": "4.0.0", - "@lerna/prerelease-id-from-version": "4.0.0", - "@lerna/prompt": "4.0.0", - "@lerna/pulse-till-done": "4.0.0", - "@lerna/run-lifecycle": "4.0.0", - "@lerna/run-topologically": "4.0.0", - "@lerna/validation-error": "4.0.0", - "@lerna/version": "4.0.0", - "fs-extra": "^9.1.0", - "libnpmaccess": "^4.0.1", - "npm-package-arg": "^8.1.0", - "npm-registry-fetch": "^9.0.0", - "npmlog": "^4.1.2", - "p-map": "^4.0.0", - "p-pipe": "^3.1.0", - "pacote": "^11.2.6", - "semver": "^7.3.4" - }, - "engines": { - "node": ">= 10.18.0" - } - }, - "node_modules/@lerna/pulse-till-done": { - "version": "4.0.0", + "node_modules/@npmcli/git/node_modules/lru-cache": { + "version": "11.2.6", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", + "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", "dev": true, - "license": "MIT", - "dependencies": { - "npmlog": "^4.1.2" - }, + "license": "BlueOak-1.0.0", "engines": { - "node": ">= 10.18.0" + "node": "20 || >=22" } }, - "node_modules/@lerna/query-graph": { - "version": "4.0.0", + "node_modules/@npmcli/git/node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", "dev": true, - "license": "MIT", - "dependencies": { - "@lerna/package-graph": "4.0.0" - }, + "license": "ISC", "engines": { - "node": ">= 10.18.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@lerna/resolve-symlink": { - "version": "4.0.0", + "node_modules/@npmcli/git/node_modules/which": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "fs-extra": "^9.1.0", - "npmlog": "^4.1.2", - "read-cmd-shim": "^2.0.0" + "isexe": "^4.0.0" + }, + "bin": { + "node-which": "bin/which.js" }, "engines": { - "node": ">= 10.18.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@lerna/rimraf-dir": { - "version": "4.0.0", + "node_modules/@npmcli/installed-package-contents": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-3.0.0.tgz", + "integrity": "sha512-fkxoPuFGvxyrH+OQzyTkX2LUEamrF4jZSmxjAtPPHHGO0dqsQ8tTKjnIS8SAnPHdk2I03BDtSMR5K/4loKg79Q==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@lerna/child-process": "4.0.0", - "npmlog": "^4.1.2", - "path-exists": "^4.0.0", - "rimraf": "^3.0.2" + "npm-bundled": "^4.0.0", + "npm-normalize-package-bin": "^4.0.0" + }, + "bin": { + "installed-package-contents": "bin/index.js" }, "engines": { - "node": ">= 10.18.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@lerna/run": { - "version": "4.0.0", + "node_modules/@npmcli/map-workspaces": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-5.0.3.tgz", + "integrity": "sha512-o2grssXo1e774E5OtEwwrgoszYRh0lqkJH+Pb9r78UcqdGJRDRfhpM8DvZPjzNLLNYeD/rNbjOKM3Ss5UABROw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@lerna/command": "4.0.0", - "@lerna/filter-options": "4.0.0", - "@lerna/npm-run-script": "4.0.0", - "@lerna/output": "4.0.0", - "@lerna/profiler": "4.0.0", - "@lerna/run-topologically": "4.0.0", - "@lerna/timer": "4.0.0", - "@lerna/validation-error": "4.0.0", - "p-map": "^4.0.0" + "@npmcli/name-from-folder": "^4.0.0", + "@npmcli/package-json": "^7.0.0", + "glob": "^13.0.0", + "minimatch": "^10.0.3" }, "engines": { - "node": ">= 10.18.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@lerna/run-lifecycle": { + "node_modules/@npmcli/map-workspaces/node_modules/@npmcli/name-from-folder": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-4.0.0.tgz", + "integrity": "sha512-qfrhVlOSqmKM8i6rkNdZzABj8MKEITGFAY+4teqBziksCQAOLutiAxM1wY2BKEd8KjUSpWmWCYxvXr0y4VTlPg==", "dev": true, - "license": "MIT", - "dependencies": { - "@lerna/npm-conf": "4.0.0", - "npm-lifecycle": "^3.1.5", - "npmlog": "^4.1.2" - }, + "license": "ISC", "engines": { - "node": ">= 10.18.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@lerna/run-topologically": { - "version": "4.0.0", + "node_modules/@npmcli/map-workspaces/node_modules/balanced-match": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.2.tgz", + "integrity": "sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==", "dev": true, "license": "MIT", "dependencies": { - "@lerna/query-graph": "4.0.0", - "p-queue": "^6.6.2" + "jackspeak": "^4.2.3" }, "engines": { - "node": ">= 10.18.0" + "node": "20 || >=22" } }, - "node_modules/@lerna/symlink-binary": { - "version": "4.0.0", + "node_modules/@npmcli/map-workspaces/node_modules/brace-expansion": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", + "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", "dev": true, "license": "MIT", "dependencies": { - "@lerna/create-symlink": "4.0.0", - "@lerna/package": "4.0.0", - "fs-extra": "^9.1.0", - "p-map": "^4.0.0" + "balanced-match": "^4.0.2" }, "engines": { - "node": ">= 10.18.0" + "node": "20 || >=22" } }, - "node_modules/@lerna/symlink-dependencies": { - "version": "4.0.0", + "node_modules/@npmcli/map-workspaces/node_modules/glob": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.5.tgz", + "integrity": "sha512-BzXxZg24Ibra1pbQ/zE7Kys4Ua1ks7Bn6pKLkVPZ9FZe4JQS6/Q7ef3LG1H+k7lUf5l4T3PLSyYyYJVYUvfgTw==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "@lerna/create-symlink": "4.0.0", - "@lerna/resolve-symlink": "4.0.0", - "@lerna/symlink-binary": "4.0.0", - "fs-extra": "^9.1.0", - "p-map": "^4.0.0", - "p-map-series": "^2.1.0" + "minimatch": "^10.2.1", + "minipass": "^7.1.2", + "path-scurry": "^2.0.0" }, "engines": { - "node": ">= 10.18.0" - } - }, - "node_modules/@lerna/timer": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.18.0" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@lerna/validation-error": { - "version": "4.0.0", + "node_modules/@npmcli/map-workspaces/node_modules/minimatch": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.1.tgz", + "integrity": "sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "npmlog": "^4.1.2" + "brace-expansion": "^5.0.2" }, "engines": { - "node": ">= 10.18.0" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@lerna/version": { - "version": "4.0.0", + "node_modules/@npmcli/metavuln-calculator": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-9.0.3.tgz", + "integrity": "sha512-94GLSYhLXF2t2LAC7pDwLaM4uCARzxShyAQKsirmlNcpidH89VA4/+K1LbJmRMgz5gy65E/QBBWQdUvGLe2Frg==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@lerna/check-working-tree": "4.0.0", - "@lerna/child-process": "4.0.0", - "@lerna/collect-updates": "4.0.0", - "@lerna/command": "4.0.0", - "@lerna/conventional-commits": "4.0.0", - "@lerna/github-client": "4.0.0", - "@lerna/gitlab-client": "4.0.0", - "@lerna/output": "4.0.0", - "@lerna/prerelease-id-from-version": "4.0.0", - "@lerna/prompt": "4.0.0", - "@lerna/run-lifecycle": "4.0.0", - "@lerna/run-topologically": "4.0.0", - "@lerna/validation-error": "4.0.0", - "chalk": "^4.1.0", - "dedent": "^0.7.0", - "load-json-file": "^6.2.0", - "minimatch": "^3.0.4", - "npmlog": "^4.1.2", - "p-map": "^4.0.0", - "p-pipe": "^3.1.0", - "p-reduce": "^2.1.0", - "p-waterfall": "^2.1.1", - "semver": "^7.3.4", - "slash": "^3.0.0", - "temp-write": "^4.0.0", - "write-json-file": "^4.3.0" + "cacache": "^20.0.0", + "json-parse-even-better-errors": "^5.0.0", + "pacote": "^21.0.0", + "proc-log": "^6.0.0", + "semver": "^7.3.5" }, "engines": { - "node": ">= 10.18.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@lerna/version/node_modules/brace-expansion": { - "version": "1.1.12", + "node_modules/@npmcli/metavuln-calculator/node_modules/json-parse-even-better-errors": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-5.0.0.tgz", + "integrity": "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ==", "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@lerna/version/node_modules/dedent": { - "version": "0.7.0", + "node_modules/@npmcli/metavuln-calculator/node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", "dev": true, - "license": "MIT" + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } }, - "node_modules/@lerna/version/node_modules/minimatch": { - "version": "3.1.2", + "node_modules/@npmcli/name-from-folder": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-3.0.0.tgz", + "integrity": "sha512-61cDL8LUc9y80fXn+lir+iVt8IS0xHqEKwPu/5jCjxQTVoSCmkXvw4vbMrzAMtmghz3/AkiBjhHkDKUH+kf7kA==", "dev": true, "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, "engines": { - "node": "*" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@lerna/write-log-file": { + "node_modules/@npmcli/node-gyp": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-4.0.0.tgz", + "integrity": "sha512-+t5DZ6mO/QFh78PByMq1fGSAub/agLJZDRfJRMeOSNCt8s9YVlTjmGpIPwPhvXTGUIJk+WszlT0rQa1W33yzNA==", "dev": true, - "license": "MIT", - "dependencies": { - "npmlog": "^4.1.2", - "write-file-atomic": "^3.0.3" - }, + "license": "ISC", "engines": { - "node": ">= 10.18.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@lerna/write-log-file/node_modules/write-file-atomic": { - "version": "3.0.3", + "node_modules/@npmcli/package-json": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-7.0.2.tgz", + "integrity": "sha512-0ylN3U5htO1SJTmy2YI78PZZjLkKUGg7EKgukb2CRi0kzyoDr0cfjHAzi7kozVhj2V3SxN1oyKqZ2NSo40z00g==", "dev": true, "license": "ISC", "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "@npmcli/git": "^7.0.0", + "glob": "^11.0.3", + "hosted-git-info": "^9.0.0", + "json-parse-even-better-errors": "^5.0.0", + "proc-log": "^6.0.0", + "semver": "^7.5.3", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@microsoft/tsdoc": { - "version": "0.15.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@microsoft/tsdoc-config": { - "version": "0.17.1", + "node_modules/@npmcli/package-json/node_modules/balanced-match": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.2.tgz", + "integrity": "sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==", "dev": true, "license": "MIT", "dependencies": { - "@microsoft/tsdoc": "0.15.1", - "ajv": "~8.12.0", - "jju": "~1.4.0", - "resolve": "~1.22.2" + "jackspeak": "^4.2.3" + }, + "engines": { + "node": "20 || >=22" } }, - "node_modules/@microsoft/tsdoc-config/node_modules/ajv": { - "version": "8.12.0", + "node_modules/@npmcli/package-json/node_modules/brace-expansion": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", + "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "balanced-match": "^4.0.2" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": "20 || >=22" } }, - "node_modules/@microsoft/tsdoc-config/node_modules/json-schema-traverse": { - "version": "1.0.0", + "node_modules/@npmcli/package-json/node_modules/glob": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, - "license": "MIT" - }, - "node_modules/@noble/curves": { - "version": "1.8.1", - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "@noble/hashes": "1.7.1" + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": "^14.21.3 || >=16" + "node": "20 || >=22" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.7.1", + "node_modules/@npmcli/package-json/node_modules/json-parse-even-better-errors": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-5.0.0.tgz", + "integrity": "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ==", + "dev": true, "license": "MIT", "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@noble/hashes": { - "version": "1.8.0", - "license": "MIT", + "node_modules/@npmcli/package-json/node_modules/minimatch": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.1.tgz", + "integrity": "sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, "engines": { - "node": "^14.21.3 || >=16" + "node": "20 || >=22" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", + "node_modules/@npmcli/package-json/node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", "dev": true, - "license": "MIT", + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/promise-spawn": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-9.0.1.tgz", + "integrity": "sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q==", + "dev": true, + "license": "ISC", "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "which": "^6.0.0" }, "engines": { - "node": ">= 8" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", + "node_modules/@npmcli/promise-spawn/node_modules/isexe": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "engines": { - "node": ">= 8" + "node": ">=20" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", + "node_modules/@npmcli/promise-spawn/node_modules/which": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "isexe": "^4.0.0" + }, + "bin": { + "node-which": "bin/which.js" }, "engines": { - "node": ">= 8" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@npmcli/ci-detect": { - "version": "1.4.0", - "dev": true, - "license": "ISC" - }, - "node_modules/@npmcli/fs": { - "version": "1.1.1", + "node_modules/@npmcli/query": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/query/-/query-4.0.1.tgz", + "integrity": "sha512-4OIPFb4weUUwkDXJf4Hh1inAn8neBGq3xsH4ZsAaN6FK3ldrFkH7jSpCc7N9xesi0Sp+EBXJ9eGMDrEww2Ztqw==", "dev": true, "license": "ISC", "dependencies": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@npmcli/git": { - "version": "2.1.0", + "node_modules/@npmcli/redact": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-3.2.2.tgz", + "integrity": "sha512-7VmYAmk4csGv08QzrDKScdzn11jHPFGyqJW39FyPgPuAp3zIaUmuCo1yxw9aGs+NEJuTGQ9Gwqpt93vtJubucg==", "dev": true, "license": "ISC", - "dependencies": { - "@npmcli/promise-spawn": "^1.3.2", - "lru-cache": "^6.0.0", - "mkdirp": "^1.0.4", - "npm-pick-manifest": "^6.1.1", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^2.0.2" + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@npmcli/git/node_modules/lru-cache": { - "version": "6.0.0", + "node_modules/@npmcli/run-script": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-10.0.3.tgz", + "integrity": "sha512-ER2N6itRkzWbbtVmZ9WKaWxVlKlOeBFF1/7xx+KA5J1xKa4JjUwBdb6tDpk0v1qA+d+VDwHI9qmLcXSWcmi+Rw==", "dev": true, "license": "ISC", "dependencies": { - "yallist": "^4.0.0" + "@npmcli/node-gyp": "^5.0.0", + "@npmcli/package-json": "^7.0.0", + "@npmcli/promise-spawn": "^9.0.0", + "node-gyp": "^12.1.0", + "proc-log": "^6.0.0", + "which": "^6.0.0" }, "engines": { - "node": ">=10" + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/run-script/node_modules/@npmcli/node-gyp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-5.0.0.tgz", + "integrity": "sha512-uuG5HZFXLfyFKqg8QypsmgLQW7smiRjVc45bqD/ofZZcR/uxEjgQU8qDPv0s9TEeMUiAAU/GC5bR6++UdTirIQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@npmcli/git/node_modules/yallist": { + "node_modules/@npmcli/run-script/node_modules/isexe": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", "dev": true, - "license": "ISC" + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=20" + } + }, + "node_modules/@npmcli/run-script/node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } }, - "node_modules/@npmcli/installed-package-contents": { - "version": "1.0.7", + "node_modules/@npmcli/run-script/node_modules/which": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", "dev": true, "license": "ISC", "dependencies": { - "npm-bundled": "^1.1.1", - "npm-normalize-package-bin": "^1.0.1" + "isexe": "^4.0.0" }, "bin": { - "installed-package-contents": "index.js" + "node-which": "bin/which.js" }, "engines": { - "node": ">= 10" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@npmcli/move-file": { - "version": "1.1.2", + "node_modules/@nx/devkit": { + "version": "22.5.1", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-22.5.1.tgz", + "integrity": "sha512-1ZJ8pCB+6EWC8X6q8tfBweg92WzFAwliBhtBkOPP8Li8GQq71ulPWRdY4lDd5pH3Ea1zKqhOtBKWdOlyDPOKYA==", "dev": true, "license": "MIT", "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" + "@zkochan/js-yaml": "0.0.7", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "minimatch": "10.1.1", + "semver": "^7.6.3", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" }, - "engines": { - "node": ">=10" + "peerDependencies": { + "nx": ">= 21 <= 23 || ^22.0.0-0" } }, - "node_modules/@npmcli/node-gyp": { - "version": "1.0.3", - "dev": true, - "license": "ISC" - }, - "node_modules/@npmcli/promise-spawn": { - "version": "1.3.2", + "node_modules/@nx/devkit/node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "infer-owner": "^1.0.4" + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@npmcli/run-script": { - "version": "1.8.6", + "node_modules/@nx/devkit/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, "license": "ISC", - "dependencies": { - "@npmcli/node-gyp": "^1.0.2", - "@npmcli/promise-spawn": "^1.3.2", - "node-gyp": "^7.1.0", - "read-package-json-fast": "^2.0.1" + "engines": { + "node": ">=12" } }, - "node_modules/@npmcli/run-script/node_modules/node-gyp": { - "version": "7.1.2", + "node_modules/@nx/nx-darwin-arm64": { + "version": "22.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-22.5.1.tgz", + "integrity": "sha512-DuvOwhXPO6l9W7/zM4/BaAbGTIXFyHVcbbCD1c7HfgZ3VfJPmcE7H4+TuQH0cigHHtpg/eGqV100NQbd7N4zwg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.3", - "nopt": "^5.0.0", - "npmlog": "^4.1.2", - "request": "^2.88.2", - "rimraf": "^3.0.2", - "semver": "^7.3.2", - "tar": "^6.0.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": ">= 10.12.0" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@npmcli/run-script/node_modules/nopt": { - "version": "5.0.0", + "node_modules/@nx/nx-darwin-x64": { + "version": "22.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-22.5.1.tgz", + "integrity": "sha512-81Lb7+rp3Qltpgy33Kc1qxk+8IWqZLhqvdLdRFSVV1FN1pPSJDFKyPjCn9oMpRryNPSJ8DgZDpfIaVVyP85rUw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@nx/nx-freebsd-x64": { + "version": "22.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-22.5.1.tgz", + "integrity": "sha512-Ig8yQN3lSz9R+Zf3NQWcvEnIzwDX4NSeaFtEliPnC3OHlQXGNXbOUfkExa0U0UUgyxa4rgnCgefmwuc12H9q2Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "22.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-22.5.1.tgz", + "integrity": "sha512-C7tGoLnR9MjKLJsLMF2VsKcDChPiygAsw6dSVgU4B650H7sBWmkEHM/QjvyRvkcZuoQBDamS/eVs/UaJu9wNhA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@nx/nx-linux-arm64-gnu": { + "version": "22.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-22.5.1.tgz", + "integrity": "sha512-GNxei+lwhzhrO9m+nNkibgxLhbkYKyFXPSRpOKLwv9VavNzJn5UmLfKJyhjNQPBOSYuNhiVPbU1Ja/qOBcozYw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@nx/nx-linux-arm64-musl": { + "version": "22.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-22.5.1.tgz", + "integrity": "sha512-VDJtdJP2nCgS8ommbfWFAKjoZCE51VH7tZyIfh8RFI5fxwoB3Pk6d6f6cmNHI/1t98YI3V7Onuf3Y9KBkYtyfQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@nx/nx-linux-x64-gnu": { + "version": "22.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-22.5.1.tgz", + "integrity": "sha512-BZ/i+KTplEJmE8ZHKgPGD513Zl86DuSGyRAvbDZ7Qf19Tei7Of6vxW+ypvVDIwmDbyXfe13u54M5gDt8iiqFGQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@nx/nx-linux-x64-musl": { + "version": "22.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-22.5.1.tgz", + "integrity": "sha512-e0VdiV6fe88Dbhill2gUjYAD9jMhHjYsafGOPR+/uaGMAYPoI1jKur6uPGY+ik6fvwvDFFl0VT2+HACKVn7RoA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@nx/nx-win32-arm64-msvc": { + "version": "22.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-22.5.1.tgz", + "integrity": "sha512-3vWZO9y7uHKeyepcU55pE8VQTKGome3mLdicvx1TCoKKl0cA3bTR341Jdo2Zl4Waa2ENk7pGQbLWRQ3ZkaA92A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@nx/nx-win32-x64-msvc": { + "version": "22.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-22.5.1.tgz", + "integrity": "sha512-4e5LduuhpBx96JgD1J3fHUGCwC+/lL+tvXp3UVtjh/AOdINGsyI+scinT3uaI9vcB5GKBcybTxbBZzwcH50w9g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, "node_modules/@octokit/auth-token": { - "version": "2.5.0", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", "dev": true, "license": "MIT", - "dependencies": { - "@octokit/types": "^6.0.3" + "engines": { + "node": ">= 18" } }, "node_modules/@octokit/core": { - "version": "3.6.0", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.2.tgz", + "integrity": "sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.1.0", + "@octokit/request": "^8.4.1", + "@octokit/request-error": "^5.1.1", + "@octokit/types": "^13.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" } }, "node_modules/@octokit/endpoint": { - "version": "6.0.12", + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz", + "integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", + "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" } }, "node_modules/@octokit/graphql": { - "version": "4.8.0", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz", + "integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", + "@octokit/request": "^8.4.1", + "@octokit/types": "^13.0.0", "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" } }, "node_modules/@octokit/openapi-types": { - "version": "12.11.0", + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", "dev": true, "license": "MIT" }, "node_modules/@octokit/plugin-enterprise-rest": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz", + "integrity": "sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw==", "dev": true, "license": "MIT" }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "2.21.3", + "version": "11.4.4-cjs.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.4.4-cjs.2.tgz", + "integrity": "sha512-2dK6z8fhs8lla5PaOTgqfCGBxgAv/le+EhPs27KklPhm1bKObpu6lXzwfUEQ16ajXzqNrKMujsFyo9K2eaoISw==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/types": "^6.40.0" + "@octokit/types": "^13.7.0" + }, + "engines": { + "node": ">= 18" }, "peerDependencies": { - "@octokit/core": ">=2" + "@octokit/core": "5" } }, "node_modules/@octokit/plugin-request-log": { - "version": "1.0.4", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.1.tgz", + "integrity": "sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==", "dev": true, "license": "MIT", + "engines": { + "node": ">= 18" + }, "peerDependencies": { - "@octokit/core": ">=3" + "@octokit/core": "5" } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "5.16.2", + "version": "13.3.2-cjs.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.3.2-cjs.1.tgz", + "integrity": "sha512-VUjIjOOvF2oELQmiFpWA1aOPdawpyaCUqcEBc/UOUnj3Xp6DJGrJ1+bjUIIDzdHjnFNO6q57ODMfdEZnoBkCwQ==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/types": "^6.39.0", - "deprecation": "^2.3.1" + "@octokit/types": "^13.8.0" + }, + "engines": { + "node": ">= 18" }, "peerDependencies": { - "@octokit/core": ">=3" + "@octokit/core": "^5" } }, "node_modules/@octokit/request": { - "version": "5.6.3", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz", + "integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", + "@octokit/endpoint": "^9.0.6", + "@octokit/request-error": "^5.1.1", + "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" } }, "node_modules/@octokit/request-error": { - "version": "2.1.0", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz", + "integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/types": "^6.0.3", + "@octokit/types": "^13.1.0", "deprecation": "^2.0.0", "once": "^1.4.0" + }, + "engines": { + "node": ">= 18" } }, "node_modules/@octokit/rest": { - "version": "18.12.0", + "version": "20.1.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.1.2.tgz", + "integrity": "sha512-GmYiltypkHHtihFwPRxlaorG5R9VAHuk/vbszVoRTGXnAsY60wYLkh/E2XiFmdZmqrisw+9FaazS1i5SbdWYgA==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/core": "^3.5.1", - "@octokit/plugin-paginate-rest": "^2.16.8", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^5.12.0" + "@octokit/core": "^5.0.2", + "@octokit/plugin-paginate-rest": "11.4.4-cjs.2", + "@octokit/plugin-request-log": "^4.0.0", + "@octokit/plugin-rest-endpoint-methods": "13.3.2-cjs.1" + }, + "engines": { + "node": ">= 18" } }, "node_modules/@octokit/types": { - "version": "6.41.0", + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^12.11.0" + "@octokit/openapi-types": "^24.2.0" } }, "node_modules/@pkgr/core": { @@ -2689,44 +3500,211 @@ } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "3.9.2", + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.19.0.tgz", + "integrity": "sha512-1hRxtYIJfJSZeM5ivbUXv9hcJP3PWRo5prG/V2sWwiubUKTa+7P62d2qxCW8jiVFX4pgRHhnHNp+qeR7Xl+6kg==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "3.9.2", + "@shikijs/types": "3.19.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "node_modules/@shikijs/langs": { - "version": "3.9.2", + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.19.0.tgz", + "integrity": "sha512-dBMFzzg1QiXqCVQ5ONc0z2ebyoi5BKz+MtfByLm0o5/nbUu3Iz8uaTCa5uzGiscQKm7lVShfZHU1+OG3t5hgwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.19.0" + } + }, + "node_modules/@shikijs/themes": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.19.0.tgz", + "integrity": "sha512-H36qw+oh91Y0s6OlFfdSuQ0Ld+5CgB/VE6gNPK+Hk4VRbVG/XQgkjnt4KzfnnoO6tZPtKJKHPjwebOCfjd6F8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.19.0" + } + }, + "node_modules/@shikijs/types": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.19.0.tgz", + "integrity": "sha512-Z2hdeEQlzuntf/BZpFG8a+Fsw9UVXdML7w0o3TgSXV3yNESGon+bs9ITkQb3Ki7zxoXOOu5oJWqZ2uto06V9iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sigstore/bundle": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-4.0.0.tgz", + "integrity": "sha512-NwCl5Y0V6Di0NexvkTqdoVfmjTaQwoLM236r89KEojGmq/jMls8S+zb7yOwAPdXvbwfKDlP+lmXgAL4vKSQT+A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.5.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@sigstore/core": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-3.1.0.tgz", + "integrity": "sha512-o5cw1QYhNQ9IroioJxpzexmPjfCe7gzafd2RY3qnMpxr4ZEja+Jad/U8sgFpaue6bOaF+z7RVkyKVV44FN+N8A==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@sigstore/protobuf-specs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.5.0.tgz", + "integrity": "sha512-MM8XIwUjN2bwvCg1QvrMtbBmpcSHrkhFSCu1D11NyPvDQ25HEc4oG5/OcQfd/Tlf/OxmKWERDj0zGE23jQaMwA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@sigstore/sign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-4.1.0.tgz", + "integrity": "sha512-Vx1RmLxLGnSUqx/o5/VsCjkuN5L7y+vxEEwawvc7u+6WtX2W4GNa7b9HEjmcRWohw/d6BpATXmvOwc78m+Swdg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^4.0.0", + "@sigstore/core": "^3.1.0", + "@sigstore/protobuf-specs": "^0.5.0", + "make-fetch-happen": "^15.0.3", + "proc-log": "^6.1.0", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@sigstore/sign/node_modules/make-fetch-happen": { + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.3.tgz", + "integrity": "sha512-iyyEpDty1mwW3dGlYXAJqC/azFn5PPvgKVwXayOGBSmKLxhKZ9fg4qIan2ePpp1vJIwfFiO34LAPZgq9SZW9Aw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/agent": "^4.0.0", + "cacache": "^20.0.1", + "http-cache-semantics": "^4.1.1", + "minipass": "^7.0.2", + "minipass-fetch": "^5.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^1.0.0", + "proc-log": "^6.0.0", + "promise-retry": "^2.0.1", + "ssri": "^13.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@sigstore/sign/node_modules/minipass-fetch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-5.0.1.tgz", + "integrity": "sha512-yHK8pb0iCGat0lDrs/D6RZmCdaBT64tULXjdxjSMAqoDi18Q3qKEUTHypHQZQd9+FYpIS+lkvpq6C/R6SbUeRw==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "3.9.2" + "minipass": "^7.0.3", + "minipass-sized": "^2.0.0", + "minizlib": "^3.0.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/@sigstore/sign/node_modules/minipass-sized": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-2.0.0.tgz", + "integrity": "sha512-zSsHhto5BcUVM2m1LurnXY6M//cGhVaegT71OfOXoprxT6o780GZd792ea6FfrQkuU4usHZIUczAQMRUE2plzA==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sigstore/sign/node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@sigstore/sign/node_modules/ssri": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-13.0.1.tgz", + "integrity": "sha512-QUiRf1+u9wPTL/76GTYlKttDEBWV1ga9ZXW8BG6kfdeyyM8LGPix9gROyg9V2+P0xNyF3X2Go526xKFdMZrHSQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@shikijs/themes": { - "version": "3.9.2", + "node_modules/@sigstore/tuf": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-4.0.1.tgz", + "integrity": "sha512-OPZBg8y5Vc9yZjmWCHrlWPMBqW5yd8+wFNl+thMdtcWz3vjVSoJQutF8YkrzI0SLGnkuFof4HSsWUhXrf219Lw==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "@shikijs/types": "3.9.2" + "@sigstore/protobuf-specs": "^0.5.0", + "tuf-js": "^4.1.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@shikijs/types": { - "version": "3.9.2", + "node_modules/@sigstore/verify": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-3.1.0.tgz", + "integrity": "sha512-mNe0Iigql08YupSOGv197YdHpPPr+EzDZmfCgMc7RPNaZTw5aLN01nBl6CHJOh3BGtnMIj83EeN4butBchc8Ag==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" + "@sigstore/bundle": "^4.0.0", + "@sigstore/core": "^3.1.0", + "@sigstore/protobuf-specs": "^0.5.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@shikijs/vscode-textmate": { - "version": "10.0.2", - "dev": true, - "license": "MIT" - }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "dev": true, @@ -2761,14 +3739,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/@transia/isomorphic": { "resolved": "packages/isomorphic", "link": true @@ -2813,6 +3783,83 @@ "dev": true, "license": "MIT" }, + "node_modules/@tufjs/canonical-json": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", + "integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@tufjs/models": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-4.1.0.tgz", + "integrity": "sha512-Y8cK9aggNRsqJVaKUlEYs4s7CvQ1b1ta2DVPyAimb0I2qhzjNk+A+mxvll/klL0RlfuIUei8BF7YWiua4kQqww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^10.1.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@tufjs/models/node_modules/balanced-match": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.2.tgz", + "integrity": "sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "jackspeak": "^4.2.3" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@tufjs/models/node_modules/brace-expansion": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", + "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@tufjs/models/node_modules/minimatch": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.1.tgz", + "integrity": "sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "dev": true, @@ -2896,6 +3943,8 @@ }, "node_modules/@types/hast": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2932,6 +3981,23 @@ "pretty-format": "^29.0.0" } }, + "node_modules/@types/jest/node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/@types/json-schema": { "version": "7.0.15", "dev": true, @@ -2943,17 +4009,23 @@ "license": "MIT" }, "node_modules/@types/lodash": { - "version": "4.17.20", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-FOvQ0YPD5NOfPgMzJihoT+Za5pdkDJWcbpuj1DjaKZIr/gxodQjY/uWEFlTNqW2ugXHUiL8lRQgw63dzKHZdeQ==", "dev": true, "license": "MIT" }, "node_modules/@types/minimatch": { "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", "dev": true, "license": "MIT" }, "node_modules/@types/minimist": { "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", "dev": true, "license": "MIT" }, @@ -2967,11 +4039,8 @@ }, "node_modules/@types/normalize-package-data": { "version": "2.4.4", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/parse-json": { - "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true, "license": "MIT" }, @@ -2982,6 +4051,8 @@ }, "node_modules/@types/unist": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "dev": true, "license": "MIT" }, @@ -3007,19 +4078,20 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.39.0", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.52.0.tgz", + "integrity": "sha512-okqtOgqu2qmZJ5iN4TWlgfF171dZmx2FzdOv2K/ixL2LZWDStL8+JgQerI2sa8eAEfoydG9+0V96m7V+P8yE1Q==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.39.0", - "@typescript-eslint/type-utils": "8.39.0", - "@typescript-eslint/utils": "8.39.0", - "@typescript-eslint/visitor-keys": "8.39.0", - "graphemer": "^1.4.0", - "ignore": "^7.0.0", + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.52.0", + "@typescript-eslint/type-utils": "8.52.0", + "@typescript-eslint/utils": "8.52.0", + "@typescript-eslint/visitor-keys": "8.52.0", + "ignore": "^7.0.5", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.1.0" + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3029,13 +4101,15 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.39.0", + "@typescript-eslint/parser": "^8.52.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", "engines": { @@ -3043,15 +4117,17 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.39.0", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.52.0.tgz", + "integrity": "sha512-iIACsx8pxRnguSYhHiMn2PvhvfpopO9FXHyn1mG5txZIsAaB6F0KwbFnUQN3KCiG3Jcuad/Cao2FAs1Wp7vAyg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.39.0", - "@typescript-eslint/types": "8.39.0", - "@typescript-eslint/typescript-estree": "8.39.0", - "@typescript-eslint/visitor-keys": "8.39.0", - "debug": "^4.3.4" + "@typescript-eslint/scope-manager": "8.52.0", + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/typescript-estree": "8.52.0", + "@typescript-eslint/visitor-keys": "8.52.0", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3066,13 +4142,15 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.39.0", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.52.0.tgz", + "integrity": "sha512-xD0MfdSdEmeFa3OmVqonHi+Cciab96ls1UhIF/qX/O/gPu5KXD0bY9lu33jj04fjzrXHcuvjBcBC+D3SNSadaw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.39.0", - "@typescript-eslint/types": "^8.39.0", - "debug": "^4.3.4" + "@typescript-eslint/tsconfig-utils": "^8.52.0", + "@typescript-eslint/types": "^8.52.0", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3086,12 +4164,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.39.0", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.52.0.tgz", + "integrity": "sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.39.0", - "@typescript-eslint/visitor-keys": "8.39.0" + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/visitor-keys": "8.52.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3102,7 +4182,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.39.0", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.52.0.tgz", + "integrity": "sha512-jl+8fzr/SdzdxWJznq5nvoI7qn2tNYV/ZBAEcaFMVXf+K6jmXvAFrgo/+5rxgnL152f//pDEAYAhhBAZGrVfwg==", "dev": true, "license": "MIT", "engines": { @@ -3117,15 +4199,17 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.39.0", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.52.0.tgz", + "integrity": "sha512-JD3wKBRWglYRQkAtsyGz1AewDu3mTc7NtRjR/ceTyGoPqmdS5oCdx/oZMWD5Zuqmo6/MpsYs0wp6axNt88/2EQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.39.0", - "@typescript-eslint/typescript-estree": "8.39.0", - "@typescript-eslint/utils": "8.39.0", - "debug": "^4.3.4", - "ts-api-utils": "^2.1.0" + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/typescript-estree": "8.52.0", + "@typescript-eslint/utils": "8.52.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3140,7 +4224,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.39.0", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.52.0.tgz", + "integrity": "sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg==", "dev": true, "license": "MIT", "engines": { @@ -3152,20 +4238,21 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.39.0", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.52.0.tgz", + "integrity": "sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.39.0", - "@typescript-eslint/tsconfig-utils": "8.39.0", - "@typescript-eslint/types": "8.39.0", - "@typescript-eslint/visitor-keys": "8.39.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" + "@typescript-eslint/project-service": "8.52.0", + "@typescript-eslint/tsconfig-utils": "8.52.0", + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/visitor-keys": "8.52.0", + "debug": "^4.4.3", + "minimatch": "^9.0.5", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3179,14 +4266,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.39.0", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.52.0.tgz", + "integrity": "sha512-wYndVMWkweqHpEpwPhwqE2lnD2DxC6WVLupU/DOt/0/v+/+iQbbzO3jOHjmBMnhu0DgLULvOaU4h4pwHYi2oRQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.39.0", - "@typescript-eslint/types": "8.39.0", - "@typescript-eslint/typescript-estree": "8.39.0" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.52.0", + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/typescript-estree": "8.52.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3201,11 +4290,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.39.0", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.52.0.tgz", + "integrity": "sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.39.0", + "@typescript-eslint/types": "8.52.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -3218,17 +4309,246 @@ }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@unrs/resolver-binding-darwin-arm64": { + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", "cpu": [ "arm64" ], @@ -3236,7 +4556,35 @@ "license": "MIT", "optional": true, "os": [ - "darwin" + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" ] }, "node_modules/@webassemblyjs/ast": { @@ -3412,9 +4760,9 @@ } }, "node_modules/@xrplf/eslint-config": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@xrplf/eslint-config/-/eslint-config-2.0.0.tgz", - "integrity": "sha512-3Re4eG/jibi9Obb9T60axzC3kQ04EGEAFVj3Fqf3lZXj919wEidLjWH7KvtafCiTq3QDJbRFzgXRc9CXxKpdfg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@xrplf/eslint-config/-/eslint-config-3.0.0.tgz", + "integrity": "sha512-bLeLS2RYrnu3tcY7YYPXJ4fPkS308waojnvzOnI/gB1ysw+BdOSBL/7CexD3tb+En8dvxn9wI5OAiUzoaQcOqw==", "dev": true, "license": "ISC", "dependencies": { @@ -3431,7 +4779,7 @@ "eslint": "^9.0.0", "eslint-config-prettier": "^10.0.0", "eslint-import-resolver-typescript": "^4.0.0", - "eslint-plugin-array-func": "^4.0.0", + "eslint-plugin-array-func": "^5.0.0", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsdoc": "^52.0.0", "eslint-plugin-jsx-a11y": "^6.0.0", @@ -3439,7 +4787,7 @@ "eslint-plugin-prettier": "^5.0.0", "eslint-plugin-react": "^7.0.0", "eslint-plugin-react-hooks": "^5.0.0", - "eslint-plugin-tsdoc": "^0.4.0", + "eslint-plugin-tsdoc": "^0.5.0", "globals": "^16.0.0", "prettier": "^3.0.0", "typescript": ">=4.8.4", @@ -3463,10 +4811,73 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/@yarnpkg/parsers": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.2.tgz", + "integrity": "sha512-/HcYgtUSiJiot/XWGLOlGxPYUG65+/31V8oqk17vZLW1xlCoR4PampyePljOxY2n8/3jz9+tIFzICsyGujJZoA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "js-yaml": "^3.10.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=18.12.0" + } + }, + "node_modules/@yarnpkg/parsers/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@yarnpkg/parsers/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@zkochan/js-yaml": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.7.tgz", + "integrity": "sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/abbrev": { - "version": "1.1.1", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", + "integrity": "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==", "dev": true, - "license": "ISC" + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } }, "node_modules/accepts": { "version": "1.3.8", @@ -3531,33 +4942,25 @@ }, "node_modules/add-stream": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", + "integrity": "sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==", "dev": true, "license": "MIT" }, "node_modules/agent-base": { - "version": "6.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agentkeepalive": { - "version": "4.6.0", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, "license": "MIT", - "dependencies": { - "humanize-ms": "^1.2.1" - }, "engines": { - "node": ">= 8.0.0" + "node": ">= 14" } }, "node_modules/aggregate-error": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, "license": "MIT", "dependencies": { @@ -3585,6 +4988,8 @@ }, "node_modules/ajv-formats": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, "license": "MIT", "dependencies": { @@ -3601,6 +5006,8 @@ }, "node_modules/ajv-formats/node_modules/ajv": { "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", "dependencies": { @@ -3616,9 +5023,21 @@ }, "node_modules/ajv-formats/node_modules/json-schema-traverse": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, "license": "MIT" }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "dev": true, @@ -3668,7 +5087,9 @@ } }, "node_modules/aproba": { - "version": "2.1.0", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", "dev": true, "license": "ISC" }, @@ -3680,47 +5101,6 @@ "node": ">=14" } }, - "node_modules/are-we-there-yet": { - "version": "1.1.7", - "dev": true, - "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "node_modules/are-we-there-yet/node_modules/isarray": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "2.3.8", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/are-we-there-yet/node_modules/safe-buffer": { - "version": "5.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/are-we-there-yet/node_modules/string_decoder": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/arg": { "version": "4.1.3", "dev": true, @@ -3757,6 +5137,8 @@ }, "node_modules/array-differ": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", "dev": true, "license": "MIT", "engines": { @@ -3765,6 +5147,8 @@ }, "node_modules/array-ify": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", "dev": true, "license": "MIT" }, @@ -3791,6 +5175,8 @@ }, "node_modules/array-union": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, "license": "MIT", "engines": { @@ -3871,27 +5257,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.reduce": { - "version": "1.0.8", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-array-method-boxes-properly": "^1.0.0", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "is-string": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array.prototype.tosorted": { "version": "1.1.4", "dev": true, @@ -3930,47 +5295,27 @@ }, "node_modules/arrify": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/asap": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/asn1": { - "version": "0.2.6", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/ast-types-flow": { "version": "0.0.8", "dev": true, "license": "MIT", "peer": true }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, "node_modules/async-function": { "version": "1.0.0", "dev": true, @@ -3981,17 +5326,11 @@ }, "node_modules/asynckit": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true, "license": "MIT" }, - "node_modules/at-least-node": { - "version": "1.0.0", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/available-typed-arrays": { "version": "1.0.7", "dev": true, @@ -4006,19 +5345,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.13.2", - "dev": true, - "license": "MIT" - }, "node_modules/axe-core": { "version": "4.10.3", "dev": true, @@ -4028,6 +5354,18 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz", + "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/axobject-query": { "version": "4.1.0", "dev": true, @@ -4154,6 +5492,27 @@ "dev": true, "license": "MIT" }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/base64id": { "version": "2.0.0", "dev": true, @@ -4162,24 +5521,94 @@ "node": "^4.5.0 || >= 5.9" } }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", + "node_modules/baseline-browser-mapping": { + "version": "2.9.12", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.12.tgz", + "integrity": "sha512-Mij6Lij93pTAIsSYy5cyBQ975Qh9uLEc5rwGTpomiZeXZL9yIS6uORJakb3ScHgfs0serMMfIbXzokPMuEiRyw==", "dev": true, - "license": "BSD-3-Clause", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/bignumber.js": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.0.tgz", + "integrity": "sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/bin-links": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-5.0.0.tgz", + "integrity": "sha512-sdleLVfCjBtgO5cNjA2HVRvWBJAHs4zwenaCPMNJAJU0yNxpzj80IpjOIimkpkr+mhlA+how5poQtt53PygbHA==", + "dev": true, + "license": "ISC", "dependencies": { - "tweetnacl": "^0.14.3" + "cmd-shim": "^7.0.0", + "npm-normalize-package-bin": "^4.0.0", + "proc-log": "^5.0.0", + "read-cmd-shim": "^5.0.0", + "write-file-atomic": "^6.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/bin-links/node_modules/cmd-shim": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-7.0.0.tgz", + "integrity": "sha512-rtpaCbr164TPPh+zFdkWpCyZuKkjpAzODfaZCf/SVJZzJN+4bHQb/LP3Jzq5/+84um3XXY8r548XiWKSborwVw==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/bin-links/node_modules/read-cmd-shim": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-5.0.0.tgz", + "integrity": "sha512-SEbJV7tohp3DAAILbEMPXavBjAnMN0tVnh4+9G8ihV4Pq3HYF9h8QNez9zkJ1ILkv9G2BjdzwctznGZXgu/HGw==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/bin-links/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/before-after-hook": { - "version": "2.2.3", + "node_modules/bin-links/node_modules/write-file-atomic": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-6.0.0.tgz", + "integrity": "sha512-GmqrO8WJ1NuzJ2DrziEI2o57jKAVIQNf8a18W3nCYU3H7PNWqCCVTeH6/NQE93CIllIgQS98rrmVkYgTX9fFJQ==", "dev": true, - "license": "Apache-2.0" - }, - "node_modules/bignumber.js": { - "version": "9.1.2", - "license": "MIT", + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, "engines": { - "node": "*" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/binary-extensions": { @@ -4193,6 +5622,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, "node_modules/body-parser": { "version": "1.20.3", "dev": true, @@ -4263,7 +5704,9 @@ } }, "node_modules/browserslist": { - "version": "4.25.1", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, "funding": [ { @@ -4281,10 +5724,11 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001726", - "electron-to-chromium": "^1.5.173", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" @@ -4312,30 +5756,44 @@ "node-int64": "^0.4.0" } }, - "node_modules/buffer-from": { - "version": "1.1.2", + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, - "license": "MIT" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } }, - "node_modules/builtins": { - "version": "1.0.3", + "node_modules/buffer-from": { + "version": "1.1.2", "dev": true, "license": "MIT" }, - "node_modules/byline": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/byte-size": { - "version": "7.0.1", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/byte-size/-/byte-size-8.1.1.tgz", + "integrity": "sha512-tUkzZWK0M/qdoLEqikxBWe4kumyuwjl3HO6zHTr4yEI23EojPtLYXdG1+AQY7MN0cGyNDvEaJ8wiYQm6P2bPxg==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=12.17" } }, "node_modules/bytes": { @@ -4347,48 +5805,136 @@ } }, "node_modules/cacache": { - "version": "15.3.0", + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-20.0.3.tgz", + "integrity": "sha512-3pUp4e8hv07k1QlijZu6Kn7c9+ZpWWk4j3F8N3xPuCExULobqJydKYOTj1FTq58srkJsXvO7LbGAH4C0ZU3WGw==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", + "@npmcli/fs": "^5.0.0", + "fs-minipass": "^3.0.0", + "glob": "^13.0.0", + "lru-cache": "^11.1.0", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" + "minipass-pipeline": "^1.2.4", + "p-map": "^7.0.2", + "ssri": "^13.0.0", + "unique-filename": "^5.0.0" }, "engines": { - "node": ">= 10" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/cacache/node_modules/lru-cache": { - "version": "6.0.0", + "node_modules/cacache/node_modules/@npmcli/fs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-5.0.0.tgz", + "integrity": "sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og==", "dev": true, "license": "ISC", "dependencies": { - "yallist": "^4.0.0" + "semver": "^7.3.5" }, "engines": { - "node": ">=10" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/cacache/node_modules/yallist": { - "version": "4.0.0", + "node_modules/cacache/node_modules/balanced-match": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.2.tgz", + "integrity": "sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "jackspeak": "^4.2.3" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/cacache/node_modules/brace-expansion": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", + "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.5.tgz", + "integrity": "sha512-BzXxZg24Ibra1pbQ/zE7Kys4Ua1ks7Bn6pKLkVPZ9FZe4JQS6/Q7ef3LG1H+k7lUf5l4T3PLSyYyYJVYUvfgTw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.1", + "minipass": "^7.1.2", + "path-scurry": "^2.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "11.2.6", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", + "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.1.tgz", + "integrity": "sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/p-map": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cacache/node_modules/ssri": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-13.0.1.tgz", + "integrity": "sha512-QUiRf1+u9wPTL/76GTYlKttDEBWV1ga9ZXW8BG6kfdeyyM8LGPix9gROyg9V2+P0xNyF3X2Go526xKFdMZrHSQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } }, "node_modules/call-bind": { "version": "1.0.8", @@ -4452,6 +5998,8 @@ }, "node_modules/camelcase-keys": { "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", "dev": true, "license": "MIT", "dependencies": { @@ -4467,7 +6015,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001731", + "version": "1.0.30001762", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001762.tgz", + "integrity": "sha512-PxZwGNvH7Ak8WX5iXzoK1KPZttBXNPuaOvI2ZYU7NrlM+d9Ov+TUvlLOBNGzVXAntMSMMlJPd+jY6ovrVjSmUw==", "dev": true, "funding": [ { @@ -4485,26 +6035,14 @@ ], "license": "CC-BY-4.0" }, - "node_modules/caseless": { - "version": "0.12.0", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/chai": { - "version": "4.5.0", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", "dev": true, "license": "MIT", - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.1.0" - }, "engines": { - "node": ">=4" + "node": ">=18" } }, "node_modules/chalk": { @@ -4531,21 +6069,12 @@ } }, "node_modules/chardet": { - "version": "0.7.0", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz", + "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==", "dev": true, "license": "MIT" }, - "node_modules/check-error": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "get-func-name": "^2.0.2" - }, - "engines": { - "node": "*" - } - }, "node_modules/chokidar": { "version": "3.6.0", "dev": true, @@ -4581,11 +6110,13 @@ } }, "node_modules/chownr": { - "version": "2.0.0", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/chrome-trace-event": { @@ -4617,6 +6148,8 @@ }, "node_modules/clean-stack": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, "license": "MIT", "engines": { @@ -4625,6 +6158,8 @@ }, "node_modules/cli-cursor": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, "license": "MIT", "dependencies": { @@ -4634,12 +6169,27 @@ "node": ">=8" } }, + "node_modules/cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cli-width": { - "version": "3.0.0", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", "dev": true, "license": "ISC", "engines": { - "node": ">= 10" + "node": ">= 12" } }, "node_modules/cliui": { @@ -4654,6 +6204,8 @@ }, "node_modules/clone": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true, "license": "MIT", "engines": { @@ -4685,14 +6237,13 @@ } }, "node_modules/cmd-shim": { - "version": "4.1.0", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-6.0.3.tgz", + "integrity": "sha512-FMabTRlc5t5zjdenF6mS0MBeFZm0XqHqeOkcskKFb/LYCcRQ5fVgLOHVc4Lq9CqABd9zhjwPjMBCJvMCziSVtA==", "dev": true, "license": "ISC", - "dependencies": { - "mkdirp-infer-owner": "^2.0.0" - }, "engines": { - "node": ">=10" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/co": { @@ -4704,14 +6255,6 @@ "node": ">= 0.12.0" } }, - "node_modules/code-point-at": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/collect-v8-coverage": { "version": "1.0.2", "dev": true, @@ -4733,6 +6276,16 @@ "dev": true, "license": "MIT" }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/colorette": { "version": "2.0.20", "dev": true, @@ -4740,6 +6293,8 @@ }, "node_modules/columnify": { "version": "1.6.0", + "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.6.0.tgz", + "integrity": "sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==", "dev": true, "license": "MIT", "dependencies": { @@ -4752,6 +6307,8 @@ }, "node_modules/combined-stream": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, "license": "MIT", "dependencies": { @@ -4763,6 +6320,8 @@ }, "node_modules/commander": { "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, "license": "MIT" }, @@ -4774,8 +6333,17 @@ "node": ">= 12.0.0" } }, + "node_modules/common-ancestor-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", + "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==", + "dev": true, + "license": "ISC" + }, "node_modules/compare-func": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", "dev": true, "license": "MIT", "dependencies": { @@ -4783,17 +6351,6 @@ "dot-prop": "^5.1.0" } }, - "node_modules/compare-func/node_modules/dot-prop": { - "version": "5.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/concat-map": { "version": "0.0.1", "dev": true, @@ -4801,6 +6358,8 @@ }, "node_modules/concat-stream": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", "dev": true, "engines": [ "node >= 6.0" @@ -4813,15 +6372,6 @@ "typedarray": "^0.0.6" } }, - "node_modules/config-chain": { - "version": "1.1.13", - "dev": true, - "license": "MIT", - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, "node_modules/confusing-browser-globals": { "version": "1.0.11", "dev": true, @@ -4856,6 +6406,8 @@ }, "node_modules/console-control-strings": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", "dev": true, "license": "ISC" }, @@ -4868,153 +6420,126 @@ } }, "node_modules/conventional-changelog-angular": { - "version": "5.0.13", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", + "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", "dev": true, "license": "ISC", "dependencies": { - "compare-func": "^2.0.0", - "q": "^1.5.1" + "compare-func": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=16" } }, "node_modules/conventional-changelog-core": { - "version": "4.2.4", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-5.0.1.tgz", + "integrity": "sha512-Rvi5pH+LvgsqGwZPZ3Cq/tz4ty7mjijhr3qR4m9IBXNbxGGYgTVVO+duXzz9aArmHxFtwZ+LRkrNIMDQzgoY4A==", "dev": true, "license": "MIT", "dependencies": { "add-stream": "^1.0.0", - "conventional-changelog-writer": "^5.0.0", - "conventional-commits-parser": "^3.2.0", - "dateformat": "^3.0.0", - "get-pkg-repo": "^4.0.0", - "git-raw-commits": "^2.0.8", + "conventional-changelog-writer": "^6.0.0", + "conventional-commits-parser": "^4.0.0", + "dateformat": "^3.0.3", + "get-pkg-repo": "^4.2.1", + "git-raw-commits": "^3.0.0", "git-remote-origin-url": "^2.0.0", - "git-semver-tags": "^4.1.1", - "lodash": "^4.17.15", - "normalize-package-data": "^3.0.0", - "q": "^1.5.1", + "git-semver-tags": "^5.0.0", + "normalize-package-data": "^3.0.3", "read-pkg": "^3.0.0", - "read-pkg-up": "^3.0.0", - "through2": "^4.0.0" + "read-pkg-up": "^3.0.0" }, "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-core/node_modules/through2": { - "version": "4.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "3" + "node": ">=14" } }, "node_modules/conventional-changelog-preset-loader": { - "version": "2.3.4", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-3.0.0.tgz", + "integrity": "sha512-qy9XbdSLmVnwnvzEisjxdDiLA4OmV3o8db+Zdg4WiFw14fP3B6XNz98X0swPPpkTd/pc1K7+adKgEDM1JCUMiA==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=14" } }, "node_modules/conventional-changelog-writer": { - "version": "5.0.1", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-6.0.1.tgz", + "integrity": "sha512-359t9aHorPw+U+nHzUXHS5ZnPBOizRxfQsWT5ZDHBfvfxQOAik+yfuhKXG66CN5LEWPpMNnIMHUTCKeYNprvHQ==", "dev": true, "license": "MIT", "dependencies": { - "conventional-commits-filter": "^2.0.7", - "dateformat": "^3.0.0", + "conventional-commits-filter": "^3.0.0", + "dateformat": "^3.0.3", "handlebars": "^4.7.7", "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "semver": "^6.0.0", - "split": "^1.0.0", - "through2": "^4.0.0" + "meow": "^8.1.2", + "semver": "^7.0.0", + "split": "^1.0.1" }, "bin": { "conventional-changelog-writer": "cli.js" }, "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-writer/node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/conventional-changelog-writer/node_modules/through2": { - "version": "4.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "3" + "node": ">=14" } }, "node_modules/conventional-commits-filter": { - "version": "2.0.7", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-3.0.0.tgz", + "integrity": "sha512-1ymej8b5LouPx9Ox0Dw/qAO2dVdfpRFq28e5Y0jJEU8ZrLdy0vOSkkIInwmxErFGhg6SALro60ZrwYFVTUDo4Q==", "dev": true, "license": "MIT", "dependencies": { "lodash.ismatch": "^4.4.0", - "modify-values": "^1.0.0" + "modify-values": "^1.0.1" }, "engines": { - "node": ">=10" + "node": ">=14" } }, "node_modules/conventional-commits-parser": { - "version": "3.2.4", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-4.0.0.tgz", + "integrity": "sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg==", "dev": true, "license": "MIT", "dependencies": { "is-text-path": "^1.0.1", - "JSONStream": "^1.0.4", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" + "JSONStream": "^1.3.5", + "meow": "^8.1.2", + "split2": "^3.2.2" }, "bin": { "conventional-commits-parser": "cli.js" }, "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-commits-parser/node_modules/through2": { - "version": "4.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "3" + "node": ">=14" } }, "node_modules/conventional-recommended-bump": { - "version": "6.1.0", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-7.0.1.tgz", + "integrity": "sha512-Ft79FF4SlOFvX4PkwFDRnaNiIVX7YbmqGU0RwccUaiGvgp3S0a8ipR2/Qxk31vclDNM+GSdJOVs2KrsUCjblVA==", "dev": true, "license": "MIT", "dependencies": { "concat-stream": "^2.0.0", - "conventional-changelog-preset-loader": "^2.3.4", - "conventional-commits-filter": "^2.0.7", - "conventional-commits-parser": "^3.2.0", - "git-raw-commits": "^2.0.8", - "git-semver-tags": "^4.1.1", - "meow": "^8.0.0", - "q": "^1.5.1" + "conventional-changelog-preset-loader": "^3.0.0", + "conventional-commits-filter": "^3.0.0", + "conventional-commits-parser": "^4.0.0", + "git-raw-commits": "^3.0.0", + "git-semver-tags": "^5.0.0", + "meow": "^8.1.2" }, "bin": { "conventional-recommended-bump": "cli.js" }, "engines": { - "node": ">=10" + "node": ">=14" } }, "node_modules/convert-source-map": { @@ -5086,18 +6611,30 @@ } }, "node_modules/cosmiconfig": { - "version": "7.1.0", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", "dev": true, "license": "MIT", "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/create-jest": { @@ -5138,6 +6675,19 @@ "node": ">= 8" } }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/custom-event": { "version": "1.0.1", "dev": true, @@ -5151,23 +6701,14 @@ }, "node_modules/dargs": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/dashdash": { - "version": "1.14.1", - "dev": true, - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/data-view-buffer": { "version": "1.0.2", "dev": true, @@ -5226,6 +6767,8 @@ }, "node_modules/dateformat": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", "dev": true, "license": "MIT", "engines": { @@ -5238,7 +6781,9 @@ "license": "MIT" }, "node_modules/debug": { - "version": "4.4.1", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -5253,16 +6798,10 @@ } } }, - "node_modules/debuglog": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/decamelize": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, "license": "MIT", "engines": { @@ -5271,6 +6810,8 @@ }, "node_modules/decamelize-keys": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", "dev": true, "license": "MIT", "dependencies": { @@ -5286,20 +6827,14 @@ }, "node_modules/decamelize-keys/node_modules/map-obj": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10" - } - }, "node_modules/dedent": { "version": "1.6.0", "dev": true, @@ -5313,17 +6848,6 @@ } } }, - "node_modules/deep-eql": { - "version": "4.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/deep-is": { "version": "0.1.4", "dev": true, @@ -5339,6 +6863,8 @@ }, "node_modules/defaults": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "dev": true, "license": "MIT", "dependencies": { @@ -5364,6 +6890,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/define-properties": { "version": "1.2.1", "dev": true, @@ -5382,17 +6918,14 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" } }, - "node_modules/delegates": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, "node_modules/depd": { "version": "2.0.0", "dev": true, @@ -5403,6 +6936,8 @@ }, "node_modules/deprecation": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", "dev": true, "license": "ISC" }, @@ -5416,11 +6951,13 @@ } }, "node_modules/detect-indent": { - "version": "6.1.0", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", + "integrity": "sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=4" } }, "node_modules/detect-newline": { @@ -5431,15 +6968,6 @@ "node": ">=8" } }, - "node_modules/dezalgo": { - "version": "1.0.4", - "dev": true, - "license": "ISC", - "dependencies": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, "node_modules/di": { "version": "0.0.1", "dev": true, @@ -5461,17 +6989,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/doctrine": { "version": "2.1.0", "dev": true, @@ -5495,17 +7012,45 @@ } }, "node_modules/dot-prop": { - "version": "6.0.1", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "dev": true, "license": "MIT", "dependencies": { "is-obj": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://dotenvx.com" + } + }, + "node_modules/dotenv-expand": { + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz", + "integrity": "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dotenv": "^16.4.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" } }, "node_modules/dunder-proto": { @@ -5521,32 +7066,31 @@ "node": ">= 0.4" } }, - "node_modules/duplexer": { - "version": "0.1.2", + "node_modules/ee-first": { + "version": "1.1.1", "dev": true, "license": "MIT" }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/ecc-jsbn/node_modules/jsbn": { - "version": "0.1.1", - "dev": true, - "license": "MIT" - }, - "node_modules/ee-first": { - "version": "1.1.1", - "dev": true, - "license": "MIT" - }, "node_modules/electron-to-chromium": { - "version": "1.5.197", + "version": "1.5.267", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", + "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", "dev": true, "license": "ISC" }, @@ -5577,6 +7121,8 @@ }, "node_modules/encoding": { "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "dev": true, "license": "MIT", "optional": true, @@ -5586,6 +7132,8 @@ }, "node_modules/encoding/node_modules/iconv-lite": { "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "license": "MIT", "optional": true, @@ -5596,6 +7144,16 @@ "node": ">=0.10.0" } }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/engine.io": { "version": "6.6.4", "dev": true, @@ -5671,6 +7229,19 @@ "node": ">=10.13.0" } }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/ent": { "version": "2.2.2", "dev": true, @@ -5703,6 +7274,8 @@ }, "node_modules/env-paths": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true, "license": "MIT", "engines": { @@ -5722,6 +7295,8 @@ }, "node_modules/err-code": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", "dev": true, "license": "MIT" }, @@ -5800,11 +7375,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, "node_modules/es-define-property": { "version": "1.0.1", "dev": true, @@ -5849,7 +7419,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.7.0", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", "dev": true, "license": "MIT" }, @@ -5930,25 +7502,24 @@ } }, "node_modules/eslint": { - "version": "9.35.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.35.0.tgz", - "integrity": "sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg==", + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", + "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.1", - "@eslint/core": "^0.15.2", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.35.0", - "@eslint/plugin-kit": "^0.3.5", + "@eslint/js": "9.39.2", + "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", @@ -6117,16 +7688,16 @@ } }, "node_modules/eslint-plugin-array-func": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-array-func/-/eslint-plugin-array-func-4.0.0.tgz", - "integrity": "sha512-p3NY2idNIvgmQLF2/62ZskYt8gOuUgQ51smRc3Lh7FtSozpNc2sg+lniz9VaCagLZHEZTl8qGJKqE7xy8O/D/g==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-array-func/-/eslint-plugin-array-func-5.1.0.tgz", + "integrity": "sha512-+OULB0IQdENBmBf8pHMPPObgV6QyfeXFin483jPonOaiurI9UFmc8UydWriK5f5Gel8xBhQLA6NzMwbck1BUJw==", "dev": true, "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "peerDependencies": { - "eslint": ">=8.40.0" + "eslint": ">=8.51.0" } }, "node_modules/eslint-plugin-es-x": { @@ -6292,7 +7863,9 @@ } }, "node_modules/eslint-plugin-n": { - "version": "17.21.3", + "version": "17.23.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.23.1.tgz", + "integrity": "sha512-68PealUpYoHOBh332JLLD9Sj7OQUDkFpmcfqt8R9sySfFSeuGJjMTJQvCRRB96zO3A/PELRLkPrzsHmzEFQQ5A==", "dev": true, "license": "MIT", "dependencies": { @@ -6388,73 +7961,231 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, - "node_modules/eslint-plugin-react-hooks": { - "version": "5.2.0", + "node_modules/eslint-plugin-react-hooks": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.12", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-tsdoc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.5.0.tgz", + "integrity": "sha512-ush8ehCwub2rgE16OIgQPFyj/o0k3T8kL++9IrAI4knsmupNo8gvfO2ERgDHWWgTC5MglbwLVRswU93HyXqNpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@microsoft/tsdoc": "0.16.0", + "@microsoft/tsdoc-config": "0.18.0", + "@typescript-eslint/utils": "~8.46.0" + } + }, + "node_modules/eslint-plugin-tsdoc/node_modules/@typescript-eslint/project-service": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.4.tgz", + "integrity": "sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.46.4", + "@typescript-eslint/types": "^8.46.4", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/eslint-plugin-tsdoc/node_modules/@typescript-eslint/scope-manager": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.4.tgz", + "integrity": "sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/visitor-keys": "8.46.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-tsdoc/node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.4.tgz", + "integrity": "sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/eslint-plugin-tsdoc/node_modules/@typescript-eslint/types": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.4.tgz", + "integrity": "sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-tsdoc/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.4.tgz", + "integrity": "sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==", "dev": true, "license": "MIT", - "peer": true, + "dependencies": { + "@typescript-eslint/project-service": "8.46.4", + "@typescript-eslint/tsconfig-utils": "8.46.4", + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/visitor-keys": "8.46.4", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/eslint-plugin-react/node_modules/brace-expansion": { - "version": "1.1.12", + "node_modules/eslint-plugin-tsdoc/node_modules/@typescript-eslint/utils": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.4.tgz", + "integrity": "sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-react/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "peer": true, "dependencies": { - "brace-expansion": "^1.1.7" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.46.4", + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/typescript-estree": "8.46.4" }, "engines": { - "node": "*" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", + "node_modules/eslint-plugin-tsdoc/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.4.tgz", + "integrity": "sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "@typescript-eslint/types": "8.46.4", + "eslint-visitor-keys": "^4.2.1" }, - "bin": { - "resolve": "bin/resolve" + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/eslint-plugin-tsdoc": { - "version": "0.4.0", + "node_modules/eslint-plugin-tsdoc/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, - "license": "MIT", - "dependencies": { - "@microsoft/tsdoc": "0.15.1", - "@microsoft/tsdoc-config": "0.17.1" + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-scope": { @@ -6634,44 +8365,213 @@ } }, "node_modules/expect": { - "version": "29.7.0", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" + "@jest/expect-utils": "30.2.0", + "@jest/get-type": "30.1.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/extend": { - "version": "3.0.2", + "node_modules/expect/node_modules/@jest/expect-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", + "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } }, - "node_modules/external-editor": { - "version": "3.1.0", + "node_modules/expect/node_modules/@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", "dev": true, "license": "MIT", "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" + "@sinclair/typebox": "^0.34.0" }, "engines": { - "node": ">=4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/extsprintf": { - "version": "1.3.0", + "node_modules/expect/node_modules/@jest/types": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", + "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", "dev": true, - "engines": [ - "node >=0.6.0" + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.5", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/expect/node_modules/@sinclair/typebox": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz", + "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==", + "dev": true, + "license": "MIT" + }, + "node_modules/expect/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/expect/node_modules/ci-info": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/expect/node_modules/jest-diff": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", + "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/expect/node_modules/jest-matcher-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", + "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "jest-diff": "30.2.0", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/expect/node_modules/jest-message-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", + "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.2.0", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.2.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/expect/node_modules/jest-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", + "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/expect/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/expect/node_modules/pretty-format": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", + "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", + "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/extend": { + "version": "3.0.2", + "dev": true, "license": "MIT" }, "node_modules/fast-deep-equal": { @@ -6686,6 +8586,8 @@ }, "node_modules/fast-glob": { "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "license": "MIT", "dependencies": { @@ -6701,6 +8603,8 @@ }, "node_modules/fast-glob/node_modules/glob-parent": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "license": "ISC", "dependencies": { @@ -6712,7 +8616,6 @@ }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", - "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { @@ -6721,7 +8624,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.6", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", "dev": true, "funding": [ { @@ -6744,7 +8649,9 @@ } }, "node_modules/fastq": { - "version": "1.19.1", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", "dev": true, "license": "ISC", "dependencies": { @@ -6761,6 +8668,8 @@ }, "node_modules/figures": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "license": "MIT", "dependencies": { @@ -6775,6 +8684,8 @@ }, "node_modules/figures/node_modules/escape-string-regexp": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, "license": "MIT", "engines": { @@ -6792,23 +8703,38 @@ "node": ">=16.0.0" } }, - "node_modules/fill-range": { - "version": "7.1.1", + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "to-regex-range": "^5.0.1" + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/filter-obj": { - "version": "1.1.0", + "node_modules/fill-range": { + "version": "7.1.1", "dev": true, "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/finalhandler": { @@ -6925,50 +8851,120 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/forever-agent": { - "version": "0.6.1", + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/front-matter": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-4.0.2.tgz", + "integrity": "sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-yaml": "^3.13.1" + } + }, + "node_modules/front-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "*" + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" } }, - "node_modules/form-data": { - "version": "2.3.3", + "node_modules/front-matter/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, "license": "MIT", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "engines": { - "node": ">= 0.12" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "license": "MIT" + }, "node_modules/fs-extra": { - "version": "9.1.0", + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz", + "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==", "dev": true, "license": "MIT", "dependencies": { - "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=14.14" } }, "node_modules/fs-minipass": { - "version": "2.1.0", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", "dev": true, "license": "ISC", "dependencies": { - "minipass": "^3.0.0" + "minipass": "^7.0.3" }, "engines": { - "node": ">= 8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/fs.realpath": { @@ -7023,69 +9019,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gauge": { - "version": "2.7.4", - "dev": true, - "license": "ISC", - "dependencies": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "node_modules/gauge/node_modules/ansi-regex": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gauge/node_modules/aproba": { - "version": "1.2.0", - "dev": true, - "license": "ISC" - }, - "node_modules/gauge/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gauge/node_modules/string-width": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gauge/node_modules/strip-ansi": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/gensync": { "version": "1.0.0-beta.2", "dev": true, @@ -7102,14 +9035,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-func-name": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/get-intrinsic": { "version": "1.3.0", "dev": true, @@ -7143,6 +9068,8 @@ }, "node_modules/get-pkg-repo": { "version": "4.2.1", + "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", + "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", "dev": true, "license": "MIT", "dependencies": { @@ -7158,8 +9085,43 @@ "node": ">=6.9.0" } }, + "node_modules/get-pkg-repo/node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/get-pkg-repo/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/get-pkg-repo/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, "node_modules/get-port": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", "dev": true, "license": "MIT", "engines": { @@ -7219,42 +9181,28 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/getpass": { - "version": "0.1.7", - "dev": true, - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, "node_modules/git-raw-commits": { - "version": "2.0.11", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-3.0.0.tgz", + "integrity": "sha512-b5OHmZ3vAgGrDn/X0kS+9qCfNKWe4K/jFnhwzVWWg0/k5eLa3060tZShrRg8Dja5kPc+YjS0Gc6y7cRr44Lpjw==", "dev": true, "license": "MIT", "dependencies": { "dargs": "^7.0.0", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" + "meow": "^8.1.2", + "split2": "^3.2.2" }, "bin": { "git-raw-commits": "cli.js" }, "engines": { - "node": ">=10" - } - }, - "node_modules/git-raw-commits/node_modules/through2": { - "version": "4.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "3" + "node": ">=14" } }, "node_modules/git-remote-origin-url": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", + "integrity": "sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==", "dev": true, "license": "MIT", "dependencies": { @@ -7267,6 +9215,8 @@ }, "node_modules/git-remote-origin-url/node_modules/pify": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, "license": "MIT", "engines": { @@ -7274,47 +9224,47 @@ } }, "node_modules/git-semver-tags": { - "version": "4.1.1", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-5.0.1.tgz", + "integrity": "sha512-hIvOeZwRbQ+7YEUmCkHqo8FOLQZCEn18yevLHADlFPZY02KJGsu5FZt9YW/lybfK2uhWFI7Qg/07LekJiTv7iA==", "dev": true, "license": "MIT", "dependencies": { - "meow": "^8.0.0", - "semver": "^6.0.0" + "meow": "^8.1.2", + "semver": "^7.0.0" }, "bin": { "git-semver-tags": "cli.js" }, "engines": { - "node": ">=10" - } - }, - "node_modules/git-semver-tags/node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node": ">=14" } }, "node_modules/git-up": { - "version": "4.0.5", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-7.0.0.tgz", + "integrity": "sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==", "dev": true, "license": "MIT", "dependencies": { - "is-ssh": "^1.3.0", - "parse-url": "^6.0.0" + "is-ssh": "^1.4.0", + "parse-url": "^8.1.0" } }, "node_modules/git-url-parse": { - "version": "11.6.0", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-14.0.0.tgz", + "integrity": "sha512-NnLweV+2A4nCvn4U/m2AoYu0pPKlsmhK9cknG7IMwsjFY1S2jxM+mAhsDxyxfCIGfGaD+dozsyX4b6vkYc83yQ==", "dev": true, "license": "MIT", "dependencies": { - "git-up": "^4.0.0" + "git-up": "^7.0.0" } }, "node_modules/gitconfiglocal": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", + "integrity": "sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==", "dev": true, "license": "BSD", "dependencies": { @@ -7402,25 +9352,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/globby": { - "version": "11.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/globrex": { "version": "0.1.2", "dev": true, @@ -7442,25 +9373,6 @@ "dev": true, "license": "ISC" }, - "node_modules/graphemer": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/gzip-size": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "duplexer": "^0.1.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/handlebars": { "version": "4.7.8", "dev": true, @@ -7481,28 +9393,10 @@ "uglify-js": "^3.1.4" } }, - "node_modules/har-schema": { - "version": "2.0.0", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/hard-rejection": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", "dev": true, "license": "MIT", "engines": { @@ -7580,6 +9474,8 @@ }, "node_modules/has-unicode": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", "dev": true, "license": "ISC" }, @@ -7595,32 +9491,28 @@ } }, "node_modules/hosted-git-info": { - "version": "4.1.0", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.2.tgz", + "integrity": "sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==", "dev": true, "license": "ISC", "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^11.1.0" }, "engines": { - "node": ">=10" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "6.0.0", + "version": "11.2.6", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", + "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, + "license": "BlueOak-1.0.0", "engines": { - "node": ">=10" + "node": "20 || >=22" } }, - "node_modules/hosted-git-info/node_modules/yallist": { - "version": "4.0.0", - "dev": true, - "license": "ISC" - }, "node_modules/html-escaper": { "version": "2.0.2", "dev": true, @@ -7628,6 +9520,8 @@ }, "node_modules/http-cache-semantics": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", "dev": true, "license": "BSD-2-Clause" }, @@ -7668,42 +9562,31 @@ } }, "node_modules/http-proxy-agent": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http-signature": { - "version": "1.2.0", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, "license": "MIT", "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" + "node": ">= 14" } }, "node_modules/https-proxy-agent": { - "version": "5.0.1", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "6", + "agent-base": "^7.1.2", "debug": "4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/human-signals": { @@ -7714,14 +9597,6 @@ "node": ">=10.17.0" } }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.0.0" - } - }, "node_modules/iconv-lite": { "version": "0.4.24", "dev": true, @@ -7733,104 +9608,97 @@ "node": ">=0.10.0" } }, - "node_modules/ignore": { - "version": "5.3.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/ignore-walk": { - "version": "3.0.4", - "dev": true, - "license": "ISC", - "dependencies": { - "minimatch": "^3.0.4" - } - }, - "node_modules/ignore-walk/node_modules/brace-expansion": { - "version": "1.1.12", + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" }, - "node_modules/ignore-walk/node_modules/minimatch": { - "version": "3.1.2", + "node_modules/ignore": { + "version": "5.3.2", "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", "engines": { - "node": "*" + "node": ">= 4" } }, - "node_modules/import-fresh": { - "version": "3.3.1", + "node_modules/ignore-walk": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-8.0.0.tgz", + "integrity": "sha512-FCeMZT4NiRQGh+YkeKMtWrOmBgWjHjMJ26WQWrRQyoyzqevdaGSakUaJW5xQYmjLlUVk2qUnCjYVBax9EKKg8A==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "minimatch": "^10.0.3" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/import-local": { - "version": "3.2.0", + "node_modules/ignore-walk/node_modules/balanced-match": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.2.tgz", + "integrity": "sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==", "dev": true, "license": "MIT", "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" + "jackspeak": "^4.2.3" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "20 || >=22" } }, - "node_modules/import-local/node_modules/find-up": { - "version": "4.1.0", + "node_modules/ignore-walk/node_modules/brace-expansion": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", + "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "balanced-match": "^4.0.2" }, "engines": { - "node": ">=8" + "node": "20 || >=22" } }, - "node_modules/import-local/node_modules/locate-path": { - "version": "5.0.0", + "node_modules/ignore-walk/node_modules/minimatch": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.1.tgz", + "integrity": "sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "p-locate": "^4.1.0" + "brace-expansion": "^5.0.2" }, "engines": { - "node": ">=8" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/import-local/node_modules/p-limit": { - "version": "2.3.0", + "node_modules/import-fresh": { + "version": "3.3.1", "dev": true, "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { "node": ">=6" @@ -7839,26 +9707,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-local/node_modules/p-locate": { - "version": "4.1.0", + "node_modules/import-local": { + "version": "3.2.0", "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/import-local/node_modules/pkg-dir": { - "version": "4.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" + "bin": { + "import-local-fixture": "fixtures/cli.js" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/imurmurhash": { @@ -7871,17 +9735,14 @@ }, "node_modules/indent-string": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/infer-owner": { - "version": "1.0.4", - "dev": true, - "license": "ISC" - }, "node_modules/inflight": { "version": "1.0.6", "dev": true, @@ -7898,61 +9759,55 @@ }, "node_modules/ini": { "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true, "license": "ISC" }, "node_modules/init-package-json": { - "version": "2.0.5", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-8.2.2.tgz", + "integrity": "sha512-pXVMn67Jdw2hPKLCuJZj62NC9B2OIDd1R3JwZXTHXuEnfN3Uq5kJbKOSld6YEU+KOGfMD82EzxFTYz5o0SSJoA==", "dev": true, "license": "ISC", "dependencies": { - "npm-package-arg": "^8.1.5", - "promzard": "^0.3.0", - "read": "~1.0.1", - "read-package-json": "^4.1.1", - "semver": "^7.3.5", + "@npmcli/package-json": "^7.0.0", + "npm-package-arg": "^13.0.0", + "promzard": "^2.0.0", + "read": "^4.0.0", + "semver": "^7.7.2", "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/init-package-json/node_modules/read-package-json": { - "version": "4.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.1", - "json-parse-even-better-errors": "^2.3.0", - "normalize-package-data": "^3.0.0", - "npm-normalize-package-bin": "^1.0.0" + "validate-npm-package-name": "^6.0.2" }, "engines": { - "node": ">=10" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/inquirer": { - "version": "7.3.3", + "version": "12.9.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-12.9.6.tgz", + "integrity": "sha512-603xXOgyfxhuis4nfnWaZrMaotNT0Km9XwwBNWUKbIDqeCY89jGr2F9YPEMiNhU6XjIP4VoWISMBFfcc5NgrTw==", "dev": true, "license": "MIT", "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.19", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.6.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" + "@inquirer/ansi": "^1.0.0", + "@inquirer/core": "^10.2.2", + "@inquirer/prompts": "^7.8.6", + "@inquirer/type": "^3.0.8", + "mute-stream": "^2.0.0", + "run-async": "^4.0.5", + "rxjs": "^7.8.2" }, "engines": { - "node": ">=8.0.0" + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, "node_modules/internal-slot": { @@ -7977,13 +9832,11 @@ } }, "node_modules/ip-address": { - "version": "9.0.5", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", "dev": true, "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, "engines": { "node": ">= 12" } @@ -8087,21 +9940,18 @@ } }, "node_modules/is-ci": { - "version": "2.0.0", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", "dev": true, "license": "MIT", "dependencies": { - "ci-info": "^2.0.0" + "ci-info": "^3.2.0" }, "bin": { "is-ci": "bin.js" } }, - "node_modules/is-ci/node_modules/ci-info": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, "node_modules/is-core-module": { "version": "2.16.1", "dev": true, @@ -8147,6 +9997,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "dev": true, @@ -8213,10 +10079,15 @@ "node": ">=0.10.0" } }, - "node_modules/is-lambda": { - "version": "1.0.1", + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=8" + } }, "node_modules/is-map": { "version": "2.0.3", @@ -8265,6 +10136,8 @@ }, "node_modules/is-obj": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true, "license": "MIT", "engines": { @@ -8273,14 +10146,8 @@ }, "node_modules/is-plain-obj": { "version": "1.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", "dev": true, "license": "MIT", "engines": { @@ -8331,6 +10198,8 @@ }, "node_modules/is-ssh": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.1.tgz", + "integrity": "sha512-JNeu1wQsHjyHgn9NcWTaXq6zWSR6hqE0++zhfZlkFBbScNkyvxCdeV8sRkSBaeLKxmbpR21brail63ACNxJ0Tg==", "dev": true, "license": "MIT", "dependencies": { @@ -8381,6 +10250,8 @@ }, "node_modules/is-text-path": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", + "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", "dev": true, "license": "MIT", "dependencies": { @@ -8404,10 +10275,18 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/is-weakmap": { "version": "2.0.2", @@ -8449,6 +10328,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/isarray": { "version": "2.0.5", "dev": true, @@ -8478,11 +10370,6 @@ "node": ">=0.10.0" } }, - "node_modules/isstream": { - "version": "0.1.2", - "dev": true, - "license": "MIT" - }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "dev": true, @@ -8561,6 +10448,40 @@ "node": ">= 0.4" } }, + "node_modules/jackspeak": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz", + "integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^9.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jasmine-core": { "version": "4.6.1", "dev": true, @@ -8804,6 +10725,21 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-environment-node/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jest-get-type": { "version": "29.6.3", "dev": true, @@ -8882,16 +10818,104 @@ } }, "node_modules/jest-mock": { - "version": "29.7.0", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", + "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", + "@jest/types": "30.2.0", "@types/node": "*", - "jest-util": "^29.7.0" + "jest-util": "30.2.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-mock/node_modules/@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-mock/node_modules/@jest/types": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", + "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.5", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-mock/node_modules/@sinclair/typebox": { + "version": "0.34.47", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.47.tgz", + "integrity": "sha512-ZGIBQ+XDvO5JQku9wmwtabcVTHJsgSWAHYtVuM9pBNNR5E88v6Jcj/llpmsjivig5X8A8HHOb4/mbEKPS5EvAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-mock/node_modules/ci-info": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-mock/node_modules/jest-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", + "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-mock/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/jest-pnp-resolver": { @@ -9021,6 +11045,21 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-runtime/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jest-snapshot": { "version": "29.7.0", "dev": true, @@ -9051,6 +11090,23 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-snapshot/node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jest-util": { "version": "29.7.0", "dev": true, @@ -9142,6 +11198,8 @@ }, "node_modules/jju": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", "dev": true, "license": "MIT" }, @@ -9151,7 +11209,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -9161,11 +11221,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbn": { - "version": "1.1.0", - "dev": true, - "license": "MIT" - }, "node_modules/jsdoc-type-pratt-parser": { "version": "4.1.0", "dev": true, @@ -9200,11 +11255,6 @@ "dev": true, "license": "MIT" }, - "node_modules/json-schema": { - "version": "0.4.0", - "dev": true, - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "dev": true, @@ -9215,8 +11265,20 @@ "dev": true, "license": "MIT" }, + "node_modules/json-stringify-nice": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz", + "integrity": "sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw==", + "dev": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/json-stringify-safe": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", "dev": true, "license": "ISC" }, @@ -9231,8 +11293,17 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true, + "license": "MIT" + }, "node_modules/jsonfile": { - "version": "6.1.0", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "dependencies": { @@ -9244,6 +11315,8 @@ }, "node_modules/jsonparse": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", "dev": true, "engines": [ "node >= 0.2.0" @@ -9252,6 +11325,8 @@ }, "node_modules/JSONStream": { "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", "dev": true, "license": "(MIT OR Apache-2.0)", "dependencies": { @@ -9265,20 +11340,6 @@ "node": "*" } }, - "node_modules/jsprim": { - "version": "1.4.2", - "dev": true, - "license": "MIT", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "dev": true, @@ -9294,6 +11355,20 @@ "node": ">=4.0" } }, + "node_modules/just-diff": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-6.0.2.tgz", + "integrity": "sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA==", + "dev": true, + "license": "MIT" + }, + "node_modules/just-diff-apply": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-5.5.0.tgz", + "integrity": "sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==", + "dev": true, + "license": "MIT" + }, "node_modules/karma": { "version": "6.4.4", "dev": true, @@ -9350,347 +11425,718 @@ "which": "bin/which" } }, - "node_modules/karma-jasmine": { - "version": "5.1.0", + "node_modules/karma-jasmine": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "jasmine-core": "^4.1.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "karma": "^6.0.0" + } + }, + "node_modules/karma-webpack": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "^7.1.3", + "minimatch": "^9.0.3", + "webpack-merge": "^4.1.5" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/karma-webpack/node_modules/webpack-merge": { + "version": "4.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.15" + } + }, + "node_modules/karma/node_modules/brace-expansion": { + "version": "1.1.12", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/karma/node_modules/minimatch": { + "version": "3.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/karma/node_modules/mkdirp": { + "version": "0.5.6", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "dev": true, + "license": "CC0-1.0", + "peer": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/lerna": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/lerna/-/lerna-9.0.4.tgz", + "integrity": "sha512-wKy9TOkkdCWPWET0R5o7mh7J0KuNNjxE0g+qTruNAt5ffWwy54wfWiJtWyDSMOrcGDt6gtisDBTKniOqK/sJvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lerna/create": "9.0.4", + "@npmcli/arborist": "9.1.6", + "@npmcli/package-json": "7.0.2", + "@npmcli/run-script": "10.0.3", + "@nx/devkit": ">=21.5.2 < 23.0.0", + "@octokit/plugin-enterprise-rest": "6.0.1", + "@octokit/rest": "20.1.2", + "aproba": "2.0.0", + "byte-size": "8.1.1", + "chalk": "4.1.0", + "cmd-shim": "6.0.3", + "color-support": "1.1.3", + "columnify": "1.6.0", + "console-control-strings": "^1.1.0", + "conventional-changelog-angular": "7.0.0", + "conventional-changelog-core": "5.0.1", + "conventional-recommended-bump": "7.0.1", + "cosmiconfig": "9.0.0", + "dedent": "1.5.3", + "envinfo": "7.13.0", + "execa": "5.0.0", + "fs-extra": "^11.2.0", + "get-port": "5.1.1", + "get-stream": "6.0.0", + "git-url-parse": "14.0.0", + "glob-parent": "6.0.2", + "has-unicode": "2.0.1", + "import-local": "3.1.0", + "ini": "^1.3.8", + "init-package-json": "8.2.2", + "inquirer": "12.9.6", + "is-ci": "3.0.1", + "is-stream": "2.0.0", + "jest-diff": ">=30.0.0 < 31", + "js-yaml": "4.1.1", + "libnpmaccess": "10.0.3", + "libnpmpublish": "11.1.2", + "load-json-file": "6.2.0", + "make-dir": "4.0.0", + "make-fetch-happen": "15.0.2", + "minimatch": "3.0.5", + "multimatch": "5.0.0", + "npm-package-arg": "13.0.1", + "npm-packlist": "10.0.3", + "npm-registry-fetch": "19.1.0", + "nx": ">=21.5.3 < 23.0.0", + "p-map": "4.0.0", + "p-map-series": "2.1.0", + "p-pipe": "3.1.0", + "p-queue": "6.6.2", + "p-reduce": "2.1.0", + "p-waterfall": "2.1.1", + "pacote": "21.0.1", + "pify": "5.0.0", + "read-cmd-shim": "4.0.0", + "resolve-from": "5.0.0", + "rimraf": "^6.1.2", + "semver": "7.7.2", + "set-blocking": "^2.0.0", + "signal-exit": "3.0.7", + "slash": "3.0.0", + "ssri": "12.0.0", + "string-width": "^4.2.3", + "tar": "7.5.7", + "temp-dir": "1.0.0", + "through": "2.3.8", + "tinyglobby": "0.2.12", + "typescript": ">=3 < 6", + "upath": "2.0.1", + "uuid": "^11.1.0", + "validate-npm-package-license": "3.0.4", + "validate-npm-package-name": "6.0.2", + "wide-align": "1.1.5", + "write-file-atomic": "5.0.1", + "write-pkg": "4.0.0", + "yargs": "17.7.2", + "yargs-parser": "21.1.1" + }, + "bin": { + "lerna": "dist/cli.js" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/lerna/node_modules/@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/lerna/node_modules/@sinclair/typebox": { + "version": "0.34.48", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.48.tgz", + "integrity": "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lerna/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/lerna/node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/lerna/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/lerna/node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/lerna/node_modules/envinfo": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", + "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", + "dev": true, + "license": "MIT", + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/lerna/node_modules/execa": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", + "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/lerna/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", - "dependencies": { - "jasmine-core": "^4.1.0" - }, "engines": { - "node": ">=12" + "node": ">=12.0.0" }, "peerDependencies": { - "karma": "^6.0.0" + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/karma-webpack": { - "version": "5.0.1", + "node_modules/lerna/node_modules/get-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", + "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", "dev": true, "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lerna/node_modules/glob": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.5.tgz", + "integrity": "sha512-BzXxZg24Ibra1pbQ/zE7Kys4Ua1ks7Bn6pKLkVPZ9FZe4JQS6/Q7ef3LG1H+k7lUf5l4T3PLSyYyYJVYUvfgTw==", + "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "glob": "^7.1.3", - "minimatch": "^9.0.3", - "webpack-merge": "^4.1.5" + "minimatch": "^10.2.1", + "minipass": "^7.1.2", + "path-scurry": "^2.0.0" }, "engines": { - "node": ">= 18" + "node": "20 || >=22" }, - "peerDependencies": { - "webpack": "^5.0.0" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/karma-webpack/node_modules/webpack-merge": { - "version": "4.2.2", + "node_modules/lerna/node_modules/glob/node_modules/balanced-match": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.2.tgz", + "integrity": "sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==", "dev": true, "license": "MIT", "dependencies": { - "lodash": "^4.17.15" + "jackspeak": "^4.2.3" + }, + "engines": { + "node": "20 || >=22" } }, - "node_modules/karma/node_modules/brace-expansion": { - "version": "1.1.12", + "node_modules/lerna/node_modules/glob/node_modules/brace-expansion": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", + "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" } }, - "node_modules/karma/node_modules/minimatch": { - "version": "3.1.2", + "node_modules/lerna/node_modules/glob/node_modules/minimatch": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.1.tgz", + "integrity": "sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^5.0.2" }, "engines": { - "node": "*" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/karma/node_modules/mkdirp": { - "version": "0.5.6", + "node_modules/lerna/node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, "license": "MIT", "dependencies": { - "minimist": "^1.2.6" + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" }, "bin": { - "mkdirp": "bin/cmd.js" + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/karma/node_modules/tmp": { - "version": "0.2.4", + "node_modules/lerna/node_modules/is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", "dev": true, "license": "MIT", "engines": { - "node": ">=14.14" + "node": ">=8" } }, - "node_modules/keyv": { - "version": "4.5.4", + "node_modules/lerna/node_modules/jest-diff": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", + "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", "dev": true, "license": "MIT", "dependencies": { - "json-buffer": "3.0.1" + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/kind-of": { - "version": "6.0.3", + "node_modules/lerna/node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/kleur": { - "version": "3.0.3", + "node_modules/lerna/node_modules/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=6" + "node": "*" } }, - "node_modules/language-subtag-registry": { - "version": "0.3.23", + "node_modules/lerna/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, - "license": "CC0-1.0", - "peer": true + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } }, - "node_modules/language-tags": { - "version": "1.0.9", + "node_modules/lerna/node_modules/pretty-format": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", + "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "language-subtag-registry": "^0.3.20" + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" }, "engines": { - "node": ">=0.10" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/lerna": { - "version": "4.0.0", + "node_modules/lerna/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "dependencies": { - "@lerna/add": "4.0.0", - "@lerna/bootstrap": "4.0.0", - "@lerna/changed": "4.0.0", - "@lerna/clean": "4.0.0", - "@lerna/cli": "4.0.0", - "@lerna/create": "4.0.0", - "@lerna/diff": "4.0.0", - "@lerna/exec": "4.0.0", - "@lerna/import": "4.0.0", - "@lerna/info": "4.0.0", - "@lerna/init": "4.0.0", - "@lerna/link": "4.0.0", - "@lerna/list": "4.0.0", - "@lerna/publish": "4.0.0", - "@lerna/run": "4.0.0", - "@lerna/version": "4.0.0", - "import-local": "^3.0.2", - "npmlog": "^4.1.2" - }, - "bin": { - "lerna": "cli.js" - }, "engines": { - "node": ">= 10.18.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/leven": { - "version": "3.1.0", + "node_modules/lerna/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/levn": { - "version": "0.4.1", + "node_modules/lerna/node_modules/rimraf": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz", + "integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "glob": "^13.0.3", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" }, "engines": { - "node": ">= 0.8.0" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/libnpmaccess": { - "version": "4.0.3", + "node_modules/lerna/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "minipass": "^3.1.1", - "npm-package-arg": "^8.1.2", - "npm-registry-fetch": "^11.0.0" + "bin": { + "semver": "bin/semver.js" }, "engines": { "node": ">=10" } }, - "node_modules/libnpmaccess/node_modules/lru-cache": { - "version": "6.0.0", + "node_modules/lerna/node_modules/tinyglobby": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", + "integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "fdir": "^6.4.3", + "picomatch": "^4.0.2" }, "engines": { - "node": ">=10" + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/libnpmaccess/node_modules/make-fetch-happen": { - "version": "9.1.0", + "node_modules/lerna/node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, "license": "ISC", "dependencies": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.2.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.2", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^6.0.0", - "ssri": "^8.0.0" + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">= 10" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/libnpmaccess/node_modules/npm-registry-fetch": { - "version": "11.0.0", + "node_modules/lerna/node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, "license": "ISC", - "dependencies": { - "make-fetch-happen": "^9.0.1", - "minipass": "^3.1.3", - "minipass-fetch": "^1.3.0", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.0.0", - "npm-package-arg": "^8.0.0" - }, "engines": { - "node": ">=10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/libnpmaccess/node_modules/socks-proxy-agent": { - "version": "6.2.1", + "node_modules/lerna/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">= 10" + "node": ">=12" } }, - "node_modules/libnpmaccess/node_modules/yallist": { - "version": "4.0.0", + "node_modules/lerna/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, - "license": "ISC" + "license": "ISC", + "engines": { + "node": ">=12" + } }, - "node_modules/libnpmpublish": { - "version": "4.0.2", + "node_modules/leven": { + "version": "3.1.0", "dev": true, - "license": "ISC", - "dependencies": { - "normalize-package-data": "^3.0.2", - "npm-package-arg": "^8.1.2", - "npm-registry-fetch": "^11.0.0", - "semver": "^7.1.3", - "ssri": "^8.0.1" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=6" } }, - "node_modules/libnpmpublish/node_modules/lru-cache": { - "version": "6.0.0", + "node_modules/levn": { + "version": "0.4.1", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, "engines": { - "node": ">=10" + "node": ">= 0.8.0" } }, - "node_modules/libnpmpublish/node_modules/make-fetch-happen": { - "version": "9.1.0", + "node_modules/libnpmaccess": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-10.0.3.tgz", + "integrity": "sha512-JPHTfWJxIK+NVPdNMNGnkz4XGX56iijPbe0qFWbdt68HL+kIvSzh+euBL8npLZvl2fpaxo+1eZSdoG15f5YdIQ==", "dev": true, "license": "ISC", "dependencies": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.2.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.2", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^6.0.0", - "ssri": "^8.0.0" + "npm-package-arg": "^13.0.0", + "npm-registry-fetch": "^19.0.0" }, "engines": { - "node": ">= 10" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/libnpmpublish/node_modules/npm-registry-fetch": { - "version": "11.0.0", + "node_modules/libnpmpublish": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/libnpmpublish/-/libnpmpublish-11.1.2.tgz", + "integrity": "sha512-tNcU3cLH7toloAzhOOrBDhjzgbxpyuYvkf+BPPnnJCdc5EIcdJ8JcT+SglvCQKKyZ6m9dVXtCVlJcA6csxKdEA==", "dev": true, "license": "ISC", "dependencies": { - "make-fetch-happen": "^9.0.1", - "minipass": "^3.1.3", - "minipass-fetch": "^1.3.0", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.0.0", - "npm-package-arg": "^8.0.0" + "@npmcli/package-json": "^7.0.0", + "ci-info": "^4.0.0", + "npm-package-arg": "^13.0.0", + "npm-registry-fetch": "^19.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.7", + "sigstore": "^4.0.0", + "ssri": "^12.0.0" }, "engines": { - "node": ">=10" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/libnpmpublish/node_modules/socks-proxy-agent": { - "version": "6.2.1", + "node_modules/libnpmpublish/node_modules/ci-info": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, "engines": { - "node": ">= 10" + "node": ">=8" } }, - "node_modules/libnpmpublish/node_modules/yallist": { - "version": "4.0.0", - "dev": true, - "license": "ISC" - }, "node_modules/lines-and-columns": { "version": "1.2.4", "dev": true, @@ -9706,6 +12152,8 @@ }, "node_modules/load-json-file": { "version": "6.2.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-6.2.0.tgz", + "integrity": "sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9720,6 +12168,8 @@ }, "node_modules/load-json-file/node_modules/type-fest": { "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { @@ -9727,11 +12177,17 @@ } }, "node_modules/loader-runner": { - "version": "4.3.0", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", + "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", "dev": true, "license": "MIT", "engines": { "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/locate-path": { @@ -9749,17 +12205,16 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash._reinterpolate": { - "version": "3.0.0", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "dev": true, "license": "MIT" }, "node_modules/lodash.ismatch": { "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", + "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", "dev": true, "license": "MIT" }, @@ -9773,21 +12228,21 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.template": { - "version": "4.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash._reinterpolate": "^3.0.0", - "lodash.templatesettings": "^4.0.0" - } - }, - "node_modules/lodash.templatesettings": { - "version": "4.2.0", + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "license": "MIT", "dependencies": { - "lodash._reinterpolate": "^3.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/log4js": { @@ -9817,14 +12272,6 @@ "loose-envify": "cli.js" } }, - "node_modules/loupe": { - "version": "2.3.7", - "dev": true, - "license": "MIT", - "dependencies": { - "get-func-name": "^2.0.1" - } - }, "node_modules/lru-cache": { "version": "5.1.1", "dev": true, @@ -9858,46 +12305,28 @@ "license": "ISC" }, "node_modules/make-fetch-happen": { - "version": "8.0.14", + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.2.tgz", + "integrity": "sha512-sI1NY4lWlXBAfjmCtVWIIpBypbBdhHtcjnwnv+gtCnsaOffyFil3aidszGC8hgzJe+fT1qix05sWxmD/Bmf/oQ==", "dev": true, "license": "ISC", "dependencies": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.0.5", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", + "@npmcli/agent": "^4.0.0", + "cacache": "^20.0.1", + "http-cache-semantics": "^4.1.1", + "minipass": "^7.0.2", + "minipass-fetch": "^4.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", + "negotiator": "^1.0.0", + "proc-log": "^5.0.0", "promise-retry": "^2.0.1", - "socks-proxy-agent": "^5.0.0", - "ssri": "^8.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "6.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" + "ssri": "^12.0.0" }, "engines": { - "node": ">=10" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/make-fetch-happen/node_modules/yallist": { - "version": "4.0.0", - "dev": true, - "license": "ISC" - }, "node_modules/makeerror": { "version": "1.0.12", "dev": true, @@ -9908,6 +12337,8 @@ }, "node_modules/map-obj": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true, "license": "MIT", "engines": { @@ -9963,6 +12394,8 @@ }, "node_modules/meow": { "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", "dev": true, "license": "MIT", "dependencies": { @@ -9987,6 +12420,8 @@ }, "node_modules/meow/node_modules/find-up": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "license": "MIT", "dependencies": { @@ -9999,11 +12434,15 @@ }, "node_modules/meow/node_modules/hosted-git-info": { "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true, "license": "ISC" }, "node_modules/meow/node_modules/locate-path": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "license": "MIT", "dependencies": { @@ -10015,6 +12454,8 @@ }, "node_modules/meow/node_modules/p-limit": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "license": "MIT", "dependencies": { @@ -10029,6 +12470,8 @@ }, "node_modules/meow/node_modules/p-locate": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "license": "MIT", "dependencies": { @@ -10040,6 +12483,8 @@ }, "node_modules/meow/node_modules/read-pkg": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, "license": "MIT", "dependencies": { @@ -10054,6 +12499,8 @@ }, "node_modules/meow/node_modules/read-pkg-up": { "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, "license": "MIT", "dependencies": { @@ -10070,6 +12517,8 @@ }, "node_modules/meow/node_modules/read-pkg-up/node_modules/type-fest": { "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { @@ -10078,6 +12527,8 @@ }, "node_modules/meow/node_modules/read-pkg/node_modules/normalize-package-data": { "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -10089,6 +12540,8 @@ }, "node_modules/meow/node_modules/read-pkg/node_modules/type-fest": { "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { @@ -10097,6 +12550,8 @@ }, "node_modules/meow/node_modules/semver": { "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "license": "ISC", "bin": { @@ -10105,6 +12560,8 @@ }, "node_modules/meow/node_modules/type-fest": { "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { @@ -10121,6 +12578,8 @@ }, "node_modules/merge2": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, "license": "MIT", "engines": { @@ -10179,6 +12638,8 @@ }, "node_modules/min-indent": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true, "license": "MIT", "engines": { @@ -10209,6 +12670,8 @@ }, "node_modules/minimist-options": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", "dev": true, "license": "MIT", "dependencies": { @@ -10221,45 +12684,50 @@ } }, "node_modules/minipass": { - "version": "3.3.6", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/minipass-collect": { - "version": "1.0.2", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", "dev": true, "license": "ISC", "dependencies": { - "minipass": "^3.0.0" + "minipass": "^7.0.3" }, "engines": { - "node": ">= 8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/minipass-fetch": { - "version": "1.4.1", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.1.tgz", + "integrity": "sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ==", "dev": true, "license": "MIT", "dependencies": { - "minipass": "^3.1.0", + "minipass": "^7.0.3", "minipass-sized": "^1.0.3", - "minizlib": "^2.0.0" + "minizlib": "^3.0.1" }, "engines": { - "node": ">=8" + "node": "^18.17.0 || >=20.5.0" }, "optionalDependencies": { - "encoding": "^0.1.12" + "encoding": "^0.1.13" } }, "node_modules/minipass-flush": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", "dev": true, "license": "ISC", "dependencies": { @@ -10269,17 +12737,30 @@ "node": ">= 8" } }, - "node_modules/minipass-json-stream": { - "version": "1.0.2", + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "jsonparse": "^1.3.1", - "minipass": "^3.0.0" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, "node_modules/minipass-pipeline": { "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "dev": true, "license": "ISC", "dependencies": { @@ -10289,58 +12770,78 @@ "node": ">=8" } }, - "node_modules/minipass-sized": { - "version": "1.0.3", + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "license": "ISC", "dependencies": { - "minipass": "^3.0.0" + "yallist": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/minipass/node_modules/yallist": { + "node_modules/minipass-pipeline/node_modules/yallist": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, "license": "ISC" }, - "node_modules/minizlib": { - "version": "2.1.2", + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", "dependencies": { - "minipass": "^3.0.0", "yallist": "^4.0.0" }, "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/minizlib/node_modules/yallist": { + "node_modules/minipass-sized/node_modules/yallist": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, "license": "ISC" }, - "node_modules/mkdirp": { - "version": "1.0.4", + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", "dev": true, "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" + "dependencies": { + "minipass": "^7.1.2" }, "engines": { - "node": ">=10" + "node": ">= 18" } }, - "node_modules/mkdirp-infer-owner": { - "version": "2.0.0", + "node_modules/mkdirp": { + "version": "1.0.4", "dev": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "infer-owner": "^1.0.4", - "mkdirp": "^1.0.3" + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" }, "engines": { "node": ">=10" @@ -10348,6 +12849,8 @@ }, "node_modules/modify-values": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", + "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", "dev": true, "license": "MIT", "engines": { @@ -10369,6 +12872,8 @@ }, "node_modules/multimatch": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", + "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==", "dev": true, "license": "MIT", "dependencies": { @@ -10387,6 +12892,8 @@ }, "node_modules/multimatch/node_modules/arrify": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", "dev": true, "license": "MIT", "engines": { @@ -10395,6 +12902,8 @@ }, "node_modules/multimatch/node_modules/brace-expansion": { "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -10404,6 +12913,8 @@ }, "node_modules/multimatch/node_modules/minimatch": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", "dependencies": { @@ -10414,9 +12925,14 @@ } }, "node_modules/mute-stream": { - "version": "0.0.8", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", "dev": true, - "license": "ISC" + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } }, "node_modules/napi-postinstall": { "version": "0.3.2", @@ -10438,7 +12954,9 @@ "license": "MIT" }, "node_modules/negotiator": { - "version": "0.6.4", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "dev": true, "license": "MIT", "engines": { @@ -10455,154 +12973,91 @@ "dev": true, "license": "MIT" }, - "node_modules/node-fetch": { - "version": "2.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "dev": true, - "license": "MIT" - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/node-gyp": { - "version": "5.1.1", + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.2.0.tgz", + "integrity": "sha512-q23WdzrQv48KozXlr0U1v9dwO/k59NHeSzn6loGcasyf0UnSrtzs8kRxM+mfwJSf0DkX0s43hcqgnSO4/VNthQ==", "dev": true, "license": "MIT", "dependencies": { "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.2", - "mkdirp": "^0.5.1", - "nopt": "^4.0.1", - "npmlog": "^4.1.2", - "request": "^2.88.0", - "rimraf": "^2.6.3", - "semver": "^5.7.1", - "tar": "^4.4.12", - "which": "^1.3.1" + "exponential-backoff": "^3.1.1", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^15.0.0", + "nopt": "^9.0.0", + "proc-log": "^6.0.0", + "semver": "^7.3.5", + "tar": "^7.5.4", + "tinyglobby": "^0.2.12", + "which": "^6.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" }, "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/node-gyp/node_modules/chownr": { - "version": "1.1.4", - "dev": true, - "license": "ISC" - }, - "node_modules/node-gyp/node_modules/fs-minipass": { - "version": "1.2.7", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^2.6.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/node-gyp/node_modules/minipass": { - "version": "2.9.0", + "node_modules/node-gyp/node_modules/abbrev": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-4.0.0.tgz", + "integrity": "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==", "dev": true, "license": "ISC", - "dependencies": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "node_modules/node-gyp/node_modules/minizlib": { - "version": "1.3.3", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^2.9.0" + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/node-gyp/node_modules/mkdirp": { - "version": "0.5.6", + "node_modules/node-gyp/node_modules/isexe": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=20" } }, - "node_modules/node-gyp/node_modules/rimraf": { - "version": "2.7.1", + "node_modules/node-gyp/node_modules/nopt": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-9.0.0.tgz", + "integrity": "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==", "dev": true, "license": "ISC", "dependencies": { - "glob": "^7.1.3" + "abbrev": "^4.0.0" }, "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/node-gyp/node_modules/semver": { - "version": "5.7.2", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/node-gyp/node_modules/tar": { - "version": "4.4.19", + "node_modules/node-gyp/node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", "dev": true, "license": "ISC", - "dependencies": { - "chownr": "^1.1.4", - "fs-minipass": "^1.2.7", - "minipass": "^2.9.0", - "minizlib": "^1.3.3", - "mkdirp": "^0.5.5", - "safe-buffer": "^5.2.1", - "yallist": "^3.1.1" - }, "engines": { - "node": ">=4.5" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/node-gyp/node_modules/which": { - "version": "1.3.1", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", "dev": true, "license": "ISC", "dependencies": { - "isexe": "^2.0.0" + "isexe": "^4.0.0" }, "bin": { - "which": "bin/which" + "node-which": "bin/which.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/node-int64": { @@ -10610,8 +13065,17 @@ "dev": true, "license": "MIT" }, + "node_modules/node-machine-id": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/node-machine-id/-/node-machine-id-1.1.12.tgz", + "integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==", + "dev": true, + "license": "MIT" + }, "node_modules/node-releases": { - "version": "2.0.19", + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", "dev": true, "license": "MIT" }, @@ -10646,19 +13110,25 @@ "license": "MIT" }, "node_modules/nopt": { - "version": "4.0.3", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", + "integrity": "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==", "dev": true, "license": "ISC", "dependencies": { - "abbrev": "1", - "osenv": "^0.1.4" + "abbrev": "^3.0.0" }, "bin": { "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/normalize-package-data": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -10671,150 +13141,182 @@ "node": ">=10" } }, - "node_modules/normalize-path": { - "version": "3.0.0", + "node_modules/normalize-package-data/node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/normalize-url": { - "version": "6.1.0", + "node_modules/normalize-package-data/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/normalize-package-data/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, "node_modules/npm-bundled": { - "version": "1.1.2", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-4.0.0.tgz", + "integrity": "sha512-IxaQZDMsqfQ2Lz37VvyyEtKLe8FsRZuysmedy/N06TU1RyVppYKXrO4xIhR0F+7ubIBox6Q7nir6fQI3ej39iA==", "dev": true, "license": "ISC", "dependencies": { - "npm-normalize-package-bin": "^1.0.1" + "npm-normalize-package-bin": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm-install-checks": { - "version": "4.0.0", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-7.1.2.tgz", + "integrity": "sha512-z9HJBCYw9Zr8BqXcllKIs5nI+QggAImbBdHphOzVYrz2CB4iQ6FzWyKmlqDZua+51nAu7FcemlbTc9VgQN5XDQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "semver": "^7.1.1" }, "engines": { - "node": ">=10" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/npm-lifecycle": { - "version": "3.1.5", + "node_modules/npm-normalize-package-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", + "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", "dev": true, - "license": "Artistic-2.0", - "dependencies": { - "byline": "^5.0.0", - "graceful-fs": "^4.1.15", - "node-gyp": "^5.0.2", - "resolve-from": "^4.0.0", - "slide": "^1.1.6", - "uid-number": "0.0.6", - "umask": "^1.1.0", - "which": "^1.3.1" + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/npm-lifecycle/node_modules/which": { - "version": "1.3.1", + "node_modules/npm-package-arg": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-13.0.1.tgz", + "integrity": "sha512-6zqls5xFvJbgFjB1B2U6yITtyGBjDBORB7suI4zA4T/sZ1OmkMFlaQSNB/4K0LtXNA1t4OprAFxPisadK5O2ag==", "dev": true, "license": "ISC", "dependencies": { - "isexe": "^2.0.0" + "hosted-git-info": "^9.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^6.0.0" }, - "bin": { - "which": "bin/which" + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/npm-normalize-package-bin": { - "version": "1.0.1", - "dev": true, - "license": "ISC" - }, - "node_modules/npm-package-arg": { - "version": "8.1.5", + "node_modules/npm-packlist": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-10.0.3.tgz", + "integrity": "sha512-zPukTwJMOu5X5uvm0fztwS5Zxyvmk38H/LfidkOMt3gbZVCyro2cD/ETzwzVPcWZA3JOyPznfUN/nkyFiyUbxg==", "dev": true, "license": "ISC", "dependencies": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" + "ignore-walk": "^8.0.0", + "proc-log": "^6.0.0" }, "engines": { - "node": ">=10" + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/npm-packlist/node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/npm-packlist": { - "version": "2.2.2", + "node_modules/npm-pick-manifest": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-11.0.3.tgz", + "integrity": "sha512-buzyCfeoGY/PxKqmBqn1IUJrZnUi1VVJTdSSRPGI60tJdUhUoSQFhs0zycJokDdOznQentgrpf8LayEHyyYlqQ==", "dev": true, "license": "ISC", "dependencies": { - "glob": "^7.1.6", - "ignore-walk": "^3.0.3", - "npm-bundled": "^1.1.1", - "npm-normalize-package-bin": "^1.0.1" - }, - "bin": { - "npm-packlist": "bin/index.js" + "npm-install-checks": "^8.0.0", + "npm-normalize-package-bin": "^5.0.0", + "npm-package-arg": "^13.0.0", + "semver": "^7.3.5" }, "engines": { - "node": ">=10" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/npm-pick-manifest": { - "version": "6.1.1", + "node_modules/npm-pick-manifest/node_modules/npm-install-checks": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-8.0.0.tgz", + "integrity": "sha512-ScAUdMpyzkbpxoNekQ3tNRdFI8SJ86wgKZSQZdUxT+bj0wVFpsEMWnkXP0twVe1gJyNF5apBWDJhhIbgrIViRA==", "dev": true, - "license": "ISC", + "license": "BSD-2-Clause", "dependencies": { - "npm-install-checks": "^4.0.0", - "npm-normalize-package-bin": "^1.0.1", - "npm-package-arg": "^8.1.2", - "semver": "^7.3.4" + "semver": "^7.1.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/npm-registry-fetch": { - "version": "9.0.0", + "node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", + "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==", "dev": true, "license": "ISC", - "dependencies": { - "@npmcli/ci-detect": "^1.0.0", - "lru-cache": "^6.0.0", - "make-fetch-happen": "^8.0.9", - "minipass": "^3.1.3", - "minipass-fetch": "^1.3.0", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.0.0", - "npm-package-arg": "^8.0.0" - }, "engines": { - "node": ">=10" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/npm-registry-fetch/node_modules/lru-cache": { - "version": "6.0.0", + "node_modules/npm-registry-fetch": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-19.1.0.tgz", + "integrity": "sha512-xyZLfs7TxPu/WKjHUs0jZOPinzBAI32kEUel6za0vH+JUTnFZ5zbHI1ZoGZRDm6oMjADtrli6FxtMlk/5ABPNw==", "dev": true, "license": "ISC", "dependencies": { - "yallist": "^4.0.0" + "@npmcli/redact": "^3.0.0", + "jsonparse": "^1.3.1", + "make-fetch-happen": "^15.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^4.0.0", + "minizlib": "^3.0.1", + "npm-package-arg": "^13.0.0", + "proc-log": "^5.0.0" }, "engines": { - "node": ">=10" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/npm-registry-fetch/node_modules/yallist": { - "version": "4.0.0", - "dev": true, - "license": "ISC" - }, "node_modules/npm-run-all": { "version": "4.1.5", "dev": true, @@ -10995,31 +13497,269 @@ "node": ">=8" } }, - "node_modules/npmlog": { - "version": "4.1.2", + "node_modules/nx": { + "version": "22.5.1", + "resolved": "https://registry.npmjs.org/nx/-/nx-22.5.1.tgz", + "integrity": "sha512-KIQqOSdoshkav9JuoH/+Vp42niA5MTRtACupe+q8CaB7bHiLsWr5nctQVC7ul3NauAmsoqNWH7t5CIi8KgrPIQ==", "dev": true, - "license": "ISC", + "hasInstallScript": true, + "license": "MIT", "dependencies": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "@napi-rs/wasm-runtime": "0.2.4", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.2", + "@zkochan/js-yaml": "0.0.7", + "axios": "^1.12.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.4.5", + "dotenv-expand": "~11.0.6", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "front-matter": "^4.0.2", + "ignore": "^7.0.5", + "jest-diff": "^30.0.2", + "jsonc-parser": "3.2.0", + "lines-and-columns": "2.0.3", + "minimatch": "10.1.1", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "picocolors": "^1.1.0", + "resolve.exports": "2.0.3", + "semver": "^7.6.3", + "string-width": "^4.2.3", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tree-kill": "^1.2.2", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yaml": "^2.6.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" + }, + "bin": { + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "22.5.1", + "@nx/nx-darwin-x64": "22.5.1", + "@nx/nx-freebsd-x64": "22.5.1", + "@nx/nx-linux-arm-gnueabihf": "22.5.1", + "@nx/nx-linux-arm64-gnu": "22.5.1", + "@nx/nx-linux-arm64-musl": "22.5.1", + "@nx/nx-linux-x64-gnu": "22.5.1", + "@nx/nx-linux-x64-musl": "22.5.1", + "@nx/nx-win32-arm64-msvc": "22.5.1", + "@nx/nx-win32-x64-msvc": "22.5.1" + }, + "peerDependencies": { + "@swc-node/register": "1.11.1", + "@swc/core": "1.15.8" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } } }, - "node_modules/number-is-nan": { - "version": "1.0.1", + "node_modules/nx/node_modules/@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", "dev": true, "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/nx/node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", + "integrity": "sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@emnapi/core": "^1.1.0", + "@emnapi/runtime": "^1.1.0", + "@tybys/wasm-util": "^0.9.0" } }, - "node_modules/oauth-sign": { + "node_modules/nx/node_modules/@sinclair/typebox": { + "version": "0.34.48", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.48.tgz", + "integrity": "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nx/node_modules/@tybys/wasm-util": { "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", + "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/nx/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", "engines": { - "node": "*" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/nx/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/nx/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/nx/node_modules/jest-diff": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", + "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/nx/node_modules/lines-and-columns": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", + "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/nx/node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nx/node_modules/pretty-format": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", + "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/nx/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nx/node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nx/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/nx/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" } }, "node_modules/object-assign": { @@ -11100,26 +13840,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.1.8", - "dev": true, - "license": "MIT", - "dependencies": { - "array.prototype.reduce": "^1.0.6", - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "gopd": "^1.0.1", - "safe-array-concat": "^1.1.2" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/object.groupby": { "version": "1.0.3", "dev": true, @@ -11183,6 +13903,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/opener": { "version": "1.5.2", "dev": true, @@ -11207,29 +13945,27 @@ "node": ">= 0.8.0" } }, - "node_modules/os-homedir": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", + "node_modules/ora": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", + "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/osenv": { - "version": "0.1.5", - "dev": true, - "license": "ISC", "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" + "bl": "^4.0.3", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "log-symbols": "^4.0.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/own-keys": { @@ -11250,6 +13986,8 @@ }, "node_modules/p-finally": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", "dev": true, "license": "MIT", "engines": { @@ -11286,6 +14024,8 @@ }, "node_modules/p-map": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, "license": "MIT", "dependencies": { @@ -11300,6 +14040,8 @@ }, "node_modules/p-map-series": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map-series/-/p-map-series-2.1.0.tgz", + "integrity": "sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q==", "dev": true, "license": "MIT", "engines": { @@ -11308,6 +14050,8 @@ }, "node_modules/p-pipe": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-3.1.0.tgz", + "integrity": "sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw==", "dev": true, "license": "MIT", "engines": { @@ -11319,6 +14063,8 @@ }, "node_modules/p-queue": { "version": "6.6.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", + "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", "dev": true, "license": "MIT", "dependencies": { @@ -11334,6 +14080,8 @@ }, "node_modules/p-reduce": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-2.1.0.tgz", + "integrity": "sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==", "dev": true, "license": "MIT", "engines": { @@ -11342,6 +14090,8 @@ }, "node_modules/p-timeout": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", "dev": true, "license": "MIT", "dependencies": { @@ -11361,6 +14111,8 @@ }, "node_modules/p-waterfall": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-waterfall/-/p-waterfall-2.1.1.tgz", + "integrity": "sha512-RRTnDb2TBG/epPRI2yYXsimO0v3BXC8Yd3ogr1545IaqKK17VGhbWVeGGN+XfCm/08OK8635nH31c8bATkHuSw==", "dev": true, "license": "MIT", "dependencies": { @@ -11373,118 +14125,200 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, "node_modules/pacote": { - "version": "11.3.5", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^2.1.0", - "@npmcli/installed-package-contents": "^1.0.6", - "@npmcli/promise-spawn": "^1.2.0", - "@npmcli/run-script": "^1.8.2", - "cacache": "^15.0.5", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "infer-owner": "^1.0.4", - "minipass": "^3.1.3", - "mkdirp": "^1.0.3", - "npm-package-arg": "^8.0.1", - "npm-packlist": "^2.1.4", - "npm-pick-manifest": "^6.0.0", - "npm-registry-fetch": "^11.0.0", + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-21.0.1.tgz", + "integrity": "sha512-LHGIUQUrcDIJUej53KJz1BPvUuHrItrR2yrnN0Kl9657cJ0ZT6QJHk9wWPBnQZhYT5KLyZWrk9jaYc2aKDu4yw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^6.0.0", + "@npmcli/installed-package-contents": "^3.0.0", + "@npmcli/package-json": "^7.0.0", + "@npmcli/promise-spawn": "^8.0.0", + "@npmcli/run-script": "^10.0.0", + "cacache": "^20.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^13.0.0", + "npm-packlist": "^10.0.1", + "npm-pick-manifest": "^10.0.0", + "npm-registry-fetch": "^19.0.0", + "proc-log": "^5.0.0", "promise-retry": "^2.0.1", - "read-package-json-fast": "^2.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.1.0" + "sigstore": "^4.0.0", + "ssri": "^12.0.0", + "tar": "^7.4.3" }, "bin": { - "pacote": "lib/bin.js" + "pacote": "bin/index.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/pacote/node_modules/@npmcli/git": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-6.0.3.tgz", + "integrity": "sha512-GUYESQlxZRAdhs3UhbB6pVRNUELQOHXwK9ruDkwmCv2aZ5y0SApQzUJCg02p3A7Ue2J5hxvlk1YI53c00NmRyQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/promise-spawn": "^8.0.0", + "ini": "^5.0.0", + "lru-cache": "^10.0.1", + "npm-pick-manifest": "^10.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^5.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/pacote/node_modules/@npmcli/promise-spawn": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-8.0.3.tgz", + "integrity": "sha512-Yb00SWaL4F8w+K8YGhQ55+xE4RUNdMHV43WZGsiTM92gS+lC0mGsn7I4hLug7pbao035S6bj3Y3w0cUNGLfmkg==", + "dev": true, + "license": "ISC", + "dependencies": { + "which": "^5.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/pacote/node_modules/hosted-git-info": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.1.0.tgz", + "integrity": "sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" }, "engines": { - "node": ">=10" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/pacote/node_modules/ini": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-5.0.0.tgz", + "integrity": "sha512-+N0ngpO3e7cRUWOJAS7qw0IZIVc6XPrW4MlFBdD066F2L4k1L6ker3hLqSq7iXxU5tgS4WGkIUElWn5vogAEnw==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/pacote/node_modules/isexe": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.5.tgz", + "integrity": "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, "node_modules/pacote/node_modules/lru-cache": { - "version": "6.0.0", + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/pacote/node_modules/npm-pick-manifest": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-10.0.0.tgz", + "integrity": "sha512-r4fFa4FqYY8xaM7fHecQ9Z2nE9hgNfJR+EmoKv0+chvzWkBcORX3r0FpTByP+CbOVJDladMXnPQGVN8PBLGuTQ==", "dev": true, "license": "ISC", "dependencies": { - "yallist": "^4.0.0" + "npm-install-checks": "^7.1.0", + "npm-normalize-package-bin": "^4.0.0", + "npm-package-arg": "^12.0.0", + "semver": "^7.3.5" }, "engines": { - "node": ">=10" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/pacote/node_modules/make-fetch-happen": { - "version": "9.1.0", + "node_modules/pacote/node_modules/npm-pick-manifest/node_modules/npm-package-arg": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-12.0.2.tgz", + "integrity": "sha512-f1NpFjNI9O4VbKMOlA5QoBq/vSQPORHcTZ2feJpFkTHJ9eQkdlmZEKSjcAhxTGInC7RlEyScT9ui67NaOsjFWA==", "dev": true, "license": "ISC", "dependencies": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.2.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.2", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^6.0.0", - "ssri": "^8.0.0" + "hosted-git-info": "^8.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^6.0.0" }, "engines": { - "node": ">= 10" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/pacote/node_modules/npm-registry-fetch": { - "version": "11.0.0", + "node_modules/pacote/node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "dev": true, "license": "ISC", "dependencies": { - "make-fetch-happen": "^9.0.1", - "minipass": "^3.1.3", - "minipass-fetch": "^1.3.0", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.0.0", - "npm-package-arg": "^8.0.0" + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" }, "engines": { - "node": ">=10" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/pacote/node_modules/socks-proxy-agent": { - "version": "6.2.1", + "node_modules/parent-module": { + "version": "1.0.1", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" + "callsites": "^3.0.0" }, "engines": { - "node": ">= 10" + "node": ">=6" } }, - "node_modules/pacote/node_modules/yallist": { + "node_modules/parse-conflict-json": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-4.0.0.tgz", + "integrity": "sha512-37CN2VtcuvKgHUs8+0b1uJeEsbGn61GRHz469C94P5xiOoqpDYJYwjg4RY9Vmz39WyZAVkR5++nbJwLMIgOCnQ==", "dev": true, - "license": "ISC" + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^4.0.0", + "just-diff": "^6.0.0", + "just-diff-apply": "^5.2.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } }, - "node_modules/parent-module": { - "version": "1.0.1", + "node_modules/parse-conflict-json/node_modules/json-parse-even-better-errors": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-4.0.0.tgz", + "integrity": "sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==", "dev": true, "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, "engines": { - "node": ">=6" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/parse-imports-exports": { @@ -11513,42 +14347,30 @@ } }, "node_modules/parse-path": { - "version": "4.0.4", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.1.0.tgz", + "integrity": "sha512-EuCycjZtfPcjWk7KTksnJ5xPMvWGA/6i4zrLYhRG0hGvC3GPU/jGUj3Cy+ZR0v30duV3e23R95T1lE2+lsndSw==", "dev": true, "license": "MIT", "dependencies": { - "is-ssh": "^1.3.0", - "protocols": "^1.4.0", - "qs": "^6.9.4", - "query-string": "^6.13.8" + "protocols": "^2.0.0" } }, - "node_modules/parse-path/node_modules/protocols": { - "version": "1.4.8", - "dev": true, - "license": "MIT" - }, "node_modules/parse-statements": { "version": "1.0.11", "dev": true, "license": "MIT" }, "node_modules/parse-url": { - "version": "6.0.5", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz", + "integrity": "sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==", "dev": true, "license": "MIT", "dependencies": { - "is-ssh": "^1.3.0", - "normalize-url": "^6.1.0", - "parse-path": "^4.0.0", - "protocols": "^1.4.0" + "parse-path": "^7.0.0" } }, - "node_modules/parse-url/node_modules/protocols": { - "version": "1.4.8", - "dev": true, - "license": "MIT" - }, "node_modules/parseurl": { "version": "1.3.3", "dev": true, @@ -11586,27 +14408,33 @@ "dev": true, "license": "MIT" }, - "node_modules/path-type": { - "version": "4.0.0", + "node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, "engines": { - "node": ">=8" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/pathval": { - "version": "1.1.1", + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.2.6", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", + "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "engines": { - "node": "*" + "node": "20 || >=22" } }, - "node_modules/performance-now": { - "version": "2.1.0", - "dev": true, - "license": "MIT" - }, "node_modules/picocolors": { "version": "1.1.1", "dev": true, @@ -11636,6 +14464,8 @@ }, "node_modules/pify": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", + "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", "dev": true, "license": "MIT", "engines": { @@ -11653,6 +14483,75 @@ "node": ">= 6" } }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "dev": true, @@ -11661,6 +14560,20 @@ "node": ">= 0.4" } }, + "node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "dev": true, @@ -11718,6 +14631,16 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/proc-log": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz", + "integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/process": { "version": "0.11.10", "dev": true, @@ -11731,13 +14654,40 @@ "dev": true, "license": "MIT" }, - "node_modules/promise-inflight": { + "node_modules/proggy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proggy/-/proggy-3.0.0.tgz", + "integrity": "sha512-QE8RApCM3IaRRxVzxrjbgNMpQEX6Wu0p0KBeoSiSEw5/bsGwZHsshF4LCxH2jp/r6BU+bqA3LrMDEYNfJnpD8Q==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/promise-all-reject-late": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz", + "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==", "dev": true, - "license": "ISC" + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/promise-call-limit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/promise-call-limit/-/promise-call-limit-3.0.2.tgz", + "integrity": "sha512-mRPQO2T1QQVw11E7+UdCJu7S61eJVWknzml9sC1heAdj1jxl0fWMBypIt9ZOcLFf8FkG995ZD7RnVk7HH72fZw==", + "dev": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/promise-retry": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "dev": true, "license": "MIT", "dependencies": { @@ -11761,11 +14711,16 @@ } }, "node_modules/promzard": { - "version": "0.3.0", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/promzard/-/promzard-2.0.0.tgz", + "integrity": "sha512-Ncd0vyS2eXGOjchIRg6PVCYKetJYrW1BSbbIo+bKdig61TB6nH2RQNF2uP+qMpsI73L/jURLWojcw8JNIKZ3gg==", "dev": true, "license": "ISC", "dependencies": { - "read": "1" + "read": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/prop-types": { @@ -11785,26 +14740,19 @@ "license": "MIT", "peer": true }, - "node_modules/proto-list": { - "version": "1.2.4", - "dev": true, - "license": "ISC" - }, "node_modules/protocols": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.2.tgz", + "integrity": "sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==", "dev": true, "license": "MIT" }, - "node_modules/psl": { - "version": "1.15.0", + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true, - "license": "MIT", - "dependencies": { - "punycode": "^2.3.1" - }, - "funding": { - "url": "https://github.com/sponsors/lupomontero" - } + "license": "MIT" }, "node_modules/punycode": { "version": "2.3.1", @@ -11837,15 +14785,6 @@ ], "license": "MIT" }, - "node_modules/q": { - "version": "1.5.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" - } - }, "node_modules/qjobs": { "version": "1.2.0", "dev": true, @@ -11854,39 +14793,10 @@ "node": ">=0.9" } }, - "node_modules/qs": { - "version": "6.14.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/query-string": { - "version": "6.14.1", - "dev": true, - "license": "MIT", - "dependencies": { - "decode-uri-component": "^0.2.0", - "filter-obj": "^1.1.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, "funding": [ { @@ -11906,6 +14816,8 @@ }, "node_modules/quick-lru": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", "dev": true, "license": "MIT", "engines": { @@ -11914,6 +14826,8 @@ }, "node_modules/randombytes": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "license": "MIT", "dependencies": { @@ -11942,104 +14856,42 @@ "node": ">= 0.8" } }, - "node_modules/react": { - "version": "19.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-is": { - "version": "18.3.1", - "dev": true, - "license": "MIT" - }, - "node_modules/read": { - "version": "1.0.7", - "dev": true, - "license": "ISC", - "dependencies": { - "mute-stream": "~0.0.4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/read-cmd-shim": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/read-package-json": { - "version": "3.0.1", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.1", - "json-parse-even-better-errors": "^2.3.0", - "normalize-package-data": "^3.0.0", - "npm-normalize-package-bin": "^1.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/read-package-json-fast": { - "version": "2.0.3", - "dev": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^2.3.0", - "npm-normalize-package-bin": "^1.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/read-package-tree": { - "version": "5.3.1", - "dev": true, - "license": "ISC", - "dependencies": { - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0", - "util-promisify": "^2.1.0" - } - }, - "node_modules/read-package-tree/node_modules/hosted-git-info": { - "version": "2.8.9", - "dev": true, - "license": "ISC" - }, - "node_modules/read-package-tree/node_modules/normalize-package-data": { - "version": "2.5.0", + "node_modules/react": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", + "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/read-package-tree/node_modules/read-package-json": { - "version": "2.1.2", + "node_modules/react-is": { + "version": "18.3.1", + "dev": true, + "license": "MIT" + }, + "node_modules/read": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/read/-/read-4.1.0.tgz", + "integrity": "sha512-uRfX6K+f+R8OOrYScaM3ixPY4erg69f8DN6pgTvMcA9iRc8iDhwrA4m3Yu8YYKsXJgVvum+m8PkRboZwwuLzYA==", "dev": true, "license": "ISC", "dependencies": { - "glob": "^7.1.1", - "json-parse-even-better-errors": "^2.3.0", - "normalize-package-data": "^2.0.0", - "npm-normalize-package-bin": "^1.0.0" + "mute-stream": "^2.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/read-package-tree/node_modules/semver": { - "version": "5.7.2", + "node_modules/read-cmd-shim": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz", + "integrity": "sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q==", "dev": true, "license": "ISC", - "bin": { - "semver": "bin/semver" + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/read-pkg": { @@ -12057,6 +14909,8 @@ }, "node_modules/read-pkg-up": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==", "dev": true, "license": "MIT", "dependencies": { @@ -12069,6 +14923,8 @@ }, "node_modules/read-pkg-up/node_modules/find-up": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12080,6 +14936,8 @@ }, "node_modules/read-pkg-up/node_modules/locate-path": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", "dev": true, "license": "MIT", "dependencies": { @@ -12092,6 +14950,8 @@ }, "node_modules/read-pkg-up/node_modules/p-limit": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, "license": "MIT", "dependencies": { @@ -12103,6 +14963,8 @@ }, "node_modules/read-pkg-up/node_modules/p-locate": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", "dev": true, "license": "MIT", "dependencies": { @@ -12114,6 +14976,8 @@ }, "node_modules/read-pkg-up/node_modules/p-try": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", "dev": true, "license": "MIT", "engines": { @@ -12122,6 +14986,8 @@ }, "node_modules/read-pkg-up/node_modules/path-exists": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "dev": true, "license": "MIT", "engines": { @@ -12207,6 +15073,8 @@ }, "node_modules/readable-stream": { "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "license": "MIT", "dependencies": { @@ -12218,17 +15086,6 @@ "node": ">= 6" } }, - "node_modules/readdir-scoped-modules": { - "version": "1.1.0", - "dev": true, - "license": "ISC", - "dependencies": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" - } - }, "node_modules/readdirp": { "version": "3.6.0", "dev": true, @@ -12253,6 +15110,8 @@ }, "node_modules/redent": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dev": true, "license": "MIT", "dependencies": { @@ -12303,44 +15162,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/request": { - "version": "2.88.2", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request/node_modules/qs": { - "version": "6.5.3", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.6" - } - }, "node_modules/require-directory": { "version": "2.1.1", "dev": true, @@ -12426,6 +15247,8 @@ }, "node_modules/restore-cursor": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, "license": "MIT", "dependencies": { @@ -12438,6 +15261,8 @@ }, "node_modules/retry": { "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "dev": true, "license": "MIT", "engines": { @@ -12446,6 +15271,8 @@ }, "node_modules/reusify": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, "license": "MIT", "engines": { @@ -12473,7 +15300,9 @@ } }, "node_modules/run-async": { - "version": "2.4.1", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-4.0.6.tgz", + "integrity": "sha512-IoDlSLTs3Yq593mb3ZoKWKXMNu3UpObxhgA/Xuid5p4bbfi2jdY1Hj0m1K+0/tEuQTxIGMhQDqGjKb7RuxGpAQ==", "dev": true, "license": "MIT", "engines": { @@ -12482,6 +15311,8 @@ }, "node_modules/run-parallel": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { @@ -12508,14 +15339,13 @@ "license": "MIT" }, "node_modules/rxjs": { - "version": "6.6.7", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" + "tslib": "^2.1.0" } }, "node_modules/safe-array-concat": { @@ -12592,7 +15422,9 @@ "license": "MIT" }, "node_modules/schema-utils": { - "version": "4.3.2", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", "dev": true, "license": "MIT", "dependencies": { @@ -12611,6 +15443,8 @@ }, "node_modules/schema-utils/node_modules/ajv": { "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", "dependencies": { @@ -12626,6 +15460,8 @@ }, "node_modules/schema-utils/node_modules/ajv-keywords": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, "license": "MIT", "dependencies": { @@ -12637,11 +15473,15 @@ }, "node_modules/schema-utils/node_modules/json-schema-traverse": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, "license": "MIT" }, "node_modules/semver": { - "version": "7.7.2", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "dev": true, "license": "ISC", "bin": { @@ -12653,6 +15493,8 @@ }, "node_modules/serialize-javascript": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -12661,6 +15503,8 @@ }, "node_modules/set-blocking": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true, "license": "ISC" }, @@ -12826,6 +15670,24 @@ "dev": true, "license": "ISC" }, + "node_modules/sigstore": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-4.1.0.tgz", + "integrity": "sha512-/fUgUhYghuLzVT/gaJoeVehLCgZiUxPCPMcyVNY0lIf/cTCz58K/WTI7PefDarXxp9nUKpEwg1yyz3eSBMTtgA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^4.0.0", + "@sigstore/core": "^3.1.0", + "@sigstore/protobuf-specs": "^0.5.0", + "@sigstore/sign": "^4.1.0", + "@sigstore/tuf": "^4.0.1", + "@sigstore/verify": "^3.1.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/sirv": { "version": "2.0.4", "dev": true, @@ -12852,16 +15714,10 @@ "node": ">=8" } }, - "node_modules/slide": { - "version": "1.1.6", - "dev": true, - "license": "ISC", - "engines": { - "node": "*" - } - }, "node_modules/smart-buffer": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true, "license": "MIT", "engines": { @@ -12976,11 +15832,13 @@ } }, "node_modules/socks": { - "version": "2.8.6", + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", "dev": true, "license": "MIT", "dependencies": { - "ip-address": "^9.0.5", + "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" }, "engines": { @@ -12989,38 +15847,31 @@ } }, "node_modules/socks-proxy-agent": { - "version": "5.0.1", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^6.0.2", - "debug": "4", - "socks": "^2.3.3" + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/sort-keys": { - "version": "4.2.0", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==", "dev": true, "license": "MIT", "dependencies": { - "is-plain-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" + "is-plain-obj": "^1.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/sort-keys/node_modules/is-plain-obj": { - "version": "2.1.0", - "dev": true, - "license": "MIT", "engines": { - "node": ">=8" + "node": ">=4" } }, "node_modules/source-map": { @@ -13117,6 +15968,8 @@ }, "node_modules/split": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", "dev": true, "license": "MIT", "dependencies": { @@ -13126,16 +15979,10 @@ "node": "*" } }, - "node_modules/split-on-first": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/split2": { "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", "dev": true, "license": "ISC", "dependencies": { @@ -13143,48 +15990,23 @@ } }, "node_modules/sprintf-js": { - "version": "1.1.3", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true, "license": "BSD-3-Clause" }, - "node_modules/sshpk": { - "version": "1.18.0", - "dev": true, - "license": "MIT", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sshpk/node_modules/jsbn": { - "version": "0.1.1", - "dev": true, - "license": "MIT" - }, "node_modules/ssri": { - "version": "8.0.1", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", + "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==", "dev": true, "license": "ISC", "dependencies": { - "minipass": "^3.1.1" + "minipass": "^7.0.3" }, "engines": { - "node": ">= 8" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/stable-hash-x": { @@ -13276,16 +16098,10 @@ "node": ">= 4.0.0" } }, - "node_modules/strict-uri-encode": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/string_decoder": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "license": "MIT", "dependencies": { @@ -13472,6 +16288,8 @@ }, "node_modules/strip-indent": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13492,22 +16310,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strong-log-transformer": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "duplexer": "^0.1.1", - "minimist": "^1.2.0", - "through": "^2.3.4" - }, - "bin": { - "sl-log-transformer": "bin/sl-log-transformer.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/supports-color": { "version": "7.2.0", "dev": true, @@ -13545,94 +16347,83 @@ } }, "node_modules/tapable": { - "version": "2.2.2", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", "dev": true, "license": "MIT", "engines": { "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/tar": { - "version": "6.2.1", + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz", + "integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dev": true, - "license": "ISC", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, "engines": { - "node": ">=8" + "node": ">=6" } }, "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", "dev": true, - "license": "ISC" + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } }, "node_modules/temp-dir": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", + "integrity": "sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==", "dev": true, "license": "MIT", "engines": { "node": ">=4" } }, - "node_modules/temp-write": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.15", - "is-stream": "^2.0.0", - "make-dir": "^3.0.0", - "temp-dir": "^1.0.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/temp-write/node_modules/make-dir": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/temp-write/node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/terser": { - "version": "5.43.1", + "version": "5.44.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", + "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.14.0", + "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -13644,7 +16435,9 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.14", + "version": "5.3.16", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", + "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -13678,6 +16471,8 @@ }, "node_modules/terser-webpack-plugin/node_modules/jest-worker": { "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, "license": "MIT", "dependencies": { @@ -13691,6 +16486,8 @@ }, "node_modules/terser-webpack-plugin/node_modules/supports-color": { "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -13738,6 +16535,8 @@ }, "node_modules/text-extensions": { "version": "1.9.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", + "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", "dev": true, "license": "MIT", "engines": { @@ -13746,6 +16545,8 @@ }, "node_modules/through": { "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true, "license": "MIT" }, @@ -13791,12 +16592,14 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.14", + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { "node": ">=12.0.0" @@ -13806,9 +16609,14 @@ } }, "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.6", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -13820,6 +16628,8 @@ }, "node_modules/tinyglobby/node_modules/picomatch": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { @@ -13830,14 +16640,13 @@ } }, "node_modules/tmp": { - "version": "0.0.33", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", "dev": true, "license": "MIT", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, "engines": { - "node": ">=0.6.0" + "node": ">=14.14" } }, "node_modules/tmpl": { @@ -13872,31 +16681,30 @@ "node": ">=6" } }, - "node_modules/tough-cookie": { - "version": "2.5.0", + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" + "license": "MIT", + "bin": { + "tree-kill": "cli.js" } }, - "node_modules/tr46": { - "version": "2.1.0", + "node_modules/treeverse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/treeverse/-/treeverse-3.0.0.tgz", + "integrity": "sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ==", "dev": true, - "license": "MIT", - "dependencies": { - "punycode": "^2.1.1" - }, + "license": "ISC", "engines": { - "node": ">=8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/trim-newlines": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true, "license": "MIT", "engines": { @@ -13904,7 +16712,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.1.0", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", "dev": true, "license": "MIT", "engines": { @@ -13947,7 +16757,9 @@ } }, "node_modules/ts-jest": { - "version": "29.4.1", + "version": "29.4.6", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.6.tgz", + "integrity": "sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==", "dev": true, "license": "MIT", "dependencies": { @@ -13957,7 +16769,7 @@ "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", - "semver": "^7.7.2", + "semver": "^7.7.3", "type-fest": "^4.41.0", "yargs-parser": "^21.1.1" }, @@ -14118,26 +16930,27 @@ } }, "node_modules/tslib": { - "version": "1.14.1", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, "license": "0BSD" }, - "node_modules/tunnel-agent": { - "version": "0.6.0", + "node_modules/tuf-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-4.1.0.tgz", + "integrity": "sha512-50QV99kCKH5P/Vs4E2Gzp7BopNV+KzTXqWeaxrfu5IQJBOULRsTIS9seSsOVT8ZnGXzCyx55nYWAi4qJzpZKEQ==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "safe-buffer": "^5.0.1" + "@tufjs/models": "4.1.0", + "debug": "^4.4.3", + "make-fetch-happen": "^15.0.1" }, "engines": { - "node": "*" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "dev": true, - "license": "Unlicense" - }, "node_modules/type-check": { "version": "0.4.0", "dev": true, @@ -14149,14 +16962,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-detect": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/type-fest": { "version": "0.21.3", "dev": true, @@ -14252,27 +17057,23 @@ }, "node_modules/typedarray": { "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", "dev": true, "license": "MIT" }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, "node_modules/typedoc": { - "version": "0.28.5", + "version": "0.28.15", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.15.tgz", + "integrity": "sha512-mw2/2vTL7MlT+BVo43lOsufkkd2CJO4zeOSuWQQsiXoV2VuEn7f6IZp2jsUDPmBMABpgR0R5jlcJ2OGEFYmkyg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@gerrit0/mini-shiki": "^3.2.2", + "@gerrit0/mini-shiki": "^3.17.0", "lunr": "^2.3.9", "markdown-it": "^14.1.0", "minimatch": "^9.0.5", - "yaml": "^2.7.1" + "yaml": "^2.8.1" }, "bin": { "typedoc": "bin/typedoc" @@ -14282,18 +17083,7 @@ "pnpm": ">= 10" }, "peerDependencies": { - "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x" - } - }, - "node_modules/typedoc/node_modules/yaml": { - "version": "2.8.1", - "dev": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" + "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x" } }, "node_modules/typescript": { @@ -14309,14 +17099,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.39.0", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.52.0.tgz", + "integrity": "sha512-atlQQJ2YkO4pfTVQmQ+wvYQwexPDOIgo+RaVcD7gHgzy/IQA+XTyuxNM9M9TVXvttkF7koBHmcwisKdOAf2EcA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.39.0", - "@typescript-eslint/parser": "8.39.0", - "@typescript-eslint/typescript-estree": "8.39.0", - "@typescript-eslint/utils": "8.39.0" + "@typescript-eslint/eslint-plugin": "8.52.0", + "@typescript-eslint/parser": "8.52.0", + "@typescript-eslint/typescript-estree": "8.52.0", + "@typescript-eslint/utils": "8.52.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -14368,22 +17160,9 @@ "bin": { "uglifyjs": "bin/uglifyjs" }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/uid-number": { - "version": "0.0.6", - "dev": true, - "license": "ISC", - "engines": { - "node": "*" - } - }, - "node_modules/umask": { - "version": "1.1.0", - "dev": true, - "license": "MIT" + "engines": { + "node": ">=0.8.0" + } }, "node_modules/unbox-primitive": { "version": "1.1.0", @@ -14408,28 +17187,42 @@ "license": "MIT" }, "node_modules/unique-filename": { - "version": "1.1.1", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-5.0.0.tgz", + "integrity": "sha512-2RaJTAvAb4owyjllTfXzFClJ7WsGxlykkPvCr9pA//LD9goVq+m4PPAeBgNodGZ7nSrntT/auWpJ6Y5IFXcfjg==", "dev": true, "license": "ISC", "dependencies": { - "unique-slug": "^2.0.0" + "unique-slug": "^6.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/unique-slug": { - "version": "2.0.2", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-6.0.0.tgz", + "integrity": "sha512-4Lup7Ezn8W3d52/xBhZBVdx323ckxa7DEvd9kPQHppTkLoJXw6ltrBCyj5pnrxj0qKDxYMJ56CoxNuFCscdTiw==", "dev": true, "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/universal-user-agent": { "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, "license": "ISC" }, "node_modules/universalify": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", "engines": { @@ -14487,6 +17280,8 @@ }, "node_modules/upath": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz", + "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", "dev": true, "license": "MIT", "engines": { @@ -14495,7 +17290,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.3", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -14536,14 +17333,6 @@ "dev": true, "license": "MIT" }, - "node_modules/util-promisify": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "object.getownpropertydescriptors": "^2.0.3" - } - }, "node_modules/utils-merge": { "version": "1.0.1", "dev": true, @@ -14553,11 +17342,17 @@ } }, "node_modules/uuid": { - "version": "3.4.0", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "license": "MIT", "bin": { - "uuid": "bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/v8-compile-cache-lib": { @@ -14597,11 +17392,13 @@ } }, "node_modules/validate-npm-package-name": { - "version": "3.0.0", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-6.0.2.tgz", + "integrity": "sha512-IUoow1YUtvoBBC06dXs8bR8B9vuA3aJfmQNKMoaPG/OFsPmoQvw8xh+6Ye25Gx9DQhoEom3Pcu9MKHerm/NpUQ==", "dev": true, "license": "ISC", - "dependencies": { - "builtins": "^1.0.3" + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/vary": { @@ -14612,19 +17409,6 @@ "node": ">= 0.8" } }, - "node_modules/verror": { - "version": "1.10.0", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "node_modules/void-elements": { "version": "2.0.1", "dev": true, @@ -14633,6 +17417,16 @@ "node": ">=0.10.0" } }, + "node_modules/walk-up-path": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-4.0.0.tgz", + "integrity": "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/walker": { "version": "1.0.8", "dev": true, @@ -14655,22 +17449,18 @@ }, "node_modules/wcwidth": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "dev": true, "license": "MIT", "dependencies": { "defaults": "^1.0.3" } }, - "node_modules/webidl-conversions": { - "version": "6.1.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=10.4" - } - }, "node_modules/webpack": { - "version": "5.101.0", + "version": "5.104.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz", + "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", "dev": true, "license": "MIT", "dependencies": { @@ -14682,22 +17472,22 @@ "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.15.0", "acorn-import-phases": "^1.0.3", - "browserslist": "^4.24.0", + "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.2", - "es-module-lexer": "^1.2.1", + "enhanced-resolve": "^5.17.4", + "es-module-lexer": "^2.0.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", + "loader-runner": "^4.3.1", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^4.3.2", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.11", - "watchpack": "^2.4.1", + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.3.16", + "watchpack": "^2.4.4", "webpack-sources": "^3.3.3" }, "bin": { @@ -14717,7 +17507,9 @@ } }, "node_modules/webpack-bundle-analyzer": { - "version": "4.10.2", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-5.1.1.tgz", + "integrity": "sha512-UzoaIA0Aigo5lUvoUkIkSoHtUK5rBJh9e2vW3Eqct0jc/L8hcruBCz/jsXEvB1hDU1G3V94jo2EJqPcFKeSSeQ==", "dev": true, "license": "MIT", "dependencies": { @@ -14727,7 +17519,6 @@ "commander": "^7.2.0", "debounce": "^1.2.1", "escape-string-regexp": "^4.0.0", - "gzip-size": "^6.0.0", "html-escaper": "^2.0.2", "opener": "^1.5.2", "picocolors": "^1.0.0", @@ -14738,7 +17529,7 @@ "webpack-bundle-analyzer": "lib/bin/analyzer.js" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 20.9.0" } }, "node_modules/webpack-bundle-analyzer/node_modules/commander": { @@ -14749,6 +17540,28 @@ "node": ">= 10" } }, + "node_modules/webpack-bundle-analyzer/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/webpack-cli": { "version": "6.0.1", "dev": true, @@ -14847,19 +17660,6 @@ "node": ">=4.0" } }, - "node_modules/whatwg-url": { - "version": "8.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/which": { "version": "2.0.2", "dev": true, @@ -14957,6 +17757,8 @@ }, "node_modules/wide-align": { "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "dev": true, "license": "ISC", "dependencies": { @@ -15015,67 +17817,73 @@ } }, "node_modules/write-json-file": { - "version": "4.3.0", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz", + "integrity": "sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==", "dev": true, "license": "MIT", "dependencies": { - "detect-indent": "^6.0.0", + "detect-indent": "^5.0.0", "graceful-fs": "^4.1.15", - "is-plain-obj": "^2.0.0", - "make-dir": "^3.0.0", - "sort-keys": "^4.0.0", - "write-file-atomic": "^3.0.0" + "make-dir": "^2.1.0", + "pify": "^4.0.1", + "sort-keys": "^2.0.0", + "write-file-atomic": "^2.4.2" }, "engines": { - "node": ">=8.3" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/write-json-file/node_modules/is-plain-obj": { + "node_modules/write-json-file/node_modules/make-dir": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, "license": "MIT", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/write-json-file/node_modules/make-dir": { - "version": "3.1.0", + "node_modules/write-json-file/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, "node_modules/write-json-file/node_modules/semver": { - "version": "6.3.1", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "license": "ISC", "bin": { - "semver": "bin/semver.js" + "semver": "bin/semver" } }, "node_modules/write-json-file/node_modules/write-file-atomic": { - "version": "3.0.3", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", "dev": true, "license": "ISC", "dependencies": { + "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "signal-exit": "^3.0.2" } }, "node_modules/write-pkg": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-4.0.0.tgz", + "integrity": "sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==", "dev": true, "license": "MIT", "dependencies": { @@ -15087,97 +17895,27 @@ "node": ">=8" } }, - "node_modules/write-pkg/node_modules/detect-indent": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/write-pkg/node_modules/make-dir": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/write-pkg/node_modules/pify": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/write-pkg/node_modules/semver": { - "version": "5.7.2", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/write-pkg/node_modules/sort-keys": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "is-plain-obj": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/write-pkg/node_modules/type-fest": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.4.1.tgz", + "integrity": "sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=6" } }, - "node_modules/write-pkg/node_modules/write-file-atomic": { - "version": "2.4.3", - "dev": true, - "license": "ISC", - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "node_modules/write-pkg/node_modules/write-json-file": { - "version": "3.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "detect-indent": "^5.0.0", - "graceful-fs": "^4.1.15", - "make-dir": "^2.1.0", - "pify": "^4.0.1", - "sort-keys": "^2.0.0", - "write-file-atomic": "^2.4.2" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/ws": { - "version": "7.5.10", - "dev": true, + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", "license": "MIT", "engines": { - "node": ">=8.3.0" + "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -15210,11 +17948,19 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "1.10.2", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", "dev": true, "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, "engines": { - "node": ">= 6" + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" } }, "node_modules/yargs": { @@ -15261,9 +18007,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", + "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "packages/isomorphic": { "name": "@transia/isomorphic", - "version": "1.0.3-alpha.1", + "version": "1.0.5-alpha.0", "license": "ISC", "dependencies": { "@noble/hashes": "^1.0.0", @@ -15282,32 +18041,13 @@ "version": "5.0.1", "license": "MIT" }, - "packages/isomorphic/node_modules/ws": { - "version": "8.18.3", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "packages/ripple-address-codec": { "name": "@transia/ripple-address-codec", - "version": "5.0.2-alpha.1", + "version": "5.0.4-alpha.0", "license": "ISC", "dependencies": { "@scure/base": "^1.1.3", - "@transia/isomorphic": "^1.0.3-alpha.1" + "@transia/isomorphic": "^1.0.5-alpha.0" }, "engines": { "node": ">= 18" @@ -15315,11 +18055,11 @@ }, "packages/ripple-binary-codec": { "name": "@transia/ripple-binary-codec", - "version": "2.5.3-alpha.1", + "version": "2.5.5-alpha.0", "license": "ISC", "dependencies": { - "@transia/isomorphic": "^1.0.3-alpha.1", - "@transia/ripple-address-codec": "^5.0.2-alpha.1", + "@transia/isomorphic": "^1.0.5-alpha.0", + "@transia/ripple-address-codec": "^5.0.4-alpha.0", "bignumber.js": "^9.0.0" }, "engines": { @@ -15328,12 +18068,12 @@ }, "packages/ripple-keypairs": { "name": "@transia/ripple-keypairs", - "version": "2.0.2-alpha.1", + "version": "2.0.4-alpha.0", "license": "ISC", "dependencies": { "@noble/curves": "^1.0.0", - "@transia/isomorphic": "^1.0.3-alpha.1", - "@transia/ripple-address-codec": "^5.0.2-alpha.1" + "@transia/isomorphic": "^1.0.5-alpha.0", + "@transia/ripple-address-codec": "^5.0.4-alpha.0" }, "engines": { "node": ">= 18" @@ -15341,27 +18081,28 @@ }, "packages/secret-numbers": { "name": "@transia/secret-numbers", - "version": "2.0.2-alpha.1", + "version": "2.0.4-alpha.0", "license": "ISC", "dependencies": { - "@transia/isomorphic": "^1.0.3-alpha.1", - "@transia/ripple-keypairs": "^2.0.2-alpha.1" + "@transia/isomorphic": "^1.0.5-alpha.0", + "@transia/ripple-keypairs": "^2.0.4-alpha.0" } }, "packages/xrpl": { "name": "@transia/xrpl", - "version": "4.4.4-alpha.1", + "version": "4.4.6-alpha.0", "license": "ISC", "dependencies": { "@scure/bip32": "^1.3.1", "@scure/bip39": "^1.2.1", - "@transia/isomorphic": "^1.0.3-alpha.1", - "@transia/ripple-address-codec": "^5.0.2-alpha.1", - "@transia/ripple-binary-codec": "^2.5.3-alpha.1", - "@transia/ripple-keypairs": "^2.0.2-alpha.1", - "@transia/secret-numbers": "^2.0.2-alpha.1", + "@transia/isomorphic": "^1.0.5-alpha.0", + "@transia/ripple-address-codec": "^5.0.4-alpha.0", + "@transia/ripple-binary-codec": "^2.5.5-alpha.0", + "@transia/ripple-keypairs": "^2.0.4-alpha.0", + "@transia/secret-numbers": "^2.0.4-alpha.0", "bignumber.js": "^9.0.0", - "eventemitter3": "^5.0.1" + "eventemitter3": "^5.0.1", + "fast-json-stable-stringify": "^2.1.0" }, "devDependencies": { "@types/node": "^18.18.38", @@ -15374,60 +18115,17 @@ "lodash": "^4.17.4", "react": "^19.0.0", "run-s": "^0.0.0", - "typedoc": "0.28.5", + "typedoc": "0.28.15", "ws": "^8.14.2" }, "engines": { "node": ">=18.0.0" } }, - "packages/xrpl/node_modules/agent-base": { - "version": "7.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, "packages/xrpl/node_modules/eventemitter3": { "version": "5.0.1", "dev": true, "license": "MIT" - }, - "packages/xrpl/node_modules/https-proxy-agent": { - "version": "7.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "packages/xrpl/node_modules/ws": { - "version": "8.18.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } } } } diff --git a/package.json b/package.json index b636573101..d85f4ffa54 100644 --- a/package.json +++ b/package.json @@ -26,29 +26,29 @@ "globals": "^16.3.0", "@eslint-community/eslint-plugin-eslint-comments": "^4.5.0", "@eslint/js": "^9.32.0", - "@xrplf/eslint-config": "^2.0.0", + "@xrplf/eslint-config": "^3.0.0", "@xrplf/prettier-config": "^1.9.1", "@types/chai": "^4.2.21", "@types/jest": "^29.2.2", "@types/lodash": "^4.14.136", "@types/node": "^18.19.29", - "typescript-eslint": "^8.39.0", + "typescript-eslint": "^8.52.0", "@types/ws": "^8.2.0", - "chai": "^4.3.4", + "chai": "^6.2.2", "copyfiles": "^2.4.1", "eslint": "^9.32.0", "eslint-config-prettier": "^10.1.8", "eslint-import-resolver-typescript": "^4.4.4", - "eslint-plugin-array-func": "^4.0.0", + "eslint-plugin-array-func": "^5.0.0", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsdoc": "^52.0.4", "eslint-plugin-n": "^17.21.3", "eslint-plugin-prettier": "^5.5.4", - "eslint-plugin-tsdoc": "^0.4.0", - "expect": "^29.3.1", + "eslint-plugin-tsdoc": "^0.5.0", + "expect": "^30.2.0", "jest": "^29.3.1", - "jest-mock": "^29.3.1", - "lerna": "^4.0.0", + "jest-mock": "^30.2.0", + "lerna": "^9.0.4", "lodash": "^4.17.21", "npm-run-all": "^4.1.5", "prettier": "^3.6.2", @@ -60,7 +60,7 @@ "ts-node": "^10.2.1", "typescript": "^5.1.6", "webpack": "^5.81.0", - "webpack-bundle-analyzer": "^4.1.0", + "webpack-bundle-analyzer": "^5.1.1", "webpack-cli": "^6.0.1" }, "workspaces": [ diff --git a/packages/isomorphic/eslint.config.js b/packages/isomorphic/eslint.config.js index c16b5e87a4..f5c4a1b90d 100644 --- a/packages/isomorphic/eslint.config.js +++ b/packages/isomorphic/eslint.config.js @@ -1,5 +1,5 @@ const globals = require('globals') -const eslintConfig = require('@xrplf/eslint-config/base') +const eslintConfig = require('@xrplf/eslint-config/base').default const tseslint = require('typescript-eslint') module.exports = [ diff --git a/packages/ripple-address-codec/eslint.config.js b/packages/ripple-address-codec/eslint.config.js index 5ebdea7561..fcb45e2af0 100644 --- a/packages/ripple-address-codec/eslint.config.js +++ b/packages/ripple-address-codec/eslint.config.js @@ -1,5 +1,5 @@ const globals = require('globals') -const eslintConfig = require('@xrplf/eslint-config/base') +const eslintConfig = require('@xrplf/eslint-config/base').default const tseslint = require('typescript-eslint') module.exports = [ diff --git a/packages/ripple-binary-codec/HISTORY.md b/packages/ripple-binary-codec/HISTORY.md index a758d2d31c..0f234fd56a 100644 --- a/packages/ripple-binary-codec/HISTORY.md +++ b/packages/ripple-binary-codec/HISTORY.md @@ -2,6 +2,25 @@ ## Unreleased +## 2.7.0 (2026-02-12) + +### Added +* Add `Int32` serialized type. + +### Fixed +* Fix STNumber serialization logic to work with large mantissa scale [10^18, 10^19-1]. +* Error if a decimal is passed into a `UInt`-typed field. + +## 2.6.0 (2025-12-16) + +### Added +* Allow `encodeForMultisigning` to work with transactions that have non-empty `SigningPubKey`. Required to encode `LoanSet` transaction by counterparty signers for signing. + +## 2.5.1 (2025-10-29) + +### Fixed +* Fix serialization/deserialization issues in `Issue` serialized type for MPTIssue. + ## 2.5.0 (2025-07-29) ### Added diff --git a/packages/ripple-binary-codec/eslint.config.js b/packages/ripple-binary-codec/eslint.config.js index 9ad2a047ef..0b0ceb6072 100644 --- a/packages/ripple-binary-codec/eslint.config.js +++ b/packages/ripple-binary-codec/eslint.config.js @@ -1,5 +1,5 @@ const globals = require('globals') -const eslintConfig = require('@xrplf/eslint-config/base') +const eslintConfig = require('@xrplf/eslint-config/base').default const tseslint = require('typescript-eslint') module.exports = [ diff --git a/packages/ripple-binary-codec/package.json b/packages/ripple-binary-codec/package.json index e7cf360ea2..1b4bda04f5 100644 --- a/packages/ripple-binary-codec/package.json +++ b/packages/ripple-binary-codec/package.json @@ -19,7 +19,7 @@ "build": "tsc --build tsconfig.build.json && copyfiles ./src/enums/definitions.json ./dist/enums/", "clean": "rm -rf ./dist ./coverage ./test/testCompiledForWeb tsconfig.build.tsbuildinfo", "prepublishOnly": "npm test", - "test": "npm run build && jest --verbose false --silent=false /Users/darkmatter/projects/ledger-works/xrpl.js/packages/ripple-binary-codec/test/binary-serializer.test.ts", + "test": "npm run build && jest --verbose false --silent=false ./test/*.test.ts", "test:browser": "npm run build && karma start ./karma.config.js", "lint": "eslint . --max-warnings 0", "generateDefinitions": "node ./tools/generateDefinitions.js" diff --git a/packages/ripple-binary-codec/src/enums/definitions.json b/packages/ripple-binary-codec/src/enums/definitions.json index 87b6f0e392..fe853ab157 100644 --- a/packages/ripple-binary-codec/src/enums/definitions.json +++ b/packages/ripple-binary-codec/src/enums/definitions.json @@ -61,2903 +61,3243 @@ } ], [ - "BatchSigners", + "LedgerEntryType", { "isSerialized": true, - "isSigningField": false, + "isSigningField": true, "isVLEncoded": false, - "nth": 31, - "type": "STArray" + "nth": 1, + "type": "UInt16" } ], [ - "RawTransactions", + "TransactionType", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 30, - "type": "STArray" + "nth": 2, + "type": "UInt16" } ], [ - "Permissions", + "SignerWeight", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 29, - "type": "STArray" + "nth": 3, + "type": "UInt16" } ], [ - "Majorities", + "TransferFee", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 16, - "type": "STArray" + "nth": 4, + "type": "UInt16" } ], [ - "AdditionalBooks", + "TradingFee", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 13, - "type": "STArray" + "nth": 5, + "type": "UInt16" } ], [ - "VoteSlots", + "DiscountedFee", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 12, - "type": "STArray" + "nth": 6, + "type": "UInt16" } ], [ - "NFTokens", + "Version", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 10, - "type": "STArray" + "nth": 16, + "type": "UInt16" } ], [ - "Memos", + "LedgerFixType", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 9, - "type": "STArray" + "nth": 21, + "type": "UInt16" } ], [ - "AffectedNodes", + "ManagementFeeRate", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 8, - "type": "STArray" + "nth": 22, + "type": "UInt16" } ], [ - "Sufficient", + "NetworkID", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 7, - "type": "STArray" + "nth": 1, + "type": "UInt32" } ], [ - "Necessary", + "Flags", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 6, - "type": "STArray" + "nth": 2, + "type": "UInt32" } ], [ - "Template", + "SourceTag", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 5, - "type": "STArray" + "nth": 3, + "type": "UInt32" } ], [ - "SignerEntries", + "Sequence", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, "nth": 4, - "type": "STArray" + "type": "UInt32" } ], [ - "Signers", + "PreviousTxnLgrSeq", { "isSerialized": true, - "isSigningField": false, + "isSigningField": true, "isVLEncoded": false, - "nth": 3, - "type": "STArray" + "nth": 5, + "type": "UInt32" } ], [ - "Parameter", + "LedgerSequence", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 40, - "type": "STObject" + "nth": 6, + "type": "UInt32" } ], [ - "InstanceParameterValue", + "CloseTime", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 39, - "type": "STObject" + "nth": 7, + "type": "UInt32" } ], [ - "InstanceParameter", + "ParentCloseTime", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 38, - "type": "STObject" + "nth": 8, + "type": "UInt32" } ], [ - "XChainCreateAccountAttestationCollectionElement", + "SigningTime", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 31, - "type": "STObject" + "nth": 9, + "type": "UInt32" } ], [ - "ShareMPTID", + "Expiration", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 2, - "type": "Hash192" + "nth": 10, + "type": "UInt32" } ], [ - "QualityOut", + "TransferRate", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 21, + "nth": 11, "type": "UInt32" } ], [ - "XChainClaimID", + "WalletSize", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 20, - "type": "UInt64" + "nth": 12, + "type": "UInt32" } ], [ - "Nickname", + "OwnerCount", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 18, - "type": "Hash256" + "nth": 13, + "type": "UInt32" } ], [ - "RippleEscrow", + "DestinationTag", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 17, - "type": "Amount" + "nth": 14, + "type": "UInt32" } ], [ - "NFTokenOffers", + "LastUpdateTime", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 4, - "type": "Vector256" + "isVLEncoded": false, + "nth": 15, + "type": "UInt32" } ], [ - "TemplateEntry", + "HighQualityIn", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 9, - "type": "STObject" + "nth": 16, + "type": "UInt32" } ], [ - "TakerGetsIssuer", + "HighQualityOut", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 4, - "type": "Hash160" + "nth": 17, + "type": "UInt32" } ], [ - "LowQualityOut", + "LowQualityIn", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 19, + "nth": 18, "type": "UInt32" } ], [ - "AssetScale", + "LowQualityOut", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 5, - "type": "UInt8" + "nth": 19, + "type": "UInt32" } ], [ - "BookDirectory", + "QualityIn", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 16, - "type": "Hash256" + "nth": 20, + "type": "UInt32" } ], [ - "XChainClaimAttestationCollectionElement", + "QualityOut", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 30, - "type": "STObject" + "nth": 21, + "type": "UInt32" } ], [ - "MemoFormat", + "StampEscrow", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 14, - "type": "Blob" + "isVLEncoded": false, + "nth": 22, + "type": "UInt32" } ], [ - "Hashes", + "BondAmount", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 2, - "type": "Vector256" + "isVLEncoded": false, + "nth": 23, + "type": "UInt32" } ], [ - "FinalFields", + "LoadFee", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 7, - "type": "STObject" + "nth": 24, + "type": "UInt32" } ], [ - "TakerGetsCurrency", + "OfferSequence", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 3, - "type": "Hash160" + "nth": 25, + "type": "UInt32" } ], [ - "LowQualityIn", + "FirstLedgerSequence", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 18, + "nth": 26, "type": "UInt32" } ], [ - "Scale", + "LastLedgerSequence", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 4, - "type": "UInt8" + "nth": 27, + "type": "UInt32" } ], [ - "XChainCreateAccountProofSig", + "TransactionIndex", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 29, - "type": "STObject" + "nth": 28, + "type": "UInt32" } ], [ - "MemoData", + "OperationLimit", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 13, - "type": "Blob" + "isVLEncoded": false, + "nth": 29, + "type": "UInt32" } ], [ - "AcceptedCredentials", + "ReferenceFeeUnits", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 28, - "type": "STArray" + "nth": 30, + "type": "UInt32" } ], [ - "Delegate", + "ReserveBase", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 12, - "type": "AccountID" + "isVLEncoded": false, + "nth": 31, + "type": "UInt32" } ], [ - "Indexes", + "ReserveIncrement", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 1, - "type": "Vector256" + "isVLEncoded": false, + "nth": 32, + "type": "UInt32" } ], [ - "PreviousFields", + "SetFlag", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 6, - "type": "STObject" + "nth": 33, + "type": "UInt32" } ], [ - "TakerPaysIssuer", + "ClearFlag", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 2, - "type": "Hash160" + "nth": 34, + "type": "UInt32" } ], [ - "TransactionResult", + "SignerQuorum", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 3, - "type": "UInt8" + "nth": 35, + "type": "UInt32" } ], [ - "HighQualityOut", + "CancelAfter", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 17, + "nth": 36, "type": "UInt32" } ], [ - "AMMID", + "FinishAfter", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 14, - "type": "Hash256" + "nth": 37, + "type": "UInt32" } ], [ - "BidMax", + "SignerListID", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 13, - "type": "Amount" + "nth": 38, + "type": "UInt32" } ], [ - "XChainClaimProofSig", + "SettleDelay", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 28, - "type": "STObject" + "nth": 39, + "type": "UInt32" } ], [ - "MemoType", + "TicketCount", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 12, - "type": "Blob" + "isVLEncoded": false, + "nth": 40, + "type": "UInt32" } ], [ - "UnauthorizeCredentials", + "TicketSequence", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 27, - "type": "STArray" + "nth": 41, + "type": "UInt32" } ], [ - "Holder", + "NFTokenTaxon", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 11, - "type": "AccountID" + "isVLEncoded": false, + "nth": 42, + "type": "UInt32" } ], [ - "Paths", + "MintedNFTokens", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 1, - "type": "PathSet" + "nth": 43, + "type": "UInt32" } ], [ - "ModifiedNode", + "BurnedNFTokens", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 5, - "type": "STObject" + "nth": 44, + "type": "UInt32" } ], [ - "GasPrice", + "VoteWeight", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 56, + "nth": 48, "type": "UInt32" } ], [ - "ExtensionSizeLimit", + "FirstNFTokenSequence", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 55, + "nth": 50, "type": "UInt32" } ], [ - "ExtensionComputeLimit", + "OracleDocumentID", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 54, + "nth": 51, "type": "UInt32" } ], [ - "MutableFlags", + "PermissionValue", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 53, + "nth": 52, "type": "UInt32" } ], [ - "PermissionValue", + "MutableFlags", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 52, + "nth": 53, "type": "UInt32" } ], [ - "OracleDocumentID", + "StartDate", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 51, + "nth": 54, "type": "UInt32" } ], [ - "FirstNFTokenSequence", + "PaymentInterval", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 50, + "nth": 55, "type": "UInt32" } ], [ - "VoteWeight", + "GracePeriod", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 48, + "nth": 56, "type": "UInt32" } ], [ - "MintedNFTokens", + "PreviousPaymentDueDate", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 43, + "nth": 57, "type": "UInt32" } ], [ - "NFTokenTaxon", + "NextPaymentDueDate", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 42, + "nth": 58, "type": "UInt32" } ], [ - "TicketSequence", + "PaymentRemaining", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 41, + "nth": 59, "type": "UInt32" } ], [ - "ContractID", + "PaymentTotal", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 38, - "type": "Hash256" + "nth": 60, + "type": "UInt32" } ], [ - "ContractHash", + "LoanSequence", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 37, - "type": "Hash256" + "nth": 61, + "type": "UInt32" } ], [ - "SettleDelay", + "CoverRateMinimum", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 39, + "nth": 62, "type": "UInt32" } ], [ - "ParentBatchID", + "CoverRateLiquidation", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 36, - "type": "Hash256" + "nth": 63, + "type": "UInt32" } ], [ - "FunctionName", + "OverpaymentFee", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 34, - "type": "Blob" + "isVLEncoded": false, + "nth": 64, + "type": "UInt32" } ], [ - "SignerListID", + "InterestRate", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 38, + "nth": 65, "type": "UInt32" } ], [ - "VaultID", + "LateInterestRate", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 35, - "type": "Hash256" + "nth": 66, + "type": "UInt32" } ], [ - "ContractCode", + "CloseInterestRate", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 33, - "type": "Blob" + "isVLEncoded": false, + "nth": 67, + "type": "UInt32" } ], [ - "FinishAfter", + "OverpaymentInterestRate", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 37, + "nth": 68, "type": "UInt32" } ], [ - "DomainID", + "ExtensionComputeLimit", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 34, - "type": "Hash256" + "nth": 69, + "type": "UInt32" } ], [ - "FinishFunction", + "ExtensionSizeLimit", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 32, - "type": "Blob" + "isVLEncoded": false, + "nth": 70, + "type": "UInt32" } ], [ - "CancelAfter", + "GasPrice", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 36, + "nth": 71, "type": "UInt32" } ], [ - "CredentialType", + "ComputationAllowance", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 31, - "type": "Blob" + "isVLEncoded": false, + "nth": 72, + "type": "UInt32" } ], [ - "SignerQuorum", + "GasUsed", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 35, + "nth": 73, "type": "UInt32" } ], [ - "LPTokenBalance", + "ParameterFlag", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 31, - "type": "Amount" + "nth": 74, + "type": "UInt32" } ], [ - "MPTokenMetadata", + "IndexNext", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 30, - "type": "Blob" + "isVLEncoded": false, + "nth": 1, + "type": "UInt64" } ], [ - "ContractReturnCode", + "IndexPrevious", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 30, + "nth": 2, "type": "UInt64" } ], [ - "ParameterValue", + "BookNode", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 1, - "type": "Data" + "nth": 3, + "type": "UInt64" } ], [ - "NFTokenBuyOffer", + "OwnerNode", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 28, - "type": "Hash256" + "nth": 4, + "type": "UInt64" } ], [ - "EPrice", + "BaseFee", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 27, - "type": "Amount" + "nth": 5, + "type": "UInt64" } ], [ - "DIDDocument", + "ExchangeRate", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 26, - "type": "Blob" + "isVLEncoded": false, + "nth": 6, + "type": "UInt64" } ], [ - "ContractAccount", + "LowNode", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 25, - "type": "AccountID" + "isVLEncoded": false, + "nth": 7, + "type": "UInt64" } ], [ - "ClearFlag", + "HighNode", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 34, - "type": "UInt32" + "nth": 8, + "type": "UInt64" } ], [ - "MinAccountCreateAmount", + "DestinationNode", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 30, - "type": "Amount" + "nth": 9, + "type": "UInt64" } ], [ - "Provider", + "Cookie", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 29, - "type": "Blob" + "isVLEncoded": false, + "nth": 10, + "type": "UInt64" } ], [ - "WalletLocator", + "ServerVersion", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 7, - "type": "Hash256" + "nth": 11, + "type": "UInt64" } ], [ - "Expiration", + "NFTokenOfferNode", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 10, - "type": "UInt32" + "nth": 12, + "type": "UInt64" } ], [ - "DestinationNode", + "EmitBurden", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 9, + "nth": 13, "type": "UInt64" } ], [ - "LowLimit", + "ReferenceCount", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 6, - "type": "Amount" + "nth": 19, + "type": "UInt64" } ], [ - "URI", + "XChainClaimID", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 5, - "type": "Blob" + "isVLEncoded": false, + "nth": 20, + "type": "UInt64" } ], [ - "Issuer", + "XChainAccountCreateCount", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 4, - "type": "AccountID" + "isVLEncoded": false, + "nth": 21, + "type": "UInt64" } ], [ - "NetworkID", + "XChainAccountClaimCount", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 1, - "type": "UInt32" + "nth": 22, + "type": "UInt64" } ], [ - "index", + "AssetPrice", { - "isSerialized": false, - "isSigningField": false, + "isSerialized": true, + "isSigningField": true, "isVLEncoded": false, - "nth": 258, - "type": "Hash256" + "nth": 23, + "type": "UInt64" } ], [ - "Sequence", + "MaximumAmount", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 4, - "type": "UInt32" + "nth": 24, + "type": "UInt64" } ], [ - "BookNode", + "OutstandingAmount", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 3, + "nth": 25, "type": "UInt64" } ], [ - "LedgerHash", + "MPTAmount", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 1, - "type": "Hash256" + "nth": 26, + "type": "UInt64" } ], [ - "LedgerIndex", + "IssuerNode", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 6, - "type": "Hash256" + "nth": 27, + "type": "UInt64" } ], [ - "HighNode", + "SubjectNode", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 8, + "nth": 28, "type": "UInt64" } ], [ - "SigningTime", + "LockedAmount", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 9, - "type": "UInt32" + "nth": 29, + "type": "UInt64" } ], [ - "AssetsAvailable", + "VaultNode", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 2, - "type": "Number" + "nth": 30, + "type": "UInt64" } ], [ - "WasmReturnCode", + "LoanBrokerNode", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 1, - "type": "Int32" + "nth": 31, + "type": "UInt64" } ], [ - "TakerGets", + "EmailHash", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 5, - "type": "Amount" + "nth": 1, + "type": "Hash128" } ], [ - "TxnSignature", + "LedgerHash", { "isSerialized": true, - "isSigningField": false, - "isVLEncoded": true, - "nth": 4, - "type": "Blob" + "isSigningField": true, + "isVLEncoded": false, + "nth": 1, + "type": "Hash256" } ], [ - "Destination", + "ParentHash", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 3, - "type": "AccountID" + "isVLEncoded": false, + "nth": 2, + "type": "Hash256" } ], [ - "MPTokenIssuanceID", + "TransactionHash", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 1, - "type": "Hash192" + "nth": 3, + "type": "Hash256" } ], [ - "LedgerFixType", + "AccountHash", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 21, - "type": "UInt16" + "nth": 4, + "type": "Hash256" } ], [ - "QualityIn", + "PreviousTxnID", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 20, - "type": "UInt32" + "nth": 5, + "type": "Hash256" } ], [ - "ReferenceCount", + "LedgerIndex", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 19, - "type": "UInt64" + "nth": 6, + "type": "Hash256" } ], [ - "InvoiceID", + "WalletLocator", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 17, + "nth": 7, "type": "Hash256" } ], [ - "MinimumOffer", + "RootIndex", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 16, - "type": "Amount" + "nth": 8, + "type": "Hash256" } ], [ - "Amendments", + "AccountTxnID", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 3, - "type": "Vector256" + "isVLEncoded": false, + "nth": 9, + "type": "Hash256" } ], [ - "NewFields", + "NFTokenID", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 8, - "type": "STObject" + "nth": 10, + "type": "Hash256" } ], [ - "Flags", + "EmitParentTxnID", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 2, - "type": "UInt32" + "nth": 11, + "type": "Hash256" } ], [ - "IndexNext", + "EmitNonce", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 1, - "type": "UInt64" + "nth": 12, + "type": "Hash256" } ], [ - "AssetsMaximum", + "EmitHookHash", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 3, - "type": "Number" + "nth": 13, + "type": "Hash256" } ], [ - "WasLockingChainSend", + "AMMID", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 19, - "type": "UInt8" + "nth": 14, + "type": "Hash256" } ], [ - "SetFlag", + "BookDirectory", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 33, - "type": "UInt32" + "nth": 16, + "type": "Hash256" } ], [ - "SignatureReward", + "InvoiceID", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 29, - "type": "Amount" + "nth": 17, + "type": "Hash256" } ], [ - "ContractJson", + "Nickname", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 1, - "type": "Json" + "nth": 18, + "type": "Hash256" } ], [ - "AssetClass", + "Amendment", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 28, - "type": "Blob" + "isVLEncoded": false, + "nth": 19, + "type": "Hash256" } ], [ - "Functions", + "Digest", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 33, - "type": "STArray" + "nth": 21, + "type": "Hash256" } ], [ - "LedgerEntryType", + "Channel", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 1, - "type": "UInt16" + "nth": 22, + "type": "Hash256" } ], [ - "ParentHash", + "ConsensusHash", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 2, + "nth": 23, "type": "Hash256" } ], [ - "PreviousTxnLgrSeq", + "CheckID", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 5, - "type": "UInt32" + "nth": 24, + "type": "Hash256" } ], [ - "OwnerNode", + "ValidatedHash", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 4, - "type": "UInt64" + "nth": 25, + "type": "Hash256" } ], [ - "Amount", + "PreviousPageMin", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 1, - "type": "Amount" + "nth": 26, + "type": "Hash256" } ], [ - "Cookie", + "NextPageMin", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 10, - "type": "UInt64" + "nth": 27, + "type": "Hash256" } ], [ - "TransferRate", + "NFTokenBuyOffer", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 11, - "type": "UInt32" + "nth": 28, + "type": "Hash256" } ], [ - "RootIndex", + "NFTokenSellOffer", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 8, + "nth": 29, "type": "Hash256" } ], [ - "WithdrawalPolicy", + "DomainID", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 20, - "type": "UInt8" + "nth": 34, + "type": "Hash256" } ], [ - "AssetsTotal", + "VaultID", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 4, - "type": "Number" + "nth": 35, + "type": "Hash256" } ], [ - "HighLimit", + "ParentBatchID", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 7, - "type": "Amount" + "nth": 36, + "type": "Hash256" } ], [ - "Signature", + "LoanBrokerID", { "isSerialized": true, - "isSigningField": false, - "isVLEncoded": true, - "nth": 6, - "type": "Blob" + "isSigningField": true, + "isVLEncoded": false, + "nth": 37, + "type": "Hash256" } ], [ - "XChainClaimAttestations", + "LoanID", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 21, - "type": "STArray" + "nth": 38, + "type": "Hash256" } ], [ - "Authorize", + "ContractHash", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 5, - "type": "AccountID" + "isVLEncoded": false, + "nth": 39, + "type": "Hash256" } ], [ - "DestinationTag", + "ContractID", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 14, - "type": "UInt32" + "nth": 40, + "type": "Hash256" } ], [ - "EmitBurden", + "hash", { - "isSerialized": true, - "isSigningField": true, + "isSerialized": false, + "isSigningField": false, "isVLEncoded": false, - "nth": 13, - "type": "UInt64" + "nth": 257, + "type": "Hash256" } ], [ - "EmitParentTxnID", + "index", { - "isSerialized": true, - "isSigningField": true, + "isSerialized": false, + "isSigningField": false, "isVLEncoded": false, - "nth": 11, + "nth": 258, "type": "Hash256" } ], [ - "DeliverMin", + "Amount", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 10, + "nth": 1, "type": "Amount" } ], [ - "VoteEntry", + "Balance", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 25, - "type": "STObject" + "nth": 2, + "type": "Amount" } ], [ - "RemoveCode", + "LimitAmount", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 9, - "type": "Blob" + "isVLEncoded": false, + "nth": 3, + "type": "Amount" } ], [ - "PriceDataSeries", + "TakerPays", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 24, - "type": "STArray" + "nth": 4, + "type": "Amount" } ], [ - "RegularKey", + "TakerGets", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 8, - "type": "AccountID" + "isVLEncoded": false, + "nth": 5, + "type": "Amount" } ], [ - "TransactionMetaData", + "LowLimit", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 2, - "type": "STObject" + "nth": 6, + "type": "Amount" } ], [ - "TickSize", + "HighLimit", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 16, - "type": "UInt8" + "nth": 7, + "type": "Amount" } ], [ - "LockedAmount", + "Fee", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 29, - "type": "UInt64" + "nth": 8, + "type": "Amount" } ], [ - "NextPageMin", + "SendMax", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 27, - "type": "Hash256" + "nth": 9, + "type": "Amount" } ], [ - "LPTokenIn", + "DeliverMin", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 26, + "nth": 10, "type": "Amount" } ], [ - "Subject", + "Amount2", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 24, - "type": "AccountID" - } - ], - [ - "Transaction", - { - "isSerialized": false, - "isSigningField": false, "isVLEncoded": false, - "nth": 257, - "type": "Transaction" + "nth": 11, + "type": "Amount" } ], [ - "LowNode", + "BidMin", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 7, - "type": "UInt64" + "nth": 12, + "type": "Amount" } ], [ - "PreviousTxnID", + "BidMax", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 5, - "type": "Hash256" + "nth": 13, + "type": "Amount" } ], [ - "ParentCloseTime", + "MinimumOffer", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 8, - "type": "UInt32" + "nth": 16, + "type": "Amount" } ], [ - "UNLModifyDisabling", + "RippleEscrow", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, "nth": 17, - "type": "UInt8" + "type": "Amount" } ], [ - "Number", + "DeliveredAmount", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 1, - "type": "Number" + "nth": 18, + "type": "Amount" } ], [ - "TakerPays", + "NFTokenBrokerFee", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 4, + "nth": 19, "type": "Amount" } ], [ - "DisabledValidator", + "BaseFeeDrops", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 19, - "type": "STObject" + "nth": 22, + "type": "Amount" } ], [ - "SigningPubKey", + "ReserveBaseDrops", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 3, - "type": "Blob" + "isVLEncoded": false, + "nth": 23, + "type": "Amount" } ], [ - "Owner", + "ReserveIncrementDrops", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 2, - "type": "AccountID" + "isVLEncoded": false, + "nth": 24, + "type": "Amount" } ], [ - "PriceData", + "LPTokenOut", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 32, - "type": "STObject" + "nth": 25, + "type": "Amount" } ], [ - "Fulfillment", + "LPTokenIn", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 16, - "type": "Blob" + "isVLEncoded": false, + "nth": 26, + "type": "Amount" } ], [ - "Generic", + "EPrice", { - "isSerialized": false, + "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 0, - "type": "Unknown" + "nth": 27, + "type": "Amount" } ], [ - "MPTAmount", + "Price", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 26, - "type": "UInt64" + "nth": 28, + "type": "Amount" } ], [ - "LastLedgerSequence", + "SignatureReward", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 27, - "type": "UInt32" + "nth": 29, + "type": "Amount" } ], [ - "CheckID", + "MinAccountCreateAmount", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 24, - "type": "Hash256" + "nth": 30, + "type": "Amount" } ], [ - "ReserveBaseDrops", + "LPTokenBalance", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 23, + "nth": 31, "type": "Amount" } ], [ - "TradingFee", + "PublicKey", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": false, - "nth": 5, - "type": "UInt16" + "isVLEncoded": true, + "nth": 1, + "type": "Blob" } ], [ - "AttestationRewardAccount", + "MessageKey", { "isSerialized": true, "isSigningField": true, "isVLEncoded": true, - "nth": 21, - "type": "AccountID" + "nth": 2, + "type": "Blob" } ], [ - "Permission", + "SigningPubKey", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": false, - "nth": 15, - "type": "STObject" + "isVLEncoded": true, + "nth": 3, + "type": "Blob" } ], [ - "Validation", + "TxnSignature", { - "isSerialized": false, + "isSerialized": true, "isSigningField": false, - "isVLEncoded": false, - "nth": 257, - "type": "Validation" + "isVLEncoded": true, + "nth": 4, + "type": "Blob" } ], [ - "AccountHash", + "URI", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": false, - "nth": 4, - "type": "Hash256" + "isVLEncoded": true, + "nth": 5, + "type": "Blob" } ], [ - "CloseTime", + "Signature", + { + "isSerialized": true, + "isSigningField": false, + "isVLEncoded": true, + "nth": 6, + "type": "Blob" + } + ], + [ + "Domain", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": false, + "isVLEncoded": true, "nth": 7, - "type": "UInt32" + "type": "Blob" } ], [ - "ExchangeRate", + "FundCode", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": false, - "nth": 6, - "type": "UInt64" + "isVLEncoded": true, + "nth": 8, + "type": "Blob" } ], [ - "LimitAmount", + "RemoveCode", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": false, + "isVLEncoded": true, + "nth": 9, + "type": "Blob" + } + ], + [ + "ExpireCode", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 10, + "type": "Blob" + } + ], + [ + "CreateCode", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 11, + "type": "Blob" + } + ], + [ + "MemoType", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 12, + "type": "Blob" + } + ], + [ + "MemoData", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 13, + "type": "Blob" + } + ], + [ + "MemoFormat", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 14, + "type": "Blob" + } + ], + [ + "Fulfillment", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 16, + "type": "Blob" + } + ], + [ + "Condition", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 17, + "type": "Blob" + } + ], + [ + "MasterSignature", + { + "isSerialized": true, + "isSigningField": false, + "isVLEncoded": true, + "nth": 18, + "type": "Blob" + } + ], + [ + "UNLModifyValidator", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 19, + "type": "Blob" + } + ], + [ + "ValidatorToDisable", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 20, + "type": "Blob" + } + ], + [ + "ValidatorToReEnable", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 21, + "type": "Blob" + } + ], + [ + "DIDDocument", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 26, + "type": "Blob" + } + ], + [ + "Data", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 27, + "type": "Blob" + } + ], + [ + "AssetClass", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 28, + "type": "Blob" + } + ], + [ + "Provider", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 29, + "type": "Blob" + } + ], + [ + "MPTokenMetadata", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 30, + "type": "Blob" + } + ], + [ + "CredentialType", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 31, + "type": "Blob" + } + ], + [ + "FinishFunction", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 32, + "type": "Blob" + } + ], + [ + "ContractCode", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 33, + "type": "Blob" + } + ], + [ + "FunctionName", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 34, + "type": "Blob" + } + ], + [ + "Account", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 1, + "type": "AccountID" + } + ], + [ + "Owner", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 2, + "type": "AccountID" + } + ], + [ + "Destination", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, "nth": 3, - "type": "Amount" + "type": "AccountID" } ], [ - "Majority", + "Issuer", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": false, + "isVLEncoded": true, + "nth": 4, + "type": "AccountID" + } + ], + [ + "Authorize", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 5, + "type": "AccountID" + } + ], + [ + "Unauthorize", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 6, + "type": "AccountID" + } + ], + [ + "RegularKey", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 8, + "type": "AccountID" + } + ], + [ + "NFTokenMinter", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 9, + "type": "AccountID" + } + ], + [ + "EmitCallback", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 10, + "type": "AccountID" + } + ], + [ + "Holder", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 11, + "type": "AccountID" + } + ], + [ + "Delegate", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 12, + "type": "AccountID" + } + ], + [ + "OtherChainSource", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, "nth": 18, - "type": "STObject" + "type": "AccountID" } ], [ - "MessageKey", + "OtherChainDestination", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 19, + "type": "AccountID" + } + ], + [ + "AttestationSignerAccount", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 20, + "type": "AccountID" + } + ], + [ + "AttestationRewardAccount", + { + "isSerialized": true, + "isSigningField": true, + "isVLEncoded": true, + "nth": 21, + "type": "AccountID" + } + ], + [ + "LockingChainDoor", { "isSerialized": true, "isSigningField": true, "isVLEncoded": true, - "nth": 2, - "type": "Blob" + "nth": 22, + "type": "AccountID" } ], [ - "DisabledValidators", + "IssuingChainDoor", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": false, - "nth": 17, - "type": "STArray" + "isVLEncoded": true, + "nth": 23, + "type": "AccountID" } ], [ - "Account", + "Subject", { "isSerialized": true, "isSigningField": true, "isVLEncoded": true, - "nth": 1, + "nth": 24, "type": "AccountID" } ], [ - "NFTokenOfferNode", + "Borrower", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": false, - "nth": 12, - "type": "UInt64" + "isVLEncoded": true, + "nth": 25, + "type": "AccountID" } ], [ - "OwnerCount", + "Counterparty", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": false, - "nth": 13, - "type": "UInt32" + "isVLEncoded": true, + "nth": 26, + "type": "AccountID" } ], [ - "NFTokenID", + "ContractAccount", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": false, - "nth": 10, - "type": "Hash256" + "isVLEncoded": true, + "nth": 27, + "type": "AccountID" } ], [ - "SendMax", + "Number", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 9, - "type": "Amount" + "nth": 1, + "type": "Number" } ], [ - "FundCode", + "AssetsAvailable", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 8, - "type": "Blob" + "isVLEncoded": false, + "nth": 2, + "type": "Number" } ], [ - "HighQualityIn", + "AssetsMaximum", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 16, - "type": "UInt32" + "nth": 3, + "type": "Number" } ], [ - "Method", + "AssetsTotal", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 2, - "type": "UInt8" + "nth": 4, + "type": "Number" } ], [ - "BurnedNFTokens", + "LossUnrealized", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 44, - "type": "UInt32" + "nth": 5, + "type": "Number" } ], [ - "TakerPaysCurrency", + "DebtTotal", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 1, - "type": "Hash160" + "nth": 6, + "type": "Number" } ], [ - "EmitHookHash", + "DebtMaximum", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 13, - "type": "Hash256" + "nth": 7, + "type": "Number" } ], [ - "BidMin", + "CoverAvailable", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 12, - "type": "Amount" + "nth": 8, + "type": "Number" } ], [ - "AuthAccount", + "LoanOriginationFee", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 27, - "type": "STObject" + "nth": 9, + "type": "Number" } ], [ - "CreateCode", + "LoanServiceFee", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 11, - "type": "Blob" + "isVLEncoded": false, + "nth": 10, + "type": "Number" } ], [ - "AuthorizeCredentials", + "LatePaymentFee", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 26, - "type": "STArray" + "nth": 11, + "type": "Number" } ], [ - "EmitCallback", + "ClosePaymentFee", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 10, - "type": "AccountID" + "isVLEncoded": false, + "nth": 12, + "type": "Number" } ], [ - "DeletedNode", + "PrincipalOutstanding", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 4, - "type": "STObject" + "nth": 13, + "type": "Number" } ], [ - "TransactionHash", + "PrincipalRequested", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 3, - "type": "Hash256" + "nth": 14, + "type": "Number" } ], [ - "LedgerSequence", + "TotalValueOutstanding", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 6, - "type": "UInt32" + "nth": 15, + "type": "Number" } ], [ - "BaseFee", + "PeriodicPayment", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 5, - "type": "UInt64" + "nth": 16, + "type": "Number" } ], [ - "Balance", + "ManagementFeeOutstanding", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 2, - "type": "Amount" + "nth": 17, + "type": "Number" } ], [ - "PublicKey", + "LoanScale", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, + "isVLEncoded": false, "nth": 1, - "type": "Blob" + "type": "Int32" } ], [ - "ServerVersion", + "WasmReturnCode", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 11, - "type": "UInt64" + "nth": 2, + "type": "Int32" } ], [ - "WalletSize", + "TransactionMetaData", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 12, - "type": "UInt32" + "nth": 2, + "type": "STObject" } ], [ - "AccountTxnID", + "CreatedNode", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 9, - "type": "Hash256" + "nth": 3, + "type": "STObject" } ], [ - "ContractResult", + "DeletedNode", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 21, - "type": "UInt8" + "nth": 4, + "type": "STObject" } ], [ - "LossUnrealized", + "ModifiedNode", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, "nth": 5, - "type": "Number" + "type": "STObject" } ], [ - "Fee", + "PreviousFields", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 8, - "type": "Amount" + "nth": 6, + "type": "STObject" } ], [ - "Domain", + "FinalFields", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, + "isVLEncoded": false, "nth": 7, - "type": "Blob" + "type": "STObject" } ], [ - "XChainCreateAccountAttestations", + "NewFields", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 22, - "type": "STArray" + "nth": 8, + "type": "STObject" } ], [ - "Unauthorize", + "TemplateEntry", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 6, - "type": "AccountID" + "isVLEncoded": false, + "nth": 9, + "type": "STObject" } ], [ - "LastUpdateTime", + "Memo", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 15, - "type": "UInt32" + "nth": 10, + "type": "STObject" } ], [ - "CloseResolution", + "SignerEntry", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 1, - "type": "UInt8" + "nth": 11, + "type": "STObject" } ], [ - "EmitNonce", + "NFToken", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, "nth": 12, - "type": "Hash256" + "type": "STObject" } ], [ - "Amount2", + "EmitDetails", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 11, - "type": "Amount" + "nth": 13, + "type": "STObject" } ], [ - "AuctionSlot", + "Permission", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 26, + "nth": 15, "type": "STObject" } ], [ - "ExpireCode", + "Signer", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 10, - "type": "Blob" + "isVLEncoded": false, + "nth": 16, + "type": "STObject" } ], [ - "AuthAccounts", + "Majority", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 25, - "type": "STArray" + "nth": 18, + "type": "STObject" } ], [ - "NFTokenMinter", + "DisabledValidator", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 9, - "type": "AccountID" + "isVLEncoded": false, + "nth": 19, + "type": "STObject" } ], [ - "CreatedNode", + "VoteEntry", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 3, + "nth": 25, "type": "STObject" } ], [ - "Version", + "AuctionSlot", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 16, - "type": "UInt16" + "nth": 26, + "type": "STObject" } ], [ - "hash", + "AuthAccount", { - "isSerialized": false, - "isSigningField": false, + "isSerialized": true, + "isSigningField": true, "isVLEncoded": false, - "nth": 257, - "type": "Hash256" + "nth": 27, + "type": "STObject" } ], [ - "SourceTag", + "XChainClaimProofSig", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 3, - "type": "UInt32" + "nth": 28, + "type": "STObject" } ], [ - "IndexPrevious", + "XChainCreateAccountProofSig", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 2, - "type": "UInt64" + "nth": 29, + "type": "STObject" } ], [ - "EmailHash", + "XChainClaimAttestationCollectionElement", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 1, - "type": "Hash128" + "nth": 30, + "type": "STObject" } ], [ - "LedgerEntry", + "XChainCreateAccountAttestationCollectionElement", { - "isSerialized": false, - "isSigningField": false, + "isSerialized": true, + "isSigningField": true, "isVLEncoded": false, - "nth": 257, - "type": "LedgerEntry" + "nth": 31, + "type": "STObject" } ], [ - "ParameterFlag", + "PriceData", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 59, - "type": "UInt32" + "nth": 32, + "type": "STObject" } ], [ - "OutstandingAmount", + "Credential", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 25, - "type": "UInt64" + "nth": 33, + "type": "STObject" } ], [ - "FirstLedgerSequence", + "RawTransaction", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 26, - "type": "UInt32" + "nth": 34, + "type": "STObject" } ], [ - "ConsensusHash", + "BatchSigner", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 23, - "type": "Hash256" + "nth": 35, + "type": "STObject" } ], [ - "BaseFeeDrops", + "Book", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 22, - "type": "Amount" + "nth": 36, + "type": "STObject" } ], [ - "Function", + "CounterpartySignature", { "isSerialized": true, - "isSigningField": true, + "isSigningField": false, "isVLEncoded": false, "nth": 37, "type": "STObject" } ], [ - "ValidatorToReEnable", + "Function", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 21, - "type": "Blob" + "isVLEncoded": false, + "nth": 38, + "type": "STObject" } ], [ - "Parameters", + "InstanceParameter", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 36, - "type": "STArray" + "nth": 39, + "type": "STObject" } ], [ - "TransferFee", + "InstanceParameterValue", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 4, - "type": "UInt16" + "nth": 40, + "type": "STObject" } ], [ - "AttestationSignerAccount", + "Parameter", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 20, - "type": "AccountID" + "isVLEncoded": false, + "nth": 41, + "type": "STObject" } ], [ - "QuoteAsset", + "Signers", { "isSerialized": true, - "isSigningField": true, + "isSigningField": false, "isVLEncoded": false, - "nth": 2, - "type": "Currency" + "nth": 3, + "type": "STArray" } ], [ - "ReserveBase", + "SignerEntries", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 31, - "type": "UInt32" + "nth": 4, + "type": "STArray" } ], [ - "Asset2", + "Template", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 4, - "type": "Issue" + "nth": 5, + "type": "STArray" } ], [ - "PreviousPageMin", + "Necessary", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 26, - "type": "Hash256" + "nth": 6, + "type": "STArray" } ], [ - "LPTokenOut", + "Sufficient", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 25, - "type": "Amount" + "nth": 7, + "type": "STArray" } ], [ - "IssuingChainDoor", + "AffectedNodes", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 23, - "type": "AccountID" + "isVLEncoded": false, + "nth": 8, + "type": "STArray" } ], [ - "XChainAccountClaimCount", + "Memos", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 22, - "type": "UInt64" + "nth": 9, + "type": "STArray" } ], [ - "BondAmount", + "NFTokens", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 23, - "type": "UInt32" + "nth": 10, + "type": "STArray" } ], [ - "NFTokenBrokerFee", + "VoteSlots", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 19, - "type": "Amount" + "nth": 12, + "type": "STArray" } ], [ - "RawTransaction", + "AdditionalBooks", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 34, - "type": "STObject" + "nth": 13, + "type": "STArray" } ], [ - "MasterSignature", + "Majorities", { "isSerialized": true, - "isSigningField": false, - "isVLEncoded": true, - "nth": 18, - "type": "Blob" + "isSigningField": true, + "isVLEncoded": false, + "nth": 16, + "type": "STArray" } ], [ - "SignerEntry", + "DisabledValidators", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 11, - "type": "STObject" + "nth": 17, + "type": "STArray" } ], [ - "IssuerNode", + "XChainClaimAttestations", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 27, - "type": "UInt64" + "nth": 21, + "type": "STArray" } ], [ - "LockingChainIssue", + "XChainCreateAccountAttestations", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 1, - "type": "Issue" + "nth": 22, + "type": "STArray" } ], [ - "TransactionIndex", + "PriceDataSeries", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 28, - "type": "UInt32" + "nth": 24, + "type": "STArray" } ], [ - "ValidatedHash", + "AuthAccounts", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, "nth": 25, - "type": "Hash256" + "type": "STArray" } ], [ - "ReserveIncrementDrops", + "AuthorizeCredentials", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 24, - "type": "Amount" + "nth": 26, + "type": "STArray" } ], [ - "DiscountedFee", + "UnauthorizeCredentials", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 6, - "type": "UInt16" + "nth": 27, + "type": "STArray" } ], [ - "LockingChainDoor", + "AcceptedCredentials", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 22, - "type": "AccountID" + "isVLEncoded": false, + "nth": 28, + "type": "STArray" } ], [ - "Signer", + "Permissions", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 16, - "type": "STObject" + "nth": 29, + "type": "STArray" } ], [ - "ComputationAllowance", + "RawTransactions", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 57, - "type": "UInt32" + "nth": 30, + "type": "STArray" } ], [ - "GasUsed", + "BatchSigners", { "isSerialized": true, - "isSigningField": true, + "isSigningField": false, "isVLEncoded": false, - "nth": 58, - "type": "UInt32" + "nth": 31, + "type": "STArray" } ], [ - "TicketCount", + "Functions", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 40, - "type": "UInt32" + "nth": 32, + "type": "STArray" } ], [ - "Metadata", + "InstanceParameters", { - "isSerialized": false, - "isSigningField": false, + "isSerialized": true, + "isSigningField": true, "isVLEncoded": false, - "nth": 257, - "type": "Metadata" + "nth": 33, + "type": "STArray" } ], [ - "StampEscrow", + "InstanceParameterValues", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 22, - "type": "UInt32" + "nth": 34, + "type": "STArray" } ], [ - "XChainAccountCreateCount", + "Parameters", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 21, - "type": "UInt64" + "nth": 35, + "type": "STArray" } ], [ - "Amendment", + "CloseResolution", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 19, - "type": "Hash256" + "nth": 1, + "type": "UInt8" } ], [ - "DeliveredAmount", + "Method", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 18, - "type": "Amount" + "nth": 2, + "type": "UInt8" } ], [ - "Credential", + "TransactionResult", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 33, - "type": "STObject" + "nth": 3, + "type": "UInt8" } ], [ - "Condition", + "Scale", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 17, - "type": "Blob" + "isVLEncoded": false, + "nth": 4, + "type": "UInt8" } ], [ - "CredentialIDs", + "AssetScale", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, + "isVLEncoded": false, "nth": 5, - "type": "Vector256" + "type": "UInt8" } ], [ - "Memo", + "TickSize", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 10, - "type": "STObject" + "nth": 16, + "type": "UInt8" } ], [ - "LoadFee", + "UNLModifyDisabling", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 24, - "type": "UInt32" + "nth": 17, + "type": "UInt8" } ], [ - "AssetPrice", + "WasLockingChainSend", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 23, - "type": "UInt64" + "nth": 19, + "type": "UInt8" } ], [ - "Digest", + "WithdrawalPolicy", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 21, - "type": "Hash256" + "nth": 20, + "type": "UInt8" } ], [ - "BatchSigner", + "ContractResult", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 35, - "type": "STObject" + "nth": 21, + "type": "UInt8" } ], [ - "UNLModifyValidator", + "TakerPaysCurrency", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 19, - "type": "Blob" + "isVLEncoded": false, + "nth": 1, + "type": "Hash160" } ], [ - "InstanceParameters", + "TakerPaysIssuer", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 34, - "type": "STArray" + "nth": 2, + "type": "Hash160" } ], [ - "TransactionType", + "TakerGetsCurrency", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 2, - "type": "UInt16" + "nth": 3, + "type": "Hash160" } ], [ - "OtherChainSource", + "TakerGetsIssuer", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 18, - "type": "AccountID" + "isVLEncoded": false, + "nth": 4, + "type": "Hash160" } ], [ - "OperationLimit", + "Paths", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 29, - "type": "UInt32" + "nth": 1, + "type": "PathSet" } ], [ - "IssuingChainIssue", + "Indexes", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": false, - "nth": 2, - "type": "Issue" + "isVLEncoded": true, + "nth": 1, + "type": "Vector256" } ], [ - "SubjectNode", + "Hashes", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": false, - "nth": 28, - "type": "UInt64" + "isVLEncoded": true, + "nth": 2, + "type": "Vector256" } ], [ - "XChainBridge", + "Amendments", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": false, - "nth": 1, - "type": "XChainBridge" + "isVLEncoded": true, + "nth": 3, + "type": "Vector256" } ], [ - "NFToken", + "NFTokenOffers", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": false, - "nth": 12, - "type": "STObject" + "isVLEncoded": true, + "nth": 4, + "type": "Vector256" } ], [ - "OfferSequence", + "CredentialIDs", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": false, - "nth": 25, - "type": "UInt32" + "isVLEncoded": true, + "nth": 5, + "type": "Vector256" } ], [ - "MaximumAmount", + "MPTokenIssuanceID", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 24, - "type": "UInt64" + "nth": 1, + "type": "Hash192" } ], [ - "Channel", + "ShareMPTID", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 22, - "type": "Hash256" + "nth": 2, + "type": "Hash192" } ], [ - "Book", + "LockingChainIssue", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 36, - "type": "STObject" + "nth": 1, + "type": "Issue" } ], [ - "ValidatorToDisable", + "IssuingChainIssue", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 20, - "type": "Blob" + "isVLEncoded": false, + "nth": 2, + "type": "Issue" } ], [ - "InstanceParameterValues", + "Asset", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 35, - "type": "STArray" + "nth": 3, + "type": "Issue" } ], [ - "SignerWeight", + "Asset2", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 3, - "type": "UInt16" + "nth": 4, + "type": "Issue" } ], [ - "OtherChainDestination", + "XChainBridge", { "isSerialized": true, "isSigningField": true, - "isVLEncoded": true, - "nth": 19, - "type": "AccountID" + "isVLEncoded": false, + "nth": 1, + "type": "XChainBridge" } ], [ @@ -2971,83 +3311,83 @@ } ], [ - "ReferenceFeeUnits", + "QuoteAsset", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 30, - "type": "UInt32" + "nth": 2, + "type": "Currency" } ], [ - "Asset", + "ParameterValue", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 3, - "type": "Issue" + "nth": 1, + "type": "Data" } ], [ - "EmitDetails", + "ParameterType", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 13, - "type": "STObject" + "nth": 1, + "type": "DataType" } ], [ - "ReserveIncrement", + "ContractJson", { "isSerialized": true, "isSigningField": true, "isVLEncoded": false, - "nth": 32, - "type": "UInt32" + "nth": 1, + "type": "Json" } ], [ - "NFTokenSellOffer", + "Transaction", { - "isSerialized": true, - "isSigningField": true, + "isSerialized": false, + "isSigningField": false, "isVLEncoded": false, - "nth": 29, - "type": "Hash256" + "nth": 257, + "type": "Transaction" } ], [ - "ParameterType", + "LedgerEntry", { - "isSerialized": true, - "isSigningField": true, + "isSerialized": false, + "isSigningField": false, "isVLEncoded": false, - "nth": 1, - "type": "DataType" + "nth": 257, + "type": "LedgerEntry" } ], [ - "Price", + "Validation", { - "isSerialized": true, - "isSigningField": true, + "isSerialized": false, + "isSigningField": false, "isVLEncoded": false, - "nth": 28, - "type": "Amount" + "nth": 257, + "type": "Validation" } ], [ - "Data", + "Metadata", { - "isSerialized": true, - "isSigningField": true, - "isVLEncoded": true, - "nth": 27, - "type": "Blob" + "isSerialized": false, + "isSigningField": false, + "isVLEncoded": false, + "nth": 257, + "type": "Metadata" } ] ], @@ -3069,6 +3409,8 @@ "FeeSettings": 115, "Invalid": -1, "LedgerHashes": 104, + "Loan": 137, + "LoanBroker": 136, "MPToken": 127, "MPTokenIssuance": 126, "NFTokenOffer": 55, @@ -3106,6 +3448,7 @@ "tecFAILED_PROCESSING": 105, "tecFROZEN": 137, "tecHAS_OBLIGATIONS": 151, + "tecHOOK_REJECTED": 153, "tecINCOMPLETE": 169, "tecINSUFFICIENT_FUNDS": 159, "tecINSUFFICIENT_PAYMENT": 161, @@ -3171,6 +3514,7 @@ "tecXCHAIN_SELF_COMMIT": 184, "tecXCHAIN_SENDING_ACCOUNT_MISMATCH": 179, "tecXCHAIN_WRONG_CHAIN": 176, + "tefALREADY": -198, "tefBAD_ADD_AUTH": -197, "tefBAD_AUTH": -196, @@ -3195,6 +3539,7 @@ "tefTOO_BIG": -181, "tefWASM_FIELD_NOT_INCLUDED": -176, "tefWRONG_PRIOR": -189, + "telBAD_DOMAIN": -398, "telBAD_PATH_COUNT": -397, "telBAD_PUBLIC_KEY": -396, @@ -3212,6 +3557,7 @@ "telNO_DST_PARTIAL": -393, "telREQUIRES_NETWORK_ID": -385, "telWRONG_NETWORK": -386, + "temARRAY_EMPTY": -253, "temARRAY_TOO_LARGE": -252, "temBAD_AMM_TOKENS": -261, @@ -3255,6 +3601,7 @@ "temREDUNDANT": -275, "temRIPPLE_EMPTY": -274, "temSEQ_AND_TICKET": -263, + "temTEMP_DISABLED": -248, "temUNCERTAIN": -265, "temUNKNOWN": -264, "temXCHAIN_BAD_PROOF": -259, @@ -3263,6 +3610,7 @@ "temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT": -255, "temXCHAIN_BRIDGE_NONDOOR_OWNER": -257, "temXCHAIN_EQUAL_DOOR_ACCOUNTS": -260, + "terADDRESS_COLLISION": -86, "terFUNDS_SPENT": -98, "terINSUF_FEE_B": -97, @@ -3270,6 +3618,7 @@ "terNO_ACCOUNT": -96, "terNO_AMM": -87, "terNO_AUTH": -95, + "terNO_DELEGATE_PERMISSION": -85, "terNO_LINE": -94, "terNO_RIPPLE": -90, "terOWNERS": -93, @@ -3277,6 +3626,7 @@ "terPRE_TICKET": -88, "terQUEUED": -89, "terRETRY": -99, + "tesSUCCESS": 0 }, "TRANSACTION_TYPES": { @@ -3294,12 +3644,12 @@ "CheckCash": 17, "CheckCreate": 16, "Clawback": 30, - "ContractCall": 77, - "ContractClawback": 75, - "ContractCreate": 72, - "ContractDelete": 74, - "ContractModify": 73, - "ContractUserDelete": 76, + "ContractCall": 90, + "ContractClawback": 88, + "ContractCreate": 85, + "ContractDelete": 87, + "ContractModify": 86, + "ContractUserDelete": 89, "CredentialAccept": 59, "CredentialCreate": 58, "CredentialDelete": 60, @@ -3313,6 +3663,15 @@ "EscrowFinish": 2, "Invalid": -1, "LedgerStateFix": 53, + "LoanBrokerCoverClawback": 78, + "LoanBrokerCoverDeposit": 76, + "LoanBrokerCoverWithdraw": 77, + "LoanBrokerDelete": 75, + "LoanBrokerSet": 74, + "LoanDelete": 81, + "LoanManage": 82, + "LoanPay": 84, + "LoanSet": 80, "MPTokenAuthorize": 57, "MPTokenIssuanceCreate": 54, "MPTokenIssuanceDestroy": 55, @@ -3366,8 +3725,6 @@ "Hash160": 17, "Hash192": 21, "Hash256": 5, - "Hash384": 22, - "Hash512": 23, "Int32": 10, "Int64": 11, "Issue": 24, @@ -3382,6 +3739,8 @@ "Transaction": 10001, "UInt16": 1, "UInt32": 2, + "UInt384": 22, + "UInt512": 23, "UInt64": 3, "UInt8": 16, "UInt96": 20, diff --git a/packages/ripple-binary-codec/src/index.ts b/packages/ripple-binary-codec/src/index.ts index e6798373cd..b87f998fdb 100644 --- a/packages/ripple-binary-codec/src/index.ts +++ b/packages/ripple-binary-codec/src/index.ts @@ -100,9 +100,7 @@ function encodeForMultisigning( if (typeof json !== 'object') { throw new Error() } - if (json['SigningPubKey'] !== '') { - throw new Error() - } + const definitionsOpt = definitions ? { definitions } : undefined return bytesToHex( multiSigningData(json as JsonObject, signer, definitionsOpt), diff --git a/packages/ripple-binary-codec/src/types/hash-128.ts b/packages/ripple-binary-codec/src/types/hash-128.ts index cc78d0f985..825ca1068c 100644 --- a/packages/ripple-binary-codec/src/types/hash-128.ts +++ b/packages/ripple-binary-codec/src/types/hash-128.ts @@ -10,7 +10,7 @@ class Hash128 extends Hash { static readonly ZERO_128: Hash128 = new Hash128(new Uint8Array(Hash128.width)) constructor(bytes: Uint8Array) { - if (bytes && bytes.byteLength === 0) { + if (bytes?.byteLength === 0) { bytes = Hash128.ZERO_128.bytes } diff --git a/packages/ripple-binary-codec/src/types/hash-160.ts b/packages/ripple-binary-codec/src/types/hash-160.ts index c681058984..f49adb28a4 100644 --- a/packages/ripple-binary-codec/src/types/hash-160.ts +++ b/packages/ripple-binary-codec/src/types/hash-160.ts @@ -9,7 +9,7 @@ class Hash160 extends Hash { static readonly ZERO_160: Hash160 = new Hash160(new Uint8Array(Hash160.width)) constructor(bytes?: Uint8Array) { - if (bytes && bytes.byteLength === 0) { + if (bytes?.byteLength === 0) { bytes = Hash160.ZERO_160.bytes } diff --git a/packages/ripple-binary-codec/src/types/hash-192.ts b/packages/ripple-binary-codec/src/types/hash-192.ts index 9c69704c5d..5b2d117dcb 100644 --- a/packages/ripple-binary-codec/src/types/hash-192.ts +++ b/packages/ripple-binary-codec/src/types/hash-192.ts @@ -9,7 +9,7 @@ class Hash192 extends Hash { static readonly ZERO_192: Hash192 = new Hash192(new Uint8Array(Hash192.width)) constructor(bytes?: Uint8Array) { - if (bytes && bytes.byteLength === 0) { + if (bytes?.byteLength === 0) { bytes = Hash192.ZERO_192.bytes } diff --git a/packages/ripple-binary-codec/src/types/index.ts b/packages/ripple-binary-codec/src/types/index.ts index 1851954481..c7bc575b4f 100644 --- a/packages/ripple-binary-codec/src/types/index.ts +++ b/packages/ripple-binary-codec/src/types/index.ts @@ -8,6 +8,7 @@ import { Hash128 } from './hash-128' import { Hash160 } from './hash-160' import { Hash192 } from './hash-192' import { Hash256 } from './hash-256' +import { Int32 } from './int-32' import { Issue } from './issue' import { STNumber } from './st-number' import { PathSet } from './path-set' @@ -33,6 +34,7 @@ const coreTypes: Record = { Hash160, Hash192, Hash256, + Int32, Issue, Number: STNumber, PathSet, @@ -63,6 +65,7 @@ export { Hash160, Hash192, Hash256, + Int32, PathSet, STArray, STObject, diff --git a/packages/ripple-binary-codec/src/types/int-32.ts b/packages/ripple-binary-codec/src/types/int-32.ts new file mode 100644 index 0000000000..03d9c0862c --- /dev/null +++ b/packages/ripple-binary-codec/src/types/int-32.ts @@ -0,0 +1,72 @@ +import { Int } from './int' +import { BinaryParser } from '../serdes/binary-parser' +import { readInt32BE, writeInt32BE } from '../utils' + +/** + * Derived Int class for serializing/deserializing signed 32-bit integers. + */ +class Int32 extends Int { + protected static readonly width: number = 32 / 8 // 4 bytes + static readonly defaultInt32: Int32 = new Int32(new Uint8Array(Int32.width)) + + // Signed 32-bit integer range + static readonly MIN_VALUE: number = -2147483648 // -2^31 + static readonly MAX_VALUE: number = 2147483647 // 2^31 - 1 + + constructor(bytes: Uint8Array) { + super(bytes ?? Int32.defaultInt32.bytes) + } + + /** + * Construct an Int32 from a BinaryParser + * + * @param parser BinaryParser to read Int32 from + * @returns An Int32 object + */ + static fromParser(parser: BinaryParser): Int { + return new Int32(parser.read(Int32.width)) + } + + /** + * Construct an Int32 object from a number or string + * + * @param val Int32 object, number, or string + * @returns An Int32 object + */ + static from(val: T): Int32 { + if (val instanceof Int32) { + return val + } + + const buf = new Uint8Array(Int32.width) + + if (typeof val === 'string') { + const num = Number(val) + if (!Number.isFinite(num) || !Number.isInteger(num)) { + throw new Error(`Cannot construct Int32 from string: ${val}`) + } + Int32.checkIntRange('Int32', num, Int32.MIN_VALUE, Int32.MAX_VALUE) + writeInt32BE(buf, num, 0) + return new Int32(buf) + } + + if (typeof val === 'number' && Number.isInteger(val)) { + Int32.checkIntRange('Int32', val, Int32.MIN_VALUE, Int32.MAX_VALUE) + writeInt32BE(buf, val, 0) + return new Int32(buf) + } + + throw new Error('Cannot construct Int32 from given value') + } + + /** + * Get the value of the Int32 object + * + * @returns the signed 32-bit integer represented by this.bytes + */ + valueOf(): number { + return readInt32BE(this.bytes, 0) + } +} + +export { Int32 } diff --git a/packages/ripple-binary-codec/src/types/int.ts b/packages/ripple-binary-codec/src/types/int.ts new file mode 100644 index 0000000000..950a464841 --- /dev/null +++ b/packages/ripple-binary-codec/src/types/int.ts @@ -0,0 +1,75 @@ +import { Comparable } from './serialized-type' + +/** + * Compare numbers and bigInts n1 and n2 + * + * @param n1 First object to compare + * @param n2 Second object to compare + * @returns -1, 0, or 1, depending on how the two objects compare + */ +function compare(n1: number | bigint, n2: number | bigint): number { + return n1 < n2 ? -1 : n1 == n2 ? 0 : 1 +} + +/** + * Base class for serializing and deserializing signed integers. + */ +abstract class Int extends Comparable { + protected static width: number + + constructor(bytes: Uint8Array) { + super(bytes) + } + + /** + * Overload of compareTo for Comparable + * + * @param other other Int to compare this to + * @returns -1, 0, or 1 depending on how the objects relate to each other + */ + compareTo(other: Int | number): number { + return compare(this.valueOf(), other.valueOf()) + } + + /** + * Convert an Int object to JSON + * + * @returns number or string represented by this.bytes + */ + toJSON(): number | string { + const val = this.valueOf() + return typeof val === 'number' ? val : val.toString() + } + + /** + * Get the value of the Int represented by this.bytes + * + * @returns the value + */ + abstract valueOf(): number | bigint + + /** + * Validate that a number is within the specified signed integer range + * + * @param typeName The name of the type (for error messages) + * @param val The number to validate + * @param min The minimum allowed value + * @param max The maximum allowed value + * @throws Error if the value is out of range + */ + // eslint-disable-next-line max-params -- for error clarity in browsers + static checkIntRange( + typeName: string, + val: number | bigint, + min: number | bigint, + max: number | bigint, + ): void { + if (val < min || val > max) { + throw new Error( + `Invalid ${typeName}: ${val} must be >= ${min} and <= ${max}`, + ) + } + } +} + +export { Int } diff --git a/packages/ripple-binary-codec/src/types/issue.ts b/packages/ripple-binary-codec/src/types/issue.ts index 3eda10bd38..9aeecd9874 100644 --- a/packages/ripple-binary-codec/src/types/issue.ts +++ b/packages/ripple-binary-codec/src/types/issue.ts @@ -1,140 +1,173 @@ -import { concat } from '@transia/isomorphic/utils' -import { BinaryParser } from '../serdes/binary-parser' - -import { AccountID } from './account-id' -import { Currency } from './currency' -import { JsonObject, SerializedType, SerializedTypeID } from './serialized-type' -import { Hash192 } from './hash-192' +import { bytesToHex, concat } from "@transia/isomorphic/utils"; +import { BinaryParser } from "../serdes/binary-parser"; + +import { AccountID } from "./account-id"; +import { Currency } from "./currency"; +import { + JsonObject, + SerializedType, + SerializedTypeID, +} from "./serialized-type"; +import { Hash192 } from "./hash-192"; +import { readUInt32BE, writeUInt32BE } from "../utils"; interface XRPIssue extends JsonObject { - currency: string + currency: string; } interface IOUIssue extends JsonObject { - currency: string - issuer: string + currency: string; + issuer: string; } interface MPTIssue extends JsonObject { - mpt_issuance_id: string + mpt_issuance_id: string; } /** * Interface for JSON objects that represent issues */ -type IssueObject = XRPIssue | IOUIssue | MPTIssue +type IssueObject = XRPIssue | IOUIssue | MPTIssue; /** * Type guard for Issue Object */ function isIssueObject(arg): arg is IssueObject { - const keys = Object.keys(arg).sort() - const isXRP = keys.length === 1 && keys[0] === 'currency' + const keys = Object.keys(arg).sort(); + const isXRP = keys.length === 1 && keys[0] === "currency"; const isIOU = - keys.length === 2 && keys[0] === 'currency' && keys[1] === 'issuer' - const isMPT = keys.length === 1 && keys[0] === 'mpt_issuance_id' + keys.length === 2 && keys[0] === "currency" && keys[1] === "issuer"; + const isMPT = keys.length === 1 && keys[0] === "mpt_issuance_id"; - return isXRP || isIOU || isMPT + return isXRP || isIOU || isMPT; } +const MPT_WIDTH = 44; +const NO_ACCOUNT = AccountID.from("0000000000000000000000000000000000000001"); + /** - * Class for serializing/Deserializing Amounts + * Class for serializing/Deserializing Issue */ class Issue extends SerializedType { - static readonly ZERO_ISSUED_CURRENCY: Issue = new Issue(new Uint8Array(20)) + static readonly XRP_ISSUE: Issue = new Issue(new Uint8Array(20)); constructor(bytes: Uint8Array) { - super(bytes ?? Issue.ZERO_ISSUED_CURRENCY.bytes) + super(bytes ?? Issue.XRP_ISSUE.bytes); } /** - * Construct an amount from an IOU or string amount + * Construct Issue from XRPIssue, IOUIssue or MPTIssue * - * @param value An Amount, object representing an IOU, MPTAmount, or a string - * representing an integer amount + * @param value An object representing an XRPIssue, IOUIssue or MPTIssue * @returns An Issue object */ static from(value: T): Issue { if (value instanceof Issue) { - return value + return value; } if (isIssueObject(value)) { if (value.currency) { - const currency = Currency.from(value.currency.toString()).toBytes() + const currency = Currency.from(value.currency.toString()).toBytes(); //IOU case if (value.issuer) { - const issuer = AccountID.from(value.issuer.toString()).toBytes() - return new Issue(concat([currency, issuer])) + const issuer = AccountID.from(value.issuer.toString()).toBytes(); + return new Issue(concat([currency, issuer])); } //XRP case - return new Issue(currency) + return new Issue(currency); } // MPT case if (value.mpt_issuance_id) { const mptIssuanceIdBytes = Hash192.from( value.mpt_issuance_id.toString(), - ).toBytes() - return new Issue(mptIssuanceIdBytes) + ).toBytes(); + const issuerAccount = mptIssuanceIdBytes.slice(4); + const sequence = Number( + readUInt32BE(mptIssuanceIdBytes.slice(0, 4), 0), + ); // sequence is in Big-endian format in mpt_issuance_id + + // Convert to Little-endian + const sequenceBuffer = new Uint8Array(4); + new DataView(sequenceBuffer.buffer).setUint32(0, sequence, true); + + return new Issue( + concat([issuerAccount, NO_ACCOUNT.toBytes(), sequenceBuffer]), + ); } } - throw new Error('Invalid type to construct an Amount') + throw new Error("Invalid type to construct an Issue"); } /** - * Read an amount from a BinaryParser + * Read Issue from a BinaryParser * - * @param parser BinaryParser to read the Amount from - * @param hint The number of bytes to consume from the parser. - * For an MPT amount, pass 24 (the fixed length for Hash192). + * @param parser BinaryParser to read the Issue from * * @returns An Issue object */ - static fromParser(parser: BinaryParser, hint?: number): Issue { - if (hint === Hash192.width) { - const mptBytes = parser.read(Hash192.width) - return new Issue(mptBytes) + static fromParser(parser: BinaryParser): Issue { + // XRP + const currencyOrAccount = parser.read(20); + if (new Currency(currencyOrAccount).toJSON() === "XRP") { + return new Issue(currencyOrAccount); } - const currency = parser.read(20) - if (new Currency(currency).toJSON() === 'XRP') { - return new Issue(currency) + + // MPT + const issuerAccountId = new AccountID(parser.read(20)); + if (NO_ACCOUNT.toHex() === issuerAccountId.toHex()) { + const sequence = parser.read(4); + return new Issue( + concat([currencyOrAccount, NO_ACCOUNT.toBytes(), sequence]), + ); } - const currencyAndIssuer = [currency, parser.read(20)] - return new Issue(concat(currencyAndIssuer)) + + // IOU + return new Issue(concat([currencyOrAccount, issuerAccountId.toBytes()])); } /** - * Get the JSON representation of this Amount + * Get the JSON representation of this IssueObject * * @returns the JSON interpretation of this.bytes */ toJSON(): IssueObject { - // If the buffer is exactly 24 bytes, treat it as an MPT amount. - if (this.toBytes().length === Hash192.width) { + // If the buffer is exactly 44 bytes, treat it as an MPTIssue. + if (this.toBytes().length === MPT_WIDTH) { + const issuerAccount = this.toBytes().slice(0, 20); + const sequence = new DataView(this.toBytes().slice(40).buffer).getUint32( + 0, + true, + ); + + // sequence part of mpt_issuance_id should be in Big-endian + const sequenceBuffer = new Uint8Array(4); + writeUInt32BE(sequenceBuffer, sequence, 0); + return { - mpt_issuance_id: this.toHex().toUpperCase(), - } + mpt_issuance_id: bytesToHex(concat([sequenceBuffer, issuerAccount])), + }; } - const parser = new BinaryParser(this.toString()) + const parser = new BinaryParser(this.toString()); - const currency = Currency.fromParser(parser) as Currency - if (currency.toJSON() === 'XRP') { - return { currency: currency.toJSON() } + const currency = Currency.fromParser(parser) as Currency; + if (currency.toJSON() === "XRP") { + return { currency: currency.toJSON() }; } - const issuer = AccountID.fromParser(parser) as AccountID + const issuer = AccountID.fromParser(parser) as AccountID; return { currency: currency.toJSON(), issuer: issuer.toJSON(), - } + }; } getSType(): SerializedTypeID { - return SerializedTypeID.STI_ISSUE + return SerializedTypeID.STI_ISSUE; } } -export { Issue, IssueObject } +export { Issue, IssueObject }; diff --git a/packages/ripple-binary-codec/src/types/st-number.ts b/packages/ripple-binary-codec/src/types/st-number.ts index 26d8304946..efea789a23 100644 --- a/packages/ripple-binary-codec/src/types/st-number.ts +++ b/packages/ripple-binary-codec/src/types/st-number.ts @@ -1,3 +1,4 @@ +/* eslint-disable complexity -- required for various checks */ import { BinaryParser } from '../serdes/binary-parser' import { SerializedType, SerializedTypeID } from './serialized-type' import { writeInt32BE, writeInt64BE, readInt32BE, readInt64BE } from '../utils' @@ -6,8 +7,9 @@ import { writeInt32BE, writeInt64BE, readInt32BE, readInt64BE } from '../utils' * Constants for mantissa and exponent normalization per XRPL Number spec. * These define allowed magnitude for mantissa and exponent after normalization. */ -const MIN_MANTISSA = BigInt('1000000000000000') -const MAX_MANTISSA = BigInt('9999999999999999') +const MIN_MANTISSA = BigInt('1000000000000000000') // 10^18 +const MAX_MANTISSA = BigInt('9999999999999999999') // 10^19 - 1 +const MAX_INT64 = BigInt('9223372036854775807') // 2^63 - 1, max signed 64-bit integer const MIN_EXPONENT = -32768 const MAX_EXPONENT = 32768 const DEFAULT_VALUE_EXPONENT = -2147483648 @@ -62,6 +64,12 @@ function extractNumberPartsFromString(val: string): { } if (expPart) exponent += parseInt(expPart, 10) + // Remove trailing zeros from mantissa and adjust exponent + while (mantissaStr.length > 1 && mantissaStr.endsWith('0')) { + mantissaStr = mantissaStr.slice(0, -1) + exponent += 1 + } + let mantissa = BigInt(mantissaStr) if (sign === '-') mantissa = -mantissa const isNegative = mantissa < BigInt(0) @@ -72,7 +80,7 @@ function extractNumberPartsFromString(val: string): { /** * Normalize the mantissa and exponent to XRPL constraints. * - * Ensures that after normalization, the mantissa is between MIN_MANTISSA and MAX_MANTISSA (unless zero). + * Ensures that after normalization, the mantissa is between MIN_MANTISSA and MAX_INT64. * Adjusts the exponent as needed by shifting the mantissa left/right (multiplying/dividing by 10). * * @param mantissa - The unnormalized mantissa (BigInt). @@ -87,16 +95,65 @@ function normalize( let m = mantissa < BigInt(0) ? -mantissa : mantissa const isNegative = mantissa < BigInt(0) - while (m !== BigInt(0) && m < MIN_MANTISSA && exponent > MIN_EXPONENT) { + // Handle zero + if (m === BigInt(0)) { + return { mantissa: BigInt(0), exponent: DEFAULT_VALUE_EXPONENT } + } + + // Grow mantissa until it reaches MIN_MANTISSA + while (m < MIN_MANTISSA && exponent > MIN_EXPONENT) { exponent -= 1 m *= BigInt(10) } + + let lastDigit: bigint | null = null + + // Shrink mantissa until it fits within MAX_MANTISSA while (m > MAX_MANTISSA) { - if (exponent >= MAX_EXPONENT) + if (exponent >= MAX_EXPONENT) { throw new Error('Mantissa and exponent are too large') + } exponent += 1 + lastDigit = m % BigInt(10) m /= BigInt(10) } + + // Handle underflow: if exponent too small or mantissa too small, throw error + if (exponent < MIN_EXPONENT || m < MIN_MANTISSA) { + throw new Error('Underflow: value too small to represent') + } + + // Handle overflow: if exponent exceeds MAX_EXPONENT after growing. + if (exponent > MAX_EXPONENT) { + throw new Error('Exponent overflow: value too large to represent') + } + + // Handle overflow: if mantissa exceeds MAX_INT64 (2^63-1) after growing. + if (m > MAX_INT64) { + if (exponent >= MAX_EXPONENT) { + throw new Error('Exponent overflow: value too large to represent') + } + exponent += 1 + lastDigit = m % BigInt(10) + m /= BigInt(10) + } + + if (lastDigit != null && lastDigit >= BigInt(5)) { + m += BigInt(1) + // After rounding, mantissa may exceed MAX_INT64 again + if (m > MAX_INT64) { + if (exponent >= MAX_EXPONENT) { + throw new Error('Exponent overflow: value too large to represent') + } + lastDigit = m % BigInt(10) + exponent += 1 + m /= BigInt(10) + if (lastDigit >= BigInt(5)) { + m += BigInt(1) + } + } + } + if (isNegative) m = -m return { mantissa: m, exponent } } @@ -159,17 +216,9 @@ export class STNumber extends SerializedType { * @throws Error if val is not a valid number string. */ static fromValue(val: string): STNumber { - const { mantissa, exponent, isNegative } = extractNumberPartsFromString(val) - let normalizedMantissa: bigint - let normalizedExponent: number - - if (mantissa === BigInt(0) && exponent === 0 && !isNegative) { - normalizedMantissa = BigInt(0) - normalizedExponent = DEFAULT_VALUE_EXPONENT - } else { - ;({ mantissa: normalizedMantissa, exponent: normalizedExponent } = - normalize(mantissa, exponent)) - } + const { mantissa, exponent } = extractNumberPartsFromString(val) + const { mantissa: normalizedMantissa, exponent: normalizedExponent } = + normalize(mantissa, exponent) const bytes = new Uint8Array(12) writeInt64BE(bytes, normalizedMantissa, 0) @@ -193,39 +242,66 @@ export class STNumber extends SerializedType { * * @returns String representation of the value */ - // eslint-disable-next-line complexity -- required toJSON(): string { const b = this.bytes - if (!b || b.length !== 12) + if (!b || b?.length !== 12) throw new Error('STNumber internal bytes not set or wrong length') // Signed 64-bit mantissa const mantissa = readInt64BE(b, 0) // Signed 32-bit exponent - const exponent = readInt32BE(b, 8) + let exponent = readInt32BE(b, 8) // Special zero: XRPL encodes canonical zero as mantissa=0, exponent=DEFAULT_VALUE_EXPONENT. if (mantissa === BigInt(0) && exponent === DEFAULT_VALUE_EXPONENT) { return '0' } - if (exponent === 0) return mantissa.toString() - // Use scientific notation for small/large exponents, decimal otherwise - if (exponent < -25 || exponent > -5) { - return `${mantissa}e${exponent}` + const isNegative = mantissa < BigInt(0) + let mantissaAbs = isNegative ? -mantissa : mantissa + + // If mantissa < MIN_MANTISSA, it was shrunk for int64 serialization (mantissa > 2^63-1). + // Restore it for proper string rendering to match rippled's internal representation. + if (mantissaAbs !== BigInt(0) && mantissaAbs < MIN_MANTISSA) { + mantissaAbs *= BigInt(10) + exponent -= 1 } - // Decimal rendering for -25 <= exp <= -5 - const isNegative = mantissa < BigInt(0) - const mantissaAbs = mantissa < BigInt(0) ? -mantissa : mantissa + // For large mantissa range (default), rangeLog = 18 + const rangeLog = 18 + + // Use scientific notation for exponents that are too small or too large + // Condition from rippled: exponent != 0 AND (exponent < -(rangeLog + 10) OR exponent > -(rangeLog - 10)) + // For rangeLog = 18: exponent != 0 AND (exponent < -28 OR exponent > -8) + if ( + exponent !== 0 && + (exponent < -(rangeLog + 10) || exponent > -(rangeLog - 10)) + ) { + // Strip trailing zeros from mantissa (matches rippled behavior) + let exp = exponent + while ( + mantissaAbs !== BigInt(0) && + mantissaAbs % BigInt(10) === BigInt(0) && + exp < MAX_EXPONENT + ) { + mantissaAbs /= BigInt(10) + exp += 1 + } + const sign = isNegative ? '-' : '' + return `${sign}${mantissaAbs}e${exp}` + } + + // Decimal rendering for -(rangeLog + 10) <= exponent <= -(rangeLog - 10) + // i.e., -28 <= exponent <= -8, or exponent == 0 + const padPrefix = rangeLog + 12 // 30 + const padSuffix = rangeLog + 8 // 26 - const padPrefix = 27 - const padSuffix = 23 const mantissaStr = mantissaAbs.toString() const rawValue = '0'.repeat(padPrefix) + mantissaStr + '0'.repeat(padSuffix) - const OFFSET = exponent + 43 - const integerPart = rawValue.slice(0, OFFSET).replace(/^0+/, '') || '0' - const fractionPart = rawValue.slice(OFFSET).replace(/0+$/, '') + const offset = exponent + padPrefix + rangeLog + 1 // exponent + 49 + + const integerPart = rawValue.slice(0, offset).replace(/^0+/, '') || '0' + const fractionPart = rawValue.slice(offset).replace(/0+$/, '') return `${isNegative ? '-' : ''}${integerPart}${ fractionPart ? '.' + fractionPart : '' diff --git a/packages/ripple-binary-codec/src/types/st-object.ts b/packages/ripple-binary-codec/src/types/st-object.ts index abe447af6a..1d96864b5e 100644 --- a/packages/ripple-binary-codec/src/types/st-object.ts +++ b/packages/ripple-binary-codec/src/types/st-object.ts @@ -3,25 +3,29 @@ import { FieldInstance, Bytes, XrplDefinitionsBase, -} from '../enums' -import { SerializedType, JsonObject, SerializedTypeID } from './serialized-type' +} from "../enums"; +import { + SerializedType, + JsonObject, + SerializedTypeID, +} from "./serialized-type"; import { xAddressToClassicAddress, isValidXAddress, -} from '@transia/ripple-address-codec' -import { BinaryParser } from '../serdes/binary-parser' -import { BinarySerializer, BytesList } from '../serdes/binary-serializer' +} from "@transia/ripple-address-codec"; +import { BinaryParser } from "../serdes/binary-parser"; +import { BinarySerializer, BytesList } from "../serdes/binary-serializer"; -import { STArray } from './st-array' -import { UInt64 } from './uint-64' +import { STArray } from "./st-array"; +import { UInt64 } from "./uint-64"; -const OBJECT_END_MARKER_BYTE = Uint8Array.from([0xe1]) -const OBJECT_END_MARKER = 'ObjectEndMarker' -const ST_OBJECT = 'STObject' -const DESTINATION = 'Destination' -const ACCOUNT = 'Account' -const SOURCE_TAG = 'SourceTag' -const DEST_TAG = 'DestinationTag' +const OBJECT_END_MARKER_BYTE = Uint8Array.from([0xe1]); +const OBJECT_END_MARKER = "ObjectEndMarker"; +const ST_OBJECT = "STObject"; +const DESTINATION = "Destination"; +const ACCOUNT = "Account"; +const SOURCE_TAG = "SourceTag"; +const DEST_TAG = "DestinationTag"; /** * Break down an X-Address into an account and a tag @@ -30,17 +34,17 @@ const DEST_TAG = 'DestinationTag' * @param xAddress X-Address corresponding to the field */ function handleXAddress(field: string, xAddress: string): JsonObject { - const decoded = xAddressToClassicAddress(xAddress) + const decoded = xAddressToClassicAddress(xAddress); - let tagName - if (field === DESTINATION) tagName = DEST_TAG - else if (field === ACCOUNT) tagName = SOURCE_TAG + let tagName; + if (field === DESTINATION) tagName = DEST_TAG; + else if (field === ACCOUNT) tagName = SOURCE_TAG; else if (decoded.tag !== false) - throw new Error(`${field} cannot have an associated tag`) + throw new Error(`${field} cannot have an associated tag`); return decoded.tag !== false ? { [field]: decoded.classicAddress, [tagName]: decoded.tag } - : { [field]: decoded.classicAddress } + : { [field]: decoded.classicAddress }; } /** @@ -52,9 +56,9 @@ function handleXAddress(field: string, xAddress: string): JsonObject { */ function checkForDuplicateTags(obj1: JsonObject, obj2: JsonObject): void { if (!(obj1[SOURCE_TAG] === undefined || obj2[SOURCE_TAG] === undefined)) - throw new Error('Cannot have Account X-Address and SourceTag') + throw new Error("Cannot have Account X-Address and SourceTag"); if (!(obj1[DEST_TAG] === undefined || obj2[DEST_TAG] === undefined)) - throw new Error('Cannot have Destination X-Address and DestinationTag') + throw new Error("Cannot have Destination X-Address and DestinationTag"); } /** @@ -68,24 +72,24 @@ class STObject extends SerializedType { * @returns A STObject object */ static fromParser(parser: BinaryParser): STObject { - const list: BytesList = new BytesList() - const bytes: BinarySerializer = new BinarySerializer(list) + const list: BytesList = new BytesList(); + const bytes: BinarySerializer = new BinarySerializer(list); while (!parser.end()) { - const field = parser.readField() + const field = parser.readField(); if (field.name === OBJECT_END_MARKER) { - break + break; } - const associatedValue = parser.readFieldValue(field) + const associatedValue = parser.readFieldValue(field); - bytes.writeFieldAndValue(field, associatedValue) + bytes.writeFieldAndValue(field, associatedValue); if (field.type.name === ST_OBJECT) { - bytes.put(OBJECT_END_MARKER_BYTE) + bytes.put(OBJECT_END_MARKER_BYTE); } } - return new STObject(list.toBytes()) + return new STObject(list.toBytes()); } /** @@ -102,22 +106,22 @@ class STObject extends SerializedType { definitions: XrplDefinitionsBase = DEFAULT_DEFINITIONS, ): STObject { if (value instanceof STObject) { - return value + return value; } - const list: BytesList = new BytesList() - const bytes: BinarySerializer = new BinarySerializer(list) + const list: BytesList = new BytesList(); + const bytes: BinarySerializer = new BinarySerializer(list); - let isUnlModify = false + let isUnlModify = false; const xAddressDecoded = Object.entries(value).reduce((acc, [key, val]) => { - let handled: JsonObject | undefined = undefined + let handled: JsonObject | undefined = undefined; if (val && isValidXAddress(val.toString())) { - handled = handleXAddress(key, val.toString()) - checkForDuplicateTags(handled, value) + handled = handleXAddress(key, val.toString()); + checkForDuplicateTags(handled, value); } - return Object.assign(acc, handled ?? { [key]: val }) - }, {}) + return Object.assign(acc, handled ?? { [key]: val }); + }, {}); function isValidFieldInstance( f: FieldInstance | undefined, @@ -126,65 +130,65 @@ class STObject extends SerializedType { f !== undefined && xAddressDecoded[f.name] !== undefined && f.isSerialized - ) + ); } let sorted = Object.keys(xAddressDecoded) .map((f: string): FieldInstance | undefined => { if (!(f in definitions.field)) { - if (f[0] === f[0].toLowerCase()) return undefined - throw new Error(`Field ${f} is not defined in the definitions`) + if (f[0] === f[0].toLowerCase()) return undefined; + throw new Error(`Field ${f} is not defined in the definitions`); } - return definitions.field[f] as FieldInstance + return definitions.field[f] as FieldInstance; }) .filter(isValidFieldInstance) .sort((a, b) => { - return a.ordinal - b.ordinal - }) + return a.ordinal - b.ordinal; + }); if (filter !== undefined) { - sorted = sorted.filter(filter) + sorted = sorted.filter(filter); } sorted.forEach((field) => { const associatedValue = field.type.name === ST_OBJECT ? this.from(xAddressDecoded[field.name], undefined, definitions) - : field.type.name === 'STArray' - ? STArray.from(xAddressDecoded[field.name], definitions) - : field.type.name === 'UInt64' - ? UInt64.from(xAddressDecoded[field.name], field.name) - : field.associatedType?.from - ? field.associatedType.from(xAddressDecoded[field.name]) - : (() => { - throw new Error( - `Type ${field.type.name} for field ${field.name} is missing associatedType.from`, - ) - })() + : field.type.name === "STArray" + ? STArray.from(xAddressDecoded[field.name], definitions) + : field.type.name === "UInt64" + ? UInt64.from(xAddressDecoded[field.name], field.name) + : field.associatedType?.from + ? field.associatedType.from(xAddressDecoded[field.name]) + : (() => { + throw new Error( + `Type ${field.type.name} for field ${field.name} is missing associatedType.from`, + ); + })(); if (associatedValue == undefined) { throw new TypeError( `Unable to interpret "${field.name}: ${ xAddressDecoded[field.name] }".`, - ) + ); } - if ((associatedValue as unknown as Bytes).name === 'UNLModify') { + if ((associatedValue as unknown as Bytes).name === "UNLModify") { // triggered when the TransactionType field has a value of 'UNLModify' - isUnlModify = true + isUnlModify = true; } // true when in the UNLModify pseudotransaction (after the transaction type has been processed) and working with the // Account field // The Account field must not be a part of the UNLModify pseudotransaction encoding, due to a bug in rippled - const isUnlModifyWorkaround = field.name == 'Account' && isUnlModify - bytes.writeFieldAndValue(field, associatedValue, isUnlModifyWorkaround) + const isUnlModifyWorkaround = field.name == "Account" && isUnlModify; + bytes.writeFieldAndValue(field, associatedValue, isUnlModifyWorkaround); if (field.type.name === ST_OBJECT) { - bytes.put(OBJECT_END_MARKER_BYTE) + bytes.put(OBJECT_END_MARKER_BYTE); } - }) + }); - return new STObject(list.toBytes()) + return new STObject(list.toBytes()); } /** @@ -194,26 +198,26 @@ class STObject extends SerializedType { * @returns a JSON object */ toJSON(definitions?: XrplDefinitionsBase): JsonObject { - const objectParser = new BinaryParser(this.toString(), definitions) - const accumulator = {} + const objectParser = new BinaryParser(this.toString(), definitions); + const accumulator = {}; while (!objectParser.end()) { - const field = objectParser.readField() + const field = objectParser.readField(); if (field.name === OBJECT_END_MARKER) { - break + break; } accumulator[field.name] = objectParser .readFieldValue(field) - .toJSON(definitions, field.name) + .toJSON(definitions, field.name); } - return accumulator + return accumulator; } getSType(): SerializedTypeID { - return SerializedTypeID.STI_OBJECT + return SerializedTypeID.STI_OBJECT; } } -export { STObject } +export { STObject }; diff --git a/packages/ripple-binary-codec/src/types/uint-16.ts b/packages/ripple-binary-codec/src/types/uint-16.ts index cc973ff915..5e2c68f6e6 100644 --- a/packages/ripple-binary-codec/src/types/uint-16.ts +++ b/packages/ripple-binary-codec/src/types/uint-16.ts @@ -30,7 +30,7 @@ class UInt16 extends UInt { return val } - if (typeof val === 'number') { + if (typeof val === 'number' && Number.isInteger(val)) { UInt16.checkUintRange(val, 0, 0xffff) const buf = new Uint8Array(UInt16.width) @@ -38,7 +38,7 @@ class UInt16 extends UInt { return new UInt16(buf) } - throw new Error('Can not construct UInt16 with given value') + throw new Error('Cannot construct UInt16 from given value') } /** diff --git a/packages/ripple-binary-codec/src/types/uint-32.ts b/packages/ripple-binary-codec/src/types/uint-32.ts index 8a3009e0bf..d9c47a2b31 100644 --- a/packages/ripple-binary-codec/src/types/uint-32.ts +++ b/packages/ripple-binary-codec/src/types/uint-32.ts @@ -38,7 +38,7 @@ class UInt32 extends UInt { return new UInt32(buf) } - if (typeof val === 'number') { + if (typeof val === 'number' && Number.isInteger(val)) { UInt32.checkUintRange(val, 0, 0xffffffff) writeUInt32BE(buf, val, 0) return new UInt32(buf) diff --git a/packages/ripple-binary-codec/src/types/uint-64.ts b/packages/ripple-binary-codec/src/types/uint-64.ts index eaaab70671..b59bcb50d2 100644 --- a/packages/ripple-binary-codec/src/types/uint-64.ts +++ b/packages/ripple-binary-codec/src/types/uint-64.ts @@ -54,7 +54,7 @@ class UInt64 extends UInt { let buf = new Uint8Array(UInt64.width) - if (typeof val === 'number') { + if (typeof val === 'number' && Number.isInteger(val)) { if (val < 0) { throw new Error('value must be an unsigned integer') } diff --git a/packages/ripple-binary-codec/src/types/uint-8.ts b/packages/ripple-binary-codec/src/types/uint-8.ts index e7636ee147..b352c90009 100644 --- a/packages/ripple-binary-codec/src/types/uint-8.ts +++ b/packages/ripple-binary-codec/src/types/uint-8.ts @@ -29,7 +29,7 @@ class UInt8 extends UInt { return val } - if (typeof val === 'number') { + if (typeof val === 'number' && Number.isInteger(val)) { UInt8.checkUintRange(val, 0, 0xff) const buf = new Uint8Array(UInt8.width) diff --git a/packages/ripple-binary-codec/test/binary-parser.test.ts b/packages/ripple-binary-codec/test/binary-parser.test.ts index e310e98802..33503a993d 100644 --- a/packages/ripple-binary-codec/test/binary-parser.test.ts +++ b/packages/ripple-binary-codec/test/binary-parser.test.ts @@ -8,7 +8,7 @@ import { makeParser, readJSON } from '../src/binary' import { BytesList } from '../src/serdes/binary-serializer' import fixtures from './fixtures/data-driven-tests.json' -const { bytesToHex } = require('@xrplf/isomorphic/utils') +const { bytesToHex } = require('@transia/isomorphic/utils') function toJSON(v) { return v.toJSON ? v.toJSON() : v diff --git a/packages/ripple-binary-codec/test/definitions.test.ts b/packages/ripple-binary-codec/test/definitions.test.ts index 82aee36c36..3d83971061 100644 --- a/packages/ripple-binary-codec/test/definitions.test.ts +++ b/packages/ripple-binary-codec/test/definitions.test.ts @@ -1,66 +1,66 @@ -import { encode, decode, XrplDefinitions } from '../src' -import normalDefinitionsJson from '../src/enums/definitions.json' -import { UInt32 } from '../src/types/uint-32' +import { encode, decode, XrplDefinitions } from "../src"; +import normalDefinitionsJson from "../src/enums/definitions.json"; +import { UInt32 } from "../src/types/uint-32"; const txJson = { - Account: 'r9LqNeG6qHxjeUocjvVki2XR35weJ9mZgQ', - Amount: '1000', - Destination: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', - Fee: '10', + Account: "r9LqNeG6qHxjeUocjvVki2XR35weJ9mZgQ", + Amount: "1000", + Destination: "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + Fee: "10", Flags: 0, Sequence: 1, - TransactionType: 'Payment', -} + TransactionType: "Payment", +}; -describe('encode and decode using new types as a parameter', function () { - it('can encode and decode a new TransactionType', function () { - const tx = { ...txJson, TransactionType: 'NewTestTransaction' } +describe("encode and decode using new types as a parameter", function () { + it("can encode and decode a new TransactionType", function () { + const tx = { ...txJson, TransactionType: "NewTestTransaction" }; // Before updating the types, this should not be encodable - expect(() => encode(tx)).toThrow() + expect(() => encode(tx)).toThrow(); // Normally this would be generated directly from rippled with something like `server_definitions`. // Added here to make it easier to see what is actually changing in the definitions.json file. - const definitions = JSON.parse(JSON.stringify(normalDefinitionsJson)) - definitions.TRANSACTION_TYPES['NewTestTransaction'] = 85 + const definitions = JSON.parse(JSON.stringify(normalDefinitionsJson)); + definitions.TRANSACTION_TYPES["NewTestTransaction"] = 222; - const newDefs = new XrplDefinitions(definitions) + const newDefs = new XrplDefinitions(definitions); - const encoded = encode(tx, newDefs) - expect(() => decode(encoded)).toThrow() - const decoded = decode(encoded, newDefs) - expect(decoded).toEqual(tx) - }) + const encoded = encode(tx, newDefs); + expect(() => decode(encoded)).toThrow(); + const decoded = decode(encoded, newDefs); + expect(decoded).toEqual(tx); + }); - it('can encode and decode a new Field', function () { - const tx = { ...txJson, NewFieldDefinition: 10 } + it("can encode and decode a new Field", function () { + const tx = { ...txJson, NewFieldDefinition: 10 }; // Before updating the types, undefined fields will throw an error - expect(() => encode(tx)).toThrow() + expect(() => encode(tx)).toThrow(); // Normally this would be generated directly from rippled with something like `server_definitions`. // Added here to make it easier to see what is actually changing in the definitions.json file. - const definitions = JSON.parse(JSON.stringify(normalDefinitionsJson)) + const definitions = JSON.parse(JSON.stringify(normalDefinitionsJson)); definitions.FIELDS.push([ - 'NewFieldDefinition', + "NewFieldDefinition", { nth: 100, isVLEncoded: false, isSerialized: true, isSigningField: true, - type: 'UInt32', + type: "UInt32", }, - ]) + ]); - const newDefs = new XrplDefinitions(definitions) + const newDefs = new XrplDefinitions(definitions); - const encoded = encode(tx, newDefs) - expect(() => decode(encoded)).toThrow() - const decoded = decode(encoded, newDefs) - expect(decoded).toEqual(tx) - }) + const encoded = encode(tx, newDefs); + expect(() => decode(encoded)).toThrow(); + const decoded = decode(encoded, newDefs); + expect(decoded).toEqual(tx); + }); - it('can encode and decode a new Field nested in STObject in STArray in STObject', function () { + it("can encode and decode a new Field nested in STObject in STArray in STObject", function () { const tx = { ...txJson, NewFieldArray: [ @@ -70,120 +70,120 @@ describe('encode and decode using new types as a parameter', function () { }, }, ], - } + }; // Before updating the types, undefined fields will throw an error - expect(() => encode(tx)).toThrow() + expect(() => encode(tx)).toThrow(); // Normally this would be generated directly from rippled with something like `server_definitions`. // Added here to make it easier to see what is actually changing in the definitions.json file. - const definitions = JSON.parse(JSON.stringify(normalDefinitionsJson)) + const definitions = JSON.parse(JSON.stringify(normalDefinitionsJson)); definitions.FIELDS.push([ - 'NewFieldArray', + "NewFieldArray", { nth: 100, isVLEncoded: false, isSerialized: true, isSigningField: true, - type: 'STArray', + type: "STArray", }, - ]) + ]); definitions.FIELDS.push([ - 'NewField', + "NewField", { nth: 101, isVLEncoded: false, isSerialized: true, isSigningField: true, - type: 'STObject', + type: "STObject", }, - ]) + ]); definitions.FIELDS.push([ - 'NewFieldValue', + "NewFieldValue", { nth: 102, isVLEncoded: false, isSerialized: true, isSigningField: true, - type: 'UInt32', + type: "UInt32", }, - ]) + ]); - const newDefs = new XrplDefinitions(definitions) + const newDefs = new XrplDefinitions(definitions); - const encoded = encode(tx, newDefs) - expect(() => decode(encoded)).toThrow() - const decoded = decode(encoded, newDefs) - expect(decoded).toEqual(tx) - }) + const encoded = encode(tx, newDefs); + expect(() => decode(encoded)).toThrow(); + const decoded = decode(encoded, newDefs); + expect(decoded).toEqual(tx); + }); - it('can encode and decode a new Type', function () { + it("can encode and decode a new Type", function () { const tx = { ...txJson, TestField: 10, // Should work the same as a UInt32 - } + }; // Normally this would be generated directly from rippled with something like `server_definitions`. // Added here to make it easier to see what is actually changing in the definitions.json file. - const definitions = JSON.parse(JSON.stringify(normalDefinitionsJson)) - definitions.TYPES.NewType = 48 + const definitions = JSON.parse(JSON.stringify(normalDefinitionsJson)); + definitions.TYPES.NewType = 48; definitions.FIELDS.push([ - 'TestField', + "TestField", { nth: 100, isVLEncoded: true, isSerialized: true, isSigningField: true, - type: 'NewType', + type: "NewType", }, - ]) + ]); // Test that before updating the types this tx fails to decode correctly. Note that undefined fields will throw an error. - expect(() => encode(tx)).toThrow() + expect(() => encode(tx)).toThrow(); class NewType extends UInt32 { // Should be the same as UInt32 } - const extendedCoreTypes = { NewType } + const extendedCoreTypes = { NewType }; - const newDefs = new XrplDefinitions(definitions, extendedCoreTypes) + const newDefs = new XrplDefinitions(definitions, extendedCoreTypes); - const encoded = encode(tx, newDefs) - expect(() => decode(encoded)).toThrow() - const decoded = decode(encoded, newDefs) - expect(decoded).toEqual(tx) - }) + const encoded = encode(tx, newDefs); + expect(() => decode(encoded)).toThrow(); + const decoded = decode(encoded, newDefs); + expect(decoded).toEqual(tx); + }); - it('removing PermissionValue does not break encoding/decoding', function () { + it("removing PermissionValue does not break encoding/decoding", function () { // Make a deep copy of definitions - const definitions = JSON.parse(JSON.stringify(normalDefinitionsJson)) + const definitions = JSON.parse(JSON.stringify(normalDefinitionsJson)); - const originalFieldsLength = definitions.FIELDS.length + const originalFieldsLength = definitions.FIELDS.length; // Remove PermissionValue from definitions if (definitions.FIELDS) { definitions.FIELDS = definitions.FIELDS.filter( - (fieldTuple: [string, object]) => fieldTuple[0] !== 'PermissionValue', - ) + (fieldTuple: [string, object]) => fieldTuple[0] !== "PermissionValue", + ); } // Verify it was deleted - const expectedFieldsLength = originalFieldsLength - 1 - expect(definitions.FIELDS.length).toBe(expectedFieldsLength) + const expectedFieldsLength = originalFieldsLength - 1; + expect(definitions.FIELDS.length).toBe(expectedFieldsLength); // Create new custom definitions - const customDefs = new XrplDefinitions(definitions) + const customDefs = new XrplDefinitions(definitions); - const tx = { ...txJson } + const tx = { ...txJson }; // It should encode and decode normally, even with PermissionValue missing - const encoded = encode(tx, customDefs) - const decoded = decode(encoded, customDefs) + const encoded = encode(tx, customDefs); + const decoded = decode(encoded, customDefs); - expect(decoded).toEqual(tx) - }) -}) + expect(decoded).toEqual(tx); + }); +}); diff --git a/packages/ripple-binary-codec/test/fixtures/codec-fixtures.json b/packages/ripple-binary-codec/test/fixtures/codec-fixtures.json index 0eb76f903f..b97e3b4341 100644 --- a/packages/ripple-binary-codec/test/fixtures/codec-fixtures.json +++ b/packages/ripple-binary-codec/test/fixtures/codec-fixtures.json @@ -33,7 +33,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "059D1E86DE5DCCCF956BF4799675B2425AF9AD44FE4CCA6FEE1C812EEF6423E6", - "Indexes": ["908D554AA0D29F660716A3EE65C61DD886B744DDF60DE70E6B16EADB770635DB"] + "Indexes": [ + "908D554AA0D29F660716A3EE65C61DD886B744DDF60DE70E6B16EADB770635DB" + ] } }, { @@ -327,7 +329,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "17CC40C6872E0C0E658C49B75D0812A70D4161DDA53324DF51FA58D3819C814B", - "Indexes": ["571BF14F28C4D97871CDACD344A8CF57E6BA287BF0440B9E0D0683D02751CC7B"] + "Indexes": [ + "571BF14F28C4D97871CDACD344A8CF57E6BA287BF0440B9E0D0683D02751CC7B" + ] } }, { @@ -376,7 +380,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "1BCA9161A199AD5E907751CBF3FBA49689D517F0E8EE823AE17B737039B41DE1", - "Indexes": ["26B894EE68470AD5AEEB55D5EBF936E6397CEE6957B93C56A2E7882CA9082873"] + "Indexes": [ + "26B894EE68470AD5AEEB55D5EBF936E6397CEE6957B93C56A2E7882CA9082873" + ] } }, { @@ -440,7 +446,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "1F9FF48419CA69FDDCC294CCEEE608F5F8A8BE11E286AD5743ED2D457C5570C4", - "Indexes": ["7D4325BE338A40BBCBCC1F351B3272EB3E76305A878E76603DE206A795871619"] + "Indexes": [ + "7D4325BE338A40BBCBCC1F351B3272EB3E76305A878E76603DE206A795871619" + ] } }, { @@ -606,7 +614,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "289CFC476B5876F28C8A3B3C5B7058EC2BDF668C37B846EA7E5E1A73A4AA0816", - "Indexes": ["BC10E40AFB79298004CDE51CB065DBDCABA86EC406E3A1CF02CE5F8A9628A2BD"] + "Indexes": [ + "BC10E40AFB79298004CDE51CB065DBDCABA86EC406E3A1CF02CE5F8A9628A2BD" + ] } }, { @@ -709,7 +719,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "2C9F00EFA5CCBD43452EF364B12C8DFCEF2B910336E5EFCE3AA412A556991582", - "Indexes": ["F721E924498EE68BFF906CD856E8332073DD350BAC9E8977AC3F31860BA1E33A"] + "Indexes": [ + "F721E924498EE68BFF906CD856E8332073DD350BAC9E8977AC3F31860BA1E33A" + ] } }, { @@ -746,7 +758,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "2FB4904ACFB96228FC002335B1B5A4C5584D9D727BBE82144F0415EB4EA0C727", - "Indexes": ["5F22826818CC83448C9DF34939AB4019D3F80C70DEB8BDBDCF0496A36DC68719"], + "Indexes": [ + "5F22826818CC83448C9DF34939AB4019D3F80C70DEB8BDBDCF0496A36DC68719" + ], "TakerPaysIssuer": "2B6C42A95B3F7EE1971E4A10098E8F1B5F66AA08" } }, @@ -760,7 +774,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "2FB4904ACFB96228FC002335B1B5A4C5584D9D727BBE82145003BAF82D03A000", - "Indexes": ["5B7F148A8DDB4EB7386C9E75C4C1ED918DEDE5C52D5BA51B694D7271EF8BDB46"], + "Indexes": [ + "5B7F148A8DDB4EB7386C9E75C4C1ED918DEDE5C52D5BA51B694D7271EF8BDB46" + ], "TakerPaysIssuer": "2B6C42A95B3F7EE1971E4A10098E8F1B5F66AA08" } }, @@ -951,7 +967,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "3F2BADB38F12C87D111D3970CD1F05FE698DB86F14DC7C5FAEB05BFB6391B00E", - "Indexes": ["73E075E64CA5E7CE60FFCD5359C1D730EDFFEE7C4D992760A87DF7EA0A34E40F"] + "Indexes": [ + "73E075E64CA5E7CE60FFCD5359C1D730EDFFEE7C4D992760A87DF7EA0A34E40F" + ] } }, { @@ -976,7 +994,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "4235CD082112FB621C02D6DA2E4F4ACFAFC91CB0585E034B936C29ABF4A76B01", - "Indexes": ["6C4C3F1C6B9D76A6EF50F377E7C3991825694C604DBE0C1DD09362045EE41997"] + "Indexes": [ + "6C4C3F1C6B9D76A6EF50F377E7C3991825694C604DBE0C1DD09362045EE41997" + ] } }, { @@ -1075,7 +1095,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "48E91FD14597FB089654DADE7B70EB08CAF421EA611D703F3E871F7D4B5AAB5D", - "Indexes": ["25DCAC87FBE4C3B66A1AFDE3C3F98E5A16333975C4FD46682F7497F27DFB9766"] + "Indexes": [ + "25DCAC87FBE4C3B66A1AFDE3C3F98E5A16333975C4FD46682F7497F27DFB9766" + ] } }, { @@ -1137,7 +1159,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "4EFC0442D07AE681F7FDFAA89C75F06F8E28CFF888593440201B0320E8F2C7BD", - "Indexes": ["1595E5D5197330F58A479200A2FDD434D7A244BD1FFEC5E5EE8CF064AE77D3F5"] + "Indexes": [ + "1595E5D5197330F58A479200A2FDD434D7A244BD1FFEC5E5EE8CF064AE77D3F5" + ] } }, { @@ -1351,7 +1375,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "98082E695CAB618590BEEA0647A5F24D2B610A686ECD49310604FC7431FAAB0D", - "Indexes": ["9BF3216E42575CA5A3CB4D0F2021EE81D0F7835BA2EDD78E05CAB44B655962BB"] + "Indexes": [ + "9BF3216E42575CA5A3CB4D0F2021EE81D0F7835BA2EDD78E05CAB44B655962BB" + ] } }, { @@ -1556,7 +1582,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "62AE37A44FE44BDCFC2BA5DD14D74BEC0AC346DA2DC1F04756044364C5BB0000", - "Indexes": ["600A398F57CAE44461B4C8C25DE12AC289F87ED125438440B33B97417FE3D82C"], + "Indexes": [ + "600A398F57CAE44461B4C8C25DE12AC289F87ED125438440B33B97417FE3D82C" + ], "TakerPaysIssuer": "2B6C42A95B3F7EE1971E4A10098E8F1B5F66AA08" } }, @@ -1932,7 +1960,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "72D60CCD3905A3ABE19049B6EE76E8E0F3A2CBAC852625C757176F1B73EF617F", - "Indexes": ["AB124EEAB087452070EC70D9DEA1A22C9766FFBBEE1025FD46495CC74148CCA8"] + "Indexes": [ + "AB124EEAB087452070EC70D9DEA1A22C9766FFBBEE1025FD46495CC74148CCA8" + ] } }, { @@ -2061,7 +2091,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "80AB25842B230D48027800213EB86023A3EAF4430E22C092D333795FFF1E5219", - "Indexes": ["42E28285A82D01DCA856118A064C8AEEE1BF8167C08186DA5BFC678687E86F7C"] + "Indexes": [ + "42E28285A82D01DCA856118A064C8AEEE1BF8167C08186DA5BFC678687E86F7C" + ] } }, { @@ -2186,7 +2218,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "8ADF3C5527CCF6D0B5863365EF40254171536C3901F1CBD9E2BC5F918A7D492A", - "Indexes": ["BC10E40AFB79298004CDE51CB065DBDCABA86EC406E3A1CF02CE5F8A9628A2BD"] + "Indexes": [ + "BC10E40AFB79298004CDE51CB065DBDCABA86EC406E3A1CF02CE5F8A9628A2BD" + ] } }, { @@ -2587,7 +2621,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "A00CD19C13A5CFA3FECB409D42B38017C07A4AEAE05A7A00347DDA17199BA683", - "Indexes": ["E49318D6DF22411C3F35581B1D28297A36E47F68B45F36A587C156E6E43CE0A6"] + "Indexes": [ + "E49318D6DF22411C3F35581B1D28297A36E47F68B45F36A587C156E6E43CE0A6" + ] } }, { @@ -2634,7 +2670,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "A39F044D860C5B5846AA7E0FAAD44DC8897F0A62B2F628AA073B21B3EC146010", - "Indexes": ["CD34D8FF7C656B66E2298DB420C918FE27DFFF2186AC8D1785D8CBF2C6BC3488"] + "Indexes": [ + "CD34D8FF7C656B66E2298DB420C918FE27DFFF2186AC8D1785D8CBF2C6BC3488" + ] } }, { @@ -2683,7 +2721,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "A7E461C6DC98F472991FDE51FADDC0082D755F553F5849875D554B52624EF1C3", - "Indexes": ["116C6D5E5C6C59C9C5362B84CB9DD30BD3D4B7CB98CE993D49C068323BF19747"] + "Indexes": [ + "116C6D5E5C6C59C9C5362B84CB9DD30BD3D4B7CB98CE993D49C068323BF19747" + ] } }, { @@ -2717,7 +2757,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "AA539C8EECE0A0CFF0DBF3BFACD6B42CD4421715428AD90B034091BD3C721038", - "Indexes": ["72307CB57E53604A0C50E653AB10E386F3835460B5585B70CB7F668C1E04AC8B"] + "Indexes": [ + "72307CB57E53604A0C50E653AB10E386F3835460B5585B70CB7F668C1E04AC8B" + ] } }, { @@ -3777,7 +3819,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "D4A00D9B3452C7F93C5F0531FA8FFB4599FEEC405CA803FBEFE0FA22137D863D", - "Indexes": ["C1C5FB39D6C15C581D822DBAF725EF7EDE40BEC9F93C52398CF5CE9F64154D6C"] + "Indexes": [ + "C1C5FB39D6C15C581D822DBAF725EF7EDE40BEC9F93C52398CF5CE9F64154D6C" + ] } }, { @@ -3787,7 +3831,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "D4B68B54869E428428078E1045B8BB66C24DD101DB3FCCBB099929B3B63BCB40", - "Indexes": ["9A551971E78FE2FB80D930A77EA0BAC2139A49D6BEB98406427C79F52A347A09"] + "Indexes": [ + "9A551971E78FE2FB80D930A77EA0BAC2139A49D6BEB98406427C79F52A347A09" + ] } }, { @@ -3862,7 +3908,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "DD23E2C60C9BC58180AC6EA7C668233EC51A0947E42FD1FAD4F5FBAED9698D95", - "Indexes": ["908D554AA0D29F660716A3EE65C61DD886B744DDF60DE70E6B16EADB770635DB"] + "Indexes": [ + "908D554AA0D29F660716A3EE65C61DD886B744DDF60DE70E6B16EADB770635DB" + ] } }, { @@ -4013,7 +4061,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "E2EC9E1BC7B4667B7A5F2F68857F6E6A478A09B5BB4F99E09F694437C4152DED", - "Indexes": ["65492B9F30F1CBEA168509128EB8619BAE02A7A7A4725FF3F8DAA70FA707A26E"] + "Indexes": [ + "65492B9F30F1CBEA168509128EB8619BAE02A7A7A4725FF3F8DAA70FA707A26E" + ] } }, { @@ -4190,7 +4240,9 @@ "IndexPrevious": "0000000000000002", "Flags": 0, "RootIndex": "8E92E688A132410427806A734DF6154B7535E439B72DECA5E4BC7CE17135C5A4", - "Indexes": ["73E075E64CA5E7CE60FFCD5359C1D730EDFFEE7C4D992760A87DF7EA0A34E40F"] + "Indexes": [ + "73E075E64CA5E7CE60FFCD5359C1D730EDFFEE7C4D992760A87DF7EA0A34E40F" + ] } }, { @@ -4294,7 +4346,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "F774E0321809251174AC85531606FB46B75EEF9F842F9697531AA535D3D0C000", - "Indexes": ["D1CB738BD08AC36DCB77191DB87C6E40FA478B86503371ED497F30931D7F4F52"], + "Indexes": [ + "D1CB738BD08AC36DCB77191DB87C6E40FA478B86503371ED497F30931D7F4F52" + ], "TakerPaysIssuer": "E8ACFC6B5EF4EA0601241525375162F43C2FF285" } }, @@ -4355,7 +4409,9 @@ "LedgerEntryType": "DirectoryNode", "Flags": 0, "RootIndex": "F95F6D3A1EF7981E5CA4D5AEC4DA63392B126C76469735BCCA26150A1AF6D9C3", - "Indexes": ["CAD951AB279A749AE648FD1DFF56C021BD66E36187022E772C31FE52106CB13B"] + "Indexes": [ + "CAD951AB279A749AE648FD1DFF56C021BD66E36187022E772C31FE52106CB13B" + ] } }, { @@ -4456,9 +4512,13 @@ "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "XChainBridge": { "LockingChainDoor": "rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL", - "LockingChainIssue": {"currency": "XRP"}, + "LockingChainIssue": { + "currency": "XRP" + }, "IssuingChainDoor": "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV", - "IssuingChainIssue": {"currency": "XRP"} + "IssuingChainIssue": { + "currency": "XRP" + } }, "Fee": "10", "Flags": 0, @@ -4476,9 +4536,13 @@ "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "XChainBridge": { "LockingChainDoor": "rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL", - "LockingChainIssue": {"currency": "XRP"}, + "LockingChainIssue": { + "currency": "XRP" + }, "IssuingChainDoor": "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV", - "IssuingChainIssue": {"currency": "XRP"} + "IssuingChainIssue": { + "currency": "XRP" + } }, "Fee": "10", "Flags": 0, @@ -4496,9 +4560,13 @@ "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "XChainBridge": { "LockingChainDoor": "rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL", - "LockingChainIssue": {"currency": "XRP"}, + "LockingChainIssue": { + "currency": "XRP" + }, "IssuingChainDoor": "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV", - "IssuingChainIssue": {"currency": "XRP"} + "IssuingChainIssue": { + "currency": "XRP" + } }, "Fee": "10", "Flags": 2147483648, @@ -4517,9 +4585,13 @@ "Amount": "10000", "XChainBridge": { "LockingChainDoor": "rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL", - "LockingChainIssue": {"currency": "XRP"}, + "LockingChainIssue": { + "currency": "XRP" + }, "IssuingChainDoor": "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV", - "IssuingChainIssue": {"currency": "XRP"} + "IssuingChainIssue": { + "currency": "XRP" + } }, "Fee": "10", "Flags": 2147483648, @@ -4537,9 +4609,13 @@ "Amount": "10000", "XChainBridge": { "LockingChainDoor": "rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL", - "LockingChainIssue": {"currency": "XRP"}, + "LockingChainIssue": { + "currency": "XRP" + }, "IssuingChainDoor": "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV", - "IssuingChainIssue": {"currency": "XRP"} + "IssuingChainIssue": { + "currency": "XRP" + } }, "Destination": "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV", "Fee": "10", @@ -4557,9 +4633,13 @@ "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "XChainBridge": { "LockingChainDoor": "rGzx83BVoqTYbGn7tiVAnFw7cbxjin13jL", - "LockingChainIssue": {"currency": "XRP"}, + "LockingChainIssue": { + "currency": "XRP" + }, "IssuingChainDoor": "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV", - "IssuingChainIssue": {"currency": "XRP"} + "IssuingChainIssue": { + "currency": "XRP" + } }, "Amount": "1000000", "Fee": "10", @@ -4660,9 +4740,18 @@ "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMDeposit", "TxnSignature": "8073C588E7EF672DD171E414638D9AF8DBE9A1359E030DE3E1C9AA6A38A2CE9E138CB56482BB844F7228D48B1E4AD7D09BB7E9F639C115958EEEA374749CA00B", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, - "LPTokenOut": {"currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", "value": "1000"}, + "Asset": { + "currency": "XRP" + }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, + "LPTokenOut": { + "currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", + "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", + "value": "1000" + }, "Fee": "10", "Flags": 65536, "Sequence": 1432289, @@ -4674,8 +4763,13 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMDeposit", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, + "Asset": { + "currency": "XRP" + }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, "Amount": "1000", "Fee": "10", "Flags": 524288, @@ -4689,10 +4783,19 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMDeposit", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, + "Asset": { + "currency": "XRP" + }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, "Amount": "1000", - "Amount2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9", "value": "500"}, + "Amount2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9", + "value": "500" + }, "Fee": "10", "Flags": 1048576, "Sequence": 1432289, @@ -4705,10 +4808,19 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMDeposit", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, + "Asset": { + "currency": "XRP" + }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, "Amount": "1000", - "LPTokenOut": {"currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", "value": "1000"}, + "LPTokenOut": { + "currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", + "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", + "value": "1000" + }, "Fee": "10", "Flags": 2097152, "Sequence": 1432289, @@ -4721,8 +4833,13 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMDeposit", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, + "Asset": { + "currency": "XRP" + }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, "Amount": "1000", "EPrice": "25", "Fee": "10", @@ -4737,9 +4854,18 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMWithdraw", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, - "LPTokenIn": {"currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", "value": "1000"}, + "Asset": { + "currency": "XRP" + }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, + "LPTokenIn": { + "currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", + "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", + "value": "1000" + }, "Fee": "10", "Flags": 65536, "Sequence": 1432289, @@ -4752,8 +4878,13 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMWithdraw", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, + "Asset": { + "currency": "XRP" + }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, "Amount": "1000", "Fee": "10", "Flags": 524288, @@ -4767,10 +4898,19 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMWithdraw", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, + "Asset": { + "currency": "XRP" + }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, "Amount": "1000", - "Amount2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9", "value": "500"}, + "Amount2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9", + "value": "500" + }, "Fee": "10", "Flags": 1048576, "Sequence": 1432289, @@ -4783,10 +4923,19 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMWithdraw", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, + "Asset": { + "currency": "XRP" + }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, "Amount": "1000", - "LPTokenIn": {"currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", "value": "1000"}, + "LPTokenIn": { + "currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", + "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", + "value": "1000" + }, "Fee": "10", "Flags": 2097152, "Sequence": 1432289, @@ -4799,8 +4948,13 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMWithdraw", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, + "Asset": { + "currency": "XRP" + }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, "Amount": "1000", "EPrice": "25", "Fee": "10", @@ -4815,11 +4969,30 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMBid", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, - "AuthAccounts": [{"AuthAccount": {"Account": "rEaHTti4HZsMBpxTAF4ncWxkcdqDh1h6P7"}}], - "BidMax": {"currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", "value": "35"}, - "BidMin": {"currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", "value": "25"}, + "Asset": { + "currency": "XRP" + }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, + "AuthAccounts": [ + { + "AuthAccount": { + "Account": "rEaHTti4HZsMBpxTAF4ncWxkcdqDh1h6P7" + } + } + ], + "BidMax": { + "currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", + "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", + "value": "35" + }, + "BidMin": { + "currency": "B3813FCAB4EE68B3D0D735D6849465A9113EE048", + "issuer": "rH438jEAzTs5PYtV6CHZqpDpwCKQmPW9Cg", + "value": "25" + }, "Fee": "10", "Flags": 0, "Sequence": 1432289, @@ -4832,8 +5005,13 @@ "json": { "Account": "rP5ZkB5RZQaECsSVR4DeSFK4fAw52BYtbw", "TransactionType": "AMMVote", - "Asset": {"currency": "XRP"}, - "Asset2": {"currency": "ETH", "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9"}, + "Asset": { + "currency": "XRP" + }, + "Asset2": { + "currency": "ETH", + "issuer": "rPyfep3gcLzkosKC9XiE77Y8DZWG6iWDT9" + }, "TradingFee": 234, "Fee": "10", "Flags": 0, @@ -4935,20 +5113,122 @@ "issuer": "rfmDuhDyLGgx94qiwf3YF8BUV5j6KSvE8" } } + }, + { + "binary": "12004124000002D36840000000000000647321ED54C1E3427192B879EBD6F1FD7306058EAE6DAF7D95B2655B053885FE7722A7127440A7C6C1EE9989F9F195A02BEA4DCFEBB887E4CA1F4D30083C84616E0FD1BCA4F4C1B84A6DA26A44B94FBBDA67FB603C78995361DEAF8120093959C639E9255702811469C0A3C6BB1F42DCB9CC4E7DD332DB60BF99D0960318E0739D43718DB5815CE070D4D514A261EC872C930000000000000000000000000000000000000001D2020000", + "json": { + "Account": "rwew5zNSiizbX6ku8YF8TjgPXJA2rpXar3", + "Asset": { + "mpt_issuance_id": "000002D2E0739D43718DB5815CE070D4D514A261EC872C93" + }, + "Fee": "100", + "Sequence": 723, + "SigningPubKey": "ED54C1E3427192B879EBD6F1FD7306058EAE6DAF7D95B2655B053885FE7722A712", + "TransactionType": "VaultCreate", + "TxnSignature": "A7C6C1EE9989F9F195A02BEA4DCFEBB887E4CA1F4D30083C84616E0FD1BCA4F4C1B84A6DA26A44B94FBBDA67FB603C78995361DEAF8120093959C639E9255702" + } + }, + { + "binary": "120041240000001A6840000000009896807321ED5E83997E2D57EF5C32DFF74AAA836E5C149CA9E49711D220289E610975560EC474401BCB501B08FAA564E4DB82843E77024585827EC1C3FEB784F656215DC3B79C90CE0B387B33661219B074E8CCF965CF2824A92B79FFB9C4A9F988F7AB19B45502701B0E7661756C74206D65746164617461701E0E7368617265206D657461646174618114B67FFA466543506DF81A26FBA98CFB604DE5FE44930DE0B6B3A763FF9C0000004E00101401031800000000000000000000000055534400000000002B13011144920AF528764094A05ADFE3C3DD58B7", + "json": { + "TransactionType": "VaultCreate", + "Sequence": 26, + "Fee": "10000000", + "SigningPubKey": "ED5E83997E2D57EF5C32DFF74AAA836E5C149CA9E49711D220289E610975560EC4", + "TxnSignature": "1BCB501B08FAA564E4DB82843E77024585827EC1C3FEB784F656215DC3B79C90CE0B387B33661219B074E8CCF965CF2824A92B79FFB9C4A9F988F7AB19B45502", + "Data": "7661756C74206D65746164617461", + "MPTokenMetadata": "7368617265206D65746164617461", + "Account": "rHdyHxQMCKyoUFeR1GW7F6pt4AR7r6D4b4", + "AssetsMaximum": "9999999999999999e80", + "WithdrawalPolicy": 1, + "Asset": { + "currency": "USD", + "issuer": "rhvkFgXoWfrDJJHdV3hKTcqXQk7ChXtf18" + } + } + }, + { + "binary": "120041240000002F6840000000009896807321ED65C3F14697756CF0952CE5B00E2374E4D91C7B74687B19C451317B67D52C3B4F7440733B3F7C63271A62E55335D4BB62448ED459ACF7BE03D624844F696406DB84A2D3FDF638F16DB4A3B6CB9BD463756003F795AA26AFCA9EB5BA53FF1ADFC4E50F701B0E7661756C74206D65746164617461701E0E7368617265206D65746164617461811499EBF31121DE67CD1015F13328E18EE2490A139D931122D7D8F56AFD68FFFFFFF500101401031800000000000000000000000055534400000000002FD289D349D05565C1D43CF5D694EECB5D8C3FF0", + "json": { + "TransactionType": "VaultCreate", + "Sequence": 47, + "Fee": "10000000", + "SigningPubKey": "ED65C3F14697756CF0952CE5B00E2374E4D91C7B74687B19C451317B67D52C3B4F", + "TxnSignature": "733B3F7C63271A62E55335D4BB62448ED459ACF7BE03D624844F696406DB84A2D3FDF638F16DB4A3B6CB9BD463756003F795AA26AFCA9EB5BA53FF1ADFC4E50F", + "Data": "7661756C74206D65746164617461", + "MPTokenMetadata": "7368617265206D65746164617461", + "Account": "rEp1sQdJbwDKmhMWmdJgx9ywnoGGr4oxKu", + "AssetsMaximum": "12347865.746832746", + "WithdrawalPolicy": 1, + "Asset": { + "currency": "USD", + "issuer": "rnMiy78qjm8KwantFnrfouvMGqzCR7apap" + } + } + }, + { + "binary": "120041240000006E6840000000004C4B407321EDFC4A4C1FF4176F27DE9BA9550ECBDB16C7517C50F73299B1E0C4633A130F7B6F744006EC52DE62AD2A97DDDB09A1B21A4C9B0B07FC992878B2590C2AF06242FC02B05E08F78610D8337285AB4E9D9C5BC7CD580C32CE405F7B305CFD225699AE1C0C8114A7AF1AF3F2907DADD86CC5CEA513A496F5E98632930CCCCCCCCCCCCCD60000000103180000000000000000000000005553440000000000A6C027452D30AACA763A09CB586DF7CE21ADC6F2", + "json": { + "TransactionType": "VaultCreate", + "Sequence": 110, + "Fee": "5000000", + "SigningPubKey": "EDFC4A4C1FF4176F27DE9BA9550ECBDB16C7517C50F73299B1E0C4633A130F7B6F", + "TxnSignature": "06EC52DE62AD2A97DDDB09A1B21A4C9B0B07FC992878B2590C2AF06242FC02B05E08F78610D8337285AB4E9D9C5BC7CD580C32CE405F7B305CFD225699AE1C0C", + "Account": "rGHdcZ5iHMH7iUe5noaYipUfDoppBHjkBX", + "AssetsMaximum": "9223372036854775900", + "Asset": { + "currency": "USD", + "issuer": "rGU6MtyTSMWiN3LXdQXUVpGcnwwf4RSC5f" + } + } + }, + { + "binary": "120041240000026B6840000000004C4B407321ED02BD2C030FB01D3A4ECA535239B54E77DA8AA31C44EEBCA079B4DBD6802F5FE77440AA1320E90677CBBD69D8F373B6E162A82B7C6DECF976BD4CDFF4D2501D394F73047A17826B4A5DEC793C2B3F958FB8881356D06B1E3B4EC641446D390D4B5A04811485573352505C7139E49D42A3702E8821C12048D3930CF053BF3C8DCCCC0000000103180000000000000000000000005553440000000000F03F27AD0A77EA2D903EDABAC26876AFA32629D9", + "json": { + "TransactionType": "VaultCreate", + "Sequence": 619, + "Fee": "5000000", + "SigningPubKey": "ED02BD2C030FB01D3A4ECA535239B54E77DA8AA31C44EEBCA079B4DBD6802F5FE7", + "TxnSignature": "AA1320E90677CBBD69D8F373B6E162A82B7C6DECF976BD4CDFF4D2501D394F73047A17826B4A5DEC793C2B3F958FB8881356D06B1E3B4EC641446D390D4B5A04", + "Account": "rDwsLJuJKQ8EMN3otL8byiKkpBFABxcDNs", + "AssetsMaximum": "9323372036854775800", + "Asset": { + "currency": "USD", + "issuer": "r4uJq3Du8WZ2Zyh1X8nwrarxtti281apfB" + } + } + }, + { + "binary": "12004124000001F36840000000004C4B407321EDAFD7A83CD7A09CF126100882728F9FA790B6CC2A29099F274B2B7F614BFF143C7440FA4C253A28EC949593E50C7A29061EA2F44F9E9BD64267DE8932C82C93658EC0224406E12A104B1FA448E0095434A32AE845883FB1404513FF9D57E58CEE8E0881149C1A8144EE13A6B71398C54632E94D4D523BB20A930DBD2FC137A300000000000403180000000000000000000000005553440000000000473C02A2B1C2E8D35A57EE0968ECCF07B9AA291A", + "json": { + "TransactionType": "VaultCreate", + "Sequence": 499, + "Fee": "5000000", + "SigningPubKey": "EDAFD7A83CD7A09CF126100882728F9FA790B6CC2A29099F274B2B7F614BFF143C", + "TxnSignature": "FA4C253A28EC949593E50C7A29061EA2F44F9E9BD64267DE8932C82C93658EC0224406E12A104B1FA448E0095434A32AE845883FB1404513FF9D57E58CEE8E08", + "Account": "rENQwXJhz9kPQ6EZErfV2UV49EtpF43yLp", + "AssetsMaximum": "99e20", + "Asset": { + "currency": "USD", + "issuer": "rfVe1DnuC7nuvGWTAFzBxaTxroEiD8XZ3w" + } + } } ], - "ledgerData": [{ - "binary": "01E91435016340767BF1C4A3EACEB081770D8ADE216C85445DD6FB002C6B5A2930F2DECE006DA18150CB18F6DD33F6F0990754C962A7CCE62F332FF9C13939B03B864117F0BDA86B6E9B4F873B5C3E520634D343EF5D9D9A4246643D64DAD278BA95DC0EAC6EB5350CF970D521276CDE21276CE60A00", - "json": { - "account_hash": "3B5C3E520634D343EF5D9D9A4246643D64DAD278BA95DC0EAC6EB5350CF970D5", - "close_flags": 0, - "close_time": 556231910, - "close_time_resolution": 10, - "ledger_index": 32052277, - "parent_close_time": 556231902, - "parent_hash": "EACEB081770D8ADE216C85445DD6FB002C6B5A2930F2DECE006DA18150CB18F6", - "total_coins": "99994494362043555", - "transaction_hash": "DD33F6F0990754C962A7CCE62F332FF9C13939B03B864117F0BDA86B6E9B4F87" + "ledgerData": [ + { + "binary": "01E91435016340767BF1C4A3EACEB081770D8ADE216C85445DD6FB002C6B5A2930F2DECE006DA18150CB18F6DD33F6F0990754C962A7CCE62F332FF9C13939B03B864117F0BDA86B6E9B4F873B5C3E520634D343EF5D9D9A4246643D64DAD278BA95DC0EAC6EB5350CF970D521276CDE21276CE60A00", + "json": { + "account_hash": "3B5C3E520634D343EF5D9D9A4246643D64DAD278BA95DC0EAC6EB5350CF970D5", + "close_flags": 0, + "close_time": 556231910, + "close_time_resolution": 10, + "ledger_index": 32052277, + "parent_close_time": 556231902, + "parent_hash": "EACEB081770D8ADE216C85445DD6FB002C6B5A2930F2DECE006DA18150CB18F6", + "total_coins": "99994494362043555", + "transaction_hash": "DD33F6F0990754C962A7CCE62F332FF9C13939B03B864117F0BDA86B6E9B4F87" + } } - }] + ] } diff --git a/packages/ripple-binary-codec/test/fixtures/contract-call-binary.json b/packages/ripple-binary-codec/test/fixtures/contract-call-binary.json index c6fedef905..93e398fd53 100644 --- a/packages/ripple-binary-codec/test/fixtures/contract-call-binary.json +++ b/packages/ripple-binary-codec/test/fixtures/contract-call-binary.json @@ -1 +1 @@ -"12004D24000000052039000F42406840000000000000C870220F66756E6374696F6E5F706172616D738114AE123A8556F3CF91154711376AFB0F894F832B3D80191478A28D084038E5C11F268DE3AAF7182805BE87BFF024E028203B00000000011B0010FFE1E028203B00000000011B0001FFFFE1E028203B00000000011B0002FFFFFFFFE1E028203B00000000011B00037FFFFFFFFFFFFFFFE1E028203B00000000011B000400000000000000000000000000000001E1E028203B00000000011B00110000000000000000000000000000000000000001E1E028203B00000000011B0015000000000000000000000000000000000000000000000001E1E028203B00000000011B0005D955DAC2E77519F05AD151A5D3C99FC8125FB39D58FF9F106F1ACA4491902C25E1E028203B00000000011B000704DEADBEEFE1E028203B00000000011B000814AE123A8556F3CF91154711376AFB0F894F832B3DE1E028203B00000000011B000640000000000F4240E1E028203B00000000011B0006D4844364C5BB00000000000000000000000000005553440000000000A407AF5856CCF3C42619DAA925813FC955C72983E1E028203B00000000011B000900044364C5BB0000FFFFFFF1E1F1" +"12005A24000000052048000F42406840000000000000C870220F66756E6374696F6E5F706172616D738114AE123A8556F3CF91154711376AFB0F894F832B3D801B1478A28D084038E5C11F268DE3AAF7182805BE87BFF023E029204A00000000011B0010FFE1E029204A00000000011B0001FFFFE1E029204A00000000011B0002FFFFFFFFE1E029204A00000000011B00037FFFFFFFFFFFFFFFE1E029204A00000000011B000400000000000000000000000000000001E1E029204A00000000011B00110000000000000000000000000000000000000001E1E029204A00000000011B0015000000000000000000000000000000000000000000000001E1E029204A00000000011B0005D955DAC2E77519F05AD151A5D3C99FC8125FB39D58FF9F106F1ACA4491902C25E1E029204A00000000011B000704DEADBEEFE1E029204A00000000011B000814AE123A8556F3CF91154711376AFB0F894F832B3DE1E029204A00000000011B000640000000000F4240E1E029204A00000000011B0006D4844364C5BB00000000000000000000000000005553440000000000A407AF5856CCF3C42619DAA925813FC955C72983E1E029204A00000000011B000910A741A462780000FFFFFFEEE1F1" diff --git a/packages/ripple-binary-codec/test/int.test.ts b/packages/ripple-binary-codec/test/int.test.ts new file mode 100644 index 0000000000..7bf7254269 --- /dev/null +++ b/packages/ripple-binary-codec/test/int.test.ts @@ -0,0 +1,203 @@ +import { Int32 } from '../src/types' +import { encode, decode } from '../src' + +describe('Int32', () => { + describe('from()', () => { + it('should create Int32 from positive number', () => { + const int32 = Int32.from(12345) + expect(int32.valueOf()).toBe(12345) + }) + + it('should create Int32 from negative number', () => { + const int32 = Int32.from(-12345) + expect(int32.valueOf()).toBe(-12345) + }) + + it('should create Int32 from zero', () => { + const int32 = Int32.from(0) + expect(int32.valueOf()).toBe(0) + }) + + it('should create Int32 from positive string', () => { + const int32 = Int32.from('67890') + expect(int32.valueOf()).toBe(67890) + }) + + it('should create Int32 from negative string', () => { + const int32 = Int32.from('-67890') + expect(int32.valueOf()).toBe(-67890) + }) + + it('should create Int32 from another Int32', () => { + const original = Int32.from(999) + const copy = Int32.from(original) + expect(copy.valueOf()).toBe(999) + }) + + it('should handle MIN_VALUE', () => { + const int32 = Int32.from(-2147483648) + expect(int32.valueOf()).toBe(-2147483648) + }) + + it('should handle MAX_VALUE', () => { + const int32 = Int32.from(2147483647) + expect(int32.valueOf()).toBe(2147483647) + }) + }) + + describe('range validation', () => { + it('should throw error when value exceeds MAX_VALUE', () => { + expect(() => Int32.from(2147483648)).toThrow( + new Error( + 'Invalid Int32: 2147483648 must be >= -2147483648 and <= 2147483647', + ), + ) + }) + + it('should throw error when value is below MIN_VALUE', () => { + expect(() => Int32.from(-2147483649)).toThrow( + new Error( + 'Invalid Int32: -2147483649 must be >= -2147483648 and <= 2147483647', + ), + ) + }) + + it('should throw error for string exceeding MAX_VALUE', () => { + expect(() => Int32.from('2147483648')).toThrow( + new Error( + 'Invalid Int32: 2147483648 must be >= -2147483648 and <= 2147483647', + ), + ) + }) + + it('should throw error for string below MIN_VALUE', () => { + expect(() => Int32.from('-2147483649')).toThrow( + new Error( + 'Invalid Int32: -2147483649 must be >= -2147483648 and <= 2147483647', + ), + ) + }) + }) + + describe('decimal validation', () => { + it('should throw error when passed a decimal number', () => { + expect(() => Int32.from(100.5)).toThrow( + new Error('Cannot construct Int32 from given value'), + ) + }) + + it('should throw error when passed a negative decimal', () => { + expect(() => Int32.from(-100.5)).toThrow( + new Error('Cannot construct Int32 from given value'), + ) + }) + + it('should throw error when passed a small decimal', () => { + expect(() => Int32.from(0.001)).toThrow( + new Error('Cannot construct Int32 from given value'), + ) + }) + + it('should throw error for decimal string', () => { + expect(() => Int32.from('1.23')).toThrow( + new Error('Cannot construct Int32 from string: 1.23'), + ) + }) + + it('should throw error for non-numeric string', () => { + expect(() => Int32.from('abc')).toThrow( + new Error('Cannot construct Int32 from string: abc'), + ) + }) + }) + + describe('compareTo()', () => { + it('should return 0 for equal values', () => { + expect(Int32.from(100).compareTo(Int32.from(100))).toBe(0) + }) + + it('should return 1 when first value is greater', () => { + expect(Int32.from(100).compareTo(Int32.from(50))).toBe(1) + }) + + it('should return -1 when first value is smaller', () => { + expect(Int32.from(50).compareTo(Int32.from(100))).toBe(-1) + }) + + it('should compare with raw number', () => { + expect(Int32.from(100).compareTo(100)).toBe(0) + expect(Int32.from(100).compareTo(50)).toBe(1) + expect(Int32.from(50).compareTo(100)).toBe(-1) + }) + + it('should handle negative values', () => { + expect(Int32.from(-100).compareTo(Int32.from(-50))).toBe(-1) + expect(Int32.from(-50).compareTo(Int32.from(-100))).toBe(1) + expect(Int32.from(-100).compareTo(Int32.from(-100))).toBe(0) + }) + + it('should compare negative and positive values', () => { + expect(Int32.from(-100).compareTo(Int32.from(100))).toBe(-1) + expect(Int32.from(100).compareTo(Int32.from(-100))).toBe(1) + }) + }) + + describe('toJSON()', () => { + it('should return number for positive value', () => { + expect(Int32.from(12345).toJSON()).toBe(12345) + }) + + it('should return number for negative value', () => { + expect(Int32.from(-12345).toJSON()).toBe(-12345) + }) + + it('should return 0 for zero', () => { + expect(Int32.from(0).toJSON()).toBe(0) + }) + }) + + describe('valueOf()', () => { + it('should allow bitwise operations', () => { + const val = Int32.from(5) + expect(val.valueOf() | 0x2).toBe(7) + }) + + it('should handle negative values in bitwise operations', () => { + const val = Int32.from(-1) + expect(val.valueOf() & 0xff).toBe(255) + }) + }) + + describe('encode/decode with Loan ledger entry', () => { + // Loan object from Devnet with LoanScale field + const loanWithScale = { + Borrower: 'rs5fUokF7Y5bxNkstM4p4JYHgqzYkFamCg', + GracePeriod: 60, + LoanBrokerID: + '18F91BD8009DAF09B5E4663BE7A395F5F193D0657B12F8D1E781EB3D449E8151', + LoanScale: -11, + LoanSequence: 1, + NextPaymentDueDate: 822779431, + PaymentInterval: 400, + PaymentRemaining: 1, + PeriodicPayment: '10000', + PrincipalOutstanding: '10000', + StartDate: 822779031, + TotalValueOutstanding: '10000', + LedgerEntryType: 'Loan', + } + + it('can encode and decode Loan with negative LoanScale', () => { + const encoded = encode(loanWithScale) + const decoded = decode(encoded) + expect(decoded).toEqual(loanWithScale) + }) + + it('can encode and decode Loan with positive LoanScale', () => { + const loan = { ...loanWithScale, LoanScale: 5 } + const encoded = encode(loan) + const decoded = decode(encoded) + expect(decoded).toEqual(loan) + }) + }) +}) diff --git a/packages/ripple-binary-codec/test/issue.test.ts b/packages/ripple-binary-codec/test/issue.test.ts index 72ba9fef34..74f33f23a8 100644 --- a/packages/ripple-binary-codec/test/issue.test.ts +++ b/packages/ripple-binary-codec/test/issue.test.ts @@ -70,7 +70,7 @@ describe('Issue type conversion functions', () => { } const mptIssue = Issue.from(mptJson) const parser = new BinaryParser(mptIssue.toHex()) - const parserIssue = Issue.fromParser(parser, 24) + const parserIssue = Issue.fromParser(parser) expect(parserIssue.toJSON()).toEqual(mptJson) }) @@ -79,6 +79,6 @@ describe('Issue type conversion functions', () => { expect(() => { // @ts-expect-error -- need to test error message Issue.from(invalidJson) - }).toThrow(new Error('Invalid type to construct an Amount')) + }).toThrow(new Error('Invalid type to construct an Issue')) }) }) diff --git a/packages/ripple-binary-codec/test/quality.test.ts b/packages/ripple-binary-codec/test/quality.test.ts index 41a53fd53d..be645363c9 100644 --- a/packages/ripple-binary-codec/test/quality.test.ts +++ b/packages/ripple-binary-codec/test/quality.test.ts @@ -1,5 +1,5 @@ const { quality } = require('../src/coretypes') -const { bytesToHex } = require('@xrplf/isomorphic/utils') +const { bytesToHex } = require('@transia/isomorphic/utils') describe('Quality encode/decode', function () { const bookDirectory = diff --git a/packages/ripple-binary-codec/test/signing-data-encoding.test.ts b/packages/ripple-binary-codec/test/signing-data-encoding.test.ts index dab7c15e16..a90127fc65 100644 --- a/packages/ripple-binary-codec/test/signing-data-encoding.test.ts +++ b/packages/ripple-binary-codec/test/signing-data-encoding.test.ts @@ -28,6 +28,22 @@ const tx_json = { 'ED5F5AC8B98974A3CA843326D9B88CEBD0560177B973EE0B149F782CFAA06DC66A', } +const multiSigningTxJson = { + TransactionType: 'LoanSet', + Flags: 0, + Sequence: 3606, + LastLedgerSequence: 3634, + LoanBrokerID: + 'B91CD2033E73E0DD17AF043FBD458CE7D996850A83DCED23FB122A3BFAA7F430', + Fee: '12', + SigningPubKey: + 'EDCEDEBC063D32FD4327C272ED2C46851129C47BE41FCA4222D4D94205AB1B587B', + TxnSignature: + 'CCF8287A8A8EC0CF47C67219639C2F7BC7E7FCF2648FD328A518E9B9FA05ADB9A28A6EFB02D17A776DAEE5D1E25623FFBEFC06B5BBC1F77104188602F865A70F', + Account: 'rHLLL3Z7uBLK49yZcMaj8FAP7DU12Nw5A5', + PrincipalRequested: '100000', +} + describe('Signing data', function () { it('can create single signing blobs', function () { const actual = encodeForSigning(tx_json) @@ -175,6 +191,50 @@ describe('Signing data', function () { ) }) + it('can create multi signing blobs with non-empty SigningPubKey', function () { + const signingAccount = 'rJ73aumLPTQQmy5wnGhvrogqf5DDhjuzc9' + const actual = encodeForMultisigning(multiSigningTxJson, signingAccount) + expect(actual).toBe( + [ + '534D5400', // signingPrefix + // TransactionType + '12', + '0050', // LoanSet = 80 + // Flags + '22', + '00000000', + // Sequence + '24', + '00000E16', // 3606 + // LastLedgerSequence + '201B', + '00000E32', // 3634 + // LoanBrokerID + '5025', + 'B91CD2033E73E0DD17AF043FBD458CE7D996850A83DCED23FB122A3BFAA7F430', + // Fee + '68', + // native amount + '400000000000000C', + // SigningPubKey + '73', + // VLLength + '21', // 33 bytes + 'EDCEDEBC063D32FD4327C272ED2C46851129C47BE41FCA4222D4D94205AB1B587B', + // Account + '81', + // VLLength + '14', + 'B32A0D322D38281C81D4F49DCCDC260A81879B57', + // PrincipalRequested + '9E', + '0DE0B6B3A7640000FFFFFFF3', + // signingAccount suffix + 'BF9B4C3302798C111649BFA38DB60525C6E1021C', + ].join(''), + ) + }) + it('can create multi signing blobs with custom definitions', function () { const customPaymentDefinitions = JSON.parse( JSON.stringify(normalDefinitions), diff --git a/packages/ripple-binary-codec/test/st-number.test.ts b/packages/ripple-binary-codec/test/st-number.test.ts index 08e050949e..e4b6519c3c 100644 --- a/packages/ripple-binary-codec/test/st-number.test.ts +++ b/packages/ripple-binary-codec/test/st-number.test.ts @@ -4,21 +4,58 @@ import { coreTypes } from '../src/types' const { Number: STNumber } = coreTypes describe('STNumber', () => { - it('should encode and decode integers', () => { - const value = '9876543210' + it('+ve normal value', () => { + const value = '99' const sn = STNumber.from(value) expect(sn.toJSON()).toEqual(value) }) - it('roundtrip integer', () => { - const value = '123456789' - const num = STNumber.from(value) - expect(num.toJSON()).toEqual('123456789') + + // scientific notation triggers in when abs(value) >= 10^11 + it('+ve very large value', () => { + const value = '100000000000' + const sn = STNumber.from(value) + expect(sn.toJSON()).toEqual('1e11') }) - it('roundtrip negative integer', () => { - const value = '-987654321' - const num = STNumber.from(value) - expect(num.toJSON()).toEqual('-987654321') + // scientific notation triggers in when abs(value) >= 10^11 + it('+ve large value', () => { + const value = '10000000000' + const sn = STNumber.from(value) + expect(sn.toJSON()).toEqual('10000000000') + }) + + it('-ve normal value', () => { + const value = '-123' + const sn = STNumber.from(value) + expect(sn.toJSON()).toEqual(value) + }) + + // scientific notation triggers in when abs(value) >= 10^11 + it('-ve very large value', () => { + const value = '-100000000000' + const sn = STNumber.from(value) + expect(sn.toJSON()).toEqual('-1e11') + }) + + // scientific notation triggers in when abs(value) >= 10^11 + it('-ve large value', () => { + const value = '-10000000000' + const sn = STNumber.from(value) + expect(sn.toJSON()).toEqual('-10000000000') + }) + + // scientific notation triggers in when abs(value) < 10^-10 + it('+ve very small value', () => { + const value = '0.00000000001' + const sn = STNumber.from(value) + expect(sn.toJSON()).toEqual('1e-11') + }) + + // scientific notation triggers in when abs(value) < 10^-10 + it('+ve small value', () => { + const value = '0.0001' + const sn = STNumber.from(value) + expect(sn.toJSON()).toEqual('0.0001') }) it('roundtrip zero', () => { @@ -36,26 +73,27 @@ describe('STNumber', () => { it('roundtrip scientific notation positive', () => { const value = '1.23e5' const num = STNumber.from(value) - // NOTE: The codec always outputs the normalized value as a decimal string, - // not necessarily in scientific notation. Only exponents < -25 or > -5 - // will use scientific notation. So "1.23e5" becomes "123000". + // scientific notation triggers in when abs(value) >= 10^11 expect(num.toJSON()).toEqual('123000') }) it('roundtrip scientific notation negative', () => { const value = '-4.56e-7' const num = STNumber.from(value) - // NOTE: The output is the normalized decimal form of the value. - // "-4.56e-7" becomes "-0.000000456" as per XRPL codec behavior. + // scientific notation triggers in when abs(value) < 10^-10 expect(num.toJSON()).toEqual('-0.000000456') }) - it('roundtrip large exponent', () => { - const value = '7.89e+20' - const num = STNumber.from(value) - // NOTE: The XRPL codec will output this in normalized scientific form, - // as mantissa=7890000000000000, exponent=5, so the output is '7890000000000000e5'. - expect(num.toJSON()).toEqual('7890000000000000e5') + it('-ve medium value', () => { + const value = '-987654321' + const sn = STNumber.from(value) + expect(sn.toJSON()).toEqual('-987654321') + }) + + it('+ve medium value', () => { + const value = '987654321' + const sn = STNumber.from(value) + expect(sn.toJSON()).toEqual('987654321') }) it('roundtrip via parser', () => { @@ -98,6 +136,71 @@ describe('STNumber', () => { expect(num.toJSON()).toEqual('-120') }) + it('decimal without exponent', () => { + const value = '0.5' + const num = STNumber.from(value) + const parser = new BinaryParser(num.toHex()) + const parsedNum = STNumber.fromParser(parser) + expect(parsedNum.toJSON()).toEqual('0.5') + }) + + it('rounds up mantissa', () => { + const value = '9223372036854775895' + const num = STNumber.from(value) + expect(num.toJSON()).toEqual('9223372036854775900') + }) + + it('rounds down mantissa', () => { + const value = '9323372036854775804' + const num = STNumber.from(value) + expect(num.toJSON()).toEqual('9323372036854775800') + }) + + it('small value with trailing zeros', () => { + const value = '0.002500' + const sn = STNumber.from(value) + expect(sn.toJSON()).toEqual('0.0025') + }) + + it('large value with trailing zeros', () => { + const value = '9900000000000000000000' + const sn = STNumber.from(value) + expect(sn.toJSON()).toEqual('99e20') + }) + + it('small value with leading zeros', () => { + const value = '0.0000000000000000000099' + const sn = STNumber.from(value) + expect(sn.toJSON()).toEqual('99e-22') + }) + + it('mantissa > MAX_MANTISSA', () => { + const value = '9999999999999999999999' + const sn = STNumber.from(value) + expect(sn.toJSON()).toEqual('1e22') + }) + + it('mantissa > MAX_INT64', () => { + const value = '92233720368547758079' + const sn = STNumber.from(value) + expect(sn.toJSON()).toEqual('922337203685477581e2') + }) + + it('throws on exponent overflow (value too large)', () => { + // 1e40000 has exponent 40000, after normalization exponent = 40000 - 18 = 39982 + // which exceeds MAX_EXPONENT (32768) + expect(() => { + STNumber.from('1e40000') + }).toThrow(new Error('Exponent overflow: value too large to represent')) + }) + + it('underflow returns zero (value too small)', () => { + // 1e-40000 has exponent -40000, which is less than MIN_EXPONENT (-32768) + expect(() => { + STNumber.from('1e-40000') + }).toThrow(new Error('Underflow: value too small to represent')) + }) + it('throws with invalid input (non-number string)', () => { expect(() => { STNumber.from('abc123') diff --git a/packages/ripple-binary-codec/test/uint.test.ts b/packages/ripple-binary-codec/test/uint.test.ts index e3165fa1ed..c737344da8 100644 --- a/packages/ripple-binary-codec/test/uint.test.ts +++ b/packages/ripple-binary-codec/test/uint.test.ts @@ -1,4 +1,4 @@ -import { UInt8, UInt64 } from '../src/types' +import { UInt8, UInt16, UInt32, UInt64 } from '../src/types' import { encode, decode } from '../src' const binary = @@ -195,3 +195,109 @@ it('UInt64 is parsed as base 10 for MPT amounts', () => { expect(typeof decodedToken.MPTAmount).toBe('string') expect(decodedToken.MPTAmount).toBe('100') }) + +describe('UInt decimal validation', () => { + describe('UInt8', () => { + it('should throw error when passed a decimal number', () => { + expect(() => UInt8.from(1.5)).toThrow( + new Error('Cannot construct UInt8 from given value'), + ) + }) + + it('should throw error when passed a negative decimal', () => { + expect(() => UInt8.from(-1.5)).toThrow( + new Error('Cannot construct UInt8 from given value'), + ) + }) + + it('should throw error when passed a small decimal', () => { + expect(() => UInt8.from(0.1)).toThrow( + new Error('Cannot construct UInt8 from given value'), + ) + }) + + it('should accept valid integer values', () => { + expect(() => UInt8.from(0)).not.toThrow() + expect(() => UInt8.from(1)).not.toThrow() + expect(() => UInt8.from(255)).not.toThrow() + }) + }) + + describe('UInt16', () => { + it('should throw error when passed a decimal number', () => { + expect(() => UInt16.from(100.5)).toThrow( + new Error('Cannot construct UInt16 from given value'), + ) + }) + + it('should throw error when passed a negative decimal', () => { + expect(() => UInt16.from(-100.5)).toThrow( + new Error('Cannot construct UInt16 from given value'), + ) + }) + + it('should throw error when passed a small decimal', () => { + expect(() => UInt16.from(0.001)).toThrow( + new Error('Cannot construct UInt16 from given value'), + ) + }) + + it('should accept valid integer values', () => { + expect(() => UInt16.from(0)).not.toThrow() + expect(() => UInt16.from(1000)).not.toThrow() + expect(() => UInt16.from(65535)).not.toThrow() + }) + }) + + describe('UInt32', () => { + it('should throw error when passed a decimal number', () => { + expect(() => UInt32.from(1000.5)).toThrow( + new Error('Cannot construct UInt32 from given value'), + ) + }) + + it('should throw error when passed a negative decimal', () => { + expect(() => UInt32.from(-1000.5)).toThrow( + new Error('Cannot construct UInt32 from given value'), + ) + }) + + it('should throw error when passed a small decimal', () => { + expect(() => UInt32.from(0.0001)).toThrow( + new Error('Cannot construct UInt32 from given value'), + ) + }) + + it('should accept valid integer values', () => { + expect(() => UInt32.from(0)).not.toThrow() + expect(() => UInt32.from(100000)).not.toThrow() + expect(() => UInt32.from(4294967295)).not.toThrow() + }) + }) + + describe('UInt64', () => { + it('should throw error when passed a decimal number', () => { + expect(() => UInt64.from(10000.5)).toThrow( + new Error('Cannot construct UInt64 from given value'), + ) + }) + + it('should throw error when passed a negative decimal', () => { + expect(() => UInt64.from(-10000.5)).toThrow( + new Error('Cannot construct UInt64 from given value'), + ) + }) + + it('should throw error when passed a small decimal', () => { + expect(() => UInt64.from(0.00001)).toThrow( + new Error('Cannot construct UInt64 from given value'), + ) + }) + + it('should accept valid integer values', () => { + expect(() => UInt64.from(0)).not.toThrow() + expect(() => UInt64.from(1000000)).not.toThrow() + expect(() => UInt64.from(BigInt('9223372036854775807'))).not.toThrow() + }) + }) +}) diff --git a/packages/ripple-binary-codec/tools/generateDefinitions.js b/packages/ripple-binary-codec/tools/generateDefinitions.js index 2e6ce29a84..21330a0af0 100644 --- a/packages/ripple-binary-codec/tools/generateDefinitions.js +++ b/packages/ripple-binary-codec/tools/generateDefinitions.js @@ -104,6 +104,7 @@ async function main() { VL: 'Blob', DIR_NODE: 'DirectoryNode', PAYCHAN: 'PayChannel', + DATATYPE: 'DataType', } if (nonstandardRenames[inp] != null) return nonstandardRenames[inp] @@ -138,12 +139,14 @@ async function main() { // process STypes let stypeHits = [ ...sfieldHeaderFile.matchAll( - /^ *STYPE\(STI_([^ ]*?) *, *([0-9-]+) *\) *\\?$/gm, + /^ *STYPE\(STI_([^ ]*?)[ \n]*,[ \n]*([0-9-]+)[ \n]*\)[ \n]*\\?$/gm, ), ] if (stypeHits.length === 0) stypeHits = [ - ...sfieldHeaderFile.matchAll(/^ *STI_([^ ]*?) *= *([0-9-]+) *,?$/gm), + ...sfieldHeaderFile.matchAll( + /^ *STI_([^ ]*?)[ \n]*=[ \n]*([0-9-]+)[ \n]*,?$/gm, + ), ] const stypeMap = {} stypeHits.forEach(([_, key, value]) => { @@ -248,7 +251,7 @@ async function main() { // Parse SField.cpp for all the SFields and their serialization info let sfieldHits = [ ...sfieldMacroFile.matchAll( - /^ *[A-Z]*TYPED_SFIELD *\( *sf([^,\n]*),[ \n]*([^, \n]+)[ \n]*,[ \n]*([0-9]+)(,.*?(notSigning))?/gm, + /^ *[A-Z]*TYPED_SFIELD[ \n]*\([ \n]*sf([^,\n]*),[ \n]*([^, \n]+)[ \n]*,[ \n]*([0-9]+)(,.*?(notSigning))?/gm, ), ] sfieldHits.push( @@ -298,7 +301,7 @@ async function main() { } hits = [ ...ledgerFormatsMacroFile.matchAll( - /^ *LEDGER_ENTRY[A-Z_]*\(lt[A-Z_]+ *, *([x0-9a-f]+) *, *([^,]+), *([^,]+), \({$/gm, + /^ *LEDGER_ENTRY[A-Z_]*\(lt[A-Z_]+[ \n]*,[ \n]*([x0-9a-f]+)[ \n]*,[ \n]*([^,]+),[ \n]*([^,]+), \({$/gm, ), ] hits.push(['', '-1', 'Invalid']) @@ -321,7 +324,7 @@ async function main() { let terHits = [ ...cleanedTerFile.matchAll( - /^ *((tel|tem|tef|ter|tes|tec)[A-Z_]+)( *= *([0-9-]+))? *,? *(\/\/[^\n]*)?$/gm, + /^ *((tel|tem|tef|ter|tes|tec)[A-Z_]+)([ \n]*=[ \n]*([0-9-]+))?[ \n]*,?[ \n]*(\/\/[^\n]*)?$/gm, ), ] let upto = -1 @@ -359,7 +362,7 @@ async function main() { let txHits = [ ...transactionsMacroFile.matchAll( - /^ *TRANSACTION\(tt[A-Z_]+ *,* ([0-9]+) *, *([A-Za-z]+).*$/gm, + /^ *TRANSACTION\(tt[A-Z_]+[ \n]*,[ \n]*([0-9]+)[ \n]*,[ \n]*([A-Za-z]+).*$/gm, ), ] txHits.push(['', '-1', 'Invalid']) diff --git a/packages/ripple-keypairs/eslint.config.js b/packages/ripple-keypairs/eslint.config.js index 56f14283b8..ed3dded4f0 100644 --- a/packages/ripple-keypairs/eslint.config.js +++ b/packages/ripple-keypairs/eslint.config.js @@ -1,5 +1,5 @@ const globals = require('globals') -const eslintConfig = require('@xrplf/eslint-config/base') +const eslintConfig = require('@xrplf/eslint-config/base').default const tseslint = require('typescript-eslint') module.exports = [ diff --git a/packages/secret-numbers/eslint.config.js b/packages/secret-numbers/eslint.config.js index c1b35e1970..8b297324f0 100644 --- a/packages/secret-numbers/eslint.config.js +++ b/packages/secret-numbers/eslint.config.js @@ -1,5 +1,5 @@ const globals = require('globals') -const eslintConfig = require('@xrplf/eslint-config/base') +const eslintConfig = require('@xrplf/eslint-config/base').default const tseslint = require('typescript-eslint') module.exports = [ diff --git a/packages/xrpl/HISTORY.md b/packages/xrpl/HISTORY.md index 177270d1e5..ba53ba2a56 100644 --- a/packages/xrpl/HISTORY.md +++ b/packages/xrpl/HISTORY.md @@ -4,6 +4,40 @@ Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xr ## Unreleased +## 4.6.0 (2026-02-12) + +### Added +* Add `faucetProtocol` (http or https) option to `fundWallet` method. Makes `fundWallet` work with locally running faucet servers. +* Add `signLoanSetByCounterparty` and `combineLoanSetCounterpartySigners` helper functions to sign and combine LoanSet transactions signed by the counterparty. +* Add newly added fields to `Loan`, `LoanBroker` and `Vault` ledger objects and lending protocol related transaction types. + +## 4.5.0 (2025-12-16) + +### Added +* Support for `Lending Protocol` (XLS-66d). +* Export signing and binary codec utilities. + +### Fixed +* Update ripple-binary-codec to 2.5.1 to address serialization/deserialization issues in `Issue` serialized type for `MPTIssue`. +* Better faucet error handling +* Mark the `AssetsAvailable`, `AssetsTotal`, and `LossUnrealized` fields of the Vault object as optional. + +## 4.4.3 (2025-11-07) + +### Added +* Export `Batch` (XLS-56) transaction types and utilities +* Add `encodeMPTokenMetadata` and `decodeMPTokenMetadata` helper functions to encode and decode MPTokenMetadata as per XLS-89 standard. + +### Fixed +* Fix incorrect type checking in `validateVaultCreate` that prevented vault creation with MPT as an asset. +* [Breaking change] Fix `MPTokenMetadata` type to adhere to the XLS-89 standard. Since XLS-89 is still in a forming state and undergoing changes, this breaking change is being released as a bug fix via patch version bump. If you are using `MPTokenMetadata` in your code, please verify that it adheres to the updated type definition. +* [Breaking change] Fix `validateMPTokenMetadata` to correctly validate MPTokenMetadata as per XLS-89 standard. Since XLS-89 is still in a forming state and undergoing changes, this breaking change is being released as a bug fix via patch version bump. If you are using `validateMPTokenMetadata` in your code, expect it to change as per the XLS-89 standard. + +## 4.4.2 (2025-09-25) + +### Fixed +* improve Batch inner transaction typing + ## 4.4.1 (2025-08-29) ### Fixed diff --git a/packages/xrpl/eslint.config.js b/packages/xrpl/eslint.config.js index 97436c9d05..04d116a11f 100644 --- a/packages/xrpl/eslint.config.js +++ b/packages/xrpl/eslint.config.js @@ -1,5 +1,5 @@ const globals = require('globals') -const eslintConfig = require('@xrplf/eslint-config/base') +const eslintConfig = require('@xrplf/eslint-config/base').default const tseslint = require('typescript-eslint') module.exports = [ diff --git a/packages/xrpl/package.json b/packages/xrpl/package.json index 95ac3d4794..b696b0944b 100644 --- a/packages/xrpl/package.json +++ b/packages/xrpl/package.json @@ -30,7 +30,8 @@ "@transia/ripple-keypairs": "^2.0.4-alpha.0", "@transia/secret-numbers": "^2.0.4-alpha.0", "bignumber.js": "^9.0.0", - "eventemitter3": "^5.0.1" + "eventemitter3": "^5.0.1", + "fast-json-stable-stringify": "^2.1.0" }, "devDependencies": { "@types/node": "^18.18.38", @@ -43,7 +44,7 @@ "lodash": "^4.17.4", "react": "^19.0.0", "run-s": "^0.0.0", - "typedoc": "0.28.5", + "typedoc": "0.28.15", "ws": "^8.14.2" }, "scripts": { diff --git a/packages/xrpl/src/Wallet/authorizeChannel.ts b/packages/xrpl/src/Wallet/authorizeChannel.ts index c9e8346beb..35c432417c 100644 --- a/packages/xrpl/src/Wallet/authorizeChannel.ts +++ b/packages/xrpl/src/Wallet/authorizeChannel.ts @@ -1,7 +1,7 @@ import { encodeForSigningClaim } from '@transia/ripple-binary-codec' import { sign } from '@transia/ripple-keypairs' -import { Wallet } from './index' +import type { Wallet } from './index' /** * Creates a signature that can be used to redeem a specific amount of XRP from a payment channel. diff --git a/packages/xrpl/src/Wallet/batchSigner.ts b/packages/xrpl/src/Wallet/batchSigner.ts index 41f82c9a5d..a1431b8be3 100644 --- a/packages/xrpl/src/Wallet/batchSigner.ts +++ b/packages/xrpl/src/Wallet/batchSigner.ts @@ -8,7 +8,7 @@ import { hashSignedTx } from '../utils/hashes' import { compareSigners, getDecodedTransaction } from './utils' -import { Wallet } from '.' +import type { Wallet } from './index' // eslint-disable-next-line max-params -- okay for helper function function constructBatchSignerObject( diff --git a/packages/xrpl/src/Wallet/counterpartySigner.ts b/packages/xrpl/src/Wallet/counterpartySigner.ts new file mode 100644 index 0000000000..b8aa4e58fe --- /dev/null +++ b/packages/xrpl/src/Wallet/counterpartySigner.ts @@ -0,0 +1,213 @@ +import { encode } from '@transia/ripple-binary-codec' +import stringify from 'fast-json-stable-stringify' + +import { ValidationError } from '../errors' +import { LoanSet, Signer, Transaction, validate } from '../models' +import { hashSignedTx } from '../utils/hashes' + +import { + compareSigners, + computeSignature, + getDecodedTransaction, +} from './utils' + +import type { Wallet } from '.' + +/** + * Signs a LoanSet transaction as the counterparty. + * + * This function adds a counterparty signature to a LoanSet transaction that has already been + * signed by the first party. The counterparty uses their wallet to sign the transaction, + * which is required for multi-party loan agreements on the XRP Ledger. + * + * @param wallet - The counterparty's wallet used for signing the transaction. + * @param transaction - The LoanSet transaction to sign. Can be either: + * - A LoanSet transaction object that has been signed by the first party + * - A serialized transaction blob (string) in hex format + * @param opts - (Optional) Options for signing the transaction. + * @param opts.multisign - Specify true/false to use multisign or actual address (classic/x-address) to make multisign tx request. + * The actual address is only needed in the case of regular key usage. + * @returns An object containing: + * - `tx`: The signed LoanSet transaction object + * - `tx_blob`: The serialized transaction blob (hex string) ready to submit to the ledger + * - `hash`: The transaction hash (useful for tracking the transaction) + * + * @throws {ValidationError} If: + * - The transaction is not a LoanSet transaction + * - The transaction is already signed by the counterparty + * - The transaction has not been signed by the first party yet + * - The transaction fails validation + */ +// eslint-disable-next-line max-lines-per-function -- for extensive validations +export function signLoanSetByCounterparty( + wallet: Wallet, + transaction: LoanSet | string, + opts: { multisign?: boolean | string } = {}, +): { + tx: LoanSet + tx_blob: string + hash: string +} { + const tx = getDecodedTransaction(transaction) + + if (tx.TransactionType !== 'LoanSet') { + throw new ValidationError('Transaction must be a LoanSet transaction.') + } + if (tx.CounterpartySignature) { + throw new ValidationError( + 'Transaction is already signed by the counterparty.', + ) + } + if (tx.TxnSignature == null || tx.SigningPubKey == null) { + throw new ValidationError( + 'Transaction must be first signed by first party.', + ) + } + + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- validate does not accept Transaction type + validate(tx as unknown as Record) + + let multisignAddress: boolean | string = false + if (typeof opts.multisign === 'string') { + multisignAddress = opts.multisign + } else if (opts.multisign) { + multisignAddress = wallet.classicAddress + } + + if (multisignAddress) { + tx.CounterpartySignature = { + Signers: [ + { + Signer: { + Account: multisignAddress, + SigningPubKey: wallet.publicKey, + TxnSignature: computeSignature( + tx, + wallet.privateKey, + multisignAddress, + ), + }, + }, + ], + } + } else { + tx.CounterpartySignature = { + SigningPubKey: wallet.publicKey, + TxnSignature: computeSignature(tx, wallet.privateKey), + } + } + + const serialized = encode(tx) + return { + tx, + tx_blob: serialized, + hash: hashSignedTx(serialized), + } +} + +/** + * Combines multiple LoanSet transactions signed by the counterparty into a single transaction. + * + * @param transactions - An array of signed LoanSet transactions (in object or blob form) to combine. + * @returns An object containing: + * - `tx`: The combined LoanSet transaction object + * - `tx_blob`: The serialized transaction blob (hex string) ready to submit to the ledger + * @throws ValidationError if: + * - There are no transactions to combine + * - Any of the transactions are not LoanSet transactions + * - Any of the transactions do not have Signers + * - Any of the transactions do not have a first party signature + */ +export function combineLoanSetCounterpartySigners( + transactions: Array, +): { + tx: LoanSet + tx_blob: string +} { + if (transactions.length === 0) { + throw new ValidationError('There are 0 transactions to combine.') + } + + const decodedTransactions: Transaction[] = transactions.map( + (txOrBlob: string | Transaction) => { + return getDecodedTransaction(txOrBlob) + }, + ) + + decodedTransactions.forEach((tx) => { + /* + * This will throw a more clear error for JS users if any of the supplied transactions has incorrect formatting + */ + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- validate does not accept Transaction type + validate(tx as unknown as Record) + + if (tx.TransactionType !== 'LoanSet') { + throw new ValidationError('Transaction must be a LoanSet transaction.') + } + + if ( + tx.CounterpartySignature?.Signers == null || + tx.CounterpartySignature.Signers.length === 0 + ) { + throw new ValidationError('CounterpartySignature must have Signers.') + } + + if (tx.TxnSignature == null || tx.SigningPubKey == null) { + throw new ValidationError( + 'Transaction must be first signed by first party.', + ) + } + }) + + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- checked above + const loanSetTransactions = decodedTransactions as LoanSet[] + + validateLoanSetTransactionEquivalence(loanSetTransactions) + + const tx = + getTransactionWithAllLoanSetCounterpartySigners(loanSetTransactions) + + return { + tx, + tx_blob: encode(tx), + } +} + +function validateLoanSetTransactionEquivalence(transactions: LoanSet[]): void { + const exampleTransaction = stringify({ + ...transactions[0], + CounterpartySignature: { + ...transactions[0].CounterpartySignature, + Signers: null, + }, + }) + + if ( + transactions.slice(1).some( + (tx) => + stringify({ + ...tx, + CounterpartySignature: { + ...tx.CounterpartySignature, + Signers: null, + }, + }) !== exampleTransaction, + ) + ) { + throw new ValidationError('LoanSet transactions are not the same.') + } +} + +function getTransactionWithAllLoanSetCounterpartySigners( + transactions: LoanSet[], +): LoanSet { + // Signers must be sorted in the combined transaction - See compareSigners' documentation for more details + const sortedSigners: Signer[] = transactions + .flatMap((tx) => tx.CounterpartySignature?.Signers ?? []) + .sort((signer1, signer2) => compareSigners(signer1.Signer, signer2.Signer)) + + return { + ...transactions[0], + CounterpartySignature: { Signers: sortedSigners }, + } +} diff --git a/packages/xrpl/src/Wallet/fundWallet.ts b/packages/xrpl/src/Wallet/fundWallet.ts index 01bab88666..9c81003efe 100644 --- a/packages/xrpl/src/Wallet/fundWallet.ts +++ b/packages/xrpl/src/Wallet/fundWallet.ts @@ -33,6 +33,11 @@ export interface FundingOptions { * specifies a request to 'faucet.altnet.rippletest.net/accounts' to fund a new wallet. */ faucetPath?: string + /** + * The protocol to use for the faucet server. Defaults to 'https'. Use 'http' to interact with a local faucet server + * running on http:// + */ + faucetProtocol?: 'http' | 'https' /** * An optional field to indicate the use case context of the faucet transaction * Ex: integration test, code snippets. @@ -101,6 +106,7 @@ export interface FundWalletOptions { faucetHost?: string faucetPath?: string amount?: string + faucetProtocol?: 'http' | 'https' usageContext?: string } @@ -121,6 +127,8 @@ export interface FundWalletOptions { * you should provide the path using this option. * Ex: client.fundWallet(null,{'faucet.altnet.rippletest.net', '/accounts'}) * specifies a request to 'faucet.altnet.rippletest.net/accounts' to fund a new wallet. + * @param options.faucetProtocol - The protocol to use for the faucet server ('http' or 'https'). + * Defaults to 'https'. Use 'http' to interact with a local faucet server running on http://. * @param options.amount - A custom amount to fund, if undefined or null, the default amount will be 1000. * @param client - A connection to the XRPL to send requests and transactions. * @param startingBalance - The amount of XRP in the given walletToFund on ledger already. @@ -145,7 +153,8 @@ export async function requestFunding( throw new XRPLFaucetError('No faucet hostname could be derived') } const pathname = options.faucetPath ?? getFaucetPath(hostname) - const response = await fetch(`https://${hostname}${pathname}`, { + const protocol = options.faucetProtocol ?? 'https' + const response = await fetch(`${protocol}://${hostname}${pathname}`, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -153,12 +162,11 @@ export async function requestFunding( body: JSON.stringify(postBody), }) - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- it can be anything - const body = await response.json() if ( response.ok && response.headers.get('Content-Type')?.startsWith('application/json') ) { + const body: unknown = await response.json() // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- It's a FaucetWallet const classicAddress = (body as FaucetWallet).account.classicAddress return processSuccessfulResponse( @@ -168,7 +176,7 @@ export async function requestFunding( startingBalance, ) } - return processError(response, body) + return processError(response) } // eslint-disable-next-line max-params -- Only used as a helper function, lines inc due to added balance. @@ -206,16 +214,26 @@ async function processSuccessfulResponse( ) } -async function processError(response: Response, body): Promise { +interface ErrorData { + body?: unknown + contentType?: string + statusCode: number +} + +async function processError(response: Response): Promise { + const errorData: ErrorData = { + contentType: response.headers.get('Content-Type') ?? undefined, + statusCode: response.status, + } + const clone = response.clone() + try { + const body: unknown = await response.json() + errorData.body = body + } catch { + errorData.body = await clone.text() + } return Promise.reject( - new XRPLFaucetError( - `Request failed: ${JSON.stringify({ - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- json response could be anything - body: body ?? {}, - contentType: response.headers.get('Content-Type'), - statusCode: response.status, - })}`, - ), + new XRPLFaucetError(`Request failed: ${JSON.stringify(errorData)}`), ) } diff --git a/packages/xrpl/src/Wallet/index.ts b/packages/xrpl/src/Wallet/index.ts index acb6a62dee..039d1fc72e 100644 --- a/packages/xrpl/src/Wallet/index.ts +++ b/packages/xrpl/src/Wallet/index.ts @@ -2,24 +2,17 @@ import { HDKey } from '@scure/bip32' import { mnemonicToSeedSync, validateMnemonic } from '@scure/bip39' import { wordlist } from '@scure/bip39/wordlists/english' import { bytesToHex } from '@transia/isomorphic/utils' -import BigNumber from 'bignumber.js' import { classicAddressToXAddress, - isValidXAddress, - xAddressToClassicAddress, encodeSeed, } from '@transia/ripple-address-codec' -import { - encodeForSigning, - encodeForMultisigning, - encode, -} from '@transia/ripple-binary-codec' +import { encode } from '@transia/ripple-binary-codec' import { deriveAddress, deriveKeypair, generateSeed, - sign, } from '@transia/ripple-keypairs' +import BigNumber from 'bignumber.js' import ECDSA from '../ECDSA' import { ValidationError } from '../errors' @@ -32,6 +25,7 @@ import { hashSignedTx } from '../utils/hashes/hashLedger' import { rfc1751MnemonicToKey } from './rfc1751' import { verifySignature } from './signer' +import { computeSignature } from './utils' const DEFAULT_ALGORITHM: ECDSA = ECDSA.ed25519 const DEFAULT_DERIVATION_PATH = "m/44'/144'/0'/0/0" @@ -467,30 +461,6 @@ export class Wallet { } } -/** - * Signs a transaction with the proper signing encoding. - * - * @param tx - A transaction to sign. - * @param privateKey - A key to sign the transaction with. - * @param signAs - Multisign only. An account address to include in the Signer field. - * Can be either a classic address or an XAddress. - * @returns A signed transaction in the proper format. - */ -function computeSignature( - tx: Transaction, - privateKey: string, - signAs?: string, -): string { - if (signAs) { - const classicAddress = isValidXAddress(signAs) - ? xAddressToClassicAddress(signAs).classicAddress - : signAs - - return sign(encodeForMultisigning(tx, classicAddress), privateKey) - } - return sign(encodeForSigning(tx), privateKey) -} - /** * Remove trailing insignificant zeros for non-XRP Payment amount. * This resolves the serialization mismatch bug when encoding/decoding a non-XRP Payment transaction @@ -512,3 +482,14 @@ function removeTrailingZeros(tx: Transaction): void { tx.Amount.value = new BigNumber(tx.Amount.value).toString() } } + +export { signMultiBatch, combineBatchSigners } from './batchSigner' + +export { multisign, verifySignature } from './signer' + +export { authorizeChannel } from './authorizeChannel' + +export { + signLoanSetByCounterparty, + combineLoanSetCounterpartySigners, +} from './counterpartySigner' diff --git a/packages/xrpl/src/Wallet/utils.ts b/packages/xrpl/src/Wallet/utils.ts index 2288d4cfb8..e966c5c1dc 100644 --- a/packages/xrpl/src/Wallet/utils.ts +++ b/packages/xrpl/src/Wallet/utils.ts @@ -1,9 +1,19 @@ -import { bytesToHex } from '@transia/isomorphic/utils' -import BigNumber from 'bignumber.js' -import { decodeAccountID } from '@transia/ripple-address-codec' -import { decode, encode } from '@transia/ripple-binary-codec' +import { bytesToHex } from "@transia/isomorphic/utils"; +import BigNumber from "bignumber.js"; +import { + decodeAccountID, + isValidXAddress, + xAddressToClassicAddress, +} from "@transia/ripple-address-codec"; +import { + decode, + encode, + encodeForMultisigning, + encodeForSigning, +} from "@transia/ripple-binary-codec"; +import { sign } from "@transia/ripple-keypairs"; -import { Transaction } from '../models' +import { Transaction } from "../models"; /** * If presented in binary form, the Signers array must be sorted based on @@ -13,18 +23,28 @@ import { Transaction } from '../models' * * @param left - A Signer to compare with. * @param right - A second Signer to compare with. - * @returns 1 if left \> right, 0 if left = right, -1 if left \< right, and null if left or right are NaN. + * @returns 1 if left \> right, 0 if left = right, -1 if left \< right. + * @throws Error if either Account is null, undefined, or invalid. */ export function compareSigners( left: T, right: T, ): number { - return addressToBigNumber(left.Account).comparedTo( + if (!left.Account || !right.Account) { + throw new Error("compareSigners: Account cannot be null or undefined"); + } + const result = addressToBigNumber(left.Account).comparedTo( addressToBigNumber(right.Account), - ) + ); + if (result === null) { + throw new Error( + "compareSigners: Invalid account address comparison resulted in NaN", + ); + } + return result; } -export const NUM_BITS_IN_HEX = 16 +export const NUM_BITS_IN_HEX = 16; /** * Converts an address to a BigNumber. @@ -33,8 +53,8 @@ export const NUM_BITS_IN_HEX = 16 * @returns A BigNumber representing the address. */ export function addressToBigNumber(address: string): BigNumber { - const hex = bytesToHex(decodeAccountID(address)) - return new BigNumber(hex, NUM_BITS_IN_HEX) + const hex = bytesToHex(decodeAccountID(address)); + return new BigNumber(hex, NUM_BITS_IN_HEX); } /** @@ -47,12 +67,36 @@ export function addressToBigNumber(address: string): BigNumber { export function getDecodedTransaction( txOrBlob: Transaction | string, ): Transaction { - if (typeof txOrBlob === 'object') { + if (typeof txOrBlob === "object") { // We need this to handle X-addresses in multisigning // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- We are casting here to get strong typing - return decode(encode(txOrBlob)) as unknown as Transaction + return decode(encode(txOrBlob)) as unknown as Transaction; } // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- We are casting here to get strong typing - return decode(txOrBlob) as unknown as Transaction + return decode(txOrBlob) as unknown as Transaction; +} + +/** + * Signs a transaction with the proper signing encoding. + * + * @param tx - A transaction to sign. + * @param privateKey - A key to sign the transaction with. + * @param signAs - Multisign only. An account address to include in the Signer field. + * Can be either a classic address or an XAddress. + * @returns A signed transaction in the proper format. + */ +export function computeSignature( + tx: Transaction, + privateKey: string, + signAs?: string, +): string { + if (signAs) { + const classicAddress = isValidXAddress(signAs) + ? xAddressToClassicAddress(signAs).classicAddress + : signAs; + + return sign(encodeForMultisigning(tx, classicAddress), privateKey); + } + return sign(encodeForSigning(tx), privateKey); } diff --git a/packages/xrpl/src/client/index.ts b/packages/xrpl/src/client/index.ts index c6e944bb0a..012420a308 100644 --- a/packages/xrpl/src/client/index.ts +++ b/packages/xrpl/src/client/index.ts @@ -1155,7 +1155,7 @@ class Client extends EventEmitter { * const newWallet = Wallet.generate() * const { balance, wallet } = await client.fundWallet(newWallet, { * amount: '10', - * faucetHost: 'https://custom-faucet.example.com', + * faucetHost: 'custom-faucet.example.com', * faucetPath: '/accounts' * }) * console.log(`Sent 10 XRP to wallet: ${address} from the given faucet. Resulting balance: ${balance} XRP`) @@ -1165,6 +1165,20 @@ class Client extends EventEmitter { * } * ``` * + * Example 3: Fund wallet using a local faucet server + * + * To interact with a faucet server running on http://, use the faucetProtocol option: + * + * ```ts + * const newWallet = Wallet.generate() + * const { balance, wallet } = await client.fundWallet(newWallet, { + * amount: '10', + * faucetHost: 'localhost:8000', + * faucetPath: '/accounts', + * faucetProtocol: 'http' + * }) + * ``` + * * @param wallet - An existing XRPL Wallet to fund. If undefined or null, a new Wallet will be created. * @param options - See below. * @param options.faucetHost - A custom host for a faucet server. On devnet, @@ -1172,6 +1186,8 @@ class Client extends EventEmitter { * attempt to determine the correct server automatically. In other environments, * or if you would like to customize the faucet host in devnet or testnet, * you should provide the host using this option. + * @param options.faucetProtocol - The protocol to use for the faucet server ('http' or 'https'). + * Defaults to 'https'. Use 'http' to interact with a local faucet server running on http://. * @param options.faucetPath - A custom path for a faucet server. On devnet, * testnet, AMM devnet, and HooksV3 testnet, `fundWallet` will * attempt to determine the correct path automatically. In other environments, diff --git a/packages/xrpl/src/index.ts b/packages/xrpl/src/index.ts index fdf34b844b..83cb825a7a 100644 --- a/packages/xrpl/src/index.ts +++ b/packages/xrpl/src/index.ts @@ -9,10 +9,8 @@ export { default as ECDSA } from './ECDSA' export * from './errors' export { FundingOptions } from './Wallet/fundWallet' -export { Wallet } from './Wallet' +export * from './Wallet' export { walletFromSecretNumbers } from './Wallet/walletFromSecretNumbers' export { keyToRFC1751Mnemonic, rfc1751MnemonicToKey } from './Wallet/rfc1751' - -export * from './Wallet/signer' diff --git a/packages/xrpl/src/models/common/index.ts b/packages/xrpl/src/models/common/index.ts index c28dcec5c8..ef1147c106 100644 --- a/packages/xrpl/src/models/common/index.ts +++ b/packages/xrpl/src/models/common/index.ts @@ -220,26 +220,110 @@ export interface PriceData { } /** - * MPTokenMetadata object as per the XLS-89d standard. + * {@link MPTokenMetadata} object as per the XLS-89 standard. + * Use {@link encodeMPTokenMetadata} utility function to convert to a compact hex string for on-ledger storage. + * Use {@link decodeMPTokenMetadata} utility function to convert from a hex string to this format. */ export interface MPTokenMetadata { + /** + * Ticker symbol used to represent the token. + * Uppercase letters (A-Z) and digits (0-9) only. Max 6 characters recommended. + * + * @example "TBILL" + */ ticker: string + + /** + * Display name of the token. + * Any UTF-8 string. + * + * @example "T-Bill Yield Token" + */ name: string + + /** + * Short description of the token. + * Any UTF-8 string. + * + * @example "A yield-bearing stablecoin backed by short-term U.S. Treasuries" + */ + desc?: string + + /** + * URI to the token icon. + * Can be a `hostname/path` (HTTPS assumed) or full URI for other protocols (e.g., ipfs://). + * + * @example "example.org/token-icon.png" or "ipfs://QmXxxx" + */ icon: string + + /** + * Top-level classification of token purpose. + * Allowed values: "rwa", "memes", "wrapped", "gaming", "defi", "other" + * + * @example "rwa" + */ asset_class: string - issuer_name: string - desc?: string + + /** + * Optional subcategory of the asset class. + * Required if `asset_class` is "rwa". + * Allowed values: "stablecoin", "commodity", "real_estate", "private_credit", "equity", "treasury", "other" + * + * @example "treasury" + */ asset_subclass?: string - urls?: MPTokenMetadataUrl[] - additional_info?: string + + /** + * The name of the issuer account. + * Any UTF-8 string. + * + * @example "Example Yield Co." + */ + issuer_name: string + + /** + * List of related URIs (site, dashboard, social media, documentation, etc.). + * Each URI object contains the link, its category, and a human-readable title. + */ + uris?: MPTokenMetadataUri[] + + /** + * Freeform field for key token details like interest rate, maturity date, term, or other relevant info. + * Can be any valid JSON object or UTF-8 string. + * + * @example { "interest_rate": "5.00%", "maturity_date": "2045-06-30" } + */ + additional_info?: string | Record } /** - * MPTokenMetadataUrl object as per the XLS-89d standard. + * {@link MPTokenMetadataUri} object as per the XLS-89 standard. + * Used within the `uris` array of {@link MPTokenMetadata}. */ -export interface MPTokenMetadataUrl { - url: string - type: string +export interface MPTokenMetadataUri { + /** + * URI to the related resource. + * Can be a `hostname/path` (HTTPS assumed) or full URI for other protocols (e.g., ipfs://). + * + * @example "exampleyield.com/tbill" or "ipfs://QmXxxx" + */ + uri: string + + /** + * The category of the link. + * Allowed values: "website", "social", "docs", "other" + * + * @example "website" + */ + category: string + + /** + * A human-readable label for the link. + * Any UTF-8 string. + * + * @example "Product Page" + */ title: string } diff --git a/packages/xrpl/src/models/index.ts b/packages/xrpl/src/models/index.ts index 56212a9bc3..22a9a9a5fe 100644 --- a/packages/xrpl/src/models/index.ts +++ b/packages/xrpl/src/models/index.ts @@ -13,6 +13,11 @@ export { convertTxFlagsToNumber, parseTransactionFlags, } from './utils/flags' +export { + validateMPTokenMetadata, + decodeMPTokenMetadata, + encodeMPTokenMetadata, +} from './utils/mptokenMetadata' export * from './methods' export * from './transactions' export * from './common' diff --git a/packages/xrpl/src/models/ledger/LedgerEntry.ts b/packages/xrpl/src/models/ledger/LedgerEntry.ts index d106090fa3..abaa50ad07 100644 --- a/packages/xrpl/src/models/ledger/LedgerEntry.ts +++ b/packages/xrpl/src/models/ledger/LedgerEntry.ts @@ -10,6 +10,8 @@ import DirectoryNode from './DirectoryNode' import Escrow from './Escrow' import FeeSettings from './FeeSettings' import LedgerHashes from './LedgerHashes' +import Loan from './Loan' +import LoanBroker from './LoanBroker' import NegativeUNL from './NegativeUNL' import Offer from './Offer' import Oracle from './Oracle' @@ -35,6 +37,8 @@ type LedgerEntry = | Escrow | FeeSettings | LedgerHashes + | Loan + | LoanBroker | NegativeUNL | Offer | Oracle @@ -61,6 +65,8 @@ type LedgerEntryFilter = | 'escrow' | 'fee' | 'hashes' + | 'loan' + | 'loan_broker' | 'mpt_issuance' | 'mptoken' | 'nft_offer' diff --git a/packages/xrpl/src/models/ledger/Loan.ts b/packages/xrpl/src/models/ledger/Loan.ts new file mode 100644 index 0000000000..cd55de3b53 --- /dev/null +++ b/packages/xrpl/src/models/ledger/Loan.ts @@ -0,0 +1,162 @@ +import { Account, XRPLNumber } from '../transactions/common' + +import { BaseLedgerEntry, HasPreviousTxnID } from './BaseLedgerEntry' + +/** + * A Loan ledger entry captures various Loan terms on-chain. It is an agreement between the Borrower and the loan issuer. + * + * @category Ledger Entries + */ +export default interface Loan extends BaseLedgerEntry, HasPreviousTxnID { + LedgerEntryType: 'Loan' + + /** + * Ledger object flags. + */ + Flags: number + + /** + * The sequence number of the Loan. + */ + LoanSequence: number + + /** + * Identifies the page where this item is referenced in the Borrower owner's directory. + */ + OwnerNode: string + + /** + * Identifies the page where this item is referenced in the LoanBrokers owner's directory. + */ + LoanBrokerNode: string + + /** + * The ID of the LoanBroker associated with this Loan Instance. + */ + LoanBrokerID: string + + /** + * The address of the account that is the borrower. + */ + Borrower: Account + + /** + * A nominal fee amount paid to the LoanBroker.Owner when the Loan is created. + */ + LoanOriginationFee?: XRPLNumber + + /** + * A nominal funds amount paid to the LoanBroker.Owner with every Loan payment. + */ + LoanServiceFee?: XRPLNumber + + /** + * A nominal funds amount paid to the LoanBroker.Owner when a payment is late. + */ + LatePaymentFee?: XRPLNumber + + /** + * A nominal funds amount paid to the LoanBroker.Owner when a full payment is made. + */ + ClosePaymentFee?: XRPLNumber + + /** + * A fee charged on over-payments in 1/10th basis points. Valid values are between 0 and 100000 inclusive. (0 - 100%) + */ + OverpaymentFee?: XRPLNumber + + /** + * Annualized interest rate of the Loan in 1/10th basis points. + */ + InterestRate?: number + + /** + * A premium is added to the interest rate for late payments in 1/10th basis points. + * Valid values are between 0 and 100000 inclusive. (0 - 100%) + */ + LateInterestRate?: number + + /** + * An interest rate charged for repaying the Loan early in 1/10th basis points. + * Valid values are between 0 and 100000 inclusive. (0 - 100%) + */ + CloseInterestRate?: number + + /** + * An interest rate charged on over-payments in 1/10th basis points. Valid values are between 0 and 100000 inclusive. (0 - 100%) + */ + OverpaymentInterestRate?: number + + /** + * The timestamp of when the Loan started Ripple Epoch. + */ + StartDate: number + + /** + * Number of seconds between Loan payments. + */ + PaymentInterval: number + + /** + * The number of seconds after the Payment Due Date that the Loan can be Defaulted. + */ + GracePeriod: number + + /** + * The timestamp of when the previous payment was made in Ripple Epoch. + */ + PreviousPaymentDueDate?: number + + /** + * The timestamp of when the next payment is due in Ripple Epoch. + */ + NextPaymentDueDate: number + + /** + * The number of payments remaining on the Loan. + */ + PaymentRemaining: number + + /** + * The total outstanding value of the Loan, including all fees and interest. + */ + TotalValueOutstanding: XRPLNumber + + /** + * The principal amount requested by the Borrower. + */ + PrincipalOutstanding: XRPLNumber + + /** + * The remaining Management Fee owed to the LoanBroker. + */ + ManagementFeeOutstanding?: XRPLNumber + + /** + * The calculated periodic payment amount for each payment interval. + */ + PeriodicPayment: XRPLNumber + + /** + * The scale factor that ensures all computed amounts are rounded to the same number of decimal places. + * It is determined based on the total loan value at creation time. + */ + LoanScale?: number +} + +export enum LoanFlags { + /** + * If set, indicates that the Loan is defaulted. + */ + lsfLoanDefault = 0x00010000, + + /** + * If set, indicates that the Loan is impaired. + */ + lsfLoanImpaired = 0x00020000, + + /** + * If set, indicates that the Loan supports overpayments. + */ + lsfLoanOverpayment = 0x00040000, +} diff --git a/packages/xrpl/src/models/ledger/LoanBroker.ts b/packages/xrpl/src/models/ledger/LoanBroker.ts new file mode 100644 index 0000000000..b5935adcd7 --- /dev/null +++ b/packages/xrpl/src/models/ledger/LoanBroker.ts @@ -0,0 +1,95 @@ +import { Account, XRPLNumber } from '../transactions/common' + +import { BaseLedgerEntry, HasPreviousTxnID } from './BaseLedgerEntry' + +/** + * The LoanBroker object captures attributes of the Lending Protocol. + * + * @category Ledger Entries + */ +export default interface LoanBroker extends BaseLedgerEntry, HasPreviousTxnID { + LedgerEntryType: 'LoanBroker' + + /** + * Ledger object flags. + */ + Flags: number + + /** + * The transaction sequence number of LoanBrokerSet transaction that created this LoanBroker object. + */ + Sequence: number + + /** + * A sequential identifier for Loan objects, incremented each time a new Loan is created by this LoanBroker instance. + */ + LoanSequence: number + + /** + * Identifies the page where this item is referenced in the owner's directory. + */ + OwnerNode: string + + /** + * Identifies the page where this item is referenced in the Vault's pseudo-account owner's directory. + */ + VaultNode: string + + /** + * The ID of the Vault object associated with this Lending Protocol Instance. + */ + VaultID: string + + /** + * The address of the LoanBroker pseudo-account. + */ + Account: Account + + /** + * The address of the Loan Broker account. + */ + Owner: Account + + /** + * The number of active Loans issued by the LoanBroker. + */ + OwnerCount?: number + + /** + * Arbitrary metadata in hex format. The field is limited to 256 bytes. + */ + Data?: string + + /** + * The 1/10th basis point fee charged by the Lending Protocol. Valid values are between 0 and 10000 inclusive. + * A value of 1 is equivalent to 1/10 bps or 0.001% + */ + ManagementFeeRate?: number + + /** + * The total asset amount the protocol owes the Vault, including interest. + */ + DebtTotal?: XRPLNumber + + /** + * The maximum amount the protocol can owe the Vault. The default value of 0 means there is no limit to the debt. + */ + DebtMaximum: XRPLNumber + + /** + * The total amount of first-loss capital deposited into the Lending Protocol. + */ + CoverAvailable?: XRPLNumber + + /** + * The 1/10th basis point of the DebtTotal that the first loss capital must cover. + * Valid values are between 0 and 100000 inclusive. A value of 1 is equivalent to 1/10 bps or 0.001%. + */ + CoverRateMinimum?: number + + /** + * The 1/10th basis point of minimum required first loss capital that is liquidated to cover a Loan default. + * Valid values are between 0 and 100000 inclusive. A value of 1 is equivalent to 1/10 bps or 0.001%. + */ + CoverRateLiquidation?: number +} diff --git a/packages/xrpl/src/models/ledger/Vault.ts b/packages/xrpl/src/models/ledger/Vault.ts index 4941568cf2..df56f53fb5 100644 --- a/packages/xrpl/src/models/ledger/Vault.ts +++ b/packages/xrpl/src/models/ledger/Vault.ts @@ -19,7 +19,7 @@ export default interface Vault extends BaseLedgerEntry, HasPreviousTxnID { /** * A bit-map of boolean flags. */ - Flags: 0 + Flags: number /** * The transaction sequence number that created the vault. @@ -49,22 +49,22 @@ export default interface Vault extends BaseLedgerEntry, HasPreviousTxnID { /** * The total value of the vault. */ - AssetsTotal: string + AssetsTotal?: string /** * The asset amount that is available in the vault. */ - AssetsAvailable: string + AssetsAvailable?: string /** * The potential loss amount that is not yet realized expressed as the vaults asset. */ - LossUnrealized: string + LossUnrealized?: string /** * The identifier of the share MPTokenIssuance object. */ - MPTokenIssuanceID: string + ShareMPTID: string /** * Indicates the withdrawal strategy used by the Vault. @@ -80,4 +80,17 @@ export default interface Vault extends BaseLedgerEntry, HasPreviousTxnID { * Arbitrary metadata about the Vault. Limited to 256 bytes. */ Data?: string + + /** + * The scaling factor for vault shares. Only applicable for IOU assets. + * Valid values are between 0 and 18 inclusive. For XRP and MPT, this is always 0. + */ + Scale?: number +} + +export enum VaultFlags { + /** + * If set, indicates that the vault is private. + */ + lsfVaultPrivate = 0x00010000, } diff --git a/packages/xrpl/src/models/ledger/index.ts b/packages/xrpl/src/models/ledger/index.ts index 0cf16eed42..3988698576 100644 --- a/packages/xrpl/src/models/ledger/index.ts +++ b/packages/xrpl/src/models/ledger/index.ts @@ -20,6 +20,8 @@ import FeeSettings, { import { Ledger, LedgerV1 } from './Ledger' import { LedgerEntry, LedgerEntryFilter } from './LedgerEntry' import LedgerHashes from './LedgerHashes' +import Loan, { LoanFlags } from './Loan' +import LoanBroker from './LoanBroker' import { MPToken } from './MPToken' import { MPTokenIssuance } from './MPTokenIssuance' import NegativeUNL, { NEGATIVE_UNL_ID } from './NegativeUNL' @@ -31,7 +33,7 @@ import PayChannel from './PayChannel' import RippleState, { RippleStateFlags } from './RippleState' import SignerList, { SignerListFlags } from './SignerList' import Ticket from './Ticket' -import Vault from './Vault' +import Vault, { VaultFlags } from './Vault' import XChainOwnedClaimID from './XChainOwnedClaimID' import XChainOwnedCreateAccountClaimID from './XChainOwnedCreateAccountClaimID' @@ -59,6 +61,9 @@ export { LedgerEntryFilter, LedgerEntry, LedgerHashes, + Loan, + LoanFlags, + LoanBroker, Majority, NEGATIVE_UNL_ID, NegativeUNL, @@ -77,6 +82,7 @@ export { SignerListFlags, Ticket, Vault, + VaultFlags, VoteSlot, XChainOwnedClaimID, XChainOwnedCreateAccountClaimID, diff --git a/packages/xrpl/src/models/methods/vaultInfo.ts b/packages/xrpl/src/models/methods/vaultInfo.ts index 78e82ae083..2ff10a95ad 100644 --- a/packages/xrpl/src/models/methods/vaultInfo.ts +++ b/packages/xrpl/src/models/methods/vaultInfo.ts @@ -48,12 +48,12 @@ export interface VaultInfoResponse extends BaseResponse { /** * Amount of assets currently available for withdrawal. */ - AssetsAvailable: string + AssetsAvailable?: string /** * Total amount of assets in the vault. */ - AssetsTotal: string + AssetsTotal?: string /** * Ledger entry type, always "Vault". @@ -165,6 +165,22 @@ export interface VaultInfoResponse extends BaseResponse { */ WithdrawalPolicy?: number + /** + * The maximum asset amount that can be held in the vault. Zero value indicates there is no cap. + */ + AssetsMaximum?: string + + /** + * Arbitrary metadata about the Vault. Limited to 256 bytes. + */ + Data?: string + + /** + * The scaling factor for vault shares. Only applicable for IOU assets. + * Valid values are between 0 and 18 inclusive. For XRP and MPT, this is always 0. + */ + Scale?: number + /** * Flags */ diff --git a/packages/xrpl/src/models/transactions/MPTokenIssuanceCreate.ts b/packages/xrpl/src/models/transactions/MPTokenIssuanceCreate.ts index b9b753cc08..b17f4394a1 100644 --- a/packages/xrpl/src/models/transactions/MPTokenIssuanceCreate.ts +++ b/packages/xrpl/src/models/transactions/MPTokenIssuanceCreate.ts @@ -1,5 +1,10 @@ import { ValidationError } from '../../errors' import { isHex, INTEGER_SANITY_CHECK, isFlagEnabled } from '../utils' +import { + MAX_MPT_META_BYTE_LENGTH, + MPT_META_WARNING_HEADER, + validateMPTokenMetadata, +} from '../utils/mptokenMetadata' import { BaseTransaction, @@ -8,9 +13,6 @@ import { validateOptionalField, isString, isNumber, - MAX_MPT_META_BYTE_LENGTH, - MPT_META_WARNING_HEADER, - validateMPTokenMetadata, } from './common' import type { TransactionMetadataBase } from './metadata' @@ -109,10 +111,9 @@ export interface MPTokenIssuanceCreate extends BaseTransaction { TransferFee?: number /** - * Optional arbitrary metadata about this issuance, encoded as a hex string and limited to 1024 bytes. - * - * The decoded value must be a UTF-8 encoded JSON object that adheres to the - * XLS-89d MPTokenMetadata standard. + * Should follow {@link https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0089-multi-purpose-token-metadata-schema | XLS-89} standard. + * Use {@link encodeMPTokenMetadata} utility function to convert to convert {@link MPTokenMetadata} to a blob. + * Use {@link decodeMPTokenMetadata} utility function to convert from a blob to {@link MPTokenMetadata}. * * While adherence to the XLS-89d format is not mandatory, non-compliant metadata * may not be discoverable by ecosystem tools such as explorers and indexers. diff --git a/packages/xrpl/src/models/transactions/common.ts b/packages/xrpl/src/models/transactions/common.ts index eaf6b1bd8d..29d9df48b5 100644 --- a/packages/xrpl/src/models/transactions/common.ts +++ b/packages/xrpl/src/models/transactions/common.ts @@ -1,5 +1,5 @@ /* eslint-disable max-lines -- common utility file */ -import { HEX_REGEX, hexToString } from '@transia/isomorphic/utils' +import { HEX_REGEX } from '@transia/isomorphic/utils' import { isValidClassicAddress, isValidXAddress, @@ -15,7 +15,6 @@ import { IssuedCurrency, IssuedCurrencyAmount, MPTAmount, - MPTokenMetadata, Memo, Signer, XChainBridge, @@ -26,50 +25,11 @@ const MEMO_SIZE = 3 export const MAX_AUTHORIZED_CREDENTIALS = 8 const MAX_CREDENTIAL_BYTE_LENGTH = 64 const MAX_CREDENTIAL_TYPE_LENGTH = MAX_CREDENTIAL_BYTE_LENGTH * 2 -export const MAX_MPT_META_BYTE_LENGTH = 1024 +const SHA_512_HALF_LENGTH = 64 // Used for Vault transactions export const VAULT_DATA_MAX_BYTE_LENGTH = 256 -// To validate MPTokenMetadata as per XLS-89d -const TICKER_REGEX = /^[A-Z0-9]{1,6}$/u - -const MAX_MPT_META_TOP_LEVEL_FIELD_COUNT = 9 - -const MPT_META_URL_FIELD_COUNT = 3 - -const MPT_META_REQUIRED_FIELDS = [ - 'ticker', - 'name', - 'icon', - 'asset_class', - 'issuer_name', -] - -const MPT_META_ASSET_CLASSES = [ - 'rwa', - 'memes', - 'wrapped', - 'gaming', - 'defi', - 'other', -] - -const MPT_META_ASSET_SUB_CLASSES = [ - 'stablecoin', - 'commodity', - 'real_estate', - 'private_credit', - 'equity', - 'treasury', - 'other', -] - -export const MPT_META_WARNING_HEADER = - 'MPTokenMetadata is not properly formatted as JSON as per the XLS-89d standard. ' + - "While adherence to this standard is not mandatory, such non-compliant MPToken's might not be discoverable " + - 'by Explorers and Indexers in the XRPL ecosystem.' - function isMemo(obj: unknown): obj is Memo { if (!isRecord(obj)) { return false @@ -118,11 +78,16 @@ function isSigner(obj: unknown): obj is Signer { ) } +// Currency object sizes const XRP_CURRENCY_SIZE = 1 -const ISSUE_SIZE = 2 -const ISSUED_CURRENCY_SIZE = 3 +const MPT_CURRENCY_SIZE = 1 +const ISSUE_CURRENCY_SIZE = 2 + +// Currency Amount object sizes +const MPT_CURRENCY_AMOUNT_SIZE = 2 +const ISSUED_CURRENCY_AMOUNT_SIZE = 3 + const XCHAIN_BRIDGE_SIZE = 4 -const MPTOKEN_SIZE = 2 const AUTHORIZE_CREDENTIAL_SIZE = 1 /** @@ -206,7 +171,16 @@ export function isXRPLNumber(value: unknown): value is XRPLNumber { * @returns Whether the Currency is properly formed. */ export function isCurrency(input: unknown): input is Currency { - return isString(input) || isIssuedCurrency(input) + return ( + isRecord(input) && + ((Object.keys(input).length === ISSUE_CURRENCY_SIZE && + isString(input.issuer) && + isString(input.currency)) || + (Object.keys(input).length === XRP_CURRENCY_SIZE && + input.currency === 'XRP') || + (Object.keys(input).length === MPT_CURRENCY_SIZE && + isString(input.mpt_issuance_id))) + ) } /** @@ -218,7 +192,7 @@ export function isCurrency(input: unknown): input is Currency { export function isIssuedCurrency(input: unknown): input is IssuedCurrency { return ( isRecord(input) && - ((Object.keys(input).length === ISSUE_SIZE && + ((Object.keys(input).length === ISSUE_CURRENCY_SIZE && isString(input.issuer) && isString(input.currency)) || (Object.keys(input).length === XRP_CURRENCY_SIZE && @@ -237,7 +211,7 @@ export function isIssuedCurrencyAmount( ): input is IssuedCurrencyAmount { return ( isRecord(input) && - Object.keys(input).length === ISSUED_CURRENCY_SIZE && + Object.keys(input).length === ISSUED_CURRENCY_AMOUNT_SIZE && isString(input.value) && isString(input.issuer) && isString(input.currency) @@ -271,7 +245,7 @@ export function isAuthorizeCredential( export function isMPTAmount(input: unknown): input is MPTAmount { return ( isRecord(input) && - Object.keys(input).length === MPTOKEN_SIZE && + Object.keys(input).length === MPT_CURRENCY_AMOUNT_SIZE && typeof input.value === 'string' && typeof input.mpt_issuance_id === 'string' ) @@ -331,6 +305,18 @@ export function isAmount(amount: unknown): amount is Amount { ) } +/** + * Verify the form and type of IOU/MPT token amount at runtime. + * + * @param amount - The object to check the form and type of. + * @returns Whether the Amount is properly formed. + */ +export function isTokenAmount( + amount: unknown, +): amount is IssuedCurrencyAmount | MPTAmount { + return isIssuedCurrencyAmount(amount) || isMPTAmount(amount) +} + /** * Verify the form and type of an XChainBridge at runtime. * @@ -358,6 +344,35 @@ export function isArray(input: unknown): input is T[] { return input != null && Array.isArray(input) } +/** + * Verify the input is a valid ledger entry id. + * + * @param input - The object to validate. + * @returns Whether the input is a valid ledger entry id. + */ +export function isLedgerEntryId(input: unknown): input is string { + return isString(input) && isHex(input) && input.length === SHA_512_HALF_LENGTH +} + +/** + * Validate input is non-empty hex string of up to a certain length. + * + * @param input - The metadata to validate. + * @param lengthUpto - The maximum length of the hex string. + * @returns Whether the input is a valid non-empty hex string up to the specified length. + */ +export function validateHexMetadata( + input: unknown, + lengthUpto: number, +): input is string { + return ( + isString(input) && + isHex(input) && + input.length > 0 && + input.length <= lengthUpto + ) +} + /* eslint-disable @typescript-eslint/restrict-template-expressions -- tx.TransactionType is checked before any calls */ /** @@ -767,183 +782,6 @@ export function isDomainID(domainID: unknown): domainID is string { ) } -/* eslint-disable max-lines-per-function -- Required here as structure validation is verbose. */ -/* eslint-disable max-statements -- Required here as structure validation is verbose. */ - -/** - * Validates if MPTokenMetadata adheres to XLS-89d standard. - * - * @param input - Hex encoded MPTokenMetadata. - * @returns Validation messages if MPTokenMetadata does not adheres to XLS-89d standard. - */ -export function validateMPTokenMetadata(input: string): string[] { - const validationMessages: string[] = [] - - if (!isHex(input)) { - validationMessages.push(`MPTokenMetadata must be in hex format.`) - return validationMessages - } - - if (input.length / 2 > MAX_MPT_META_BYTE_LENGTH) { - validationMessages.push( - `MPTokenMetadata must be max ${MAX_MPT_META_BYTE_LENGTH} bytes.`, - ) - return validationMessages - } - - let jsonMetaData: unknown - - try { - jsonMetaData = JSON.parse(hexToString(input)) - } catch (err) { - validationMessages.push( - `MPTokenMetadata is not properly formatted as JSON - ${String(err)}`, - ) - return validationMessages - } - - if ( - jsonMetaData == null || - typeof jsonMetaData !== 'object' || - Array.isArray(jsonMetaData) - ) { - validationMessages.push( - 'MPTokenMetadata is not properly formatted as per XLS-89d.', - ) - return validationMessages - } - - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- It must be some JSON object. - const obj = jsonMetaData as Record - - // validating structure - - // check for maximum number of fields - const fieldCount = Object.keys(obj).length - if (fieldCount > MAX_MPT_META_TOP_LEVEL_FIELD_COUNT) { - validationMessages.push( - `MPTokenMetadata must not contain more than ${MAX_MPT_META_TOP_LEVEL_FIELD_COUNT} top-level fields (found ${fieldCount}).`, - ) - return validationMessages - } - - const incorrectRequiredFields = MPT_META_REQUIRED_FIELDS.filter( - (field) => !isString(obj[field]), - ) - - if (incorrectRequiredFields.length > 0) { - incorrectRequiredFields.forEach((field) => - validationMessages.push(`${field} is required and must be string.`), - ) - return validationMessages - } - - if (obj.desc != null && !isString(obj.desc)) { - validationMessages.push(`desc must be a string.`) - return validationMessages - } - - if (obj.asset_subclass != null && !isString(obj.asset_subclass)) { - validationMessages.push(`asset_subclass must be a string.`) - return validationMessages - } - - if ( - obj.additional_info != null && - !isString(obj.additional_info) && - !isRecord(obj.additional_info) - ) { - validationMessages.push(`additional_info must be a string or JSON object.`) - return validationMessages - } - - if (obj.urls != null) { - if (!Array.isArray(obj.urls)) { - validationMessages.push('urls must be an array as per XLS-89d.') - return validationMessages - } - if (!obj.urls.every(isValidMPTokenMetadataUrlStructure)) { - validationMessages.push( - 'One or more urls are not structured per XLS-89d.', - ) - return validationMessages - } - } - - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Required here. - const mptMPTokenMetadata = obj as unknown as MPTokenMetadata - - // validating content - if (!TICKER_REGEX.test(mptMPTokenMetadata.ticker)) { - validationMessages.push( - `ticker should have uppercase letters (A-Z) and digits (0-9) only. Max 6 characters recommended.`, - ) - } - - if (!mptMPTokenMetadata.icon.startsWith('https://')) { - validationMessages.push(`icon should be a valid https url.`) - } - - if ( - !MPT_META_ASSET_CLASSES.includes( - mptMPTokenMetadata.asset_class.toLowerCase(), - ) - ) { - validationMessages.push( - `asset_class should be one of ${MPT_META_ASSET_CLASSES.join(', ')}.`, - ) - } - - if ( - mptMPTokenMetadata.asset_subclass != null && - !MPT_META_ASSET_SUB_CLASSES.includes( - mptMPTokenMetadata.asset_subclass.toLowerCase(), - ) - ) { - validationMessages.push( - `asset_subclass should be one of ${MPT_META_ASSET_SUB_CLASSES.join( - ', ', - )}.`, - ) - } - - if ( - mptMPTokenMetadata.asset_class.toLowerCase() === 'rwa' && - mptMPTokenMetadata.asset_subclass == null - ) { - validationMessages.push( - `asset_subclass is required when asset_class is rwa.`, - ) - } - - if ( - mptMPTokenMetadata.urls != null && - !mptMPTokenMetadata.urls.every((ele) => ele.url.startsWith('https://')) - ) { - validationMessages.push(`url should be a valid https url.`) - } - - return validationMessages -} -/* eslint-enable max-lines-per-function */ -/* eslint-enable max-statements */ - -function isValidMPTokenMetadataUrlStructure(input: unknown): boolean { - if (input == null) { - return false - } - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Required here. - const obj = input as Record - - return ( - typeof obj === 'object' && - isString(obj.url) && - isString(obj.type) && - isString(obj.title) && - Object.keys(obj).length === MPT_META_URL_FIELD_COUNT - ) -} - /** * Enum representing values of {@link ContractParameter} transaction flags. * diff --git a/packages/xrpl/src/models/transactions/index.ts b/packages/xrpl/src/models/transactions/index.ts index 34ced61aa9..a61071f187 100644 --- a/packages/xrpl/src/models/transactions/index.ts +++ b/packages/xrpl/src/models/transactions/index.ts @@ -1,4 +1,9 @@ -export { BaseTransaction, isMPTAmount, validateMPTokenMetadata } from './common' +export { + BaseTransaction, + GlobalFlags, + GlobalFlagsInterface, + isMPTAmount, +} from './common' export { validate, PseudoTransaction, @@ -33,7 +38,7 @@ export { AMMWithdrawFlagsInterface, AMMWithdraw, } from './AMMWithdraw' -export { Batch } from './batch' +export { Batch, BatchFlags, BatchFlagsInterface, BatchSigner } from './batch' export { CheckCancel } from './checkCancel' export { CheckCash } from './checkCash' export { CheckCreate } from './checkCreate' @@ -59,6 +64,19 @@ export { EscrowCancel } from './escrowCancel' export { EscrowCreate } from './escrowCreate' export { EscrowFinish } from './escrowFinish' export { EnableAmendment, EnableAmendmentFlags } from './enableAmendment' +export { LoanBrokerSet } from './loanBrokerSet' +export { LoanBrokerDelete } from './loanBrokerDelete' +export { LoanBrokerCoverDeposit } from './loanBrokerCoverDeposit' +export { LoanBrokerCoverWithdraw } from './loanBrokerCoverWithdraw' +export { LoanBrokerCoverClawback } from './loanBrokerCoverClawback' +export { LoanSet, LoanSetFlags, LoanSetFlagsInterface } from './loanSet' +export { LoanDelete } from './loanDelete' +export { + LoanManage, + LoanManageFlags, + LoanManageFlagsInterface, +} from './loanManage' +export { LoanPay, LoanPayFlags, LoanPayFlagsInterface } from './loanPay' export { MPTokenAuthorize, MPTokenAuthorizeFlags, diff --git a/packages/xrpl/src/models/transactions/loanBrokerCoverClawback.ts b/packages/xrpl/src/models/transactions/loanBrokerCoverClawback.ts new file mode 100644 index 0000000000..b7d1d18b2f --- /dev/null +++ b/packages/xrpl/src/models/transactions/loanBrokerCoverClawback.ts @@ -0,0 +1,68 @@ +import BigNumber from 'bignumber.js' + +import { ValidationError } from '../../errors' +import { IssuedCurrencyAmount, MPTAmount } from '../common' + +import { + BaseTransaction, + isLedgerEntryId, + validateBaseTransaction, + isString, + validateOptionalField, + isTokenAmount, +} from './common' + +/** + * The LoanBrokerCoverClawback transaction claws back the First-Loss Capital from the Loan Broker. + * The transaction can only be submitted by the Issuer of the Loan asset. + * Furthermore, the transaction can only clawback funds up to the minimum cover required for the current loans. + * + * @category Transaction Models + */ +export interface LoanBrokerCoverClawback extends BaseTransaction { + TransactionType: 'LoanBrokerCoverClawback' + + /** + * The Loan Broker ID from which to withdraw First-Loss Capital. + * Must be provided if the Amount is an MPT, or Amount is an IOU + * and issuer is specified as the Account submitting the transaction. + */ + LoanBrokerID?: string + + /** + * The First-Loss Capital amount to clawback. + * If the amount is 0 or not provided, clawback funds up to LoanBroker.DebtTotal * LoanBroker.CoverRateMinimum. + */ + Amount?: IssuedCurrencyAmount | MPTAmount +} + +/** + * Verify the form and type of an LoanBrokerCoverClawback at runtime. + * + * @param tx - LoanBrokerCoverClawback Transaction. + * @throws When LoanBrokerCoverClawback is Malformed. + */ +export function validateLoanBrokerCoverClawback( + tx: Record, +): void { + validateBaseTransaction(tx) + + validateOptionalField(tx, 'LoanBrokerID', isString) + validateOptionalField(tx, 'Amount', isTokenAmount) + + if (tx.LoanBrokerID != null && !isLedgerEntryId(tx.LoanBrokerID)) { + throw new ValidationError( + `LoanBrokerCoverClawback: LoanBrokerID must be 64 characters hexadecimal string`, + ) + } + + if (tx.Amount != null && new BigNumber(tx.Amount.value).isLessThan(0)) { + throw new ValidationError(`LoanBrokerCoverClawback: Amount must be >= 0`) + } + + if (tx.LoanBrokerID == null && tx.Amount == null) { + throw new ValidationError( + `LoanBrokerCoverClawback: Either LoanBrokerID or Amount is required`, + ) + } +} diff --git a/packages/xrpl/src/models/transactions/loanBrokerCoverDeposit.ts b/packages/xrpl/src/models/transactions/loanBrokerCoverDeposit.ts new file mode 100644 index 0000000000..02800dc843 --- /dev/null +++ b/packages/xrpl/src/models/transactions/loanBrokerCoverDeposit.ts @@ -0,0 +1,51 @@ +import { ValidationError } from '../../errors' +import { Amount, MPTAmount } from '../common' + +import { + BaseTransaction, + isLedgerEntryId, + validateBaseTransaction, + isString, + validateRequiredField, + isAmount, +} from './common' + +/** + * The transaction deposits First Loss Capital into the LoanBroker object. + * + * @category Transaction Models + */ +export interface LoanBrokerCoverDeposit extends BaseTransaction { + TransactionType: 'LoanBrokerCoverDeposit' + + /** + * The Loan Broker ID to deposit First-Loss Capital. + */ + LoanBrokerID: string + + /** + * The First-Loss Capital amount to deposit. + */ + Amount: Amount | MPTAmount +} + +/** + * Verify the form and type of an LoanBrokerCoverDeposit at runtime. + * + * @param tx - LoanBrokerCoverDeposit Transaction. + * @throws When LoanBrokerCoverDeposit is Malformed. + */ +export function validateLoanBrokerCoverDeposit( + tx: Record, +): void { + validateBaseTransaction(tx) + + validateRequiredField(tx, 'LoanBrokerID', isString) + validateRequiredField(tx, 'Amount', isAmount) + + if (!isLedgerEntryId(tx.LoanBrokerID)) { + throw new ValidationError( + `LoanBrokerCoverDeposit: LoanBrokerID must be 64 characters hexadecimal string`, + ) + } +} diff --git a/packages/xrpl/src/models/transactions/loanBrokerCoverWithdraw.ts b/packages/xrpl/src/models/transactions/loanBrokerCoverWithdraw.ts new file mode 100644 index 0000000000..acb413670f --- /dev/null +++ b/packages/xrpl/src/models/transactions/loanBrokerCoverWithdraw.ts @@ -0,0 +1,67 @@ +import { ValidationError } from '../../errors' +import { Amount, MPTAmount } from '../common' + +import { + BaseTransaction, + isLedgerEntryId, + validateBaseTransaction, + isString, + validateRequiredField, + isAmount, + Account, + validateOptionalField, + isAccount, + isNumber, +} from './common' + +/** + * The LoanBrokerCoverWithdraw transaction withdraws the First-Loss Capital from the LoanBroker. + * + * @category Transaction Models + */ +export interface LoanBrokerCoverWithdraw extends BaseTransaction { + TransactionType: 'LoanBrokerCoverWithdraw' + + /** + * The Loan Broker ID from which to withdraw First-Loss Capital. + */ + LoanBrokerID: string + + /** + * The First-Loss Capital amount to withdraw. + */ + Amount: Amount | MPTAmount + + /** + * An account to receive the assets. It must be able to receive the asset. + */ + Destination?: Account + + /** + * Arbitrary tag identifying the reason for the withdrawal to the destination. + */ + DestinationTag?: number +} + +/** + * Verify the form and type of an LoanBrokerCoverWithdraw at runtime. + * + * @param tx - LoanBrokerCoverWithdraw Transaction. + * @throws When LoanBrokerCoverWithdraw is Malformed. + */ +export function validateLoanBrokerCoverWithdraw( + tx: Record, +): void { + validateBaseTransaction(tx) + + validateRequiredField(tx, 'LoanBrokerID', isString) + validateRequiredField(tx, 'Amount', isAmount) + validateOptionalField(tx, 'Destination', isAccount) + validateOptionalField(tx, 'DestinationTag', isNumber) + + if (!isLedgerEntryId(tx.LoanBrokerID)) { + throw new ValidationError( + `LoanBrokerCoverWithdraw: LoanBrokerID must be 64 characters hexadecimal string`, + ) + } +} diff --git a/packages/xrpl/src/models/transactions/loanBrokerDelete.ts b/packages/xrpl/src/models/transactions/loanBrokerDelete.ts new file mode 100644 index 0000000000..d93387e7ae --- /dev/null +++ b/packages/xrpl/src/models/transactions/loanBrokerDelete.ts @@ -0,0 +1,41 @@ +import { ValidationError } from '../../errors' + +import { + BaseTransaction, + isLedgerEntryId, + validateBaseTransaction, + isString, + validateRequiredField, +} from './common' + +/** + * The transaction deletes LoanBroker ledger object. + * + * @category Transaction Models + */ +export interface LoanBrokerDelete extends BaseTransaction { + TransactionType: 'LoanBrokerDelete' + + /** + * The Loan Broker ID that the transaction is deleting. + */ + LoanBrokerID: string +} + +/** + * Verify the form and type of an LoanBrokerDelete at runtime. + * + * @param tx - LoanBrokerDelete Transaction. + * @throws When LoanBrokerDelete is Malformed. + */ +export function validateLoanBrokerDelete(tx: Record): void { + validateBaseTransaction(tx) + + validateRequiredField(tx, 'LoanBrokerID', isString) + + if (!isLedgerEntryId(tx.LoanBrokerID)) { + throw new ValidationError( + `LoanBrokerDelete: LoanBrokerID must be 64 characters hexadecimal string`, + ) + } +} diff --git a/packages/xrpl/src/models/transactions/loanBrokerSet.ts b/packages/xrpl/src/models/transactions/loanBrokerSet.ts new file mode 100644 index 0000000000..173684bc1e --- /dev/null +++ b/packages/xrpl/src/models/transactions/loanBrokerSet.ts @@ -0,0 +1,152 @@ +import BigNumber from 'bignumber.js' + +import { ValidationError } from '../../errors' + +import { + BaseTransaction, + validateHexMetadata, + isLedgerEntryId, + isNumber, + isXRPLNumber, + validateBaseTransaction, + validateOptionalField, + isString, + validateRequiredField, + XRPLNumber, +} from './common' + +const MAX_DATA_LENGTH = 512 +const MAX_MANAGEMENT_FEE_RATE = 10000 +const MAX_COVER_RATE_MINIMUM = 100000 +const MAX_COVER_RATE_LIQUIDATION = 100000 + +/** + * The transaction creates a new LoanBroker object or updates an existing one. + * + * @category Transaction Models + */ +export interface LoanBrokerSet extends BaseTransaction { + TransactionType: 'LoanBrokerSet' + + /** + * The Vault ID that the Lending Protocol will use to access liquidity. + */ + VaultID: string + + /** + * The Loan Broker ID that the transaction is modifying. + */ + LoanBrokerID?: string + + /** + * Arbitrary metadata in hex format. The field is limited to 512 characters. + */ + Data?: string + + /** + * The 1/10th basis point fee charged by the Lending Protocol Owner. Valid values are between 0 and 10000 inclusive (1% - 10%). + */ + ManagementFeeRate?: number + + /** + * The maximum amount the protocol can owe the Vault. + * The default value of 0 means there is no limit to the debt. Must not be negative. + */ + DebtMaximum?: XRPLNumber + + /** + * The 1/10th basis point DebtTotal that the first loss capital must cover. Valid values are between 0 and 100000 inclusive. + */ + CoverRateMinimum?: number + + /** + * The 1/10th basis point of minimum required first loss capital liquidated to cover a Loan default. + * Valid values are between 0 and 100000 inclusive. + */ + CoverRateLiquidation?: number +} + +/** + * Verify the form and type of an LoanBrokerSet at runtime. + * + * @param tx - LoanBrokerSet Transaction. + * @throws When LoanBrokerSet is Malformed. + */ +// eslint-disable-next-line max-statements, max-lines-per-function -- due to exhaustive validations +export function validateLoanBrokerSet(tx: Record): void { + validateBaseTransaction(tx) + + validateRequiredField(tx, 'VaultID', isString) + validateOptionalField(tx, 'LoanBrokerID', isString) + validateOptionalField(tx, 'Data', isString) + validateOptionalField(tx, 'ManagementFeeRate', isNumber) + validateOptionalField(tx, 'DebtMaximum', isXRPLNumber) + validateOptionalField(tx, 'CoverRateMinimum', isNumber) + validateOptionalField(tx, 'CoverRateLiquidation', isNumber) + + if (!isLedgerEntryId(tx.VaultID)) { + throw new ValidationError( + `LoanBrokerSet: VaultID must be 64 characters hexadecimal string`, + ) + } + + if (tx.LoanBrokerID != null && !isLedgerEntryId(tx.LoanBrokerID)) { + throw new ValidationError( + `LoanBrokerSet: LoanBrokerID must be 64 characters hexadecimal string`, + ) + } + + if (tx.Data != null && !validateHexMetadata(tx.Data, MAX_DATA_LENGTH)) { + throw new ValidationError( + `LoanBrokerSet: Data must be a valid non-empty hex string up to ${MAX_DATA_LENGTH} characters`, + ) + } + + if ( + tx.ManagementFeeRate != null && + (tx.ManagementFeeRate < 0 || tx.ManagementFeeRate > MAX_MANAGEMENT_FEE_RATE) + ) { + throw new ValidationError( + `LoanBrokerSet: ManagementFeeRate must be between 0 and ${MAX_MANAGEMENT_FEE_RATE} inclusive`, + ) + } + + if (tx.DebtMaximum != null && new BigNumber(tx.DebtMaximum).isLessThan(0)) { + throw new ValidationError( + 'LoanBrokerSet: DebtMaximum must be a non-negative value', + ) + } + + if ( + tx.CoverRateMinimum != null && + (tx.CoverRateMinimum < 0 || tx.CoverRateMinimum > MAX_COVER_RATE_MINIMUM) + ) { + throw new ValidationError( + `LoanBrokerSet: CoverRateMinimum must be between 0 and ${MAX_COVER_RATE_MINIMUM} inclusive`, + ) + } + + if ( + tx.CoverRateLiquidation != null && + (tx.CoverRateLiquidation < 0 || + tx.CoverRateLiquidation > MAX_COVER_RATE_LIQUIDATION) + ) { + throw new ValidationError( + `LoanBrokerSet: CoverRateLiquidation must be between 0 and ${MAX_COVER_RATE_LIQUIDATION} inclusive`, + ) + } + + // Validate that either both CoverRateMinimum and CoverRateLiquidation are zero, + // or both are non-zero. + const coverRateMinimumValue = tx.CoverRateMinimum ?? 0 + const coverRateLiquidationValue = tx.CoverRateLiquidation ?? 0 + + if ( + (coverRateMinimumValue === 0 && coverRateLiquidationValue !== 0) || + (coverRateMinimumValue !== 0 && coverRateLiquidationValue === 0) + ) { + throw new ValidationError( + 'LoanBrokerSet: CoverRateMinimum and CoverRateLiquidation must both be zero or both be non-zero', + ) + } +} diff --git a/packages/xrpl/src/models/transactions/loanDelete.ts b/packages/xrpl/src/models/transactions/loanDelete.ts new file mode 100644 index 0000000000..7d8b9274d4 --- /dev/null +++ b/packages/xrpl/src/models/transactions/loanDelete.ts @@ -0,0 +1,41 @@ +import { ValidationError } from '../../errors' + +import { + BaseTransaction, + isLedgerEntryId, + validateBaseTransaction, + isString, + validateRequiredField, +} from './common' + +/** + * The transaction deletes an existing Loan object. + * + * @category Transaction Models + */ +export interface LoanDelete extends BaseTransaction { + TransactionType: 'LoanDelete' + + /** + * The ID of the Loan object to be deleted. + */ + LoanID: string +} + +/** + * Verify the form and type of an LoanDelete at runtime. + * + * @param tx - LoanDelete Transaction. + * @throws When LoanDelete is Malformed. + */ +export function validateLoanDelete(tx: Record): void { + validateBaseTransaction(tx) + + validateRequiredField(tx, 'LoanID', isString) + + if (!isLedgerEntryId(tx.LoanID)) { + throw new ValidationError( + `LoanDelete: LoanID must be 64 characters hexadecimal string`, + ) + } +} diff --git a/packages/xrpl/src/models/transactions/loanManage.ts b/packages/xrpl/src/models/transactions/loanManage.ts new file mode 100644 index 0000000000..f8059a3bb7 --- /dev/null +++ b/packages/xrpl/src/models/transactions/loanManage.ts @@ -0,0 +1,106 @@ +/* eslint-disable no-bitwise -- required to check flags */ +import { ValidationError } from '../../errors' + +import { + BaseTransaction, + isLedgerEntryId, + validateBaseTransaction, + isString, + validateRequiredField, + GlobalFlagsInterface, +} from './common' + +/** + * The transaction modifies an existing Loan object. + * + * @category Transaction Models + */ +export interface LoanManage extends BaseTransaction { + TransactionType: 'LoanManage' + + /** + * The ID of the Loan object to be updated. + */ + LoanID: string + + Flags?: number | LoanManageFlagsInterface +} + +/** + * Transaction Flags for an LoanManage Transaction. + * + * @category Transaction Flags + */ +export enum LoanManageFlags { + /** + * Indicates that the Loan should be defaulted. + */ + tfLoanDefault = 0x00010000, + + /** + * Indicates that the Loan should be impaired. + */ + tfLoanImpair = 0x00020000, + + /** + * Indicates that the Loan should be un-impaired. + */ + tfLoanUnimpair = 0x00040000, +} + +/** + * Map of flags to boolean values representing {@link LoanManage} transaction + * flags. + * + * @category Transaction Flags + */ +export interface LoanManageFlagsInterface extends GlobalFlagsInterface { + tfLoanDefault?: boolean + tfLoanImpair?: boolean + tfLoanUnimpair?: boolean +} + +/** + * Verify the form and type of an LoanManage at runtime. + * + * @param tx - LoanManage Transaction. + * @throws When LoanManage is Malformed. + */ +export function validateLoanManage(tx: Record): void { + validateBaseTransaction(tx) + + validateRequiredField(tx, 'LoanID', isString) + + if (!isLedgerEntryId(tx.LoanID)) { + throw new ValidationError( + `LoanManage: LoanID must be 64 characters hexadecimal string`, + ) + } + + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- for LoanManage it should be among these two + const txFlags = (tx as { Flags?: number | LoanManageFlagsInterface }).Flags + if (txFlags == null) { + return + } + + let flags = 0 + if (typeof txFlags === 'number') { + flags = txFlags + } else { + if (txFlags.tfLoanImpair) { + flags |= LoanManageFlags.tfLoanImpair + } + if (txFlags.tfLoanUnimpair) { + flags |= LoanManageFlags.tfLoanUnimpair + } + } + + if ( + (flags & LoanManageFlags.tfLoanImpair) === LoanManageFlags.tfLoanImpair && + (flags & LoanManageFlags.tfLoanUnimpair) === LoanManageFlags.tfLoanUnimpair + ) { + throw new ValidationError( + 'LoanManage: tfLoanImpair and tfLoanUnimpair cannot both be present', + ) + } +} diff --git a/packages/xrpl/src/models/transactions/loanPay.ts b/packages/xrpl/src/models/transactions/loanPay.ts new file mode 100644 index 0000000000..4f67ae536a --- /dev/null +++ b/packages/xrpl/src/models/transactions/loanPay.ts @@ -0,0 +1,114 @@ +import { ValidationError } from '../../errors' +import { Amount, MPTAmount } from '../common' +import { isFlagEnabled } from '../utils' + +import { + BaseTransaction, + isLedgerEntryId, + validateBaseTransaction, + isString, + validateRequiredField, + isAmount, + GlobalFlagsInterface, +} from './common' + +/** + * Enum representing values of {@link LoanPay} transaction flags. + * + * @category Transaction Flags + */ +export enum LoanPayFlags { + /** + * Indicates that remaining payment amount should be treated as an overpayment. + */ + tfLoanOverpayment = 0x00010000, + /** + * Indicates that the borrower is making a full early repayment. + */ + tfLoanFullPayment = 0x00020000, + /** + * Indicates that the borrower is making a late loan payment. + */ + tfLoanLatePayment = 0x00040000, +} + +/** + * Map of flags to boolean values representing {@link LoanPay} transaction + * flags. + * + * @category Transaction Flags + */ +export interface LoanPayFlagsInterface extends GlobalFlagsInterface { + tfLoanOverpayment?: boolean + tfLoanFullPayment?: boolean + tfLoanLatePayment?: boolean +} + +/** + * The Borrower submits a LoanPay transaction to make a Payment on the Loan. + * + * @category Transaction Models + */ +export interface LoanPay extends BaseTransaction { + TransactionType: 'LoanPay' + + /** + * The ID of the Loan object to be paid to. + */ + LoanID: string + + /** + * The amount of funds to pay. + */ + Amount: Amount | MPTAmount + + Flags?: number | LoanPayFlagsInterface +} + +/** + * Verify the form and type of an LoanPay at runtime. + * + * @param tx - LoanPay Transaction. + * @throws When LoanPay is Malformed. + */ +export function validateLoanPay(tx: Record): void { + validateBaseTransaction(tx) + + validateRequiredField(tx, 'LoanID', isString) + validateRequiredField(tx, 'Amount', isAmount) + + if (!isLedgerEntryId(tx.LoanID)) { + throw new ValidationError( + `LoanPay: LoanID must be 64 characters hexadecimal string`, + ) + } + + // Validate that at most one of the payment type flags is set + if (typeof tx.Flags === 'number') { + const flagsSet = [ + isFlagEnabled(tx.Flags, LoanPayFlags.tfLoanLatePayment), + isFlagEnabled(tx.Flags, LoanPayFlags.tfLoanFullPayment), + isFlagEnabled(tx.Flags, LoanPayFlags.tfLoanOverpayment), + ].filter(Boolean).length + + if (flagsSet > 1) { + throw new ValidationError( + 'LoanPay: Only one of tfLoanLatePayment, tfLoanFullPayment, or tfLoanOverpayment flags can be set', + ) + } + } else if (tx.Flags != null && typeof tx.Flags === 'object') { + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- required to check flag values + const flags = tx.Flags as unknown as Record + const flagsSet = [ + flags.tfLoanLatePayment, + flags.tfLoanFullPayment, + flags.tfLoanOverpayment, + ].filter(Boolean).length + + if (flagsSet > 1) { + throw new ValidationError( + 'LoanPay: Only one of tfLoanLatePayment, tfLoanFullPayment, or tfLoanOverpayment flags can be set', + ) + } + } +} diff --git a/packages/xrpl/src/models/transactions/loanSet.ts b/packages/xrpl/src/models/transactions/loanSet.ts new file mode 100644 index 0000000000..8f09dd6f3a --- /dev/null +++ b/packages/xrpl/src/models/transactions/loanSet.ts @@ -0,0 +1,270 @@ +import { ValidationError } from '../../errors' +import { Signer } from '../common' + +import { + BaseTransaction, + validateHexMetadata, + isLedgerEntryId, + isNumber, + isXRPLNumber, + validateBaseTransaction, + validateOptionalField, + isString, + validateRequiredField, + XRPLNumber, + GlobalFlagsInterface, + Account, + isAccount, + isRecord, +} from './common' + +const MAX_DATA_LENGTH = 512 +const MAX_OVER_PAYMENT_FEE_RATE = 100_000 +const MAX_INTEREST_RATE = 100_000 +const MAX_LATE_INTEREST_RATE = 100_000 +const MAX_CLOSE_INTEREST_RATE = 100_000 +const MAX_OVER_PAYMENT_INTEREST_RATE = 100_000 +const MIN_PAYMENT_INTERVAL = 60 + +/** + * The transaction creates a new Loan object. + * + * @category Transaction Models + */ +export interface LoanSet extends BaseTransaction { + TransactionType: 'LoanSet' + + /** + * The Loan Broker ID associated with the loan. + */ + LoanBrokerID: string + + /** + * The principal amount requested by the Borrower. + */ + PrincipalRequested: XRPLNumber + + /** + * The signature of the counterparty over the transaction. + */ + CounterpartySignature?: CounterpartySignature + + /** + * The address of the counterparty of the Loan. + */ + Counterparty?: Account + + /** + * Arbitrary metadata in hex format. The field is limited to 512 characters. + */ + Data?: string + + /** + * A nominal funds amount paid to the LoanBroker.Owner when the Loan is created. + */ + LoanOriginationFee?: XRPLNumber + + /** + * A nominal amount paid to the LoanBroker.Owner with every Loan payment. + */ + LoanServiceFee?: XRPLNumber + + /** + * A nominal funds amount paid to the LoanBroker.Owner when a payment is late. + */ + LatePaymentFee?: XRPLNumber + + /** + * A nominal funds amount paid to the LoanBroker.Owner when an early full repayment is made. + */ + ClosePaymentFee?: XRPLNumber + + /** + * A fee charged on overpayments in 1/10th basis points. Valid values are between 0 and 100000 inclusive. (0 - 100%) + */ + OverpaymentFee?: number + + /** + * Annualized interest rate of the Loan in in 1/10th basis points. Valid values are between 0 and 100000 inclusive. (0 - 100%) + */ + InterestRate?: number + + /** + * A premium added to the interest rate for late payments in in 1/10th basis points. + * Valid values are between 0 and 100000 inclusive. (0 - 100%) + */ + LateInterestRate?: number + + /** + * A Fee Rate charged for repaying the Loan early in 1/10th basis points. + * Valid values are between 0 and 100000 inclusive. (0 - 100%) + */ + CloseInterestRate?: number + + /** + * An interest rate charged on over payments in 1/10th basis points. Valid values are between 0 and 100000 inclusive. (0 - 100%) + */ + OverpaymentInterestRate?: number + + /** + * The total number of payments to be made against the Loan. + */ + PaymentTotal?: number + + /** + * Number of seconds between Loan payments. + */ + PaymentInterval?: number + + /** + * The number of seconds after the Loan's Payment Due Date can be Defaulted. + */ + GracePeriod?: number + + Flags?: number | LoanSetFlagsInterface +} + +/** + * An inner object that contains the signature of the Lender over the transaction. + */ +export interface CounterpartySignature { + /** + * The Public Key to be used to verify the validity of the signature. + */ + SigningPubKey?: string + + /** + * The signature of over all signing fields. + */ + TxnSignature?: string + + /** + * An array of transaction signatures from the Counterparty signers to indicate their approval of this transaction. + */ + Signers?: Signer[] +} + +/** + * Transaction Flags for an LoanSet Transaction. + * + * @category Transaction Flags + */ +export enum LoanSetFlags { + /** + * Indicates that the loan supports over payments. + */ + tfLoanOverpayment = 0x00010000, +} + +/** + * Map of flags to boolean values representing {@link LoanSet} transaction + * flags. + * + * @category Transaction Flags + */ +export interface LoanSetFlagsInterface extends GlobalFlagsInterface { + tfLoanOverpayment?: boolean +} + +/** + * Verify the form and type of an LoanSet at runtime. + * + * @param tx - LoanSet Transaction. + * @throws When LoanSet is Malformed. + */ +// eslint-disable-next-line max-lines-per-function, max-statements -- due to many validations +export function validateLoanSet(tx: Record): void { + validateBaseTransaction(tx) + + validateRequiredField(tx, 'LoanBrokerID', isString) + validateRequiredField(tx, 'PrincipalRequested', isXRPLNumber) + validateOptionalField(tx, 'CounterpartySignature', isRecord) + validateOptionalField(tx, 'Data', isString) + validateOptionalField(tx, 'Counterparty', isAccount) + validateOptionalField(tx, 'LoanOriginationFee', isXRPLNumber) + validateOptionalField(tx, 'LoanServiceFee', isXRPLNumber) + validateOptionalField(tx, 'LatePaymentFee', isXRPLNumber) + validateOptionalField(tx, 'ClosePaymentFee', isXRPLNumber) + validateOptionalField(tx, 'OverpaymentFee', isNumber) + validateOptionalField(tx, 'InterestRate', isNumber) + validateOptionalField(tx, 'LateInterestRate', isNumber) + validateOptionalField(tx, 'CloseInterestRate', isNumber) + validateOptionalField(tx, 'OverpaymentInterestRate', isNumber) + validateOptionalField(tx, 'PaymentTotal', isNumber) + validateOptionalField(tx, 'PaymentInterval', isNumber) + validateOptionalField(tx, 'GracePeriod', isNumber) + + if (!isLedgerEntryId(tx.LoanBrokerID)) { + throw new ValidationError( + `LoanSet: LoanBrokerID must be 64 characters hexadecimal string`, + ) + } + + if (tx.Data != null && !validateHexMetadata(tx.Data, MAX_DATA_LENGTH)) { + throw new ValidationError( + `LoanSet: Data must be a valid non-empty hex string up to ${MAX_DATA_LENGTH} characters`, + ) + } + + if ( + tx.OverpaymentFee != null && + (tx.OverpaymentFee < 0 || tx.OverpaymentFee > MAX_OVER_PAYMENT_FEE_RATE) + ) { + throw new ValidationError( + `LoanSet: OverpaymentFee must be between 0 and ${MAX_OVER_PAYMENT_FEE_RATE} inclusive`, + ) + } + + if ( + tx.InterestRate != null && + (tx.InterestRate < 0 || tx.InterestRate > MAX_INTEREST_RATE) + ) { + throw new ValidationError( + `LoanSet: InterestRate must be between 0 and ${MAX_INTEREST_RATE} inclusive`, + ) + } + + if ( + tx.LateInterestRate != null && + (tx.LateInterestRate < 0 || tx.LateInterestRate > MAX_LATE_INTEREST_RATE) + ) { + throw new ValidationError( + `LoanSet: LateInterestRate must be between 0 and ${MAX_LATE_INTEREST_RATE} inclusive`, + ) + } + + if ( + tx.CloseInterestRate != null && + (tx.CloseInterestRate < 0 || tx.CloseInterestRate > MAX_CLOSE_INTEREST_RATE) + ) { + throw new ValidationError( + `LoanSet: CloseInterestRate must be between 0 and ${MAX_CLOSE_INTEREST_RATE} inclusive`, + ) + } + + if ( + tx.OverpaymentInterestRate != null && + (tx.OverpaymentInterestRate < 0 || + tx.OverpaymentInterestRate > MAX_OVER_PAYMENT_INTEREST_RATE) + ) { + throw new ValidationError( + `LoanSet: OverpaymentInterestRate must be between 0 and ${MAX_OVER_PAYMENT_INTEREST_RATE} inclusive`, + ) + } + + if (tx.PaymentInterval != null && tx.PaymentInterval < MIN_PAYMENT_INTERVAL) { + throw new ValidationError( + `LoanSet: PaymentInterval must be greater than or equal to ${MIN_PAYMENT_INTERVAL}`, + ) + } + + if ( + tx.PaymentInterval != null && + tx.GracePeriod != null && + tx.GracePeriod > tx.PaymentInterval + ) { + throw new ValidationError( + `LoanSet: GracePeriod must not be greater than PaymentInterval`, + ) + } +} diff --git a/packages/xrpl/src/models/transactions/transaction.ts b/packages/xrpl/src/models/transactions/transaction.ts index f0bc81e642..40e542861d 100644 --- a/packages/xrpl/src/models/transactions/transaction.ts +++ b/packages/xrpl/src/models/transactions/transaction.ts @@ -43,6 +43,24 @@ import { EnableAmendment } from './enableAmendment' import { EscrowCancel, validateEscrowCancel } from './escrowCancel' import { EscrowCreate, validateEscrowCreate } from './escrowCreate' import { EscrowFinish, validateEscrowFinish } from './escrowFinish' +import { + LoanBrokerCoverClawback, + validateLoanBrokerCoverClawback, +} from './loanBrokerCoverClawback' +import { + LoanBrokerCoverDeposit, + validateLoanBrokerCoverDeposit, +} from './loanBrokerCoverDeposit' +import { + LoanBrokerCoverWithdraw, + validateLoanBrokerCoverWithdraw, +} from './loanBrokerCoverWithdraw' +import { LoanBrokerDelete, validateLoanBrokerDelete } from './loanBrokerDelete' +import { LoanBrokerSet, validateLoanBrokerSet } from './loanBrokerSet' +import { LoanDelete, validateLoanDelete } from './loanDelete' +import { LoanManage, validateLoanManage } from './loanManage' +import { LoanPay, validateLoanPay } from './loanPay' +import { LoanSet, validateLoanSet } from './loanSet' import { TransactionMetadata } from './metadata' import { MPTokenAuthorize, validateMPTokenAuthorize } from './MPTokenAuthorize' import { @@ -172,6 +190,15 @@ export type SubmittableTransaction = | EscrowCancel | EscrowCreate | EscrowFinish + | LoanBrokerSet + | LoanBrokerCoverClawback + | LoanBrokerCoverDeposit + | LoanBrokerCoverWithdraw + | LoanBrokerDelete + | LoanSet + | LoanDelete + | LoanManage + | LoanPay | MPTokenAuthorize | MPTokenIssuanceCreate | MPTokenIssuanceDestroy @@ -398,6 +425,42 @@ export function validate(transaction: Record): void { validateEscrowFinish(tx) break + case 'LoanBrokerCoverClawback': + validateLoanBrokerCoverClawback(tx) + break + + case 'LoanBrokerCoverDeposit': + validateLoanBrokerCoverDeposit(tx) + break + + case 'LoanBrokerCoverWithdraw': + validateLoanBrokerCoverWithdraw(tx) + break + + case 'LoanBrokerDelete': + validateLoanBrokerDelete(tx) + break + + case 'LoanBrokerSet': + validateLoanBrokerSet(tx) + break + + case 'LoanSet': + validateLoanSet(tx) + break + + case 'LoanManage': + validateLoanManage(tx) + break + + case 'LoanDelete': + validateLoanDelete(tx) + break + + case 'LoanPay': + validateLoanPay(tx) + break + case 'MPTokenAuthorize': validateMPTokenAuthorize(tx) break diff --git a/packages/xrpl/src/models/transactions/vaultCreate.ts b/packages/xrpl/src/models/transactions/vaultCreate.ts index 67cd38772b..da3f44c441 100644 --- a/packages/xrpl/src/models/transactions/vaultCreate.ts +++ b/packages/xrpl/src/models/transactions/vaultCreate.ts @@ -1,6 +1,11 @@ import { ValidationError } from '../../errors' import { Currency } from '../common' import { hasFlag, isHex } from '../utils' +import { + MAX_MPT_META_BYTE_LENGTH, + MPT_META_WARNING_HEADER, + validateMPTokenMetadata, +} from '../utils/mptokenMetadata' import { BaseTransaction, @@ -14,11 +19,10 @@ import { VAULT_DATA_MAX_BYTE_LENGTH, XRPLNumber, isXRPLNumber, - MAX_MPT_META_BYTE_LENGTH, - MPT_META_WARNING_HEADER, - validateMPTokenMetadata, } from './common' +const MAX_SCALE = 18 + /** * Enum representing withdrawal strategies for a Vault. */ @@ -71,10 +75,9 @@ export interface VaultCreate extends BaseTransaction { AssetsMaximum?: XRPLNumber /** - * Arbitrary metadata about the share MPT, in hex format, limited to 1024 bytes. - * - * The decoded value must be a UTF-8 encoded JSON object that adheres to the - * XLS-89d MPTokenMetadata standard. + * Should follow {@link https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0089-multi-purpose-token-metadata-schema | XLS-89} standard. + * Use {@link encodeMPTokenMetadata} utility function to convert to convert {@link MPTokenMetadata} to a blob. + * Use {@link decodeMPTokenMetadata} utility function to convert from a blob to {@link MPTokenMetadata}. * * While adherence to the XLS-89d format is not mandatory, non-compliant metadata * may not be discoverable by ecosystem tools such as explorers and indexers. @@ -90,6 +93,12 @@ export interface VaultCreate extends BaseTransaction { * The PermissionedDomain object ID associated with the shares of this Vault. */ DomainID?: string + + /** + * The scaling factor for vault shares. Only applicable for IOU assets. + * Valid values are between 0 and 18 inclusive. For XRP and MPT, this must not be provided. + */ + Scale?: number } /* eslint-disable max-lines-per-function -- Not needed to reduce function */ @@ -109,6 +118,7 @@ export function validateVaultCreate(tx: Record): void { validateOptionalField(tx, 'MPTokenMetadata', isString) validateOptionalField(tx, 'WithdrawalPolicy', isNumber) validateOptionalField(tx, 'DomainID', isString) + validateOptionalField(tx, 'Scale', isNumber) if (tx.Data !== undefined) { const dataHex = tx.Data @@ -148,6 +158,30 @@ export function validateVaultCreate(tx: Record): void { ) } + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- required to check asset type + const asset = tx.Asset as unknown as Record + const isXRP = asset.currency === 'XRP' + const isMPT = 'mpt_issuance_id' in asset + const isIOU = !isXRP && !isMPT + + if (tx.Scale !== undefined) { + // Scale must not be provided for XRP or MPT assets + if (isXRP || isMPT) { + throw new ValidationError( + 'VaultCreate: Scale parameter must not be provided for XRP or MPT assets', + ) + } + + // For IOU assets, Scale must be between 0 and 18 inclusive + if (isIOU) { + if (!Number.isInteger(tx.Scale) || tx.Scale < 0 || tx.Scale > MAX_SCALE) { + throw new ValidationError( + `VaultCreate: Scale must be a number between 0 and ${MAX_SCALE} inclusive for IOU assets`, + ) + } + } + } + if (tx.MPTokenMetadata != null) { const validationMessages = validateMPTokenMetadata(tx.MPTokenMetadata) diff --git a/packages/xrpl/src/models/transactions/vaultWithdraw.ts b/packages/xrpl/src/models/transactions/vaultWithdraw.ts index 448a61f6f0..ceb5a36e55 100644 --- a/packages/xrpl/src/models/transactions/vaultWithdraw.ts +++ b/packages/xrpl/src/models/transactions/vaultWithdraw.ts @@ -9,6 +9,7 @@ import { Account, validateOptionalField, isAccount, + isNumber, } from './common' /** @@ -34,6 +35,11 @@ export interface VaultWithdraw extends BaseTransaction { * An account to receive the assets. It must be able to receive the asset. */ Destination?: Account + + /** + * Arbitrary tag identifying the reason for the withdrawal to the destination. + */ + DestinationTag?: number } /** @@ -48,4 +54,5 @@ export function validateVaultWithdraw(tx: Record): void { validateRequiredField(tx, 'VaultID', isString) validateRequiredField(tx, 'Amount', isAmount) validateOptionalField(tx, 'Destination', isAccount) + validateOptionalField(tx, 'DestinationTag', isNumber) } diff --git a/packages/xrpl/src/models/utils/flags.ts b/packages/xrpl/src/models/utils/flags.ts index ff04bf86f4..4ebdb40d5f 100644 --- a/packages/xrpl/src/models/utils/flags.ts +++ b/packages/xrpl/src/models/utils/flags.ts @@ -10,6 +10,8 @@ import { AMMDepositFlags } from '../transactions/AMMDeposit' import { AMMWithdrawFlags } from '../transactions/AMMWithdraw' import { BatchFlags } from '../transactions/batch' import { GlobalFlags } from '../transactions/common' +import { LoanManageFlags } from '../transactions/loanManage' +import { LoanPayFlags } from '../transactions/loanPay' import { MPTokenAuthorizeFlags } from '../transactions/MPTokenAuthorize' import { MPTokenIssuanceCreateFlags } from '../transactions/MPTokenIssuanceCreate' import { MPTokenIssuanceSetFlags } from '../transactions/MPTokenIssuanceSet' @@ -55,6 +57,8 @@ const txToFlag = { AMMDeposit: AMMDepositFlags, AMMWithdraw: AMMWithdrawFlags, Batch: BatchFlags, + LoanManage: LoanManageFlags, + LoanPay: LoanPayFlags, MPTokenAuthorize: MPTokenAuthorizeFlags, MPTokenIssuanceCreate: MPTokenIssuanceCreateFlags, MPTokenIssuanceSet: MPTokenIssuanceSetFlags, diff --git a/packages/xrpl/src/models/utils/mptokenMetadata.ts b/packages/xrpl/src/models/utils/mptokenMetadata.ts new file mode 100644 index 0000000000..767a2e0791 --- /dev/null +++ b/packages/xrpl/src/models/utils/mptokenMetadata.ts @@ -0,0 +1,529 @@ +/* eslint-disable max-lines -- utility file */ +/* eslint-disable no-continue -- makes logic easier to write and read in this case */ + +import { hexToString, stringToHex } from '@transia/isomorphic/utils' +import stableStringify from 'fast-json-stable-stringify' + +import type { MPTokenMetadata } from '../common' +import { isRecord, isString } from '../transactions/common' + +import { isHex } from '.' + +export const MAX_MPT_META_BYTE_LENGTH = 1024 +export const MPT_META_WARNING_HEADER = + 'MPTokenMetadata is not properly formatted as JSON as per the XLS-89 standard. ' + + "While adherence to this standard is not mandatory, such non-compliant MPToken's might not be discoverable " + + 'by Explorers and Indexers in the XRPL ecosystem.' + +const MPT_META_URI_FIELDS = [ + { + long: 'uri', + compact: 'u', + }, + { + long: 'category', + compact: 'c', + }, + { + long: 'title', + compact: 't', + }, +] + +const MPT_META_ALL_FIELDS = [ + { + long: 'ticker', + compact: 't', + validate(obj: Record): string[] { + if (obj[this.long] != null && obj[this.compact] != null) { + return [ + `${this.long}/${this.compact}: both long and compact forms present. expected only one.`, + ] + } + + const value = obj[this.long] ?? obj[this.compact] + if (!isString(value) || !/^[A-Z0-9]{1,6}$/u.test(value)) { + return [ + `${this.long}/${this.compact}: should have uppercase letters (A-Z) and digits (0-9) only. Max 6 characters recommended.`, + ] + } + + return [] + }, + }, + { + long: 'name', + compact: 'n', + validate(obj: Record): string[] { + if (obj[this.long] != null && obj[this.compact] != null) { + return [ + `${this.long}/${this.compact}: both long and compact forms present. expected only one.`, + ] + } + + const value = obj[this.long] ?? obj[this.compact] + if (!isString(value) || value.length === 0) { + return [`${this.long}/${this.compact}: should be a non-empty string.`] + } + + return [] + }, + }, + { + long: 'icon', + compact: 'i', + validate(obj: Record): string[] { + if (obj[this.long] != null && obj[this.compact] != null) { + return [ + `${this.long}/${this.compact}: both long and compact forms present. expected only one.`, + ] + } + + const value = obj[this.long] ?? obj[this.compact] + if (!isString(value) || value.length === 0) { + return [`${this.long}/${this.compact}: should be a non-empty string.`] + } + + return [] + }, + }, + { + long: 'asset_class', + compact: 'ac', + validate(obj: Record): string[] { + if (obj[this.long] != null && obj[this.compact] != null) { + return [ + `${this.long}/${this.compact}: both long and compact forms present. expected only one.`, + ] + } + + const value = obj[this.long] ?? obj[this.compact] + const MPT_META_ASSET_CLASSES = [ + 'rwa', + 'memes', + 'wrapped', + 'gaming', + 'defi', + 'other', + ] + + if (!isString(value) || !MPT_META_ASSET_CLASSES.includes(value)) { + return [ + `${this.long}/${this.compact}: should be one of ${MPT_META_ASSET_CLASSES.join( + ', ', + )}.`, + ] + } + return [] + }, + }, + { + long: 'issuer_name', + compact: 'in', + validate(obj: Record): string[] { + if (obj[this.long] != null && obj[this.compact] != null) { + return [ + `${this.long}/${this.compact}: both long and compact forms present. expected only one.`, + ] + } + + const value = obj[this.long] ?? obj[this.compact] + if (!isString(value) || value.length === 0) { + return [`${this.long}/${this.compact}: should be a non-empty string.`] + } + + return [] + }, + }, + { + long: 'desc', + compact: 'd', + validate(obj: Record): string[] { + if (obj[this.long] != null && obj[this.compact] != null) { + return [ + `${this.long}/${this.compact}: both long and compact forms present. expected only one.`, + ] + } + + if (obj[this.long] === undefined && obj[this.compact] === undefined) { + return [] + } + const value = obj[this.long] ?? obj[this.compact] + if (!isString(value) || value.length === 0) { + return [`${this.long}/${this.compact}: should be a non-empty string.`] + } + + return [] + }, + }, + { + long: 'asset_subclass', + compact: 'as', + required: false, + validate(obj: Record): string[] { + if (obj[this.long] != null && obj[this.compact] != null) { + return [ + `${this.long}/${this.compact}: both long and compact forms present. expected only one.`, + ] + } + + const value = obj[this.long] ?? obj[this.compact] + if ( + (obj.asset_class === 'rwa' || obj.ac === 'rwa') && + value === undefined + ) { + return [ + `${this.long}/${this.compact}: required when asset_class is rwa.`, + ] + } + + if (obj[this.long] === undefined && obj[this.compact] === undefined) { + return [] + } + + const MPT_META_ASSET_SUB_CLASSES = [ + 'stablecoin', + 'commodity', + 'real_estate', + 'private_credit', + 'equity', + 'treasury', + 'other', + ] + if (!isString(value) || !MPT_META_ASSET_SUB_CLASSES.includes(value)) { + return [ + `${this.long}/${this.compact}: should be one of ${MPT_META_ASSET_SUB_CLASSES.join( + ', ', + )}.`, + ] + } + return [] + }, + }, + { + long: 'uris', + compact: 'us', + required: false, + // eslint-disable-next-line max-lines-per-function -- required for validation + validate(obj: Record): string[] { + if (obj[this.long] != null && obj[this.compact] != null) { + return [ + `${this.long}/${this.compact}: both long and compact forms present. expected only one.`, + ] + } + + if (obj[this.long] === undefined && obj[this.compact] === undefined) { + return [] + } + const value = obj[this.long] ?? obj[this.compact] + if (!Array.isArray(value) || value.length === 0) { + return [`${this.long}/${this.compact}: should be a non-empty array.`] + } + + const messages: string[] = [] + for (const uriObj of value) { + if ( + !isRecord(uriObj) || + Object.keys(uriObj).length !== MPT_META_URI_FIELDS.length + ) { + messages.push( + `${this.long}/${this.compact}: should be an array of objects each with uri/u, category/c, and title/t properties.`, + ) + continue + } + + // Check for both long and compact forms in the same URI object + for (const uriField of MPT_META_URI_FIELDS) { + if ( + uriObj[uriField.long] != null && + uriObj[uriField.compact] != null + ) { + messages.push( + `${this.long}/${this.compact}: should not have both ${uriField.long} and ${uriField.compact} fields.`, + ) + break + } + } + + const uri = uriObj.uri ?? uriObj.u + const category = uriObj.category ?? uriObj.c + const title = uriObj.title ?? uriObj.t + if (!isString(uri) || !isString(category) || !isString(title)) { + messages.push( + `${this.long}/${this.compact}: should be an array of objects each with uri/u, category/c, and title/t properties.`, + ) + } + } + return messages + }, + }, + { + long: 'additional_info', + compact: 'ai', + required: false, + validate(obj: Record): string[] { + if (obj[this.long] != null && obj[this.compact] != null) { + return [ + `${this.long}/${this.compact}: both long and compact forms present. expected only one.`, + ] + } + + if (obj[this.long] === undefined && obj[this.compact] === undefined) { + return [] + } + const value = obj[this.long] ?? obj[this.compact] + if (!isString(value) && !isRecord(value)) { + return [ + `${this.long}/${this.compact}: should be a string or JSON object.`, + ] + } + + return [] + }, + }, +] + +/** + * Shortens long field names to their compact form equivalents. + * Reverse operation of {@link expandKeys}. + * + * @param input - Object with potentially long field names. + * @param mappings - Array of field mappings with long and compact names. + * @returns Object with shortened compact field names. + */ +function shortenKeys( + input: Record, + mappings: Array<{ long: string; compact: string }>, +): Record { + const output: Record = {} + + for (const [key, value] of Object.entries(input)) { + const mapping = mappings.find( + ({ long, compact }) => long === key || compact === key, + ) + // Extra keys stays there + if (mapping === undefined) { + output[key] = value + continue + } + + // Both long and compact forms are present + if ( + input[mapping.long] !== undefined && + input[mapping.compact] !== undefined + ) { + output[key] = value + continue + } + + output[mapping.compact] = value + } + + return output +} + +/** + * Encodes {@link MPTokenMetadata} object to a hex string. + * Steps: + * 1. Shorten long field names to their compact form equivalents. + * 2. Sort the fields alphabetically for deterministic encoding. + * 3. Stringify the object. + * 4. Convert to hex. + * + * @param mptokenMetadata - {@link MPTokenMetadata} to encode. + * @returns Hex encoded {@link MPTokenMetadata}. + * @throws Error if input is not a JSON object. + * @category Utilities + */ +export function encodeMPTokenMetadata( + mptokenMetadata: MPTokenMetadata, +): string { + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Required here to implement type-guard + let input = mptokenMetadata as unknown as Record + + if (!isRecord(input)) { + throw new Error('MPTokenMetadata must be JSON object.') + } + + input = shortenKeys(input, MPT_META_ALL_FIELDS) + + if (Array.isArray(input.uris)) { + input.uris = input.uris.map( + (uri: Record): Record => { + if (isRecord(uri)) { + return shortenKeys(uri, MPT_META_URI_FIELDS) + } + return uri + }, + ) + } + + if (Array.isArray(input.us)) { + input.us = input.us.map( + (uri: Record): Record => { + if (isRecord(uri)) { + return shortenKeys(uri, MPT_META_URI_FIELDS) + } + return uri + }, + ) + } + + return stringToHex(stableStringify(input)).toUpperCase() +} + +/** + * Expands compact field names to their long form equivalents. + * Reverse operation of {@link shortenKeys}. + * + * @param input - Object with potentially compact field names. + * @param mappings - Array of field mappings with long and compact names. + * @returns Object with expanded long field names. + */ +function expandKeys( + input: Record, + mappings: Array<{ long: string; compact: string }>, +): Record { + const output: Record = {} + + for (const [key, value] of Object.entries(input)) { + const mapping = mappings.find( + ({ long, compact }) => long === key || compact === key, + ) + // Extra keys stays there + if (mapping === undefined) { + output[key] = value + continue + } + + // Both long and compact forms are present + if ( + input[mapping.long] !== undefined && + input[mapping.compact] !== undefined + ) { + output[key] = value + continue + } + + output[mapping.long] = value + } + + return output +} + +/** + * Decodes hex-encoded {@link MPTokenMetadata} into a JSON object. + * Converts compact field names to their corresponding long-form equivalents. + * + * @param input - Hex encoded {@link MPTokenMetadata}. + * @returns Decoded {@link MPTokenMetadata} object with long field names. + * @throws Error if input is not valid hex or cannot be parsed as JSON. + * @category Utilities + */ +export function decodeMPTokenMetadata(input: string): MPTokenMetadata { + if (!isHex(input)) { + throw new Error('MPTokenMetadata must be in hex format.') + } + + let jsonMetaData: unknown + try { + jsonMetaData = JSON.parse(hexToString(input)) + } catch (err) { + throw new Error( + `MPTokenMetadata is not properly formatted as JSON - ${String(err)}`, + ) + } + + if (!isRecord(jsonMetaData)) { + throw new Error('MPTokenMetadata must be a JSON object.') + } + + let output = jsonMetaData + + output = expandKeys(output, MPT_META_ALL_FIELDS) + + if (Array.isArray(output.uris)) { + output.uris = output.uris.map( + (uri: Record): Record => { + if (isRecord(uri)) { + return expandKeys(uri, MPT_META_URI_FIELDS) + } + return uri + }, + ) + } + + if (Array.isArray(output.us)) { + output.us = output.us.map( + (uri: Record): Record => { + if (isRecord(uri)) { + return expandKeys(uri, MPT_META_URI_FIELDS) + } + return uri + }, + ) + } + + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Required here as output is now properly formatted + return output as unknown as MPTokenMetadata +} + +/** + * Validates {@link MPTokenMetadata} adheres to XLS-89 standard. + * + * @param input - Hex encoded {@link MPTokenMetadata}. + * @returns Validation messages if {@link MPTokenMetadata} does not adheres to XLS-89 standard. + * @category Utilities + */ +export function validateMPTokenMetadata(input: string): string[] { + const validationMessages: string[] = [] + + // Validate hex format + if (!isHex(input)) { + validationMessages.push(`MPTokenMetadata must be in hex format.`) + return validationMessages + } + + // Validate byte length + if (input.length / 2 > MAX_MPT_META_BYTE_LENGTH) { + validationMessages.push( + `MPTokenMetadata must be max ${MAX_MPT_META_BYTE_LENGTH} bytes.`, + ) + return validationMessages + } + + // Parse JSON + let jsonMetaData: unknown + try { + jsonMetaData = JSON.parse(hexToString(input)) + } catch (err) { + validationMessages.push( + `MPTokenMetadata is not properly formatted as JSON - ${String(err)}`, + ) + return validationMessages + } + + // Validate JSON structure + if (!isRecord(jsonMetaData)) { + validationMessages.push( + 'MPTokenMetadata is not properly formatted JSON object as per XLS-89.', + ) + return validationMessages + } + + if (Object.keys(jsonMetaData).length > MPT_META_ALL_FIELDS.length) { + validationMessages.push( + `MPTokenMetadata must not contain more than ${MPT_META_ALL_FIELDS.length} top-level fields (found ${ + Object.keys(jsonMetaData).length + }).`, + ) + } + + const obj = jsonMetaData + + for (const property of MPT_META_ALL_FIELDS) { + validationMessages.push(...property.validate(obj)) + } + + return validationMessages +} diff --git a/packages/xrpl/src/sugar/autofill.ts b/packages/xrpl/src/sugar/autofill.ts index f73ead5909..c6ac45cefb 100644 --- a/packages/xrpl/src/sugar/autofill.ts +++ b/packages/xrpl/src/sugar/autofill.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/consistent-type-assertions -- required here */ /* eslint-disable max-lines -- lots of helper functions needed for autofill */ import { xAddressToClassicAddress, @@ -8,8 +9,14 @@ import BigNumber from 'bignumber.js' import { type Client } from '..' import { ValidationError, XrplError } from '../errors' -import { AccountInfoRequest, AccountObjectsRequest } from '../models/methods' +import { LoanBroker } from '../models/ledger' +import { + AccountInfoRequest, + AccountObjectsRequest, + LedgerEntryRequest, +} from '../models/methods' import { Batch, Payment, Transaction } from '../models/transactions' +import { Account } from '../models/transactions/common' import { xrpToDrops } from '../utils' import getFeeXrp, { getGasEstimate } from './getFeeXrp' @@ -152,7 +159,6 @@ function validateAccountAddress( ): void { // if X-address is given, convert it to classic address const { classicAccount, tag } = getClassicAccountAndTag( - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- okay here tx[accountField] as string, ) // eslint-disable-next-line no-param-reassign -- param reassign is safe @@ -262,6 +268,50 @@ async function fetchOwnerReserveFee(client: Client): Promise { return new BigNumber(fee) } +/** + * Fetches the total number of signers for the counterparty of a LoanSet transaction. + * + * @param client - The client object used to make the request. + * @param tx - The transaction object for which the counterparty signers count needs to be fetched. + * @returns A Promise that resolves to the number of signers for the counterparty. + * @throws {ValidationError} Throws an error if LoanBrokerID is not provided in the transaction. + */ +async function fetchCounterPartySignersCount( + client: Client, + tx: Transaction, +): Promise { + let counterParty: Account | undefined = tx.Counterparty as Account | undefined + // Loan Borrower initiated the transaction, Loan Broker is the counterparty. + if (counterParty == null) { + if (tx.LoanBrokerID == null) { + throw new ValidationError( + 'LoanBrokerID is required for LoanSet transaction', + ) + } + const resp = ( + await client.request({ + command: 'ledger_entry', + index: tx.LoanBrokerID, + ledger_index: 'validated', + } as LedgerEntryRequest) + ).result.node as LoanBroker + + counterParty = resp.Owner + } + + // Now fetch the signer list for the counterparty. + const signerListRequest: AccountInfoRequest = { + command: 'account_info', + account: counterParty, + ledger_index: 'validated', + signer_lists: true, + } + + const signerListResponse = await client.request(signerListRequest) + const signerList = signerListResponse.result.signer_lists?.[0] + return signerList?.SignerEntries.length ?? 1 +} + /** * Calculates the fee per transaction type. * @@ -280,9 +330,11 @@ async function calculateFeePerTransactionType( const netFeeDrops = xrpToDrops(netFeeXRP) let baseFee = new BigNumber(netFeeDrops) - const isSpecialTxCost = ['AccountDelete', 'AMMCreate'].includes( - tx.TransactionType, - ) + const isSpecialTxCost = [ + 'AccountDelete', + 'AMMCreate', + 'VaultCreate', + ].includes(tx.TransactionType) // EscrowFinish Transaction with Fulfillment if (tx.TransactionType === 'EscrowFinish' && tx.Fulfillment != null) { @@ -317,6 +369,22 @@ async function calculateFeePerTransactionType( baseFee = BigNumber.sum(baseFee, scaleValue(netFeeDrops, signersCount)) } + // LoanSet transactions have additional fees based on the number of signers for the counterparty. + if (tx.TransactionType === 'LoanSet') { + const counterPartySignersCount = await fetchCounterPartySignersCount( + client, + tx, + ) + baseFee = BigNumber.sum( + baseFee, + scaleValue(netFeeDrops, counterPartySignersCount), + ) + // eslint-disable-next-line no-console -- necessary to inform users about autofill behavior + console.warn( + `For LoanSet transaction the auto calculated Fee accounts for total number of signers the counterparty has to avoid transaction failure.`, + ) + } + const maxFeeDrops = xrpToDrops(client.maxFeeXRP) const totalFee = isSpecialTxCost ? baseFee diff --git a/packages/xrpl/src/sugar/getOrderbook.ts b/packages/xrpl/src/sugar/getOrderbook.ts index ecb6291b59..c31041e8e3 100644 --- a/packages/xrpl/src/sugar/getOrderbook.ts +++ b/packages/xrpl/src/sugar/getOrderbook.ts @@ -17,7 +17,7 @@ function sortOffers(offers: BookOffer[]): BookOffer[] { const qualityA = offerA.quality ?? 0 const qualityB = offerB.quality ?? 0 - return new BigNumber(qualityA).comparedTo(qualityB) + return new BigNumber(qualityA).comparedTo(qualityB) ?? 0 }) } diff --git a/packages/xrpl/src/utils/hashes/index.ts b/packages/xrpl/src/utils/hashes/index.ts index 236a171aa3..aac44718e5 100644 --- a/packages/xrpl/src/utils/hashes/index.ts +++ b/packages/xrpl/src/utils/hashes/index.ts @@ -185,4 +185,52 @@ export function hashPaymentChannel( ) } +/** + * Compute the hash of a Vault. + * + * @param address - Account of the Vault Owner (Account submitting VaultCreate transaction). + * @param sequence - Sequence number of the Transaction that created the Vault object. + * @returns The computed hash of the Vault object. + * @category Utilities + */ +export function hashVault(address: string, sequence: number): string { + return sha512Half( + ledgerSpaceHex('vault') + + addressToHex(address) + + sequence.toString(HEX).padStart(BYTE_LENGTH * 2, '0'), + ) +} + +/** + * Compute the hash of a LoanBroker. + * + * @param address - Account of the Lender (Account submitting LoanBrokerSet transaction, i.e. Lender). + * @param sequence - Sequence number of the Transaction that created the LoanBroker object. + * @returns The computed hash of the LoanBroker object. + * @category Utilities + */ +export function hashLoanBroker(address: string, sequence: number): string { + return sha512Half( + ledgerSpaceHex('loanBroker') + + addressToHex(address) + + sequence.toString(HEX).padStart(BYTE_LENGTH * 2, '0'), + ) +} + +/** + * Compute the hash of a Loan. + * + * @param loanBrokerId - The LoanBrokerID of the associated LoanBroker object. + * @param loanSequence - The sequence number of the Loan. + * @returns The computed hash of the Loan object. + * @category Utilities + */ +export function hashLoan(loanBrokerId: string, loanSequence: number): string { + return sha512Half( + ledgerSpaceHex('loan') + + loanBrokerId + + loanSequence.toString(HEX).padStart(BYTE_LENGTH * 2, '0'), + ) +} + export { hashLedgerHeader, hashSignedTx, hashLedger, hashStateTree, hashTxTree } diff --git a/packages/xrpl/src/utils/hashes/ledgerSpaces.ts b/packages/xrpl/src/utils/hashes/ledgerSpaces.ts index e2af0c6aae..f14c888ce8 100644 --- a/packages/xrpl/src/utils/hashes/ledgerSpaces.ts +++ b/packages/xrpl/src/utils/hashes/ledgerSpaces.ts @@ -6,7 +6,7 @@ * * Each namespace is just a single character prefix. * - * See [LedgerNameSpace enum](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/LedgerFormats.h#L100). + * See [LedgerNameSpace enum](https://github.com/XRPLF/rippled/blob/master/src/libxrpl/protocol/Indexes.cpp#L66). */ const ledgerSpaces = { account: 'a', @@ -29,6 +29,9 @@ const ledgerSpaces = { paychan: 'x', check: 'C', depositPreauth: 'p', + vault: 'V', + loanBroker: 'l', + loan: 'L', } export default ledgerSpaces diff --git a/packages/xrpl/src/utils/index.ts b/packages/xrpl/src/utils/index.ts index b2facd1115..f8959d7110 100644 --- a/packages/xrpl/src/utils/index.ts +++ b/packages/xrpl/src/utils/index.ts @@ -20,6 +20,7 @@ import { encodeForMultisigning as rbcEncodeForMultisigning, encodeForSigning as rbcEncodeForSigning, encodeForSigningClaim as rbcEncodeForSigningClaim, + encodeForSigningBatch as rbcEncodeForSigningBatch, } from '@transia/ripple-binary-codec' import { verify as verifyKeypairSignature } from '@transia/ripple-keypairs' @@ -46,6 +47,9 @@ import { hashLedgerHeader, hashEscrow, hashPaymentChannel, + hashVault, + hashLoanBroker, + hashLoan, } from './hashes' import parseNFTokenID from './parseNFTokenID' import { @@ -124,6 +128,16 @@ function encodeForMultiSigning(object: Transaction, signer: string): string { return rbcEncodeForMultisigning(object, signer) } +/** + * Encodes a Batched Transaction for multi-account signing + * + * @param object - Batched Transaction in JSON format. + * @returns A hex string representing the encoded object. + */ +function encodeForSigningBatch(object: Transaction): string { + return rbcEncodeForSigningBatch(object) +} + /** * Decodes a hex string into a transaction | ledger entry * @@ -179,6 +193,9 @@ const hashes = { hashLedgerHeader, hashEscrow, hashPaymentChannel, + hashVault, + hashLoanBroker, + hashLoan, } export { @@ -225,6 +242,7 @@ export { decode, encodeForMultiSigning, encodeForSigning, + encodeForSigningBatch, encodeForSigningClaim, getNFTokenID, parseNFTokenID, diff --git a/packages/xrpl/test/client/autofill.test.ts b/packages/xrpl/test/client/autofill.test.ts index d3d6ffe224..b68b2ddd08 100644 --- a/packages/xrpl/test/client/autofill.test.ts +++ b/packages/xrpl/test/client/autofill.test.ts @@ -7,6 +7,7 @@ import { Payment, Transaction, Batch, + type LoanSet, } from '../../src' import { ValidationError } from '../../src/errors' import rippled from '../fixtures/rippled' @@ -518,4 +519,76 @@ describe('client.autofill', function () { assert.strictEqual(txResult.RawTransactions[0].RawTransaction.Sequence, 24) assert.strictEqual(txResult.RawTransactions[1].RawTransaction.Sequence, 23) }) + + it('should autofill LoanSet transaction', async function () { + const tx: LoanSet = { + TransactionType: 'LoanSet', + Account: 'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf', + LoanBrokerID: + 'E9A08C918E26407493CC4ADD381BA979CFEB7E440D0863B01FB31C231D167E42', + PrincipalRequested: '100000', + } + testContext.mockRippled!.addResponse('account_info', { + status: 'success', + type: 'response', + result: { + account_data: { + Sequence: 23, + }, + signer_lists: [ + { + SignerEntries: [ + { + SignerEntry: { + Account: 'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf', + }, + }, + { + SignerEntry: { + Account: 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn', + }, + }, + { + SignerEntry: { + Account: 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn', + }, + }, + ], + }, + ], + }, + }) + testContext.mockRippled!.addResponse('ledger', { + status: 'success', + type: 'response', + result: { + ledger_index: 9038214, + }, + }) + testContext.mockRippled!.addResponse('server_info', { + status: 'success', + type: 'response', + result: { + info: { + validated_ledger: { + base_fee_xrp: 0.00001, + }, + }, + }, + }) + testContext.mockRippled!.addResponse('ledger_entry', { + status: 'success', + type: 'response', + result: { + node: { + LedgerEntryType: 'LoanBroker', + Account: 'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf', + }, + }, + }) + + const txResult = await testContext.client.autofill(tx) + // base_fee + 3 * base_fee + assert.strictEqual(txResult.Fee, '48') + }) }) diff --git a/packages/xrpl/test/connection.test.ts b/packages/xrpl/test/connection.test.ts index af7af5e691..c23b55a135 100644 --- a/packages/xrpl/test/connection.test.ts +++ b/packages/xrpl/test/connection.test.ts @@ -81,10 +81,13 @@ async function createServer(): Promise { describe('Connection', function () { let clientContext: XrplTestContext + const CONNECTION_TIMEOUT = 1000 beforeEach(async () => { // console.log(`before: `, expect.getState().currentTestName) - clientContext = await setupClient() + clientContext = await setupClient({ + clientOptions: { connectionTimeout: CONNECTION_TIMEOUT }, + }) }) afterEach(async () => { // console.log(`after: `, expect.getState().currentTestName) @@ -425,7 +428,7 @@ describe('Connection', function () { } catch (error) { // @ts-expect-error -- Error has a message expect(error.message).toEqual( - "Error: connect() timed out after 5000 ms. If your internet connection is working, the rippled server may be blocked or inaccessible. You can also try setting the 'connectionTimeout' option in the Client constructor.", + `Error: connect() timed out after ${CONNECTION_TIMEOUT} ms. If your internet connection is working, the rippled server may be blocked or inaccessible. You can also try setting the 'connectionTimeout' option in the Client constructor.`, ) expect(spy).toHaveBeenCalled() // @ts-expect-error -- Promise throws timeout error after test is done @@ -636,7 +639,7 @@ describe('Connection', function () { reject(new XrplError(`should not throw error, got ${String(error)}`)) }) - setTimeout(resolve, 5000) + setTimeout(resolve, 500) }) const disconnectedPromise = new Promise((resolve) => { @@ -915,7 +918,7 @@ describe('Connection', function () { reject(new XrplError('Should not emit error.')) }) - setTimeout(resolve, 5000) + setTimeout(resolve, 500) }) let disconnectedCount = 0 @@ -1015,7 +1018,7 @@ describe('Connection', function () { // wait to ensure that XrplError is not thrown after test is done await new Promise((resolve) => { - setTimeout(resolve, 2000) + setTimeout(resolve, 1500) }) assert.includeMembers(traceMessages, [ diff --git a/packages/xrpl/test/faucet/fundWallet.test.ts b/packages/xrpl/test/faucet/fundWallet.test.ts index 5a8a7b6aeb..839af4ee53 100644 --- a/packages/xrpl/test/faucet/fundWallet.test.ts +++ b/packages/xrpl/test/faucet/fundWallet.test.ts @@ -121,12 +121,13 @@ describe('fundWallet', function () { throw new Error('Error not thrown') } catch (error) { - await api.disconnect() expect(error).toEqual( new XRPLFaucetError( - 'Request failed: {"body":{"error":"Invalid amount","detail":"Must be an integer"},"contentType":"application/json; charset=utf-8","statusCode":400}', + 'Request failed: {"contentType":"application/json; charset=utf-8","statusCode":400,"body":{"error":"Invalid amount","detail":"Must be an integer"}}', ), ) + } finally { + await api.disconnect() } }) }) diff --git a/packages/xrpl/test/fixtures/transactions/mptokenMetadataEncodeDecodeData.json b/packages/xrpl/test/fixtures/transactions/mptokenMetadataEncodeDecodeData.json new file mode 100644 index 0000000000..7b0742cfef --- /dev/null +++ b/packages/xrpl/test/fixtures/transactions/mptokenMetadataEncodeDecodeData.json @@ -0,0 +1,298 @@ +[ + { + "testName": "valid long MPTokenMetadata", + "mptMetadata": { + "ticker": "TBILL", + "name": "T-Bill Yield Token", + "desc": "A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.", + "icon": "https://example.org/tbill-icon.png", + "asset_class": "rwa", + "asset_subclass": "treasury", + "issuer_name": "Example Yield Co.", + "uris": [ + { + "uri": "https://exampleyield.co/tbill", + "category": "website", + "title": "Product Page" + }, + { + "uri": "https://exampleyield.co/docs", + "category": "docs", + "title": "Yield Token Docs" + } + ], + "additional_info": { + "interest_rate": "5.00%", + "interest_type": "variable", + "yield_source": "U.S. Treasury Bills", + "maturity_date": "2045-06-30", + "cusip": "912796RX0" + } + }, + "expectedLongForm": { + "ticker": "TBILL", + "name": "T-Bill Yield Token", + "desc": "A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.", + "icon": "https://example.org/tbill-icon.png", + "asset_class": "rwa", + "asset_subclass": "treasury", + "issuer_name": "Example Yield Co.", + "uris": [ + { + "uri": "https://exampleyield.co/tbill", + "category": "website", + "title": "Product Page" + }, + { + "uri": "https://exampleyield.co/docs", + "category": "docs", + "title": "Yield Token Docs" + } + ], + "additional_info": { + "interest_rate": "5.00%", + "interest_type": "variable", + "yield_source": "U.S. Treasury Bills", + "maturity_date": "2045-06-30", + "cusip": "912796RX0" + } + }, + "hex": "7B226163223A22727761222C226169223A7B226375736970223A22393132373936525830222C22696E7465726573745F72617465223A22352E303025222C22696E7465726573745F74797065223A227661726961626C65222C226D617475726974795F64617465223A22323034352D30362D3330222C227969656C645F736F75726365223A22552E532E2054726561737572792042696C6C73227D2C226173223A227472656173757279222C2264223A2241207969656C642D62656172696E6720737461626C65636F696E206261636B65642062792073686F72742D7465726D20552E532E205472656173757269657320616E64206D6F6E6579206D61726B657420696E737472756D656E74732E222C2269223A2268747470733A2F2F6578616D706C652E6F72672F7462696C6C2D69636F6E2E706E67222C22696E223A224578616D706C65205969656C6420436F2E222C226E223A22542D42696C6C205969656C6420546F6B656E222C2274223A225442494C4C222C227573223A5B7B2263223A2277656273697465222C2274223A2250726F647563742050616765222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F7462696C6C227D2C7B2263223A22646F6373222C2274223A225969656C6420546F6B656E20446F6373222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F646F6373227D5D7D" + }, + { + "testName": "valid MPTokenMetadata with all short field names", + "mptMetadata": { + "t": "TBILL", + "n": "T-Bill Yield Token", + "d": "A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.", + "i": "https://example.org/tbill-icon.png", + "ac": "rwa", + "as": "treasury", + "in": "Example Yield Co.", + "us": [ + { + "u": "https://exampleyield.co/tbill", + "c": "website", + "t": "Product Page" + }, + { + "u": "https://exampleyield.co/docs", + "c": "docs", + "t": "Yield Token Docs" + } + ], + "ai": { + "interest_rate": "5.00%", + "interest_type": "variable", + "yield_source": "U.S. Treasury Bills", + "maturity_date": "2045-06-30", + "cusip": "912796RX0" + } + }, + "expectedLongForm": { + "ticker": "TBILL", + "name": "T-Bill Yield Token", + "desc": "A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.", + "icon": "https://example.org/tbill-icon.png", + "asset_class": "rwa", + "asset_subclass": "treasury", + "issuer_name": "Example Yield Co.", + "uris": [ + { + "uri": "https://exampleyield.co/tbill", + "category": "website", + "title": "Product Page" + }, + { + "uri": "https://exampleyield.co/docs", + "category": "docs", + "title": "Yield Token Docs" + } + ], + "additional_info": { + "interest_rate": "5.00%", + "interest_type": "variable", + "yield_source": "U.S. Treasury Bills", + "maturity_date": "2045-06-30", + "cusip": "912796RX0" + } + }, + "hex": "7B226163223A22727761222C226169223A7B226375736970223A22393132373936525830222C22696E7465726573745F72617465223A22352E303025222C22696E7465726573745F74797065223A227661726961626C65222C226D617475726974795F64617465223A22323034352D30362D3330222C227969656C645F736F75726365223A22552E532E2054726561737572792042696C6C73227D2C226173223A227472656173757279222C2264223A2241207969656C642D62656172696E6720737461626C65636F696E206261636B65642062792073686F72742D7465726D20552E532E205472656173757269657320616E64206D6F6E6579206D61726B657420696E737472756D656E74732E222C2269223A2268747470733A2F2F6578616D706C652E6F72672F7462696C6C2D69636F6E2E706E67222C22696E223A224578616D706C65205969656C6420436F2E222C226E223A22542D42696C6C205969656C6420546F6B656E222C2274223A225442494C4C222C227573223A5B7B2263223A2277656273697465222C2274223A2250726F647563742050616765222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F7462696C6C227D2C7B2263223A22646F6373222C2274223A225969656C6420546F6B656E20446F6373222C2275223A2268747470733A2F2F6578616D706C657969656C642E636F2F646F6373227D5D7D" + }, + { + "testName": "valid MPTokenMetadata with mixed short and long field names", + "mptMetadata": { + "ticker": "CRYPTO", + "n": "Crypto Token", + "icon": "https://example.org/crypto-icon.png", + "asset_class": "gaming", + "d": "A gaming token for virtual worlds.", + "issuer_name": "Gaming Studios Inc.", + "as": "equity", + "uris": [ + { + "uri": "https://gamingstudios.com", + "c": "website", + "title": "Main Website" + }, + { + "uri": "https://gamingstudios.com", + "category": "website", + "t": "Main Website" + } + ], + "ai": "Gaming ecosystem token" + }, + "expectedLongForm": { + "ticker": "CRYPTO", + "name": "Crypto Token", + "icon": "https://example.org/crypto-icon.png", + "asset_class": "gaming", + "desc": "A gaming token for virtual worlds.", + "issuer_name": "Gaming Studios Inc.", + "asset_subclass": "equity", + "uris": [ + { + "uri": "https://gamingstudios.com", + "category": "website", + "title": "Main Website" + }, + { + "uri": "https://gamingstudios.com", + "category": "website", + "title": "Main Website" + } + ], + "additional_info": "Gaming ecosystem token" + }, + "hex": "7B226163223A2267616D696E67222C226169223A2247616D696E672065636F73797374656D20746F6B656E222C226173223A22657175697479222C2264223A22412067616D696E6720746F6B656E20666F72207669727475616C20776F726C64732E222C2269223A2268747470733A2F2F6578616D706C652E6F72672F63727970746F2D69636F6E2E706E67222C22696E223A2247616D696E672053747564696F7320496E632E222C226E223A2243727970746F20546F6B656E222C2274223A2243525950544F222C227573223A5B7B2263223A2277656273697465222C2274223A224D61696E2057656273697465222C2275223A2268747470733A2F2F67616D696E6773747564696F732E636F6D227D2C7B2263223A2277656273697465222C2274223A224D61696E2057656273697465222C2275223A2268747470733A2F2F67616D696E6773747564696F732E636F6D227D5D7D" + }, + { + "testName": "with extra fields", + "mptMetadata": { + "ticker": "CRYPTO", + "n": "Crypto Token", + "icon": "https://example.org/crypto-icon.png", + "asset_class": "gaming", + "d": "A gaming token for virtual worlds.", + "issuer_name": "Gaming Studios Inc.", + "as": "equity", + "uris": [ + { + "uri": "https://gamingstudios.com", + "c": "website", + "title": "Main Website" + }, + { + "uri": "https://gamingstudios.com", + "category": "website", + "t": "Main Website" + } + ], + "ai": "Gaming ecosystem token", + "extra": { + "extra": "extra" + } + }, + "expectedLongForm": { + "ticker": "CRYPTO", + "name": "Crypto Token", + "icon": "https://example.org/crypto-icon.png", + "asset_class": "gaming", + "desc": "A gaming token for virtual worlds.", + "issuer_name": "Gaming Studios Inc.", + "asset_subclass": "equity", + "uris": [ + { + "uri": "https://gamingstudios.com", + "category": "website", + "title": "Main Website" + }, + { + "uri": "https://gamingstudios.com", + "category": "website", + "title": "Main Website" + } + ], + "additional_info": "Gaming ecosystem token", + "extra": { + "extra": "extra" + } + }, + "hex": "7B226163223A2267616D696E67222C226169223A2247616D696E672065636F73797374656D20746F6B656E222C226173223A22657175697479222C2264223A22412067616D696E6720746F6B656E20666F72207669727475616C20776F726C64732E222C226578747261223A7B226578747261223A226578747261227D2C2269223A2268747470733A2F2F6578616D706C652E6F72672F63727970746F2D69636F6E2E706E67222C22696E223A2247616D696E672053747564696F7320496E632E222C226E223A2243727970746F20546F6B656E222C2274223A2243525950544F222C227573223A5B7B2263223A2277656273697465222C2274223A224D61696E2057656273697465222C2275223A2268747470733A2F2F67616D696E6773747564696F732E636F6D227D2C7B2263223A2277656273697465222C2274223A224D61696E2057656273697465222C2275223A2268747470733A2F2F67616D696E6773747564696F732E636F6D227D5D7D" + }, + { + "testName": "with unkown null fields", + "mptMetadata": { + "t": "CRYPTO", + "extra": null + }, + "expectedLongForm": { + "ticker": "CRYPTO", + "extra": null + }, + "hex": "7B226578747261223A6E756C6C2C2274223A2243525950544F227D" + }, + { + "testName": "multiple uris and us", + "mptMetadata": { + "t": "CRYPTO", + "uris": [ + { + "u": "https://gamingstudios.com", + "c": "website", + "t": "Main Website" + } + ], + "us": [ + { + "uri": "https://gamingstudios.com", + "category": "website", + "title": "Main Website" + } + ] + }, + "expectedLongForm": { + "ticker": "CRYPTO", + "uris": [ + { + "uri": "https://gamingstudios.com", + "category": "website", + "title": "Main Website" + } + ], + "us": [ + { + "uri": "https://gamingstudios.com", + "category": "website", + "title": "Main Website" + } + ] + }, + "hex": "7B2274223A2243525950544F222C2275726973223A5B7B2263223A2277656273697465222C2274223A224D61696E2057656273697465222C2275223A2268747470733A2F2F67616D696E6773747564696F732E636F6D227D5D2C227573223A5B7B2263223A2277656273697465222C2274223A224D61696E2057656273697465222C2275223A2268747470733A2F2F67616D696E6773747564696F732E636F6D227D5D7D" + }, + { + "testName": "multiple keys in uri", + "mptMetadata": { + "us": [ + { + "uri": "https://gamingstudios.com", + "u": "website", + "category": "Main Website", + "c": "Main Website" + } + ] + }, + "expectedLongForm": { + "uris": [ + { + "uri": "https://gamingstudios.com", + "u": "website", + "category": "Main Website", + "c": "Main Website" + } + ] + }, + "hex": "7B227573223A5B7B2263223A224D61696E2057656273697465222C2263617465676F7279223A224D61696E2057656273697465222C2275223A2277656273697465222C22757269223A2268747470733A2F2F67616D696E6773747564696F732E636F6D227D5D7D" + } +] diff --git a/packages/xrpl/test/fixtures/transactions/mptokenMetadata.json b/packages/xrpl/test/fixtures/transactions/mptokenMetadataValidationData.json similarity index 55% rename from packages/xrpl/test/fixtures/transactions/mptokenMetadata.json rename to packages/xrpl/test/fixtures/transactions/mptokenMetadataValidationData.json index 33470e7a34..6f3a28934e 100644 --- a/packages/xrpl/test/fixtures/transactions/mptokenMetadata.json +++ b/packages/xrpl/test/fixtures/transactions/mptokenMetadataValidationData.json @@ -9,15 +9,15 @@ "asset_class": "rwa", "asset_subclass": "treasury", "issuer_name": "Example Yield Co.", - "urls": [ + "uris": [ { - "url": "https://exampleyield.co/tbill", - "type": "website", + "uri": "https://exampleyield.co/tbill", + "category": "website", "title": "Product Page" }, { - "url": "https://exampleyield.co/docs", - "type": "docs", + "uri": "https://exampleyield.co/docs", + "category": "docs", "title": "Yield Token Docs" } ], @@ -31,6 +31,79 @@ }, "validationMessages": [] }, + { + "testName": "valid MPTokenMetadata with all short field names", + "mptMetadata": { + "t": "TBILL", + "n": "T-Bill Yield Token", + "d": "A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.", + "i": "https://example.org/tbill-icon.png", + "ac": "rwa", + "as": "treasury", + "in": "Example Yield Co.", + "us": [ + { + "u": "https://exampleyield.co/tbill", + "c": "website", + "t": "Product Page" + }, + { + "u": "https://exampleyield.co/docs", + "c": "docs", + "t": "Yield Token Docs" + } + ], + "ai": { + "interest_rate": "5.00%", + "interest_type": "variable", + "yield_source": "U.S. Treasury Bills", + "maturity_date": "2045-06-30", + "cusip": "912796RX0" + } + }, + "validationMessages": [] + }, + { + "testName": "valid MPTokenMetadata with mixed short and long field names", + "mptMetadata": { + "ticker": "CRYPTO", + "n": "Crypto Token", + "icon": "https://example.org/crypto-icon.png", + "asset_class": "gaming", + "d": "A gaming token for virtual worlds.", + "issuer_name": "Gaming Studios Inc.", + "as": "equity", + "uris": [ + { + "uri": "https://gamingstudios.com", + "c": "website", + "title": "Main Website" + }, + { + "uri": "https://gamingstudios.com", + "category": "website", + "t": "Main Website" + } + ], + "ai": "Gaming ecosystem token" + }, + "validationMessages": [] + }, + { + "testName": "conflicting short and long fields - ticker and t", + "mptMetadata": { + "ticker": "TBILL", + "t": "BILL", + "name": "T-Bill Token", + "icon": "https://example.com/icon.png", + "asset_class": "rwa", + "asset_subclass": "treasury", + "issuer_name": "Issuer" + }, + "validationMessages": [ + "ticker/t: both long and compact forms present. expected only one." + ] + }, { "testName": "missing ticker", "mptMetadata": { @@ -40,15 +113,15 @@ "asset_class": "rwa", "asset_subclass": "treasury", "issuer_name": "Example Yield Co.", - "urls": [ + "uris": [ { - "url": "https://exampleyield.co/tbill", - "type": "website", + "uri": "https://exampleyield.co/tbill", + "category": "website", "title": "Product Page" }, { - "url": "https://exampleyield.co/docs", - "type": "docs", + "uri": "https://exampleyield.co/docs", + "category": "docs", "title": "Yield Token Docs" } ], @@ -61,7 +134,7 @@ } }, "validationMessages": [ - "ticker is required and must be string." + "ticker/t: should have uppercase letters (A-Z) and digits (0-9) only. Max 6 characters recommended." ] }, { @@ -75,21 +148,21 @@ "issuer_name": "Issuer" }, "validationMessages": [ - "ticker should have uppercase letters (A-Z) and digits (0-9) only. Max 6 characters recommended." + "ticker/t: should have uppercase letters (A-Z) and digits (0-9) only. Max 6 characters recommended." ] }, { - "testName": "icon not https", + "testName": "icon not present", "mptMetadata": { "ticker": "TBILL", "name": "T-Bill Token", - "icon": "http://example.com/icon.png", + "icon": null, "asset_class": "rwa", "asset_subclass": "treasury", "issuer_name": "Issuer" }, "validationMessages": [ - "icon should be a valid https url." + "icon/i: should be a non-empty string." ] }, { @@ -103,7 +176,7 @@ "issuer_name": "Issuer" }, "validationMessages": [ - "asset_class should be one of rwa, memes, wrapped, gaming, defi, other." + "asset_class/ac: should be one of rwa, memes, wrapped, gaming, defi, other." ] }, { @@ -117,7 +190,7 @@ "issuer_name": "Issuer" }, "validationMessages": [ - "asset_subclass should be one of stablecoin, commodity, real_estate, private_credit, equity, treasury, other." + "asset_subclass/as: should be one of stablecoin, commodity, real_estate, private_credit, equity, treasury, other." ] }, { @@ -130,11 +203,11 @@ "issuer_name": "Issuer" }, "validationMessages": [ - "asset_subclass is required when asset_class is rwa." + "asset_subclass/as: required when asset_class is rwa." ] }, { - "testName": "urls not https", + "testName": "uris empty", "mptMetadata": { "ticker": "TBILL", "name": "T-Bill Token", @@ -142,16 +215,10 @@ "asset_class": "defi", "issuer_name": "Issuer", "asset_subclass": "stablecoin", - "urls": [ - { - "url": "http://notsecure.com", - "type": "website", - "title": "Homepage" - } - ] + "uris": [] }, "validationMessages": [ - "url should be a valid https url." + "uris/us: should be a non-empty array." ] }, { @@ -168,7 +235,7 @@ ] }, "validationMessages": [ - "additional_info must be a string or JSON object." + "additional_info/ai: should be a string or JSON object." ] }, { @@ -182,7 +249,7 @@ "additional_info": 123 }, "validationMessages": [ - "additional_info must be a string or JSON object." + "additional_info/ai: should be a string or JSON object." ] }, { @@ -195,9 +262,9 @@ "asset_class": "rwamemes", "asset_subclass": "treasurymemes", "issuer_name": "Example Yield Co.", - "urls": [ + "uris": [ { - "url": "http://notsecure.com", + "uri": "http://notsecure.com", "type": "website", "title": "Homepage" } @@ -211,29 +278,28 @@ } }, "validationMessages": [ - "ticker should have uppercase letters (A-Z) and digits (0-9) only. Max 6 characters recommended.", - "icon should be a valid https url.", - "asset_class should be one of rwa, memes, wrapped, gaming, defi, other.", - "asset_subclass should be one of stablecoin, commodity, real_estate, private_credit, equity, treasury, other.", - "url should be a valid https url." + "ticker/t: should have uppercase letters (A-Z) and digits (0-9) only. Max 6 characters recommended.", + "asset_class/ac: should be one of rwa, memes, wrapped, gaming, defi, other.", + "asset_subclass/as: should be one of stablecoin, commodity, real_estate, private_credit, equity, treasury, other.", + "uris/us: should be an array of objects each with uri/u, category/c, and title/t properties." ] }, { "testName": "null mptMetadata", "mptMetadata": null, "validationMessages": [ - "MPTokenMetadata is not properly formatted as per XLS-89d." + "MPTokenMetadata is not properly formatted JSON object as per XLS-89." ] }, { "testName": "empty mptMetadata", "mptMetadata": {}, "validationMessages": [ - "ticker is required and must be string.", - "name is required and must be string.", - "icon is required and must be string.", - "asset_class is required and must be string.", - "issuer_name is required and must be string." + "ticker/t: should have uppercase letters (A-Z) and digits (0-9) only. Max 6 characters recommended.", + "name/n: should be a non-empty string.", + "icon/i: should be a non-empty string.", + "asset_class/ac: should be one of rwa, memes, wrapped, gaming, defi, other.", + "issuer_name/in: should be a non-empty string." ] }, { @@ -255,10 +321,10 @@ "issuer_name": "Example Yield Co.", "issuer_address": "123 Example Yield Co.", "issuer_account": "321 Example Yield Co.", - "urls": [ + "uris": [ { - "url": "http://notsecure.com", - "type": "website", + "uri": "http://notsecure.com", + "category": "website", "title": "Homepage" } ], @@ -275,7 +341,7 @@ ] }, { - "testName": "more than 3 url fields", + "testName": "more than 3 uri fields", "mptMetadata": { "ticker": "TBILL", "name": "T-Bill Yield Token", @@ -284,10 +350,10 @@ "asset_class": "rwa", "asset_subclass": "treasury", "issuer_name": "Example Yield Co.", - "urls": [ + "uris": [ { - "url": "https://notsecure.com", - "type": "website", + "uri": "https://notsecure.com", + "category": "website", "title": "Homepage", "footer": "footer" } @@ -301,11 +367,11 @@ } }, "validationMessages": [ - "One or more urls are not structured per XLS-89d." + "uris/us: should be an array of objects each with uri/u, category/c, and title/t properties." ] }, { - "testName": "invalid url structure", + "testName": "invalid uris structure", "mptMetadata": { "ticker": "TBILL", "name": "T-Bill Yield Token", @@ -314,7 +380,7 @@ "asset_class": "rwa", "asset_subclass": "treasury", "issuer_name": "Example Yield Co.", - "urls": "urls", + "uris": "uris", "additional_info": { "interest_rate": "5.00%", "interest_type": "variable", @@ -324,11 +390,11 @@ } }, "validationMessages": [ - "urls must be an array as per XLS-89d." + "uris/us: should be a non-empty array." ] }, { - "testName": "invalid url inner structure", + "testName": "invalid uri inner structure", "mptMetadata": { "ticker": "TBILL", "name": "T-Bill Yield Token", @@ -337,7 +403,7 @@ "asset_class": "rwa", "asset_subclass": "treasury", "issuer_name": "Example Yield Co.", - "urls": [ + "uris": [ 1, 2 ], @@ -350,7 +416,38 @@ } }, "validationMessages": [ - "One or more urls are not structured per XLS-89d." + "uris/us: should be an array of objects each with uri/u, category/c, and title/t properties.", + "uris/us: should be an array of objects each with uri/u, category/c, and title/t properties." + ] + }, + { + "testName": "conflicting uri long and compact forms", + "mptMetadata": { + "ticker": "TBILL", + "name": "T-Bill Yield Token", + "desc": "A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.", + "icon": "https://example.org/tbill-icon.png", + "asset_class": "rwa", + "asset_subclass": "treasury", + "issuer_name": "Example Yield Co.", + "uris": [ + { + "uri": "https://exampleyield.co/tbill", + "u": "website", + "title": "Product Page" + } + ], + "additional_info": { + "interest_rate": "5.00%", + "interest_type": "variable", + "yield_source": "U.S. Treasury Bills", + "maturity_date": "2045-06-30", + "cusip": "912796RX0" + } + }, + "validationMessages": [ + "uris/us: should not have both uri and u fields.", + "uris/us: should be an array of objects each with uri/u, category/c, and title/t properties." ] }, { @@ -363,65 +460,65 @@ "asset_class": "rwa", "asset_subclass": "treasury", "issuer_name": "Example Yield Co.", - "urls": [ + "uris": [ { - "url": "https://exampleyield.co/tbill", - "type": "website", + "uri": "https://exampleyield.co/tbill", + "category": "website", "title": "Product Page" }, { - "url": "https://exampleyield.co/docs", - "type": "docs", + "uri": "https://exampleyield.co/docs", + "category": "docs", "title": "Yield Token Docs" }, { - "url": "https://exampleyield.co/docs", - "type": "docs", + "uri": "https://exampleyield.co/docs", + "category": "docs", "title": "Yield Token Docs" }, { - "url": "https://exampleyield.co/docs", - "type": "docs", + "uri": "https://exampleyield.co/docs", + "category": "docs", "title": "Yield Token Docs" }, { - "url": "https://exampleyield.co/docs", - "type": "docs", + "uri": "https://exampleyield.co/docs", + "category": "docs", "title": "Yield Token Docs" }, { - "url": "https://exampleyield.co/docs", - "type": "docs", + "uri": "https://exampleyield.co/docs", + "category": "docs", "title": "Yield Token Docs" }, { - "url": "https://exampleyield.co/docs", - "type": "docs", + "uri": "https://exampleyield.co/docs", + "category": "docs", "title": "Yield Token Docs" }, { - "url": "https://exampleyield.co/docs", - "type": "docs", + "uri": "https://exampleyield.co/docs", + "category": "docs", "title": "Yield Token Docs" }, { - "url": "https://exampleyield.co/docs", - "type": "docs", + "uri": "https://exampleyield.co/docs", + "category": "docs", "title": "Yield Token Docs" }, { - "url": "https://exampleyield.co/docs", - "type": "docs", + "uri": "https://exampleyield.co/docs", + "category": "docs", "title": "Yield Token Docs" }, { - "url": "https://exampleyield.co/docs", - "type": "docs", + "uri": "https://exampleyield.co/docs", + "category": "docs", "title": "Yield Token Docs" }, { - "url": "https://exampleyield.co/docs", - "type": "docs", + "uri": "https://exampleyield.co/docs", + "category": "docs", "title": "Yield Token Docs" } ], @@ -436,5 +533,30 @@ "validationMessages": [ "MPTokenMetadata must be max 1024 bytes." ] + }, + { + "testName": "null values", + "mptMetadata": { + "ticker": null, + "name": null, + "desc": null, + "icon": null, + "asset_class": null, + "asset_subclass": null, + "issuer_name": null, + "uris": null, + "additional_info": null + }, + "validationMessages": [ + "ticker/t: should have uppercase letters (A-Z) and digits (0-9) only. Max 6 characters recommended.", + "name/n: should be a non-empty string.", + "icon/i: should be a non-empty string.", + "asset_class/ac: should be one of rwa, memes, wrapped, gaming, defi, other.", + "issuer_name/in: should be a non-empty string.", + "desc/d: should be a non-empty string.", + "asset_subclass/as: should be one of stablecoin, commodity, real_estate, private_credit, equity, treasury, other.", + "uris/us: should be a non-empty array.", + "additional_info/ai: should be a string or JSON object." + ] } ] diff --git a/packages/xrpl/test/integration/requests/getAggregatePrice.test.ts b/packages/xrpl/test/integration/requests/getAggregatePrice.test.ts index 9a8d1f62f3..56477f9fe1 100644 --- a/packages/xrpl/test/integration/requests/getAggregatePrice.test.ts +++ b/packages/xrpl/test/integration/requests/getAggregatePrice.test.ts @@ -24,11 +24,18 @@ describe('get_aggregate_price', function () { it( 'base', async () => { + const closeTime: string = ( + await testContext.client.request({ + command: 'ledger', + ledger_index: 'validated', + }) + ).result.ledger.close_time_iso + const tx: OracleSet = { TransactionType: 'OracleSet', Account: testContext.wallet.classicAddress, OracleDocumentID: 1234, - LastUpdateTime: Math.floor(Date.now() / 1000), + LastUpdateTime: Math.floor(new Date(closeTime).getTime() / 1000) + 20, PriceDataSeries: [ { PriceData: { diff --git a/packages/xrpl/test/integration/requests/vaultInfo.test.ts b/packages/xrpl/test/integration/requests/vaultInfo.test.ts index 385cb3ddb1..bc8821da7e 100644 --- a/packages/xrpl/test/integration/requests/vaultInfo.test.ts +++ b/packages/xrpl/test/integration/requests/vaultInfo.test.ts @@ -5,6 +5,8 @@ import { VaultCreate, VaultInfoResponse, VaultWithdrawalPolicy, + AccountSet, + AccountSetAsfFlags, } from '../../../src' import { Vault } from '../../../src/models/ledger' import serverUrl from '../serverUrl' @@ -23,6 +25,7 @@ describe('Single Asset Vault', function () { }) afterEach(async () => teardownClient(testContext)) + // eslint-disable-next-line max-statements -- comprehensive vault_info test requires multiple assertions it('base', async function () { const tx: VaultCreate = { TransactionType: 'VaultCreate', @@ -32,8 +35,6 @@ describe('Single Asset Vault', function () { Data: stringToHex('vault metadata'), MPTokenMetadata: stringToHex('share metadata'), AssetsMaximum: '1000000000', - // This covers owner reserve fee with potentially high open_ledger_cost - Fee: '5000000', } await testTransaction(testContext.client, tx, testContext.wallet) @@ -80,12 +81,12 @@ describe('Single Asset Vault', function () { VaultWithdrawalPolicy.vaultStrategyFirstComeFirstServe, ) assert.equal( - vault.AssetsTotal, + vault.AssetsTotal ?? '0', '0', 'New Vault should have zero total assets', ) assert.equal( - vault.AssetsAvailable, + vault.AssetsAvailable ?? '0', '0', 'New Vault should have zero available assets', ) @@ -116,6 +117,18 @@ describe('Single Asset Vault', function () { 'mpt_issuance_id should match ShareMPTID', ) + assert.equal( + vault.AssetsMaximum, + '1000000000', + 'AssetsMaximum should match the value from VaultCreate', + ) + + assert.equal( + vault.Data, + stringToHex('vault metadata'), + 'Data should match the value from VaultCreate', + ) + // Fetch vault_info using owner and seq const vaultInfoRes2: VaultInfoResponse = await testContext.client.request({ command: 'vault_info', @@ -128,4 +141,71 @@ describe('Single Asset Vault', function () { ) assert.equal(vaultInfoRes2.result.vault.index, vault.index) }) + + it('IOU asset with Scale', async function () { + // Set DefaultRipple flag on the issuer account for IOU support + const accountSetTx: AccountSet = { + TransactionType: 'AccountSet', + Account: testContext.wallet.classicAddress, + SetFlag: AccountSetAsfFlags.asfDefaultRipple, + } + await testTransaction(testContext.client, accountSetTx, testContext.wallet) + + const tx: VaultCreate = { + TransactionType: 'VaultCreate', + Account: testContext.wallet.classicAddress, + Asset: { + currency: 'USD', + issuer: testContext.wallet.classicAddress, + }, + WithdrawalPolicy: VaultWithdrawalPolicy.vaultStrategyFirstComeFirstServe, + Scale: 10, + Data: stringToHex('iou vault metadata'), + } + + await testTransaction(testContext.client, tx, testContext.wallet) + + // Fetch the vault ledger entry to get its ID + const result = await testContext.client.request({ + command: 'account_objects', + account: testContext.wallet.classicAddress, + type: 'vault', + }) + const vaultObj = result.result.account_objects.find((obj) => { + const vault = obj as Vault + const asset = vault.Asset as unknown as Record + return ( + asset.currency === 'USD' && + asset.issuer === testContext.wallet.classicAddress + ) + }) as Vault + assert.isDefined(vaultObj, 'Should find IOU vault') + + // Fetch vault_info using vault_id + const vaultInfoRes: VaultInfoResponse = await testContext.client.request({ + command: 'vault_info', + vault_id: vaultObj.index, + }) + const { vault } = vaultInfoRes.result + + assert.isDefined(vault, 'vault_info response should include a vault') + assert.deepEqual( + vault.Asset, + { + currency: 'USD', + issuer: testContext.wallet.classicAddress, + }, + 'Vault Asset should be USD', + ) + assert.equal( + vault.Scale, + 10, + 'Scale should match the value from VaultCreate', + ) + assert.equal( + vault.Data, + stringToHex('iou vault metadata'), + 'Data should match the value from VaultCreate', + ) + }) }) diff --git a/packages/xrpl/test/integration/transactions/ammBid.test.ts b/packages/xrpl/test/integration/transactions/ammBid.test.ts index 8f0dd34b0a..8284140405 100644 --- a/packages/xrpl/test/integration/transactions/ammBid.test.ts +++ b/packages/xrpl/test/integration/transactions/ammBid.test.ts @@ -58,7 +58,7 @@ describe('AMMBid', function () { const afterPriceValue = parseFloat(auction_slot.price.value) const beforePriceValue = parseFloat(preAuctionSlot.price.value) - const diffPriceValue = 0.00268319257224121 + const diffPriceValue = 0.002683192572241211 const expectedPriceValue = beforePriceValue + diffPriceValue const afterLPTokenValue = parseFloat(lp_token.value) diff --git a/packages/xrpl/test/integration/transactions/delegateSet.test.ts b/packages/xrpl/test/integration/transactions/delegateSet.test.ts index b93ca73c41..961627b2f1 100644 --- a/packages/xrpl/test/integration/transactions/delegateSet.test.ts +++ b/packages/xrpl/test/integration/transactions/delegateSet.test.ts @@ -88,13 +88,13 @@ describe('DelegateSet', function () { EmailHash: '10000000002000000000300000000012', } - // Expect transaction to fail with tecNO_DELEGATE_PERMISSION error + // Expect transaction to fail with terNO_DELEGATE_PERMISSION error await testTransaction( testContext.client, accountSetTx, bob, undefined, - 'tecNO_DELEGATE_PERMISSION', + 'terNO_DELEGATE_PERMISSION', ) }, TIMEOUT, diff --git a/packages/xrpl/test/integration/transactions/lendingProtocol.test.ts b/packages/xrpl/test/integration/transactions/lendingProtocol.test.ts new file mode 100644 index 0000000000..d8040d4fec --- /dev/null +++ b/packages/xrpl/test/integration/transactions/lendingProtocol.test.ts @@ -0,0 +1,720 @@ +/* eslint-disable max-statements -- required to test entire flow */ + +import { assert } from 'chai' + +import { + type MPTokenAuthorize, + type MPTokenIssuanceCreate, + type Payment, + type TxResponse, + type VaultCreate, + type VaultDeposit, + type LoanBrokerSet, + type LoanBrokerDelete, + type LoanBrokerCoverDeposit, + type LoanBrokerCoverWithdraw, + type LoanBrokerCoverClawback, + Wallet, + type LoanSet, + type LoanDelete, + type LoanManage, + type LoanPay, + verifySignature, + type SignerListSet, + LoanManageFlags, + type MPTAmount, + signLoanSetByCounterparty, + combineLoanSetCounterpartySigners, +} from '../../../src' +import { + LoanFlags, + type Loan, + type LoanBroker, +} from '../../../src/models/ledger' +import { type MPTokenIssuanceCreateMetadata } from '../../../src/models/transactions/MPTokenIssuanceCreate' +import { hashLoan, hashLoanBroker, hashVault } from '../../../src/utils/hashes' +import serverUrl from '../serverUrl' +import { + setupClient, + teardownClient, + type XrplIntegrationTestContext, +} from '../setup' +import { generateFundedWallet, testTransaction } from '../utils' + +interface VaultObject { + mptIssuanceId: string + vaultObjectId: string +} + +// how long before each test case times out +const TIMEOUT = 20000 + +describe('Lending Protocol IT', () => { + let testContext: XrplIntegrationTestContext + + beforeEach(async () => { + testContext = await setupClient(serverUrl) + }, TIMEOUT) + + afterEach(async () => { + await teardownClient(testContext) + }, TIMEOUT) + + it( + 'Lending protocol integration test with single signing', + async () => { + const vaultOwnerWallet = await generateFundedWallet(testContext.client) + const depositorWallet = await generateFundedWallet(testContext.client) + const borrowerWallet = await generateFundedWallet(testContext.client) + + // The Vault Owner and Loan Broker must be on the same account. + const loanBrokerWallet = vaultOwnerWallet + + // ========== STEP 1: Create Vault ========== + // The vault is the pool of funds that the loan broker will lend from + const vaultCreateTx: VaultCreate = { + TransactionType: 'VaultCreate', + Asset: { + currency: 'XRP', + }, + Account: vaultOwnerWallet.address, + AssetsMaximum: '1e17', + } + + const vaultCreateResp = await testTransaction( + testContext.client, + vaultCreateTx, + vaultOwnerWallet, + ) + + const vaultObjectId = hashVault( + vaultCreateResp.result.tx_json.Account, + vaultCreateResp.result.tx_json.Sequence as number, + ) + + // ========== STEP 2: Deposit Funds into Vault ========== + // The depositor funds the vault with 10 XRP that will be lent to borrowers + const vaultDepositTx: VaultDeposit = { + TransactionType: 'VaultDeposit', + Account: depositorWallet.address, + VaultID: vaultObjectId, + Amount: '10000000', + } + + await testTransaction(testContext.client, vaultDepositTx, depositorWallet) + + // ========== STEP 3: Create Loan Broker ========== + // The loan broker manages the lending protocol and sets debt limits + const loanBrokerSetTx: LoanBrokerSet = { + TransactionType: 'LoanBrokerSet', + Account: loanBrokerWallet.address, + VaultID: vaultObjectId, + DebtMaximum: '25000000', + ManagementFeeRate: 10000, + } + + const loanBrokerTxResp = await testTransaction( + testContext.client, + loanBrokerSetTx, + loanBrokerWallet, + ) + + const loanBrokerObjectId = hashLoanBroker( + loanBrokerTxResp.result.tx_json.Account, + loanBrokerTxResp.result.tx_json.Sequence as number, + ) + + // Verify LoanBroker object was created + const loanBrokerObjects = await testContext.client.request({ + command: 'account_objects', + account: loanBrokerWallet.address, + type: 'loan_broker', + }) + + const loanBrokerObject: LoanBroker = + loanBrokerObjects.result.account_objects.find( + (obj) => obj.index === loanBrokerObjectId, + ) as LoanBroker + + assert.equal(loanBrokerObject.index, loanBrokerObjectId) + assert.equal(loanBrokerObject.DebtMaximum, loanBrokerSetTx.DebtMaximum) + + // ========== STEP 4: Create Loan ========== + // The loan broker initiates a loan for the borrower + // This requires dual signatures: broker and borrower + let loanSetTx: LoanSet = { + TransactionType: 'LoanSet', + Account: loanBrokerWallet.address, + LoanBrokerID: loanBrokerObjectId, + PrincipalRequested: '5000000', + Counterparty: borrowerWallet.address, + PaymentTotal: 3, + Data: '010203', + } + loanSetTx = await testContext.client.autofill(loanSetTx) + const { tx_blob } = loanBrokerWallet.sign(loanSetTx) + + assert.isTrue(verifySignature(tx_blob)) + + const { tx: borrowerSignedTx } = signLoanSetByCounterparty( + borrowerWallet, + tx_blob, + ) + + await testTransaction( + testContext.client, + borrowerSignedTx, + loanBrokerWallet, + ) + + const loanObjectId = hashLoan( + loanBrokerObjectId, + loanBrokerObject.LoanSequence, + ) + const loanObjects = await testContext.client.request({ + command: 'account_objects', + account: borrowerWallet.address, + type: 'loan', + }) + + const loanObject: Loan = loanObjects.result.account_objects.find( + (obj) => obj.index === loanObjectId, + ) as Loan + + // Verify Loan object was created with correct fields + assert.equal(loanObject.index, loanObjectId) + assert.equal( + loanObject.PrincipalOutstanding, + loanSetTx.PrincipalRequested, + ) + assert.equal(loanObject.LoanBrokerID, loanBrokerObject.index) + assert.equal(loanObject.Borrower, borrowerWallet.address) + assert.equal(loanObject.PaymentRemaining, loanSetTx.PaymentTotal) + + // ========== STEP 5: Make Loan Payment ========== + // Borrower makes a periodic payment on the loan + const paymentAmount = '2500000' + const loanPayTx: LoanPay = { + TransactionType: 'LoanPay', + Account: borrowerWallet.address, + LoanID: loanObjectId, + Amount: paymentAmount, + } + + await testTransaction(testContext.client, loanPayTx, borrowerWallet) + + // Verify loan state after payment + const updatedLoanObjects = await testContext.client.request({ + command: 'account_objects', + account: borrowerWallet.address, + type: 'loan', + }) + + const paidLoan: Loan = updatedLoanObjects.result.account_objects.find( + (obj) => obj.index === loanObjectId, + ) as Loan + + // After payment, the principal outstanding should be reduced + assert.isTrue( + parseInt(paidLoan.PrincipalOutstanding, 10) < + parseInt(loanObject.PrincipalOutstanding, 10), + 'Principal should decrease after payment', + ) + // Payment remaining should be decremented + assert.equal( + paidLoan.PaymentRemaining, + loanObject.PaymentRemaining - 1, + 'Payment remaining should decrease by 1', + ) + + // assert principal outstanding is not zero + assert.isTrue( + parseInt(paidLoan.PrincipalOutstanding, 10) > 0, + 'Principal should not be zero', + ) + + assert.equal( + paidLoan.PrincipalOutstanding, + paidLoan.TotalValueOutstanding, + 'Principal should equal TotalValueOutstanding', + ) + + // ManagementFeeOutstanding = (TotalValueOutstanding - PrincipalOutstanding) * ManagementFeeRate + // In this case, ManagementFeeOutstanding should be zero, thus unspecified + assert.isUndefined(paidLoan.ManagementFeeOutstanding) + + // ========== STEP 5B: Make Second Payment with tfLoanFullPayment Flag ========== + // Borrower makes the final payment with tfLoanFullPayment flag + // This flag indicates the borrower is making a full early repayment + const finalPaymentAmount = paidLoan.PrincipalOutstanding + const fullPaymentTx: LoanPay = { + TransactionType: 'LoanPay', + Account: borrowerWallet.address, + LoanID: loanObjectId, + Amount: finalPaymentAmount, + Flags: { + tfLoanFullPayment: true, + }, + } + + await testTransaction(testContext.client, fullPaymentTx, borrowerWallet) + + // Verify loan state after full payment + const finalLoanObjects = await testContext.client.request({ + command: 'account_objects', + account: borrowerWallet.address, + type: 'loan', + }) + + const finalLoan: Loan = finalLoanObjects.result.account_objects.find( + (obj) => obj.index === loanObjectId, + ) as Loan + + assert.isUndefined(finalLoan.PrincipalOutstanding) + assert.isUndefined(finalLoan.PaymentRemaining) + }, + TIMEOUT, + ) + + it( + 'Lending protocol integration test with multi-signing', + async () => { + const vaultOwnerWallet = await generateFundedWallet(testContext.client) + const mptIssuerWallet = await generateFundedWallet(testContext.client) + const depositorWallet = await generateFundedWallet(testContext.client) + const borrowerWallet = await generateFundedWallet(testContext.client) + const signer1 = await generateFundedWallet(testContext.client) + const signer2 = await generateFundedWallet(testContext.client) + + // Setup Multi-Signing + await setupMultiSigning(testContext, borrowerWallet, signer1, signer2) + + // The Vault Owner and Loan Broker must be on the same account. + const loanBrokerWallet = vaultOwnerWallet + + // Create a vault + const vaultObj: VaultObject = await createSingleAssetVault( + testContext, + vaultOwnerWallet, + mptIssuerWallet, + ) + + // Depositor Authorizes to hold MPT + const mptAuthorizeTx: MPTokenAuthorize = { + TransactionType: 'MPTokenAuthorize', + MPTokenIssuanceID: vaultObj.mptIssuanceId, + Account: depositorWallet.address, + } + await testTransaction(testContext.client, mptAuthorizeTx, depositorWallet) + + // Transfer some MPTs from the issuer to depositor + const paymentTx: Payment = { + TransactionType: 'Payment', + Account: mptIssuerWallet.address, + Destination: depositorWallet.address, + Amount: { + mpt_issuance_id: vaultObj.mptIssuanceId, + value: '500000', + }, + } + await testTransaction(testContext.client, paymentTx, mptIssuerWallet) + + // Loan Broker Authorizes to hold MPT + const loanBrokerMptAuthorizeTx: MPTokenAuthorize = { + TransactionType: 'MPTokenAuthorize', + MPTokenIssuanceID: vaultObj.mptIssuanceId, + Account: loanBrokerWallet.address, + } + await testTransaction( + testContext.client, + loanBrokerMptAuthorizeTx, + loanBrokerWallet, + ) + + // Transfer some MPTs from the issuer to Loan Broker + const loanBrokerPaymentTx: Payment = { + TransactionType: 'Payment', + Account: mptIssuerWallet.address, + Destination: loanBrokerWallet.address, + Amount: { + mpt_issuance_id: vaultObj.mptIssuanceId, + value: '500000', + }, + } + await testTransaction( + testContext.client, + loanBrokerPaymentTx, + mptIssuerWallet, + ) + + // Depositor deposits 200000 MPTs into the vault + const depositAmount = '200000' + const vaultDepositTx: VaultDeposit = { + TransactionType: 'VaultDeposit', + Account: depositorWallet.address, + VaultID: vaultObj.vaultObjectId, + Amount: { + mpt_issuance_id: vaultObj.mptIssuanceId, + value: depositAmount, + }, + } + await testTransaction(testContext.client, vaultDepositTx, depositorWallet) + + // Create LoanBroker ledger object to capture attributes of the Lending Protocol + const loanBrokerSetTx: LoanBrokerSet = { + TransactionType: 'LoanBrokerSet', + Account: loanBrokerWallet.address, + VaultID: vaultObj.vaultObjectId, + DebtMaximum: '100000', + } + + const loanBrokerTxResp = await testTransaction( + testContext.client, + loanBrokerSetTx, + loanBrokerWallet, + ) + + const loanBrokerObjectId = hashLoanBroker( + loanBrokerTxResp.result.tx_json.Account, + loanBrokerTxResp.result.tx_json.Sequence as number, + ) + + const loanBrokerObjects = await testContext.client.request({ + command: 'account_objects', + account: loanBrokerWallet.address, + type: 'loan_broker', + }) + + const loanBrokerObject: LoanBroker = + loanBrokerObjects.result.account_objects.find( + (obj) => obj.index === loanBrokerObjectId, + ) as LoanBroker + + // Assert LoanBroker object exists in objects tracked by Lender. + assert.equal(loanBrokerObject.index, loanBrokerObjectId) + assert.equal(loanBrokerObject.DebtMaximum, loanBrokerSetTx.DebtMaximum) + + // Create a Loan object + let loanSetTx: LoanSet = { + TransactionType: 'LoanSet', + Account: loanBrokerWallet.address, + LoanBrokerID: loanBrokerObjectId, + PrincipalRequested: '100000', + InterestRate: 0, + Counterparty: borrowerWallet.address, + PaymentTotal: 1, + } + + // Fails as loan borrower has not signed yet. + await testTransaction( + testContext.client, + loanSetTx, + loanBrokerWallet, + undefined, + 'temBAD_SIGNER', + ) + + // Loan broker signs the transaction and sends it to the borrower + loanSetTx = await testContext.client.autofill(loanSetTx) + const { tx_blob } = loanBrokerWallet.sign(loanSetTx) + + // Borrower first verifies the TxnSignature for to make sure that it came from the loan broker. + assert.isTrue(verifySignature(tx_blob)) + + // Borrower signs the transaction and fills in the CounterpartySignature to confirm the + // loan terms. + const { tx: signer1SignedTx } = signLoanSetByCounterparty( + signer1, + tx_blob, + { multisign: true }, + ) + + const { tx: signer2SignedTx } = signLoanSetByCounterparty( + signer2, + tx_blob, + { multisign: true }, + ) + + const { tx: combinedSignedTx } = combineLoanSetCounterpartySigners([ + signer1SignedTx, + signer2SignedTx, + ]) + + await testTransaction( + testContext.client, + combinedSignedTx, + borrowerWallet, + ) + + // Assert Loan object exists in objects tracked by Borrower. + const loanObjectId = hashLoan( + loanBrokerObjectId, + loanBrokerObject.LoanSequence, + ) + const loanObjects = await testContext.client.request({ + command: 'account_objects', + account: borrowerWallet.address, + type: 'loan', + }) + + let loanObject: Loan = loanObjects.result.account_objects.find( + (obj) => obj.index === loanObjectId, + ) as Loan + + assert.equal(loanObject.index, loanObjectId) + assert.equal( + loanObject.PrincipalOutstanding, + loanSetTx.PrincipalRequested, + ) + assert.equal(loanObject.LoanBrokerID, loanBrokerObject.index) + assert.equal(loanObject.Borrower, borrowerWallet.address) + assert.equal(loanObject.PaymentRemaining, loanSetTx.PaymentTotal) + + // Test LoanBrokerCoverDeposit + const loanBrokerCoverDepositTx: LoanBrokerCoverDeposit = { + TransactionType: 'LoanBrokerCoverDeposit', + Account: loanBrokerWallet.address, + LoanBrokerID: loanBrokerObjectId, + Amount: { + mpt_issuance_id: vaultObj.mptIssuanceId, + value: '50000', + }, + } + await testTransaction( + testContext.client, + loanBrokerCoverDepositTx, + loanBrokerWallet, + ) + + // Assert LoanBroker object has updated CoverAvailable + const loanBrokerCoverDepositResult = await testContext.client.request({ + command: 'ledger_entry', + index: loanBrokerObjectId, + }) + const loanBrokerCoverDepositObject = loanBrokerCoverDepositResult.result + .node as LoanBroker + assert.equal( + loanBrokerCoverDepositObject.CoverAvailable, + (loanBrokerCoverDepositTx.Amount as MPTAmount).value, + ) + + // Test LoanBrokerCoverWithdraw + const loanBrokerCoverWithdrawTx: LoanBrokerCoverWithdraw = { + TransactionType: 'LoanBrokerCoverWithdraw', + Account: loanBrokerWallet.address, + LoanBrokerID: loanBrokerObjectId, + Amount: { + mpt_issuance_id: vaultObj.mptIssuanceId, + value: '25000', + }, + Destination: loanBrokerWallet.address, + DestinationTag: 10, + } + await testTransaction( + testContext.client, + loanBrokerCoverWithdrawTx, + loanBrokerWallet, + ) + + // Assert LoanBroker object has updated CoverAvailable + const loanBrokerCoverWithdrawResult = await testContext.client.request({ + command: 'ledger_entry', + index: loanBrokerObjectId, + }) + const loanBrokerCoverWithdrawObject = loanBrokerCoverWithdrawResult.result + .node as LoanBroker + assert.equal( + loanBrokerCoverWithdrawObject.CoverAvailable, + ( + BigInt(loanBrokerCoverDepositObject.CoverAvailable as string) - + BigInt((loanBrokerCoverWithdrawTx.Amount as MPTAmount).value) + ).toString(), + ) + + // Test LoanManage - Mark loan as impaired + const loanManageTx: LoanManage = { + TransactionType: 'LoanManage', + Account: loanBrokerWallet.address, + LoanID: loanObjectId, + Flags: LoanManageFlags.tfLoanImpair, + } + await testTransaction(testContext.client, loanManageTx, loanBrokerWallet) + + // Assert Loan object is impaired + const loanManageResult = await testContext.client.request({ + command: 'account_objects', + account: borrowerWallet.address, + type: 'loan', + }) + loanObject = loanManageResult.result.account_objects.find( + (obj) => obj.index === loanObjectId, + ) as Loan + assert.equal(loanObject.Flags, LoanFlags.lsfLoanImpaired) + + // Test LoanPay + const loanPayTx: LoanPay = { + TransactionType: 'LoanPay', + Account: borrowerWallet.address, + LoanID: loanObjectId, + Amount: { + mpt_issuance_id: vaultObj.mptIssuanceId, + value: '100000', + }, + } + await testTransaction(testContext.client, loanPayTx, borrowerWallet) + + loanObject = ( + await testContext.client.request({ + command: 'ledger_entry', + index: loanObjectId, + }) + ).result.node as Loan + // Loan gets un-impaired when a payment is made + assert.equal(loanObject.Flags, 0) + // Entire loan is paid off + assert.isUndefined(loanObject.TotalValueOutstanding) + + // Test LoanDelete + const loanDeleteTx: LoanDelete = { + TransactionType: 'LoanDelete', + Account: borrowerWallet.address, + LoanID: loanObjectId, + } + await testTransaction(testContext.client, loanDeleteTx, borrowerWallet) + + // Assert Loan object is deleted + const loanDeleteResult = await testContext.client.request({ + command: 'account_objects', + account: borrowerWallet.address, + type: 'loan', + }) + assert.equal(loanDeleteResult.result.account_objects.length, 0) + + // Test LoanBrokerCoverClawback + const loanBrokerCoverClawbackTx: LoanBrokerCoverClawback = { + TransactionType: 'LoanBrokerCoverClawback', + Account: mptIssuerWallet.address, + LoanBrokerID: loanBrokerObjectId, + Amount: { + mpt_issuance_id: vaultObj.mptIssuanceId, + value: '10000', + }, + } + await testTransaction( + testContext.client, + loanBrokerCoverClawbackTx, + mptIssuerWallet, + ) + const loanBrokerCoverClawbackResult = await testContext.client.request({ + command: 'ledger_entry', + index: loanBrokerObjectId, + }) + + const loanBrokerCoverClawbackObject = loanBrokerCoverClawbackResult.result + .node as LoanBroker + assert.equal( + loanBrokerCoverClawbackObject.CoverAvailable, + ( + BigInt(loanBrokerCoverWithdrawObject.CoverAvailable as string) - + BigInt((loanBrokerCoverClawbackTx.Amount as MPTAmount).value) + ).toString(), + ) + + // Test LoanBrokerDelete + const loanBrokerDeleteTx: LoanBrokerDelete = { + TransactionType: 'LoanBrokerDelete', + Account: loanBrokerWallet.address, + LoanBrokerID: loanBrokerObjectId, + } + await testTransaction( + testContext.client, + loanBrokerDeleteTx, + loanBrokerWallet, + ) + const loanBrokerDeleteResult = await testContext.client.request({ + command: 'account_objects', + account: loanBrokerWallet.address, + type: 'loan_broker', + }) + assert.equal(loanBrokerDeleteResult.result.account_objects.length, 0) + }, + TIMEOUT, + ) +}) + +async function createSingleAssetVault( + testContext: XrplIntegrationTestContext, + vaultOwnerWallet: Wallet, + mptIssuerWallet: Wallet, +): Promise { + const mptIssuanceId = await createMPToken(testContext, mptIssuerWallet) + + const vaultCreateTx: VaultCreate = { + TransactionType: 'VaultCreate', + Asset: { + mpt_issuance_id: mptIssuanceId, + }, + Account: vaultOwnerWallet.address, + } + + const vaultCreateResp = await testTransaction( + testContext.client, + vaultCreateTx, + vaultOwnerWallet, + ) + + const vaultObjectId = hashVault( + vaultCreateResp.result.tx_json.Account, + vaultCreateResp.result.tx_json.Sequence as number, + ) + + return { mptIssuanceId, vaultObjectId } +} + +async function createMPToken( + testContext: XrplIntegrationTestContext, + mptIssuerWallet: Wallet, +): Promise { + const mptCreateTx: MPTokenIssuanceCreate = { + TransactionType: 'MPTokenIssuanceCreate', + Flags: { + tfMPTCanTransfer: true, + tfMPTCanClawback: true, + }, + Account: mptIssuerWallet.address, + } + + const response = await testTransaction( + testContext.client, + mptCreateTx, + mptIssuerWallet, + ) + + const txResponse: TxResponse = await testContext.client.request({ + command: 'tx', + transaction: response.result.tx_json.hash, + }) + + return (txResponse.result.meta as MPTokenIssuanceCreateMetadata) + .mpt_issuance_id as string +} + +// eslint-disable-next-line max-params -- required here for three wallets +async function setupMultiSigning( + testContext: XrplIntegrationTestContext, + wallet: Wallet, + signer1: Wallet, + signer2: Wallet, +): Promise { + const transaction: SignerListSet = { + TransactionType: 'SignerListSet', + Account: wallet.address, + SignerQuorum: 2, + SignerEntries: [ + { SignerEntry: { Account: signer1.address, SignerWeight: 1 } }, + { SignerEntry: { Account: signer2.address, SignerWeight: 1 } }, + ], + } + + await testTransaction(testContext.client, transaction, wallet) +} diff --git a/packages/xrpl/test/integration/transactions/mptokenIssuanceCreate.test.ts b/packages/xrpl/test/integration/transactions/mptokenIssuanceCreate.test.ts index 59088d8dd9..51208dad55 100644 --- a/packages/xrpl/test/integration/transactions/mptokenIssuanceCreate.test.ts +++ b/packages/xrpl/test/integration/transactions/mptokenIssuanceCreate.test.ts @@ -1,6 +1,11 @@ import { assert } from 'chai' -import { MPTokenIssuanceCreate } from '../../../src' +import { + decodeMPTokenMetadata, + encodeMPTokenMetadata, + MPTokenIssuanceCreate, + MPTokenMetadata, +} from '../../../src' import serverUrl from '../serverUrl' import { setupClient, @@ -23,12 +28,41 @@ describe('MPTokenIssuanceCreate', function () { it( 'base', async () => { + const metadata: MPTokenMetadata = { + ticker: 'TBILL', + name: 'T-Bill Yield Token', + desc: 'A yield-bearing stablecoin backed by short-term U.S. Treasuries and money market instruments.', + icon: 'example.org/tbill-icon.png', + asset_class: 'rwa', + asset_subclass: 'treasury', + issuer_name: 'Example Yield Co.', + uris: [ + { + uri: 'exampleyield.co/tbill', + category: 'website', + title: 'Product Page', + }, + { + uri: 'exampleyield.co/docs', + category: 'docs', + title: 'Yield Token Docs', + }, + ], + additional_info: { + interest_rate: '5.00%', + interest_type: 'variable', + yield_source: 'U.S. Treasury Bills', + maturity_date: '2045-06-30', + cusip: '912796RX0', + }, + } const tx: MPTokenIssuanceCreate = { TransactionType: 'MPTokenIssuanceCreate', Account: testContext.wallet.classicAddress, // 0x7fffffffffffffff MaximumAmount: '9223372036854775807', AssetScale: 2, + MPTokenMetadata: encodeMPTokenMetadata(metadata), } await testTransaction(testContext.client, tx, testContext.wallet) @@ -48,6 +82,14 @@ describe('MPTokenIssuanceCreate', function () { accountObjectsResponse.result.account_objects[0].MaximumAmount, `9223372036854775807`, ) + + assert.deepStrictEqual( + decodeMPTokenMetadata( + // @ts-expect-error: Known issue with unknown object type + accountObjectsResponse.result.account_objects[0].MPTokenMetadata, + ), + metadata, + ) }, TIMEOUT, ) diff --git a/packages/xrpl/test/integration/transactions/oracleDelete.test.ts b/packages/xrpl/test/integration/transactions/oracleDelete.test.ts index b3452e0469..6dddeb8e8a 100644 --- a/packages/xrpl/test/integration/transactions/oracleDelete.test.ts +++ b/packages/xrpl/test/integration/transactions/oracleDelete.test.ts @@ -24,11 +24,18 @@ describe('OracleDelete', function () { it( 'base', async () => { + const closeTime: string = ( + await testContext.client.request({ + command: 'ledger', + ledger_index: 'validated', + }) + ).result.ledger.close_time_iso + const setTx: OracleSet = { TransactionType: 'OracleSet', Account: testContext.wallet.classicAddress, OracleDocumentID: 1234, - LastUpdateTime: Math.floor(Date.now() / 1000), + LastUpdateTime: Math.floor(new Date(closeTime).getTime() / 1000) + 20, PriceDataSeries: [ { PriceData: { diff --git a/packages/xrpl/test/integration/transactions/oracleSet.test.ts b/packages/xrpl/test/integration/transactions/oracleSet.test.ts index f1c79b86e5..2c103bb059 100644 --- a/packages/xrpl/test/integration/transactions/oracleSet.test.ts +++ b/packages/xrpl/test/integration/transactions/oracleSet.test.ts @@ -25,11 +25,18 @@ describe('OracleSet', function () { it( 'base', async () => { + const closeTime: string = ( + await testContext.client.request({ + command: 'ledger', + ledger_index: 'validated', + }) + ).result.ledger.close_time_iso + const tx: OracleSet = { TransactionType: 'OracleSet', Account: testContext.wallet.classicAddress, OracleDocumentID: 1234, - LastUpdateTime: Math.floor(Date.now() / 1000), + LastUpdateTime: Math.floor(new Date(closeTime).getTime() / 1000) + 20, PriceDataSeries: [ { PriceData: { diff --git a/packages/xrpl/test/integration/transactions/singleAssetVault.test.ts b/packages/xrpl/test/integration/transactions/singleAssetVault.test.ts index f0d5493eb5..1c14292dc6 100644 --- a/packages/xrpl/test/integration/transactions/singleAssetVault.test.ts +++ b/packages/xrpl/test/integration/transactions/singleAssetVault.test.ts @@ -4,11 +4,16 @@ import { assert } from 'chai' import { AccountSet, AccountSetAsfFlags, + MPTCurrency, + MPTokenAuthorize, + MPTokenIssuanceCreate, Payment, TrustSet, TrustSetFlags, + TxResponse, VaultClawback, VaultCreate, + VaultCreateFlags, VaultDelete, VaultDeposit, VaultSet, @@ -17,7 +22,8 @@ import { Wallet, XRP, } from '../../../src' -import { Vault } from '../../../src/models/ledger' +import { Vault, VaultFlags } from '../../../src/models/ledger' +import { MPTokenIssuanceCreateMetadata } from '../../../src/models/transactions/MPTokenIssuanceCreate' import serverUrl from '../serverUrl' import { setupClient, @@ -37,7 +43,7 @@ describe('Single Asset Vault', function () { beforeEach(async () => { testContext = await setupClient(serverUrl) - issuerWallet = testContext.wallet + issuerWallet = await generateFundedWallet(testContext.client) vaultOwnerWallet = await generateFundedWallet(testContext.client) holderWallet = await generateFundedWallet(testContext.client) }) @@ -72,7 +78,7 @@ describe('Single Asset Vault', function () { LimitAmount: { currency: currencyCode, issuer: issuerWallet.classicAddress, - value: '1000', + value: '9999999999999999e80', }, } @@ -85,7 +91,7 @@ describe('Single Asset Vault', function () { Amount: { currency: currencyCode, issuer: issuerWallet.classicAddress, - value: '1000', + value: '9999999999', }, } @@ -103,9 +109,8 @@ describe('Single Asset Vault', function () { VaultWithdrawalPolicy.vaultStrategyFirstComeFirstServe, Data: stringToHex('vault metadata'), MPTokenMetadata: stringToHex('share metadata'), - AssetsMaximum: '500', - // This covers owner reserve fee with potentially high open_ledger_cost - Fee: '5000000', + AssetsMaximum: '9999900000000000000000000', + Scale: 2, } await testTransaction(testContext.client, tx, vaultOwnerWallet) @@ -131,7 +136,8 @@ describe('Single Asset Vault', function () { VaultWithdrawalPolicy.vaultStrategyFirstComeFirstServe, ) assert.equal(vault.Data, tx.Data) - assert.equal(assetsMaximum, '500') + assert.equal(assetsMaximum, '99999e20') + assert.equal(vault.Scale, 2) // --- VaultSet Transaction --- // Increase the AssetsMaximum to 1000 and update Data @@ -185,7 +191,7 @@ describe('Single Asset Vault', function () { // Should have new balance after deposit (this assumes AssetsTotal tracks deposits) assert.equal( - afterDepositVault.AssetsTotal, + afterDepositVault.AssetsTotal ?? '0', depositAmount, 'Vault should reflect deposited assets', ) @@ -202,6 +208,8 @@ describe('Single Asset Vault', function () { issuer: issuerWallet.classicAddress, value: withdrawAmount, }, + Destination: holderWallet.classicAddress, + DestinationTag: 10, Fee: '5000000', } @@ -218,9 +226,9 @@ describe('Single Asset Vault', function () { // Should have reduced balance after withdrawal (should be 0 if all withdrawn) assert.equal( - afterWithdrawVault.AssetsTotal, + afterWithdrawVault.AssetsTotal ?? '0', ( - BigInt(afterDepositVault.AssetsTotal) - BigInt(withdrawAmount) + BigInt(afterDepositVault.AssetsTotal ?? '0') - BigInt(withdrawAmount) ).toString(), 'Vault should reflect withdrawn assets', ) @@ -243,6 +251,250 @@ describe('Single Asset Vault', function () { await testTransaction(testContext.client, vaultClawbackTx, issuerWallet) + // Fetch the vault again to confirm clawback + const afterClawbackResult = await testContext.client.request({ + command: 'account_objects', + account: vaultOwnerWallet.classicAddress, + type: 'vault', + }) + + const afterClawbackVault = afterClawbackResult.result + .account_objects[0] as Vault + + assert.equal( + afterClawbackVault.AssetsTotal ?? '0', + ( + BigInt(afterWithdrawVault.AssetsTotal ?? '0') - BigInt(clawbackAmount) + ).toString(), + 'Vault should reflect assets after clawback', + ) + + // --- VaultDelete Transaction --- + const vaultDeleteTx: VaultDelete = { + TransactionType: 'VaultDelete', + Account: vaultOwnerWallet.classicAddress, + VaultID: vaultId, + Fee: '5000000', + } + + await testTransaction(testContext.client, vaultDeleteTx, vaultOwnerWallet) + + // Fetch the vault again to confirm deletion (should be empty) + const afterDeleteResult = await testContext.client.request({ + command: 'account_objects', + account: vaultOwnerWallet.classicAddress, + type: 'vault', + }) + + assert.equal( + afterDeleteResult.result.account_objects.length, + 0, + 'Vault should be deleted from account objects', + ) + }, + TIMEOUT, + ) + + it( + 'MPT in vault', + // eslint-disable-next-line max-statements -- needed to test all Vault transactions in one sequence flow + async () => { + // --- Issue MPT --- + const mptCreateTx: MPTokenIssuanceCreate = { + TransactionType: 'MPTokenIssuanceCreate', + AssetScale: 2, + Flags: { + tfMPTCanTransfer: true, + tfMPTCanClawback: true, + }, + Account: issuerWallet.address, + } + + const response = await testTransaction( + testContext.client, + mptCreateTx, + issuerWallet, + ) + + const txResponse: TxResponse = await testContext.client.request({ + command: 'tx', + transaction: response.result.tx_json.hash, + }) + + const mptIssuanceId = ( + txResponse.result.meta as MPTokenIssuanceCreateMetadata + ).mpt_issuance_id as string + + // --- Holder Authorizes to hold MPT --- + const mptAuthorizeTx: MPTokenAuthorize = { + TransactionType: 'MPTokenAuthorize', + MPTokenIssuanceID: mptIssuanceId, + Account: holderWallet.classicAddress, + } + + await testTransaction(testContext.client, mptAuthorizeTx, holderWallet) + + // --- Send some MPTs to Holder --- + const paymentTx: Payment = { + TransactionType: 'Payment', + Account: issuerWallet.classicAddress, + Destination: holderWallet.classicAddress, + Amount: { + mpt_issuance_id: mptIssuanceId, + value: '1000', + }, + } + + await testTransaction(testContext.client, paymentTx, issuerWallet) + + // --- VaultCreate --- + const vaultCreateTx: VaultCreate = { + TransactionType: 'VaultCreate', + Account: vaultOwnerWallet.classicAddress, + Asset: { + mpt_issuance_id: mptIssuanceId, + }, + WithdrawalPolicy: + VaultWithdrawalPolicy.vaultStrategyFirstComeFirstServe, + Data: stringToHex('vault metadata'), + MPTokenMetadata: stringToHex('share metadata'), + AssetsMaximum: '500', + Flags: VaultCreateFlags.tfVaultShareNonTransferable, + } + + await testTransaction(testContext.client, vaultCreateTx, vaultOwnerWallet) + + const result = await testContext.client.request({ + command: 'account_objects', + account: vaultOwnerWallet.classicAddress, + type: 'vault', + }) + const vault = result.result.account_objects[0] as Vault + const vaultId = vault.index + const asset = vault.Asset as MPTCurrency + const assetsMaximum = vault.AssetsMaximum as string + const vaultFlags = vault.Flags + + // confirm that the Vault was actually created + assert.equal(result.result.account_objects.length, 1) + assert.isDefined(vault, 'Vault ledger object should exist') + assert.equal(vault.Owner, vaultOwnerWallet.classicAddress) + assert.equal(asset.mpt_issuance_id, mptIssuanceId) + assert.equal( + vault.WithdrawalPolicy, + VaultWithdrawalPolicy.vaultStrategyFirstComeFirstServe, + ) + assert.equal(vault.Data, vaultCreateTx.Data) + assert.equal(assetsMaximum, '500') + assert.notEqual(vaultFlags, VaultFlags.lsfVaultPrivate) + + // --- VaultSet Transaction --- + // Increase the AssetsMaximum to 1000 and update Data + const vaultSetTx: VaultSet = { + TransactionType: 'VaultSet', + Account: vaultOwnerWallet.classicAddress, + VaultID: vaultId, + AssetsMaximum: '1000', + Data: stringToHex('updated metadata'), + Fee: '5000000', + } + + await testTransaction(testContext.client, vaultSetTx, vaultOwnerWallet) + + // Fetch the vault again to confirm updates + const updatedResult = await testContext.client.request({ + command: 'account_objects', + account: vaultOwnerWallet.classicAddress, + type: 'vault', + }) + const updatedVault = updatedResult.result.account_objects[0] as Vault + + assert.equal(updatedVault.AssetsMaximum, '1000') + assert.equal(updatedVault.Data, stringToHex('updated metadata')) + + // --- VaultDeposit Transaction --- + // Deposit 10 MPT to the vault + const depositAmount = '10' + const vaultDepositTx: VaultDeposit = { + TransactionType: 'VaultDeposit', + Account: holderWallet.classicAddress, + VaultID: vaultId, + Amount: { + mpt_issuance_id: mptIssuanceId, + value: depositAmount, + }, + Fee: '5000000', + } + + await testTransaction(testContext.client, vaultDepositTx, holderWallet) + + // Fetch the vault again to confirm deposit + const afterDepositResult = await testContext.client.request({ + command: 'account_objects', + account: vaultOwnerWallet.classicAddress, + type: 'vault', + }) + const afterDepositVault = afterDepositResult.result + .account_objects[0] as Vault + + // Should have new balance after deposit (this assumes AssetsTotal tracks deposits) + assert.equal( + afterDepositVault.AssetsTotal, + depositAmount, + 'Vault should reflect deposited assets', + ) + + // --- VaultWithdraw Transaction --- + // Withdraw 5 MPT from the vault + const withdrawAmount = '5' + const vaultWithdrawTx: VaultWithdraw = { + TransactionType: 'VaultWithdraw', + Account: holderWallet.classicAddress, + VaultID: vaultId, + Amount: { + mpt_issuance_id: mptIssuanceId, + value: withdrawAmount, + }, + Fee: '5000000', + } + + await testTransaction(testContext.client, vaultWithdrawTx, holderWallet) + + // Fetch the vault again to confirm withdrawal + const afterWithdrawResult = await testContext.client.request({ + command: 'account_objects', + account: vaultOwnerWallet.classicAddress, + type: 'vault', + }) + const afterWithdrawVault = afterWithdrawResult.result + .account_objects[0] as Vault + + // Should have reduced balance after withdrawal (should be 0 if all withdrawn) + assert.equal( + afterWithdrawVault.AssetsTotal ?? '0', + ( + BigInt(afterDepositVault.AssetsTotal ?? '0') - BigInt(withdrawAmount) + ).toString(), + 'Vault should reflect withdrawn assets', + ) + + // --- VaultClawback Transaction --- + // Claw back 5 MPT from the vault + const clawbackAmount = '5' + const vaultClawbackTx: VaultClawback = { + TransactionType: 'VaultClawback', + Account: issuerWallet.classicAddress, + VaultID: vaultId, + Holder: holderWallet.classicAddress, + Amount: { + mpt_issuance_id: mptIssuanceId, + value: clawbackAmount, + }, + Fee: '5000000', + } + + await testTransaction(testContext.client, vaultClawbackTx, issuerWallet) + // Fetch the vault again to confirm clawback const afterClawbackResult = await testContext.client.request({ command: 'account_objects', @@ -253,9 +505,9 @@ describe('Single Asset Vault', function () { .account_objects[0] as Vault assert.equal( - afterClawbackVault.AssetsTotal, + afterClawbackVault.AssetsTotal ?? '0', ( - BigInt(afterWithdrawVault.AssetsTotal) - BigInt(clawbackAmount) + BigInt(afterWithdrawVault.AssetsTotal ?? '0') - BigInt(clawbackAmount) ).toString(), 'Vault should reflect assets after clawback', ) diff --git a/packages/xrpl/test/integration/utils.ts b/packages/xrpl/test/integration/utils.ts index 075fed251f..078432c4bf 100644 --- a/packages/xrpl/test/integration/utils.ts +++ b/packages/xrpl/test/integration/utils.ts @@ -93,6 +93,38 @@ export function subscribeDone(client: Client): void { client.removeAllListeners() } +/** + * Checks if a specific amendment is enabled on the server. + * + * @param client - The XRPL client. + * @param amendmentName - The name of the amendment to check (e.g., 'PermissionDelegation'). + * @returns True if the amendment is enabled, false otherwise. + */ +export async function isAmendmentEnabled( + client: Client, + amendmentName: string, +): Promise { + try { + const featureResponse = await client.request({ + command: 'feature', + }) + + // Search through all features to find the one with the matching name + const features = featureResponse.result.features + for (const feature of Object.values(features)) { + if (feature.name === amendmentName) { + return feature.enabled + } + } + + // Amendment not found + return false + } catch (error) { + // If the feature command fails, assume the amendment is not enabled + return false + } +} + export async function submitTransaction({ client, transaction, diff --git a/packages/xrpl/test/models/MPTokenIssuanceCreate.test.ts b/packages/xrpl/test/models/MPTokenIssuanceCreate.test.ts index 85fc972c68..d127183c19 100644 --- a/packages/xrpl/test/models/MPTokenIssuanceCreate.test.ts +++ b/packages/xrpl/test/models/MPTokenIssuanceCreate.test.ts @@ -1,11 +1,11 @@ import { stringToHex } from '@transia/isomorphic/src/utils' import { MPTokenIssuanceCreateFlags, MPTokenMetadata } from '../../src' +import { validateMPTokenIssuanceCreate } from '../../src/models/transactions/MPTokenIssuanceCreate' import { MAX_MPT_META_BYTE_LENGTH, MPT_META_WARNING_HEADER, -} from '../../src/models/transactions/common' -import { validateMPTokenIssuanceCreate } from '../../src/models/transactions/MPTokenIssuanceCreate' +} from '../../src/models/utils/mptokenMetadata' import { assertTxIsValid, assertTxValidationError } from '../testUtils' const assertValid = (tx: any): void => @@ -164,7 +164,8 @@ describe('MPTokenMetadata warnings', function () { asset_class: 'rwa', asset_subclass: 'treasury', issuer_name: 'Issuer', - } + uris: ['apple'], + } as unknown as MPTokenMetadata const tx = { TransactionType: 'MPTokenIssuanceCreate', Account: 'rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm', @@ -175,7 +176,7 @@ describe('MPTokenMetadata warnings', function () { const expectedMessage = [ MPT_META_WARNING_HEADER, - '- icon should be a valid https url.', + '- uris/us: should be an array of objects each with uri/u, category/c, and title/t properties.', ].join('\n') expect(console.warn).toHaveBeenCalledWith( diff --git a/packages/xrpl/test/models/loanBrokerCoverClawback.test.ts b/packages/xrpl/test/models/loanBrokerCoverClawback.test.ts new file mode 100644 index 0000000000..7bd9a99fbf --- /dev/null +++ b/packages/xrpl/test/models/loanBrokerCoverClawback.test.ts @@ -0,0 +1,57 @@ +import { validateLoanBrokerCoverClawback } from '../../src/models/transactions/loanBrokerCoverClawback' +import { assertTxIsValid, assertTxValidationError } from '../testUtils' + +const assertValid = (tx: any): void => + assertTxIsValid(tx, validateLoanBrokerCoverClawback) + +const assertInvalid = (tx: any, errorMessage: string): void => + assertTxValidationError(tx, validateLoanBrokerCoverClawback, errorMessage) + +describe('unit test LoanBrokerCoverClawback', () => { + let tx: any + + beforeEach(() => { + tx = { + TransactionType: 'LoanBrokerCoverClawback', + LoanBrokerID: + 'E9A08C918E26407493CC4ADD381BA979CFEB7E440D0863B01FB31C231D167E42', + Account: 'rPGxCzMicNJRe1U1CD5QyNjXdLUtdgSa7B', + Amount: { + mpt_issuance_id: '0000012FFD9EE5DA93AC614B4DB94D7E0FCE415CA51BED47', + value: '1000000', + }, + } + }) + + test('valid tx', () => { + assertValid(tx) + }) + + test('incorrect LoanBrokerID', () => { + tx.LoanBrokerID = 'INCORRECT_VALUE' + assertInvalid( + tx, + 'LoanBrokerCoverClawback: LoanBrokerID must be 64 characters hexadecimal string', + ) + }) + + test('incorrect Amount', () => { + tx.Amount = { + mpt_issuanceId: '0000012FFD9EE5DA93AC614B4DB94D7E0FCE415CA51BED47', + value: '1000000', + } + assertInvalid(tx, 'LoanBrokerCoverClawback: invalid field Amount') + + tx.Amount = '100' + assertInvalid(tx, 'LoanBrokerCoverClawback: invalid field Amount') + }) + + test('missing LoanBrokerId and Amount', () => { + delete tx.LoanBrokerID + delete tx.Amount + assertInvalid( + tx, + 'LoanBrokerCoverClawback: Either LoanBrokerID or Amount is required', + ) + }) +}) diff --git a/packages/xrpl/test/models/loanBrokerCoverDeposit.test.ts b/packages/xrpl/test/models/loanBrokerCoverDeposit.test.ts new file mode 100644 index 0000000000..fac3bcc802 --- /dev/null +++ b/packages/xrpl/test/models/loanBrokerCoverDeposit.test.ts @@ -0,0 +1,51 @@ +import { validateLoanBrokerCoverDeposit } from '../../src/models/transactions/loanBrokerCoverDeposit' +import { assertTxIsValid, assertTxValidationError } from '../testUtils' + +const assertValid = (tx: any): void => + assertTxIsValid(tx, validateLoanBrokerCoverDeposit) + +const assertInvalid = (tx: any, errorMessage: string): void => + assertTxValidationError(tx, validateLoanBrokerCoverDeposit, errorMessage) + +describe('unit test LoanBrokerCoverDeposit', () => { + let tx: any + + beforeEach(() => { + tx = { + TransactionType: 'LoanBrokerCoverDeposit', + LoanBrokerID: + 'E9A08C918E26407493CC4ADD381BA979CFEB7E440D0863B01FB31C231D167E42', + Account: 'rPGxCzMicNJRe1U1CD5QyNjXdLUtdgSa7B', + Amount: { + mpt_issuance_id: '0000012FFD9EE5DA93AC614B4DB94D7E0FCE415CA51BED47', + value: '1000000', + }, + } + }) + + test('valid tx', () => { + assertValid(tx) + }) + + test('incorrect LoanBrokerID', () => { + tx.LoanBrokerID = 'INCORRECT_VALUE' + assertInvalid( + tx, + 'LoanBrokerCoverDeposit: LoanBrokerID must be 64 characters hexadecimal string', + ) + + delete tx.LoanBrokerID + assertInvalid(tx, 'LoanBrokerCoverDeposit: missing field LoanBrokerID') + }) + + test('incorrect Amount', () => { + tx.Amount = { + mpt_issuanceId: '0000012FFD9EE5DA93AC614B4DB94D7E0FCE415CA51BED47', + value: '1000000', + } + assertInvalid(tx, 'LoanBrokerCoverDeposit: invalid field Amount') + + delete tx.Amount + assertInvalid(tx, 'LoanBrokerCoverDeposit: missing field Amount') + }) +}) diff --git a/packages/xrpl/test/models/loanBrokerCoverWithdraw.test.ts b/packages/xrpl/test/models/loanBrokerCoverWithdraw.test.ts new file mode 100644 index 0000000000..5e82d972f9 --- /dev/null +++ b/packages/xrpl/test/models/loanBrokerCoverWithdraw.test.ts @@ -0,0 +1,52 @@ +import { validateLoanBrokerCoverWithdraw } from '../../src/models/transactions/loanBrokerCoverWithdraw' +import { assertTxIsValid, assertTxValidationError } from '../testUtils' + +const assertValid = (tx: any): void => + assertTxIsValid(tx, validateLoanBrokerCoverWithdraw) + +const assertInvalid = (tx: any, errorMessage: string): void => + assertTxValidationError(tx, validateLoanBrokerCoverWithdraw, errorMessage) + +describe('unit test LoanBrokerCoverWithdraw', () => { + let tx: any + + beforeEach(() => { + tx = { + TransactionType: 'LoanBrokerCoverWithdraw', + LoanBrokerID: + 'E9A08C918E26407493CC4ADD381BA979CFEB7E440D0863B01FB31C231D167E42', + Account: 'rPGxCzMicNJRe1U1CD5QyNjXdLUtdgSa7B', + Amount: { + mpt_issuance_id: '0000012FFD9EE5DA93AC614B4DB94D7E0FCE415CA51BED47', + value: '1000000', + }, + Destination: 'rPvt4Ff6G7Y1kxjk6h3jjwTvtmDSaNa8Wh', + } + }) + + test('valid tx', () => { + assertValid(tx) + }) + + test('incorrect LoanBrokerID', () => { + tx.LoanBrokerID = 'INCORRECT_VALUE' + assertInvalid( + tx, + 'LoanBrokerCoverWithdraw: LoanBrokerID must be 64 characters hexadecimal string', + ) + + delete tx.LoanBrokerID + assertInvalid(tx, 'LoanBrokerCoverWithdraw: missing field LoanBrokerID') + }) + + test('incorrect Amount', () => { + tx.Amount = { + mpt_issuanceId: '0000012FFD9EE5DA93AC614B4DB94D7E0FCE415CA51BED47', + value: '1000000', + } + assertInvalid(tx, 'LoanBrokerCoverWithdraw: invalid field Amount') + + delete tx.Amount + assertInvalid(tx, 'LoanBrokerCoverWithdraw: missing field Amount') + }) +}) diff --git a/packages/xrpl/test/models/loanBrokerDelete.test.ts b/packages/xrpl/test/models/loanBrokerDelete.test.ts new file mode 100644 index 0000000000..3584bbd029 --- /dev/null +++ b/packages/xrpl/test/models/loanBrokerDelete.test.ts @@ -0,0 +1,36 @@ +import { validateLoanBrokerDelete } from '../../src/models/transactions/loanBrokerDelete' +import { assertTxIsValid, assertTxValidationError } from '../testUtils' + +const assertValid = (tx: any): void => + assertTxIsValid(tx, validateLoanBrokerDelete) + +const assertInvalid = (tx: any, errorMessage: string): void => + assertTxValidationError(tx, validateLoanBrokerDelete, errorMessage) + +describe('unit test LoanBrokerDelete', () => { + let tx: any + + beforeEach(() => { + tx = { + TransactionType: 'LoanBrokerDelete', + LoanBrokerID: + 'E9A08C918E26407493CC4ADD381BA979CFEB7E440D0863B01FB31C231D167E42', + Account: 'rPGxCzMicNJRe1U1CD5QyNjXdLUtdgSa7B', + } + }) + + test('valid tx', () => { + assertValid(tx) + }) + + test('incorrect LoanBrokerID', () => { + tx.LoanBrokerID = 'INCORRECT_VALUE' + assertInvalid( + tx, + 'LoanBrokerDelete: LoanBrokerID must be 64 characters hexadecimal string', + ) + + delete tx.LoanBrokerID + assertInvalid(tx, 'LoanBrokerDelete: missing field LoanBrokerID') + }) +}) diff --git a/packages/xrpl/test/models/loanBrokerSet.test.ts b/packages/xrpl/test/models/loanBrokerSet.test.ts new file mode 100644 index 0000000000..1243c7f749 --- /dev/null +++ b/packages/xrpl/test/models/loanBrokerSet.test.ts @@ -0,0 +1,130 @@ +import { validateLoanBrokerSet } from '../../src/models/transactions/loanBrokerSet' +import { assertTxIsValid, assertTxValidationError } from '../testUtils' + +const assertValid = (tx: any): void => + assertTxIsValid(tx, validateLoanBrokerSet) + +const assertInvalid = (tx: any, errorMessage: string): void => + assertTxValidationError(tx, validateLoanBrokerSet, errorMessage) + +describe('unit test LoanBrokerSet', () => { + let tx: any + + beforeEach(() => { + tx = { + TransactionType: 'LoanBrokerSet', + VaultID: + '000004D417A9CE049C9A71A62B004659B5F1AAAB1BEA1EFDE4E01EB3497FD999', + LoanBrokerID: + 'E9A08C918E26407493CC4ADD381BA979CFEB7E440D0863B01FB31C231D167E42', + Data: 'ABCD', + ManagementFeeRate: 500, + DebtMaximum: '10e10', + CoverRateMinimum: 50, + CoverRateLiquidation: 20, + Account: 'rPGxCzMicNJRe1U1CD5QyNjXdLUtdgSa7B', + } + }) + + test('valid tx', () => { + assertValid(tx) + }) + + test('incorrect VaultID', () => { + tx.VaultID = 'INCORRECT_VALUE' + assertInvalid( + tx, + 'LoanBrokerSet: VaultID must be 64 characters hexadecimal string', + ) + + delete tx.VaultID + assertInvalid(tx, 'LoanBrokerSet: missing field VaultID') + }) + + test('incorrect LoanBrokerID', () => { + tx.LoanBrokerID = 'INCORRECT_VALUE' + assertInvalid( + tx, + 'LoanBrokerSet: LoanBrokerID must be 64 characters hexadecimal string', + ) + }) + + test('incorrect Data', () => { + tx.Data = 'INCORRECT_VALUE' + assertInvalid( + tx, + 'LoanBrokerSet: Data must be a valid non-empty hex string up to 512 characters', + ) + + tx.Data = '' + assertInvalid( + tx, + 'LoanBrokerSet: Data must be a valid non-empty hex string up to 512 characters', + ) + + tx.Data = 'A'.repeat(513) + assertInvalid( + tx, + 'LoanBrokerSet: Data must be a valid non-empty hex string up to 512 characters', + ) + }) + + test('incorrect ManagementFeeRate', () => { + tx.ManagementFeeRate = 123324 + assertInvalid( + tx, + 'LoanBrokerSet: ManagementFeeRate must be between 0 and 10000 inclusive', + ) + }) + + test('incorrect DebtMaximum', () => { + tx.DebtMaximum = '-1e10' + assertInvalid(tx, 'LoanBrokerSet: DebtMaximum must be a non-negative value') + }) + + test('incorrect CoverRateMinimum', () => { + tx.CoverRateMinimum = 12323487 + assertInvalid( + tx, + 'LoanBrokerSet: CoverRateMinimum must be between 0 and 100000 inclusive', + ) + }) + + test('incorrect CoverRateLiquidation', () => { + tx.CoverRateLiquidation = 12323487 + assertInvalid( + tx, + 'LoanBrokerSet: CoverRateLiquidation must be between 0 and 100000 inclusive', + ) + }) + + test('CoverRateMinimum and CoverRateLiquidation both zero', () => { + tx.CoverRateMinimum = 0 + tx.CoverRateLiquidation = 0 + assertValid(tx) + }) + + test('CoverRateMinimum and CoverRateLiquidation both non-zero', () => { + tx.CoverRateMinimum = 10 + tx.CoverRateLiquidation = 20 + assertValid(tx) + }) + + test('CoverRateMinimum is zero and CoverRateLiquidation is non-zero', () => { + tx.CoverRateMinimum = 0 + tx.CoverRateLiquidation = 10 + assertInvalid( + tx, + 'LoanBrokerSet: CoverRateMinimum and CoverRateLiquidation must both be zero or both be non-zero', + ) + }) + + test('CoverRateMinimum is non-zero and CoverRateLiquidation is zero', () => { + tx.CoverRateMinimum = 10 + tx.CoverRateLiquidation = 0 + assertInvalid( + tx, + 'LoanBrokerSet: CoverRateMinimum and CoverRateLiquidation must both be zero or both be non-zero', + ) + }) +}) diff --git a/packages/xrpl/test/models/loanManage.test.ts b/packages/xrpl/test/models/loanManage.test.ts new file mode 100644 index 0000000000..07a5020b7b --- /dev/null +++ b/packages/xrpl/test/models/loanManage.test.ts @@ -0,0 +1,49 @@ +import { + LoanManageFlags, + validateLoanManage, +} from '../../src/models/transactions/loanManage' +import { assertTxIsValid, assertTxValidationError } from '../testUtils' + +const assertValid = (tx: any): void => assertTxIsValid(tx, validateLoanManage) + +const assertInvalid = (tx: any, errorMessage: string): void => + assertTxValidationError(tx, validateLoanManage, errorMessage) + +describe('unit test LoanManage', () => { + let tx: any + + beforeEach(() => { + tx = { + TransactionType: 'LoanManage', + LoanID: + 'E9A08C918E26407493CC4ADD381BA979CFEB7E440D0863B01FB31C231D167E42', + Account: 'rPGxCzMicNJRe1U1CD5QyNjXdLUtdgSa7B', + } + }) + + test('valid tx with no flags', () => { + assertValid(tx) + }) + + test('invalid tx with both tfLoanImpair and tfLoanUnimpair flags', () => { + // eslint-disable-next-line no-bitwise -- needed here + tx.Flags = LoanManageFlags.tfLoanImpair | LoanManageFlags.tfLoanUnimpair + assertInvalid( + tx, + 'LoanManage: tfLoanImpair and tfLoanUnimpair cannot both be present', + ) + }) + + test('incorrect LoanID', () => { + tx.LoanID = 'INCORRECT_VALUE' + assertInvalid( + tx, + 'LoanManage: LoanID must be 64 characters hexadecimal string', + ) + }) + + test('missing LoanID', () => { + delete tx.LoanID + assertInvalid(tx, 'LoanManage: missing field LoanID') + }) +}) diff --git a/packages/xrpl/test/models/loanPay.test.ts b/packages/xrpl/test/models/loanPay.test.ts new file mode 100644 index 0000000000..897269d220 --- /dev/null +++ b/packages/xrpl/test/models/loanPay.test.ts @@ -0,0 +1,86 @@ +import { + validateLoanPay, + LoanPayFlags, +} from '../../src/models/transactions/loanPay' +import { assertTxIsValid, assertTxValidationError } from '../testUtils' + +const assertValid = (tx: any): void => assertTxIsValid(tx, validateLoanPay) + +const assertInvalid = (tx: any, errorMessage: string): void => + assertTxValidationError(tx, validateLoanPay, errorMessage) + +describe('unit test LoanPay', () => { + let tx: any + + beforeEach(() => { + tx = { + TransactionType: 'LoanPay', + LoanID: + '000004D417A9CE049C9A71A62B004659B5F1AAAB1BEA1EFDE4E01EB3497FD999', + Amount: '1000000', + Account: 'rPGxCzMicNJRe1U1CD5QyNjXdLUtdgSa7B', + } + }) + + test('valid tx with no flags', () => { + assertValid(tx) + }) + + test('valid tx with tfLoanOverpayment flag (numeric)', () => { + tx.Flags = LoanPayFlags.tfLoanOverpayment + assertValid(tx) + }) + + test('valid tx with tfLoanFullPayment flag (numeric)', () => { + tx.Flags = LoanPayFlags.tfLoanFullPayment + assertValid(tx) + }) + + test('valid tx with tfLoanLatePayment flag (numeric)', () => { + tx.Flags = LoanPayFlags.tfLoanLatePayment + assertValid(tx) + }) + + test('throws w/ multiple flags set (numeric) - tfLoanOverpayment and tfLoanFullPayment', () => { + // eslint-disable-next-line no-bitwise -- testing flag combinations + tx.Flags = LoanPayFlags.tfLoanOverpayment | LoanPayFlags.tfLoanFullPayment + assertInvalid( + tx, + 'LoanPay: Only one of tfLoanLatePayment, tfLoanFullPayment, or tfLoanOverpayment flags can be set', + ) + }) + + test('valid tx with tfLoanOverpayment flag (object)', () => { + tx.Flags = { tfLoanOverpayment: true } + assertValid(tx) + }) + + test('invalid tx with tfLoanFullPayment and tfLoanOverpayment flag (object)', () => { + tx.Flags = { tfLoanFullPayment: true, tfLoanOverpayment: true } + assertInvalid( + tx, + 'LoanPay: Only one of tfLoanLatePayment, tfLoanFullPayment, or tfLoanOverpayment flags can be set', + ) + }) + + test('incorrect LoanID', () => { + tx.LoanID = 'INCORRECT_VALUE' + assertInvalid( + tx, + 'LoanPay: LoanID must be 64 characters hexadecimal string', + ) + + delete tx.LoanID + assertInvalid(tx, 'LoanPay: missing field LoanID') + }) + + test('missing Amount', () => { + delete tx.Amount + assertInvalid(tx, 'LoanPay: missing field Amount') + }) + + test('invalid Amount', () => { + tx.Amount = 123 + assertInvalid(tx, 'LoanPay: invalid field Amount') + }) +}) diff --git a/packages/xrpl/test/models/utils.test.ts b/packages/xrpl/test/models/utils.test.ts index e6648b02fd..3f6b0c8515 100644 --- a/packages/xrpl/test/models/utils.test.ts +++ b/packages/xrpl/test/models/utils.test.ts @@ -14,12 +14,11 @@ import { TrustSet, TrustSetFlags, } from '../../src' -import { AuthorizeCredential } from '../../src/models/common' +import { AuthorizeCredential, MPTokenMetadata } from '../../src/models/common' import { AccountRootFlags } from '../../src/models/ledger' import { containsDuplicates, GlobalFlags, - validateMPTokenMetadata, } from '../../src/models/transactions/common' import { isFlagEnabled } from '../../src/models/utils' import { @@ -28,7 +27,13 @@ import { parseAccountRootFlags, parseTransactionFlags, } from '../../src/models/utils/flags' -import mptMetadataTests from '../fixtures/transactions/mptokenMetadata.json' +import { + decodeMPTokenMetadata, + encodeMPTokenMetadata, + validateMPTokenMetadata, +} from '../../src/models/utils/mptokenMetadata' +import mptMetadataEncodeDecodeTests from '../fixtures/transactions/mptokenMetadataEncodeDecodeData.json' +import mptMetadataValidationTests from '../fixtures/transactions/mptokenMetadataValidationData.json' /** * Utils Testing. @@ -575,7 +580,7 @@ describe('Models Utils', function () { }) describe('MPTokenMetadata validation messages', function () { - for (const testCase of mptMetadataTests) { + for (const testCase of mptMetadataValidationTests) { const testName: string = testCase.testName it(`should validate messages for: ${testName}`, function () { const validationMessages = validateMPTokenMetadata( @@ -586,8 +591,48 @@ describe('Models Utils', function () { ), ) - assert.deepStrictEqual(testCase.validationMessages, validationMessages) + assert.deepStrictEqual(validationMessages, testCase.validationMessages) + }) + } + }) + + describe('MPTokenMetadata encode/decode', function () { + for (const testCase of mptMetadataEncodeDecodeTests) { + const testName: string = testCase.testName + it(`encode/decode: ${testName}`, function () { + const encodedHex = encodeMPTokenMetadata( + testCase.mptMetadata as MPTokenMetadata, + ) + assert.equal(encodedHex, testCase.hex) + + const decoded = decodeMPTokenMetadata(encodedHex) as unknown as Record< + string, + unknown + > + assert.deepStrictEqual(decoded, testCase.expectedLongForm) }) } + + it('throws error for invalid JSON', function () { + assert.throws( + () => + encodeMPTokenMetadata('invalid json' as unknown as MPTokenMetadata), + `MPTokenMetadata must be JSON object.`, + ) + }) + + it('throws error for invalid hex', function () { + assert.throws( + () => decodeMPTokenMetadata('invalid'), + `MPTokenMetadata must be in hex format.`, + ) + }) + + it('throws error for invalid JSON underneath hex', function () { + assert.throws( + () => decodeMPTokenMetadata('464F4F'), + `MPTokenMetadata is not properly formatted as JSON - SyntaxError: Unexpected token 'F', "FOO" is not valid JSON`, + ) + }) }) }) diff --git a/packages/xrpl/test/models/vaultCreate.test.ts b/packages/xrpl/test/models/vaultCreate.test.ts index c971aa535a..fd5f25703c 100644 --- a/packages/xrpl/test/models/vaultCreate.test.ts +++ b/packages/xrpl/test/models/vaultCreate.test.ts @@ -6,8 +6,8 @@ import { VaultCreateFlags, VaultWithdrawalPolicy, } from '../../src/models/transactions' -import { MPT_META_WARNING_HEADER } from '../../src/models/transactions/common' import { validateVaultCreate } from '../../src/models/transactions/vaultCreate' +import { MPT_META_WARNING_HEADER } from '../../src/models/utils/mptokenMetadata' import { assertTxIsValid, assertTxValidationError } from '../testUtils' const assertValid = (tx: any): void => assertTxIsValid(tx, validateVaultCreate) @@ -35,6 +35,20 @@ describe('VaultCreate', function () { assertValid(tx) }) + it('verifies MPT/IOU Currency as Asset', function () { + tx.Asset = { + mpt_issuance_id: + '983F536DBB46D5BBF43A0B5890576874EE1CF48CE31CA508A529EC17CD1A90EF', + } + assertValid(tx) + + tx.Asset = { + currency: 'USD', + issuer: 'rfmDuhDyLGgx94qiwf3YF8BUV5j6KSvE8', + } + assertValid(tx) + }) + it('throws w/ missing Asset', function () { // @ts-expect-error for test tx.Asset = undefined @@ -93,6 +107,98 @@ describe('VaultCreate', function () { 'VaultCreate: Cannot set DomainID unless tfVaultPrivate flag is set.', ) }) + + describe('Scale field validation', function () { + it('throws w/ Scale provided for XRP asset', function () { + tx.Asset = { currency: 'XRP' } + tx.Scale = 5 + assertInvalid( + tx, + 'VaultCreate: Scale parameter must not be provided for XRP or MPT assets', + ) + }) + + it('throws w/ Scale provided for MPT asset', function () { + tx.Asset = { + mpt_issuance_id: + '983F536DBB46D5BBF43A0B5890576874EE1CF48CE31CA508A529EC17CD1A90EF', + } + tx.Scale = 5 + assertInvalid( + tx, + 'VaultCreate: Scale parameter must not be provided for XRP or MPT assets', + ) + }) + + it('allows Scale for IOU asset with valid value (0)', function () { + tx.Asset = { + currency: 'USD', + issuer: 'rfmDuhDyLGgx94qiwf3YF8BUV5j6KSvE8', + } + tx.Scale = 0 + assertValid(tx) + }) + + it('allows Scale for IOU asset with valid value (18)', function () { + tx.Asset = { + currency: 'USD', + issuer: 'rfmDuhDyLGgx94qiwf3YF8BUV5j6KSvE8', + } + tx.Scale = 18 + assertValid(tx) + }) + + it('allows Scale for IOU asset with valid value (10)', function () { + tx.Asset = { + currency: 'USD', + issuer: 'rfmDuhDyLGgx94qiwf3YF8BUV5j6KSvE8', + } + tx.Scale = 10 + assertValid(tx) + }) + + it('throws w/ Scale less than 0 for IOU asset', function () { + tx.Asset = { + currency: 'USD', + issuer: 'rfmDuhDyLGgx94qiwf3YF8BUV5j6KSvE8', + } + tx.Scale = -1 + assertInvalid( + tx, + 'VaultCreate: Scale must be a number between 0 and 18 inclusive for IOU assets', + ) + }) + + it('throws w/ Scale greater than 18 for IOU asset', function () { + tx.Asset = { + currency: 'USD', + issuer: 'rfmDuhDyLGgx94qiwf3YF8BUV5j6KSvE8', + } + tx.Scale = 19 + assertInvalid( + tx, + 'VaultCreate: Scale must be a number between 0 and 18 inclusive for IOU assets', + ) + }) + + it('throws w/ non-number Scale for IOU asset', function () { + tx.Asset = { + currency: 'USD', + issuer: 'rfmDuhDyLGgx94qiwf3YF8BUV5j6KSvE8', + } + // @ts-expect-error for test + tx.Scale = 'invalid' + assertInvalid(tx, 'VaultCreate: invalid field Scale') + }) + + it('allows no Scale for IOU asset', function () { + tx.Asset = { + currency: 'USD', + issuer: 'rfmDuhDyLGgx94qiwf3YF8BUV5j6KSvE8', + } + assertValid(tx) + }) + }) }) /** @@ -112,11 +218,10 @@ describe('MPTokenMetadata warnings', function () { const mptMetaData: MPTokenMetadata = { ticker: 'TBILL', name: 'T-Bill Token', - icon: 'http://example.com/icon.png', asset_class: 'rwa', asset_subclass: 'treasury', issuer_name: 'Issuer', - } + } as MPTokenMetadata const tx = { TransactionType: 'VaultCreate', Account: 'rfmDuhDyLGgx94qiwf3YF8BUV5j6KSvE8', @@ -129,7 +234,7 @@ describe('MPTokenMetadata warnings', function () { const expectedMessage = [ MPT_META_WARNING_HEADER, - '- icon should be a valid https url.', + '- icon/i: should be a non-empty string.', ].join('\n') expect(console.warn).toHaveBeenCalledWith( diff --git a/packages/xrpl/test/setupClient.ts b/packages/xrpl/test/setupClient.ts index ca365be25f..0da756ddf0 100644 --- a/packages/xrpl/test/setupClient.ts +++ b/packages/xrpl/test/setupClient.ts @@ -1,4 +1,4 @@ -import { Client } from '../src/client' +import { Client, ClientOptions } from '../src/client' import createMockRippled, { type MockedWebSocketServer, @@ -16,11 +16,14 @@ export interface XrplTestContext { async function setupMockRippledConnection( port: number, + options: { + clientOptions?: ClientOptions + } = {}, ): Promise { const context: XrplTestContext = { mockRippled: createMockRippled(port), _mockedServerPort: port, - client: new Client(`ws://localhost:${port}`), + client: new Client(`ws://localhost:${port}`, options.clientOptions ?? {}), servers: [port], } @@ -35,9 +38,13 @@ async function setupMockRippledConnection( return context.client.connect().then(() => context) } -async function setupClient(): Promise { +async function setupClient( + options: { + clientOptions?: ClientOptions + } = {}, +): Promise { return getFreePort().then(async (port) => { - return setupMockRippledConnection(port) + return setupMockRippledConnection(port, options) }) } diff --git a/packages/xrpl/test/utils/hashes.test.ts b/packages/xrpl/test/utils/hashes.test.ts index ac789c95b0..32eb6e8c3f 100644 --- a/packages/xrpl/test/utils/hashes.test.ts +++ b/packages/xrpl/test/utils/hashes.test.ts @@ -21,6 +21,9 @@ import { hashAccountRoot, hashOfferId, hashSignerListId, + hashVault, + hashLoanBroker, + hashLoan, } from '../../src/utils/hashes' import fixtures from '../fixtures/rippled' import { assertResultMatch } from '../testUtils' @@ -149,6 +152,37 @@ describe('Hashes', function () { assert.equal(actualEntryHash, expectedEntryHash) }) + it('calcVaultEntryHash', function () { + const account = 'rDcMtA1XpH5DGwiaqFif2cYCvgk5vxHraS' + const sequence = 18 + const expectedEntryHash = + '9C3208D7F99E5644643542518859401A96C93D80CC5F757AF0DF1781046C0A6A' + const actualEntryHash = hashVault(account, sequence) + + assert.equal(actualEntryHash, expectedEntryHash) + }) + + it('calcLoanBrokerHash', function () { + const account = 'rNTrjogemt4dZD13PaqphezBWSmiApNH4K' + const sequence = 84 + const expectedEntryHash = + 'E799B84AC949CE2D8F27435C784F15C72E6A23ACA6841BA6D2F37A1E5DA4110F' + const actualEntryHash = hashLoanBroker(account, sequence) + + assert.equal(actualEntryHash, expectedEntryHash) + }) + + it('calcLoanHash', function () { + const loanBrokerId = + 'AEB642A65066A6E6F03D312713475D958E0B320B74AD1A76B5B2EABB752E52AA' + const loanSequence = 1 + const expectedEntryHash = + 'E93874AB62125DF2E86FB6C724B261F8E654E0334715C4D7160C0F148CDC9B47' + const actualEntryHash = hashLoan(loanBrokerId, loanSequence) + + assert.equal(actualEntryHash, expectedEntryHash) + }) + it('Hash a signed transaction correctly', function () { const expected_hash = '458101D51051230B1D56E9ACAFAA34451BF65FA000F95DF6F0FF5B3A62D83FC2' diff --git a/packages/xrpl/test/wallet/counterpartySigner.test.ts b/packages/xrpl/test/wallet/counterpartySigner.test.ts new file mode 100644 index 0000000000..8f233532d2 --- /dev/null +++ b/packages/xrpl/test/wallet/counterpartySigner.test.ts @@ -0,0 +1,171 @@ +// Add one test for single signing and one test for multi-signing + +import { assert } from 'chai' + +import { LoanSet, Wallet } from '../../src' +import { + combineLoanSetCounterpartySigners, + signLoanSetByCounterparty, +} from '../../src/Wallet/counterpartySigner' + +describe('counterpartySigner', function () { + it('single sign', function () { + const borrowerWallet = Wallet.fromSeed('sEd7FqVHfNZ2UdGAwjssxPev2ujwJoT') + const singedLoanSet = { + TransactionType: 'LoanSet', + Flags: 0, + Sequence: 1702, + LastLedgerSequence: 1725, + PaymentTotal: 1, + LoanBrokerID: + '033D9B59DBDC4F48FB6708892E7DB0E8FBF9710C3A181B99D9FAF7B9C82EF077', + Fee: '480', + Account: 'rpfK3KEEBwXjUXKQnvAs1SbQhVKu7CSkY1', + Counterparty: 'rp7Tj3Uu1RDrDd1tusge3bVBhUjNvzD19Y', + PrincipalRequested: '5000000', + } + + const expectedLoanSet = { + TransactionType: 'LoanSet', + Flags: 0, + Sequence: 1702, + LastLedgerSequence: 1725, + PaymentTotal: 1, + LoanBrokerID: + '033D9B59DBDC4F48FB6708892E7DB0E8FBF9710C3A181B99D9FAF7B9C82EF077', + Fee: '480', + SigningPubKey: + 'EDFF8D8C5AC309EAA4F3A0C6D2AAF9A9DFA0724063398110365D4631971F604C4C', + TxnSignature: + '1AF5B3118F5F292EDCEAB34A4180792240AF86258C6BC8340D7523D396424F63B4BD4EAF20DE7C5AA9B472DB86AC36E956DAD02288638E59D90C7A0F6BF6E802', + Account: 'rpfK3KEEBwXjUXKQnvAs1SbQhVKu7CSkY1', + Counterparty: 'rp7Tj3Uu1RDrDd1tusge3bVBhUjNvzD19Y', + PrincipalRequested: '5000000', + CounterpartySignature: { + SigningPubKey: + 'ED1139D765C2C8F175153EE663D2CBE574685D5FCF61A6A33DF7AC72C9903D3F94', + TxnSignature: + '440B839B41834A9292B23A8DB547EA34DC89FC8313056C96812384A860848381C4F11867F1092594D3E263DB2433CEB07E2AD312944FF68F2E2EF995ABAE9C05', + }, + } + + assert.throws(() => { + signLoanSetByCounterparty(borrowerWallet, singedLoanSet as LoanSet) + }, 'Transaction must be first signed by first party.') + + assert.throws(() => { + signLoanSetByCounterparty(borrowerWallet, { + ...singedLoanSet, + TransactionType: 'Payment', + } as unknown as LoanSet) + }, 'Transaction must be a LoanSet transaction.') + + assert.throws(() => { + signLoanSetByCounterparty(borrowerWallet, { + ...singedLoanSet, + CounterpartySignature: { + SigningPubKey: '', + TxnSignature: '', + }, + } as LoanSet) + }, 'Transaction is already signed by the counterparty.') + + const { tx: borrowerSignedTx } = signLoanSetByCounterparty(borrowerWallet, { + ...singedLoanSet, + TxnSignature: + '1AF5B3118F5F292EDCEAB34A4180792240AF86258C6BC8340D7523D396424F63B4BD4EAF20DE7C5AA9B472DB86AC36E956DAD02288638E59D90C7A0F6BF6E802', + SigningPubKey: + 'EDFF8D8C5AC309EAA4F3A0C6D2AAF9A9DFA0724063398110365D4631971F604C4C', + } as LoanSet) + + assert.deepEqual(borrowerSignedTx, expectedLoanSet as LoanSet) + }) + + it('multi sign', function () { + const signerWallet1 = Wallet.fromSeed('sEdSyBUScyy9msTU36wdR68XkskQky5') + const signerWallet2 = Wallet.fromSeed('sEdT8LubWzQv3VAx1JQqctv78N28zLA') + + const singedLoanSet = { + TransactionType: 'LoanSet', + Flags: 0, + Sequence: 1807, + LastLedgerSequence: 1838, + PaymentTotal: 1, + InterestRate: 0, + LoanBrokerID: + 'D1902EFBFF8C6536322D48B9F3B974AEC29AC826CF6BEA6218C886581A712AFE', + Fee: '720', + SigningPubKey: + 'EDE7E70883C11FFDEB28A1FEDA20C89352E3FCFEAABFF9EF890A08664E5687ECD2', + TxnSignature: + '0438178AF327FC54C42638A4EDB0EB9A701B2D6192388BE8A4C7A61DD82EA4510D10C0CADAD3D8A7EBC7B08C3F2A50F12F686B47ED2562EE6792434322E94B0E', + Account: 'rpmFCkiUFiufA3HdLagJCWGbzByaQLJKKJ', + Counterparty: 'rQnFUSfgnLNA2KzvKUjRX69tbv7WX76UXW', + PrincipalRequested: '100000', + } + + const expectedLoanSet = { + TransactionType: 'LoanSet', + Flags: 0, + Sequence: 1807, + LastLedgerSequence: 1838, + PaymentTotal: 1, + InterestRate: 0, + LoanBrokerID: + 'D1902EFBFF8C6536322D48B9F3B974AEC29AC826CF6BEA6218C886581A712AFE', + Fee: '720', + SigningPubKey: + 'EDE7E70883C11FFDEB28A1FEDA20C89352E3FCFEAABFF9EF890A08664E5687ECD2', + TxnSignature: + '0438178AF327FC54C42638A4EDB0EB9A701B2D6192388BE8A4C7A61DD82EA4510D10C0CADAD3D8A7EBC7B08C3F2A50F12F686B47ED2562EE6792434322E94B0E', + Account: 'rpmFCkiUFiufA3HdLagJCWGbzByaQLJKKJ', + Counterparty: 'rQnFUSfgnLNA2KzvKUjRX69tbv7WX76UXW', + PrincipalRequested: '100000', + CounterpartySignature: { + Signers: [ + { + Signer: { + SigningPubKey: + 'EDD184F5FE58EC1375AB1CF17A3C5A12A8DEE89DD5228772D69E28EE37438FE59E', + TxnSignature: + 'C3A989FFA24CE21AE9E1734653387B34044A82B13F34B7B1175CB20118F9EF904ABEA691E4D3EFFD1EBF63C3B50F29AA89B68AF4A70CF74601CD326772D1680E', + Account: 'rBJMcbqnAaxcUeEPF7WiaoHCtFiTmga7un', + }, + }, + { + Signer: { + SigningPubKey: + 'ED121AF03981F6496E47854955F65FC8763232D74EBF73877889514137BB72720A', + TxnSignature: + '3A3D91798FCF56289BBF53A97D0CB07CFB5050CFBA05451A1C9A3A9E370AE81DCC3134E6CC35579ACA8937F15DF358DAB728054AC17C3858177C6947C1E21806', + Account: 'rKQhhSnRXJyqDq5BFtWG2E6zxAdq6wDyQC', + }, + }, + ], + }, + } + + const { tx: signer1SignedTx } = signLoanSetByCounterparty( + signerWallet1, + singedLoanSet as LoanSet, + { multisign: true }, + ) + + const { tx: signer2SignedTx } = signLoanSetByCounterparty( + signerWallet2, + singedLoanSet as LoanSet, + { multisign: true }, + ) + + assert.throws(() => { + combineLoanSetCounterpartySigners([]) + }, 'There are 0 transactions to combine.') + + const { tx: combinedSignedTx } = combineLoanSetCounterpartySigners([ + signer1SignedTx, + signer2SignedTx, + ]) + + assert.deepEqual(combinedSignedTx, expectedLoanSet as LoanSet) + }) +})