diff --git a/.github/workflows/backport-pull-request.yml b/.github/workflows/backport-pull-request.yml new file mode 100644 index 0000000000..e0b6c49bbf --- /dev/null +++ b/.github/workflows/backport-pull-request.yml @@ -0,0 +1,55 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +name: Open a backport PR to merge the release branch into main + +on: + # automatically called by release.yml + workflow_dispatch: + # can also be manually triggered when a patch fix is merged into the release branch and needs to be back-ported + workflow_call: + secrets: + RELEASE_AUTOMATION_BOT_PAT: + required: true + +env: + release_branch: smithy-rs-release-1.x.y + +jobs: + create-backport-pull-request: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.RELEASE_AUTOMATION_BOT_PAT }} + + - name: Prepare backport branch + id: backport-branch + run: | + # This step assumes the merge runs cleanly without conflicts, which should be the case when + # this workflow is called by the release workflow right after a release tag has been created. + git config --local user.name "AWS SDK Rust Bot" + git config --local user.email "aws-sdk-rust-primary@amazon.com" + + git fetch + git checkout origin/main + backport_branch="merge-${{ env.release_branch }}-to-main-$(date +%s)" + git checkout -b "${backport_branch}" + + git merge "origin/${{ env.release_branch }}" -m 'Merge remote-tracking branch "origin/${{ env.release_branch }}" into "merge-${{ env.release_branch }}-to-main"' + git push origin HEAD + + echo "branch_name=${backport_branch}" > $GITHUB_OUTPUT + + - name: Create pull request + env: + GITHUB_TOKEN: ${{ secrets.RELEASE_AUTOMATION_BOT_PAT }} + run: | + gh pr create \ + --title "Merge ${{ env.release_branch }} into main" \ + --body "Merge it with \`gh pr merge --admin --merge\` or manually merge it with the merge commit (not squash merge)." \ + --base main \ + --head ${{ steps.backport-branch.outputs.branch_name }} \ + --label "needs-sdk-review" \ + --draft diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml deleted file mode 100644 index 98f246d84f..0000000000 --- a/.github/workflows/canary.yml +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0 - -name: Canary -on: - workflow_dispatch: - -jobs: - canary: - name: Canary - runs-on: ubuntu-latest - steps: - - name: Invoke canary in aws-sdk-rust - run: echo "Hello World" diff --git a/.github/workflows/ci-main.yml b/.github/workflows/ci-main.yml index 652f57fdd1..5bdbfecd08 100644 --- a/.github/workflows/ci-main.yml +++ b/.github/workflows/ci-main.yml @@ -23,6 +23,7 @@ jobs: acquire-base-image: runs-on: smithy_ubuntu-latest_8-core name: Acquire Base Image + timeout-minutes: 60 outputs: docker-login-password: ${{ steps.set-token.outputs.docker-login-password }} permissions: @@ -68,3 +69,5 @@ jobs: secrets: ENCRYPTED_DOCKER_PASSWORD: ${{ needs.acquire-base-image.outputs.docker-login-password }} DOCKER_LOGIN_TOKEN_PASSPHRASE: ${{ secrets.DOCKER_LOGIN_TOKEN_PASSPHRASE }} + CANARY_GITHUB_ACTIONS_ROLE_ARN: ${{ secrets.CANARY_GITHUB_ACTIONS_ROLE_ARN }} + CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME: ${{ secrets.CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME }} diff --git a/.github/workflows/ci-merge-queue.yml b/.github/workflows/ci-merge-queue.yml index 1ab21e4d3e..b9e3f24d88 100644 --- a/.github/workflows/ci-merge-queue.yml +++ b/.github/workflows/ci-merge-queue.yml @@ -22,6 +22,7 @@ jobs: # The login password is encrypted with the repo secret DOCKER_LOGIN_TOKEN_PASSPHRASE save-docker-login-token: name: Save a docker login token + timeout-minutes: 10 outputs: docker-login-password: ${{ steps.set-token.outputs.docker-login-password }} permissions: @@ -51,6 +52,7 @@ jobs: name: Acquire Base Image needs: save-docker-login-token runs-on: ubuntu-latest + timeout-minutes: 60 env: ENCRYPTED_DOCKER_PASSWORD: ${{ needs.save-docker-login-token.outputs.docker-login-password }} DOCKER_LOGIN_TOKEN_PASSPHRASE: ${{ secrets.DOCKER_LOGIN_TOKEN_PASSPHRASE }} @@ -91,3 +93,5 @@ jobs: secrets: ENCRYPTED_DOCKER_PASSWORD: ${{ needs.save-docker-login-token.outputs.docker-login-password }} DOCKER_LOGIN_TOKEN_PASSPHRASE: ${{ secrets.DOCKER_LOGIN_TOKEN_PASSPHRASE }} + CANARY_GITHUB_ACTIONS_ROLE_ARN: ${{ secrets.CANARY_GITHUB_ACTIONS_ROLE_ARN }} + CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME: ${{ secrets.CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME }} diff --git a/.github/workflows/ci-pr-forks.yml b/.github/workflows/ci-pr-forks.yml index 22afcaba53..36a2a2d8db 100644 --- a/.github/workflows/ci-pr-forks.yml +++ b/.github/workflows/ci-pr-forks.yml @@ -20,6 +20,7 @@ jobs: name: Acquire Base Image if: ${{ github.event.pull_request.head.repo.full_name != 'smithy-lang/smithy-rs' }} runs-on: ubuntu-latest + timeout-minutes: 60 steps: - uses: actions/checkout@v4 with: @@ -42,4 +43,5 @@ jobs: if: ${{ github.event.pull_request.head.repo.full_name != 'smithy-lang/smithy-rs' }} uses: ./.github/workflows/ci.yml with: + run_canary: false run_sdk_examples: true diff --git a/.github/workflows/ci-pr.yml b/.github/workflows/ci-pr.yml index fc3be305cc..31fc8fbf50 100644 --- a/.github/workflows/ci-pr.yml +++ b/.github/workflows/ci-pr.yml @@ -21,6 +21,7 @@ jobs: # The login password is encrypted with the repo secret DOCKER_LOGIN_TOKEN_PASSPHRASE save-docker-login-token: name: Save a docker login token + timeout-minutes: 10 if: ${{ github.event.pull_request.head.repo.full_name == 'smithy-lang/smithy-rs' }} outputs: docker-login-password: ${{ steps.set-token.outputs.docker-login-password }} @@ -50,6 +51,7 @@ jobs: # it uploads the image as a build artifact for other jobs to download and use. acquire-base-image: name: Acquire Base Image + timeout-minutes: 60 needs: save-docker-login-token if: ${{ github.event.pull_request.head.repo.full_name == 'smithy-lang/smithy-rs' }} runs-on: smithy_ubuntu-latest_8-core @@ -93,6 +95,8 @@ jobs: secrets: ENCRYPTED_DOCKER_PASSWORD: ${{ needs.save-docker-login-token.outputs.docker-login-password }} DOCKER_LOGIN_TOKEN_PASSPHRASE: ${{ secrets.DOCKER_LOGIN_TOKEN_PASSPHRASE }} + CANARY_GITHUB_ACTIONS_ROLE_ARN: ${{ secrets.CANARY_GITHUB_ACTIONS_ROLE_ARN }} + CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME: ${{ secrets.CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME }} # The PR bot requires a Docker build image, so make it depend on the `acquire-base-image` job. pr_bot: @@ -109,8 +113,9 @@ jobs: SMITHY_RS_PULL_REQUEST_CDN_ROLE_ARN: ${{ secrets.SMITHY_RS_PULL_REQUEST_CDN_ROLE_ARN }} semver-checks: - name: check the semver status of this PR + name: Check PR semver compliance runs-on: smithy_ubuntu-latest_8-core + timeout-minutes: 20 needs: - save-docker-login-token - acquire-base-image @@ -148,6 +153,6 @@ jobs: with: action: check-semver action-arguments: ${{ github.event.pull_request.base.sha }} ${{ fromJSON(steps.check-breaking-label.outputs.result).isBreaking }} - - name: print help message + - name: Print help message if: failure() - run: echo "::error::This pull request contains breaking changes. Please add the `breaking-changes` label and a changelog entry" + run: echo "::error::This pull request either contains breaking changes, or has cross-crate changes that may be backwards compatible, but that cargo-semver-checks cannot verify. Please scrutinize the change for backwards compatibility." diff --git a/.github/workflows/ci-tls.yml b/.github/workflows/ci-tls.yml index e4c542842d..bfb3a5d2f5 100644 --- a/.github/workflows/ci-tls.yml +++ b/.github/workflows/ci-tls.yml @@ -11,6 +11,7 @@ env: name: Verify client TLS configuration on: + workflow_dispatch: pull_request: push: branches: [main] @@ -19,13 +20,19 @@ jobs: verify-tls-config: name: Verify TLS configuration runs-on: ubuntu-latest + timeout-minutes: 20 steps: - name: Install packages shell: bash run: | sudo apt-get update - sudo apt-get -y install gcc make python3-pip nginx git ruby openjdk-17-jre pkg-config libssl-dev faketime + sudo apt-get -y install gcc make python3-pip nginx git ruby pkg-config libssl-dev faketime pip3 install certbuilder crlbuilder + - name: Configure JDK + uses: actions/setup-java@v4 + with: + distribution: corretto + java-version: 17 - name: Stop nginx run: sudo systemctl stop nginx - name: Checkout smithy-rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3549114183..ac9f36213b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,6 +9,11 @@ name: Test on: workflow_call: inputs: + run_canary: + description: Whether to run the canary or not. + required: false + default: true + type: boolean run_sdk_examples: description: Whether to run the SDK example checks or not. required: false @@ -27,9 +32,13 @@ on: required: false DOCKER_LOGIN_TOKEN_PASSPHRASE: required: false + CANARY_GITHUB_ACTIONS_ROLE_ARN: + required: false + CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME: + required: false env: - rust_version: 1.74.1 + rust_version: 1.75.0 rust_toolchain_components: clippy,rustfmt ENCRYPTED_DOCKER_PASSWORD: ${{ secrets.ENCRYPTED_DOCKER_PASSWORD }} DOCKER_LOGIN_TOKEN_PASSPHRASE: ${{ secrets.DOCKER_LOGIN_TOKEN_PASSPHRASE }} @@ -39,6 +48,7 @@ jobs: # and also runs some checks/lints so that those are run sooner rather than later. generate: name: Generate + timeout-minutes: 25 runs-on: smithy_ubuntu-latest_8-core # To avoid repeating setup boilerplate, we have the actual commands # in a matrix strategy. These commands get run in the steps after all the setup. @@ -75,6 +85,7 @@ jobs: test-codegen: name: Test Codegen runs-on: ${{ matrix.test.runner }} + timeout-minutes: 30 # To avoid repeating setup boilerplate, we have the actual test commands # in a matrix strategy. These commands get run in the steps after all the setup. strategy: @@ -131,6 +142,7 @@ jobs: check-semver-hazards: name: Check for semver hazards runs-on: smithy_ubuntu-latest_8-core + timeout-minutes: 20 steps: - uses: actions/checkout@v4 with: @@ -153,6 +165,7 @@ jobs: name: Test the SDK needs: generate runs-on: ${{ matrix.test.runner }} + timeout-minutes: 20 # To avoid repeating setup boilerplate, we have the actual test commands # in a matrix strategy. These commands get run in the steps after all the setup. strategy: @@ -226,6 +239,7 @@ jobs: test-rust-windows: name: Rust Tests on Windows runs-on: windows-latest + timeout-minutes: 20 env: # Disable incremental compilation to reduce disk space use CARGO_INCREMENTAL: 0 @@ -260,6 +274,7 @@ jobs: test-exotic-platform-support: name: Exotic platform support runs-on: ubuntu-latest + timeout-minutes: 10 strategy: fail-fast: false matrix: @@ -352,12 +367,57 @@ jobs: shell: bash run: cross test --target ${{ matrix.target }} --manifest-path "aws/rust-runtime/Cargo.toml" ${{ matrix.test_aws_exclude }} --workspace + # Run the canary against generated SDKs + # + # In addition to Matrix Success, this job will also be required to pass for merge. + # CI execution from forked repositories will skip this job, and when it does + # this skipped job will report its status as "Success". + # https://docs.github.com/en/actions/using-jobs/using-conditions-to-control-job-execution#overview + canary: + name: Canary + if: ${{ inputs.run_canary }} + needs: generate + runs-on: smithy_ubuntu-latest_8-core + timeout-minutes: 20 + permissions: + id-token: write + contents: read + steps: + - uses: actions/checkout@v4 + with: + path: smithy-rs + ref: ${{ inputs.git_ref }} + - name: Configure credentials + id: creds + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-region: us-west-2 + role-to-assume: ${{ secrets.CANARY_GITHUB_ACTIONS_ROLE_ARN }} + output-credentials: true + - name: Run canary + uses: ./smithy-rs/.github/actions/docker-build + with: + action: run-canary + action-arguments: ${{ secrets.CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME }} ${{ steps.creds.outputs.aws-access-key-id }} ${{ steps.creds.outputs.aws-secret-access-key }} ${{ steps.creds.outputs.aws-session-token }} + + # This is always a failing job since forked repositories do not have necessary repository secrets + # to run the PR bot workflow or the canary workflow + ask-maintainer-to-run-pr-bot-and-canary: + name: Ask maintainer to run the PR bot and canary workflows + if: ${{ !inputs.run_canary }} + runs-on: ubuntu-latest + steps: + - run: | + echo "PR bot and canary cannot be invoked from a forked repository. Ask a maintainer to manually invoke them using your PR." + exit 1 + # This job is split out from the rest since it is not required to pass for merge check-sdk-examples: name: Check SDK Examples if: ${{ inputs.run_sdk_examples }} needs: generate runs-on: ubuntu-latest + timeout-minutes: 20 steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/claim-crate-names.yml b/.github/workflows/claim-crate-names.yml index 6f0ec0b2f5..607ac15e79 100644 --- a/.github/workflows/claim-crate-names.yml +++ b/.github/workflows/claim-crate-names.yml @@ -10,7 +10,7 @@ concurrency: cancel-in-progress: true env: - rust_version: 1.74.1 + rust_version: 1.75.0 name: Claim unpublished crate names on crates.io run-name: ${{ github.workflow }} diff --git a/.github/workflows/credentials-verification.yml b/.github/workflows/credentials-verification.yml index 94d907477e..4b83b9ba1a 100644 --- a/.github/workflows/credentials-verification.yml +++ b/.github/workflows/credentials-verification.yml @@ -9,6 +9,7 @@ jobs: # Verifies the token used by the bot to publish crates to crates.io verify-crates-io-token: name: Verify Crates.io Token + if: github.repository == 'smithy-lang/smithy-rs' runs-on: ubuntu-latest steps: - name: Checkout smithy-rs @@ -34,6 +35,7 @@ jobs: # Verifies the token used to perform actions on the repository on behalf of the bot user verify-personal-access-token: name: Verify Personal Access Token + if: github.repository == 'smithy-lang/smithy-rs' runs-on: ubuntu-latest steps: - name: Checkout smithy-rs diff --git a/.github/workflows/dry-run-release-scheduled.yml b/.github/workflows/dry-run-release-scheduled.yml new file mode 100644 index 0000000000..8b239d4772 --- /dev/null +++ b/.github/workflows/dry-run-release-scheduled.yml @@ -0,0 +1,26 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +# This workflow performs a scheduled dry-run for smithy-rs release. +# When run, it only produces release artifacts, but will not cut a release tag in GitHub or publish to crates.io. + +name: Scheduled smithy-rs dry-run release +run-name: ${{ github.workflow }} +on: + schedule: + # Runs 00:00 UTC every day + - cron: 0 0 * * * + +jobs: + smithy-rs-scheduled-dry-run-release: + name: Scheduled dry-run release + uses: ./.github/workflows/release.yml + with: + commit_sha: main + dry_run: true + skip_ci: true + secrets: + RELEASE_AUTOMATION_BOT_PAT: ${{ secrets.RELEASE_AUTOMATION_BOT_PAT }} + RELEASE_AUTOMATION_BOT_CRATESIO_TOKEN: ${{ secrets.RELEASE_AUTOMATION_BOT_CRATESIO_TOKEN }} + CANARY_GITHUB_ACTIONS_ROLE_ARN: ${{ secrets.CANARY_GITHUB_ACTIONS_ROLE_ARN }} + CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME: ${{ secrets.CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME }} diff --git a/.github/workflows/dry-run-release.yml b/.github/workflows/dry-run-release.yml new file mode 100644 index 0000000000..385a389a4a --- /dev/null +++ b/.github/workflows/dry-run-release.yml @@ -0,0 +1,38 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +# This workflow performs a manual dry-run for smithy-rs release. +# When run, it only produces release artifacts, but will not cut a release tag in GitHub or publish to crates.io. + +name: Smithy-rs dry-run release +run-name: ${{ github.workflow }}-${{ inputs.commit_sha }} +on: + workflow_dispatch: + inputs: + commit_sha: + description: | + Commit SHA: The SHA of the git commit that you want to release. + You must use the non-abbreviated SHA (e.g. b2318b0 won't work!). + Alternatively, you can use the name of a branch. + required: true + type: string + skip_ci: + description: Skip CI + required: true + type: boolean + default: true + +jobs: + smithy-rs-manual-dry-run-release: + name: Manual dry run release + if: ${{ github.event_name == 'workflow_dispatch' }} + uses: ./.github/workflows/release.yml + with: + commit_sha: ${{ inputs.commit_sha }} + dry_run: true + skip_ci: ${{ inputs.skip_ci }} + secrets: + RELEASE_AUTOMATION_BOT_PAT: ${{ secrets.RELEASE_AUTOMATION_BOT_PAT }} + RELEASE_AUTOMATION_BOT_CRATESIO_TOKEN: ${{ secrets.RELEASE_AUTOMATION_BOT_CRATESIO_TOKEN }} + CANARY_GITHUB_ACTIONS_ROLE_ARN: ${{ secrets.CANARY_GITHUB_ACTIONS_ROLE_ARN }} + CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME: ${{ secrets.CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME }} diff --git a/.github/workflows/github-pages.yml b/.github/workflows/github-pages.yml index 306c2276fb..1ffe657cd6 100644 --- a/.github/workflows/github-pages.yml +++ b/.github/workflows/github-pages.yml @@ -8,7 +8,7 @@ on: name: Update GitHub Pages env: - rust_version: 1.74.1 + rust_version: 1.75.0 # Allow only one doc pages build to run at a time for the entire smithy-rs repo concurrency: diff --git a/.github/workflows/manual-canary.yml b/.github/workflows/manual-canary.yml index 887781060f..a6be3352d9 100644 --- a/.github/workflows/manual-canary.yml +++ b/.github/workflows/manual-canary.yml @@ -8,11 +8,98 @@ on: description: The PR number to invoke the canary for. required: true type: string +run-name: ${{ github.workflow }} for Pull Request ${{ inputs.pull_request_number }} + +# Allow one instance of this workflow per pull request, and cancel older runs when new changes are pushed +concurrency: + group: manual-canary-${{ inputs.pull_request_number }} + cancel-in-progress: true jobs: + get-pr-info: + name: Get PR info + runs-on: ubuntu-latest + steps: + - name: Get PR info + id: get-pr-info + uses: actions/github-script@v7 + with: + script: | + const response = await github.rest.pulls.get({ + pull_number: ${{ inputs.pull_request_number }}, + owner: context.repo.owner, + repo: context.repo.repo, + }); + const data = { + commit_sha: response.data.head.sha, + }; + console.log("data:", data); + return data; + outputs: + pull_data: ${{ steps.get-pr-info.outputs.result }} + + acquire-base-image: + name: Acquire Base Image + needs: + - get-pr-info + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + path: smithy-rs + # The ref used needs to match the HEAD revision of the PR being diffed, or else + # the `docker-build` action won't find the built Docker image. + ref: ${{ fromJSON(needs.get-pr-info.outputs.pull_data).commit_sha }} + fetch-depth: 0 + - name: Acquire base image + id: acquire + run: ./smithy-rs/.github/scripts/acquire-build-image + - name: Upload base image + uses: actions/upload-artifact@v4 + with: + name: smithy-rs-base-image + path: smithy-rs-base-image + retention-days: 1 + + generate: + name: Generate + needs: + - acquire-base-image + - get-pr-info + runs-on: smithy_ubuntu-latest_8-core + steps: + - uses: actions/checkout@v4 + with: + path: smithy-rs + ref: ${{ fromJSON(needs.get-pr-info.outputs.pull_data).commit_sha }} + - name: Generate a subset of SDKs for the canary + uses: ./smithy-rs/.github/actions/docker-build + with: + action: generate-aws-sdk-for-canary + canary: name: Canary - runs-on: ubuntu-latest + needs: + - generate + - get-pr-info + runs-on: smithy_ubuntu-latest_8-core + permissions: + id-token: write + contents: read steps: - - name: Invoke canary - run: echo "Hello World" + - uses: actions/checkout@v4 + with: + path: smithy-rs + ref: ${{ fromJSON(needs.get-pr-info.outputs.pull_data).commit_sha }} + - name: Configure credentials + id: creds + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-region: us-west-2 + role-to-assume: ${{ secrets.CANARY_GITHUB_ACTIONS_ROLE_ARN }} + output-credentials: true + - name: Run canary + uses: ./smithy-rs/.github/actions/docker-build + with: + action: run-canary + action-arguments: ${{ secrets.CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME }} ${{ steps.creds.outputs.aws-access-key-id }} ${{ steps.creds.outputs.aws-secret-access-key }} ${{ steps.creds.outputs.aws-session-token }} diff --git a/.github/workflows/prod-release.yml b/.github/workflows/prod-release.yml new file mode 100644 index 0000000000..a479a8ab16 --- /dev/null +++ b/.github/workflows/prod-release.yml @@ -0,0 +1,32 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +# This workflow performs a production smithy-rs release. It will cut a release tag in GitHub and publish to crates.io. +# It is idempotent (e.g. won't publish the same crates to crates.io twice), so we can run it repeatedly until it succeeds. + +name: Smithy-rs prod release +run-name: ${{ github.workflow }} (${{ inputs.commit_sha }}) +on: + workflow_dispatch: + inputs: + commit_sha: + description: | + Commit SHA: The SHA of the git commit that you want to release. + You must use the non-abbreviated SHA (e.g. b2318b0 won't work!). + Alternatively, you can use the name of a branch. + required: true + type: string + +jobs: + smithy-rs-prod-release: + name: Prod release + uses: ./.github/workflows/release.yml + with: + commit_sha: ${{ inputs.commit_sha }} + dry_run: false + skip_ci: false + secrets: + RELEASE_AUTOMATION_BOT_PAT: ${{ secrets.RELEASE_AUTOMATION_BOT_PAT }} + RELEASE_AUTOMATION_BOT_CRATESIO_TOKEN: ${{ secrets.RELEASE_AUTOMATION_BOT_CRATESIO_TOKEN }} + CANARY_GITHUB_ACTIONS_ROLE_ARN: ${{ secrets.CANARY_GITHUB_ACTIONS_ROLE_ARN }} + CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME: ${{ secrets.CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME }} diff --git a/.github/workflows/pull-request-bot.yml b/.github/workflows/pull-request-bot.yml index d9aa3cd808..b3fab3ff2b 100644 --- a/.github/workflows/pull-request-bot.yml +++ b/.github/workflows/pull-request-bot.yml @@ -28,7 +28,7 @@ concurrency: env: apt_dependencies: libssl-dev gnuplot jq - java_version: 11 + java_version: 17 rust_toolchain_components: clippy,rustfmt rust_nightly_version: nightly-2024-02-07 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7c84ec8af7..31d3661a1f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,8 +1,8 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -# This workflow performs a release of smithy-rs. It is manually -# kicked off via GitHub Actions workflow dispatch. +# This is the shared release workflow run by both `prod-release.yml` and `dry-run-release.yml'. +# A calling workflow will indicate whether it wants to run this with a prod run or a dry run. # Allow only one release to run at a time concurrency: @@ -10,25 +10,33 @@ concurrency: cancel-in-progress: true env: - rust_version: 1.74.1 + rust_version: 1.75.0 name: Release smithy-rs -run-name: ${{ inputs.dry_run && 'Dry run' || 'Prod run' }} - ${{ github.workflow }} (${{ inputs.commit_sha }}) on: - workflow_dispatch: + workflow_call: inputs: commit_sha: - description: | - Commit SHA: The SHA of the git commit that you want to release. - You must use the non-abbreviated SHA (e.g. b2318b0 won't work!). + description: The SHA of the git commit that you want to release. required: true type: string dry_run: - description: | - Dry run: When selected, it only produces release artifacts, but will not cut a release tag in GitHub or publish to crates.io + description: When true, it only produces release artifacts, but will not cut a release tag in GitHub or publish to crates.io. required: true type: boolean - default: true + skip_ci: + description: Skip CI when executing a release + required: true + type: boolean + secrets: + RELEASE_AUTOMATION_BOT_PAT: + required: true + RELEASE_AUTOMATION_BOT_CRATESIO_TOKEN: + required: true + CANARY_GITHUB_ACTIONS_ROLE_ARN: + required: true + CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME: + required: true jobs: check-actor-for-prod-run: @@ -80,14 +88,19 @@ jobs: retention-days: 1 release-ci: - name: Prerelease checks - if: inputs.dry_run == false + name: Pre-release checks + # We need `always` here otherwise this job won't run if the previous job has been skipped + # See https://samanpavel.medium.com/github-actions-conditional-job-execution-e6aa363d2867 + if: always() && inputs.skip_ci == false needs: - acquire-base-image uses: ./.github/workflows/ci.yml with: run_sdk_examples: false git_ref: ${{ inputs.commit_sha }} + secrets: + CANARY_GITHUB_ACTIONS_ROLE_ARN: ${{ secrets.CANARY_GITHUB_ACTIONS_ROLE_ARN }} + CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME: ${{ secrets.CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME }} check-semver-hazards: name: Check for semver hazards @@ -235,36 +248,12 @@ jobs: publisher publish -y --location . fi - trim-changelog-next-on-main: - name: Remove released entries from CHANGELOG.next.toml on the main branch - if: inputs.dry_run == false && needs.get-or-create-release-branch.outputs.new_release_series == true + open-backport-pull-request: + name: Open backport pull request to merge the release branch back to main needs: - - get-or-create-release-branch - release - runs-on: ubuntu-latest - steps: - - name: Checkout smithy-rs - uses: actions/checkout@v4 - with: - ref: ${{ inputs.commit_sha }} - path: smithy-rs - token: ${{ secrets.RELEASE_AUTOMATION_BOT_PAT }} - - name: Empty CHANGELOG.next.toml - uses: ./smithy-rs/.github/actions/docker-build - with: - action: generate-new-changelog-next-toml - - name: Download all artifacts - uses: ./smithy-rs/.github/actions/download-all-artifacts - - name: Push smithy-rs changes - working-directory: generate-new-changelog-next-toml/smithy-rs - shell: bash - run: | - set -eux - - # This will fail if other commits have been pushed to `main` after `commit_sha` - # In particular, this will ALWAYS fail if you are creating a new release series from - # a commit that is not the current tip of `main`. - # We can build more refined automation to handle this case in the future - until then, it'll require - # a manual PR to edit the current CHANGELOG.next.toml file and remove the released entries. - git -c 'user.name=AWS SDK Rust Bot' -c 'user.email=aws-sdk-rust-primary@amazon.com' commit CHANGELOG.next.toml --message "Remove released entries from \`CHANGELOG.next.toml\`" - git push origin main + # See https://github.com/actions/runner/issues/2205#issuecomment-1381988186 for details on the workaround + if: inputs.dry_run == false && always() && needs.release.result == 'success' + uses: ./.github/workflows/backport-pull-request.yml + secrets: + RELEASE_AUTOMATION_BOT_PAT: ${{ secrets.RELEASE_AUTOMATION_BOT_PAT }} diff --git a/.github/workflows/update-sdk-next.yml b/.github/workflows/update-sdk-next.yml index b47a8b7a86..1adf9be052 100644 --- a/.github/workflows/update-sdk-next.yml +++ b/.github/workflows/update-sdk-next.yml @@ -40,12 +40,12 @@ jobs: with: distribution: corretto java-package: jdk - java-version: 11 + java-version: 17 # Rust is only used to `rustfmt` the generated code; doesn't need to match MSRV - name: Set up Rust uses: dtolnay/rust-toolchain@master with: - toolchain: 1.74.1 + toolchain: 1.75.0 - name: Delete old SDK run: | - name: Generate a fresh SDK diff --git a/CHANGELOG.md b/CHANGELOG.md index c7554bc309..a07701dbd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,65 @@ +April 30th, 2024 +================ +**New this release:** +- :tada: (client, [smithy-rs#119](https://github.com/smithy-lang/smithy-rs/issues/119), [smithy-rs#3595](https://github.com/smithy-lang/smithy-rs/issues/3595), [smithy-rs#3593](https://github.com/smithy-lang/smithy-rs/issues/3593), [smithy-rs#3585](https://github.com/smithy-lang/smithy-rs/issues/3585), [smithy-rs#3571](https://github.com/smithy-lang/smithy-rs/issues/3571), [smithy-rs#3569](https://github.com/smithy-lang/smithy-rs/issues/3569)) Added support for waiters. Services that model waiters now have a `Waiters` trait that adds + some methods prefixed with `wait_until` to the existing clients. + + For example, if there was a waiter modeled for "thing" that takes a "thing ID", using + that waiter would look as follows: + + ```rust + use my_generated_client::client::Waiters; + + let result = client.wait_until_thing() + .thing_id("someId") + .wait(Duration::from_secs(120)) + .await; + ``` +- :bug: (all, [smithy-rs#3603](https://github.com/smithy-lang/smithy-rs/issues/3603)) Fix event stream `:content-type` message headers for struct messages. Note: this was the `:content-type` header on individual event message frames that was incorrect, not the HTTP `content-type` header for the initial request. + + +April 19th, 2024 +================ +**New this release:** +- :tada: (server, [smithy-rs#3430](https://github.com/smithy-lang/smithy-rs/issues/3430)) Implement `std::error::Error` for `ConstraintViolation` +- (all, [smithy-rs#3553](https://github.com/smithy-lang/smithy-rs/issues/3553)) Upgraded MSRV to Rust 1.75 + + +April 11th, 2024 +================ +**New this release:** +- :tada: (all, [smithy-rs#3485](https://github.com/smithy-lang/smithy-rs/issues/3485)) Stalled stream protection now supports request upload streams. It is currently off by default, but will be enabled by default in a future release. To enable it now, you can do the following: + + ```rust + let config = my_service::Config::builder() + .stalled_stream_protection(StalledStreamProtectionConfig::enabled().build()) + // ... + .build(); + ``` +- :bug: (all, [smithy-rs#3427](https://github.com/smithy-lang/smithy-rs/issues/3427)) `SharedIdentityResolver` now respects an existing cache partition when the `ResolveIdentity` implementation + provides one already. +- :bug: (all, [smithy-rs#3485](https://github.com/smithy-lang/smithy-rs/issues/3485)) Stalled stream protection on downloads will now only trigger if the upstream source is too slow. Previously, stalled stream protection could be erroneously triggered if the user was slowly consuming the stream slower than the minimum speed limit. +- :bug: (all, [smithy-rs#2546](https://github.com/smithy-lang/smithy-rs/issues/2546)) Unions with unit target member shape are now fully supported + + +April 2nd, 2024 +=============== +**Breaking Changes:** +- :bug::warning: (client, [aws-sdk-rust#1111](https://github.com/awslabs/aws-sdk-rust/issues/1111), [smithy-rs#3513](https://github.com/smithy-lang/smithy-rs/issues/3513), @Ten0) Make `BehaviorVersion` be future-proof by disallowing it to be constructed via the `BehaviorVersion {}` syntax. + +**New this release:** +- :tada: (all, [smithy-rs#3539](https://github.com/smithy-lang/smithy-rs/issues/3539)) Add FIPS support to our Hyper 1.0-based client. Customers can enable this mode by enabling the `crypto-aws-lc-fips` on `aws-smithy-experimental`. To construct a client using the new client, consult this [example](https://github.com/awslabs/aws-sdk-rust/blob/release-2024-03-29/sdk/s3/tests/hyper-10.rs). + + Please note that support for Hyper 1.0 remains experimental. +- (all, [smithy-rs#3389](https://github.com/smithy-lang/smithy-rs/issues/3389)) All requests are now retryable, even if they are deserialized successfully. Previously, this was not allowed. +- (all, [smithy-rs#3539](https://github.com/smithy-lang/smithy-rs/issues/3539)) Fix bug in Hyper 1.0 support where https URLs returned an error + +**Contributors** +Thank you for your contributions! ❤ +- @Ten0 ([aws-sdk-rust#1111](https://github.com/awslabs/aws-sdk-rust/issues/1111), [smithy-rs#3513](https://github.com/smithy-lang/smithy-rs/issues/3513)) + + March 25th, 2024 ================ **New this release:** diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index 86762ed1b2..029f25c346 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -11,96 +11,9 @@ # meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "client | server | all"} # author = "rcoh" -[[aws-sdk-rust]] -message = "Ability to add an inline policy or a list of policy ARNs to the `WebIdentityTokenCredentialsProvider` builder." -references = ["smithy-rs#3506"] -meta = { "breaking" = false, "tada" = true, "bug" = false } -author = "mokhaled2992" - -[[aws-sdk-rust]] -message = "Make `BehaviorVersion` be future-proof by disallowing it to be constructed via the `BehaviorVersion {}` syntax." -references = ["aws-sdk-rust#1111", "smithy-rs#3513"] -meta = { "breaking" = true, "tada" = false, "bug" = true } -author = "Ten0" - -[[smithy-rs]] -message = "Make `BehaviorVersion` be future-proof by disallowing it to be constructed via the `BehaviorVersion {}` syntax." -references = ["aws-sdk-rust#1111", "smithy-rs#3513"] -meta = { "breaking" = true, "tada" = false, "bug" = true, "target" = "client" } -author = "Ten0" - -[[smithy-rs]] -message = """ -Stalled stream protection now supports request upload streams. It is currently off by default, but will be enabled by default in a future release. To enable it now, you can do the following: - -```rust -let config = my_service::Config::builder() - .stalled_stream_protection(StalledStreamProtectionConfig::enabled().build()) - // ... - .build(); -``` -""" -references = ["smithy-rs#3485"] -meta = { "breaking" = false, "tada" = true, "bug" = false } -authors = ["jdisanti"] - -[[aws-sdk-rust]] -message = """ -Stalled stream protection now supports request upload streams. It is currently off by default, but will be enabled by default in a future release. To enable it now, you can do the following: - -```rust -let config = aws_config::defaults(BehaviorVersion::latest()) - .stalled_stream_protection(StalledStreamProtectionConfig::enabled().build()) - .load() - .await; -``` -""" -references = ["smithy-rs#3485"] -meta = { "breaking" = false, "tada" = true, "bug" = false } -author = "jdisanti" [[smithy-rs]] -message = "Stalled stream protection on downloads will now only trigger if the upstream source is too slow. Previously, stalled stream protection could be erroneously triggered if the user was slowly consuming the stream slower than the minimum speed limit." -references = ["smithy-rs#3485"] -meta = { "breaking" = false, "tada" = false, "bug" = true } -authors = ["jdisanti"] - -[[aws-sdk-rust]] -message = "Users may now set service-specific configuration in the environment. For more information, see [this discussion topic](https://github.com/smithy-lang/smithy-rs/discussions/3537)." -references = ["smithy-rs#3493"] -meta = { "breaking" = false, "tada" = true, "bug" = false } -author = "Velfi" - -[[smithy-rs]] -message = "All requests are now retryable, even if they are deserialized successfully. Previously, this was not allowed." -references = ["smithy-rs#3389"] -meta = { "breaking" = false, "tada" = false, "bug" = false } -authors = ["Velfi"] - -[[aws-sdk-rust]] -message = "All requests are now retryable, even if they are deserialized successfully. Previously, this was not allowed." -references = ["smithy-rs#3389"] -meta = { "breaking" = false, "tada" = false, "bug" = false } -author = "Velfi" - -[[smithy-rs]] -message = "Fix bug in Hyper 1.0 support where https URLs returned an error" -references = ["smithy-rs#3539"] -meta = { "breaking" = false, "tada" = false, "bug" = false } -author = "rcoh" - -[[smithy-rs]] -message = """Add FIPS support to our Hyper 1.0-based client. Customers can enable this mode by enabling the `crypto-aws-lc-fips` on `aws-smithy-experimental`. To construct a client using the new client, consult this [example](https://github.com/awslabs/aws-sdk-rust/blob/release-2024-03-29/sdk/s3/tests/hyper-10.rs). - -Please note that support for Hyper 1.0 remains experimental.""" -references = ["smithy-rs#3539"] -meta = { "breaking" = false, "tada" = true, "bug" = false } -author = "rcoh" - -[[aws-sdk-rust]] -message = """Add FIPS support to our Hyper 1.0-based client. Customers can enable this mode by enabling the `crypto-aws-lc-fips` on `aws-smithy-experimental`. To construct a client using the new client, consult this [example](https://github.com/awslabs/aws-sdk-rust/blob/release-2024-03-29/sdk/s3/tests/hyper-10.rs). - -Please note that support for Hyper 1.0 remains experimental.""" -references = ["smithy-rs#3539"] -meta = { "breaking" = false, "tada" = true, "bug" = false } -author = "rcoh" +message = "Implement Debug for DateTime" +references = ["smithy-rs#3161"] +meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "all" } +author = "mnissenb" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1f8fd78c6d..e3e710ed0e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,6 +36,7 @@ To send us a pull request, please: 4. Commit to your fork using clear commit messages. 5. Send us a pull request, answering any default questions in the pull request interface. 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. +7. Ask maintainers to manually trigger [canary](https://github.com/smithy-lang/smithy-rs/actions/workflows/manual-canary.yml) and [PR bot](https://github.com/smithy-lang/smithy-rs/actions/workflows/manual-pull-request-bot.yml) workflows using your pull request number. Those workflows cannot run in your fork and are always skipped as such. GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). diff --git a/aws/SDK_CHANGELOG.next.json b/aws/SDK_CHANGELOG.next.json index 4a0150b8b6..9b2f12ea55 100644 --- a/aws/SDK_CHANGELOG.next.json +++ b/aws/SDK_CHANGELOG.next.json @@ -6,214 +6,204 @@ "smithy-rs": [], "aws-sdk-rust": [ { - "message": "The types in the aws-http crate were moved into aws-runtime. Deprecated type aliases were put in place to point to the new locations.", + "message": "`DefaultS3ExpressIdentityProvider` now uses `BehaviorVersion` threaded through from the outer S3 client, instead of always creating `BehaviorVersion::latest()` on the fly.", "meta": { - "bug": false, + "bug": true, "breaking": false, "tada": false }, - "author": "jdisanti", + "author": "ysaito1001", "references": [ - "smithy-rs#3355" + "smithy-rs#3478" ], - "since-commit": "403580262f6089c62747b20b6ed1cfc7a09e79bc", - "age": 4 + "since-commit": "2561e01afca63a28b5034a99c610373f84545721", + "age": 5 }, { - "message": "Add `try_into_http1x` and `try_from_http1x` to Request and Response container types.", + "message": "Users may now set an endpoint URL from the env or profile file:\n\n- env: `AWS_ENDPOINT_URL=\"http://localhost\"`\n- profile: `endpoint_url = http://localhost`\n\nUsers may also ignore endpoint URLs sourced from the env and profile files:\n\n- env: `AWS_IGNORE_CONFIGURED_ENDPOINT_URLS=\"true\"`\n- profile: `ignore_configured_endpoint_urls = true`\n", "meta": { "bug": false, "breaking": false, - "tada": false + "tada": true }, - "author": "rcoh", + "author": "Velfi", "references": [ - "aws-sdk-rust#977", - "smithy-rs#3365", - "smithy-rs#3373" + "smithy-rs#3488" ], - "since-commit": "403580262f6089c62747b20b6ed1cfc7a09e79bc", - "age": 4 + "since-commit": "2561e01afca63a28b5034a99c610373f84545721", + "age": 5 }, { - "message": "It is now possible to send customized presigned requests. You can now call `.customize()..presigned(...).await`. Previously, only normal requests supported customization.", + "message": "Fix a bug where a `sigv4-s3express` auth scheme was incorrectly positioned at the front of `auth_scheme_options` and was used when no auth schemes were available for an endpoint.", "meta": { - "bug": false, + "bug": true, "breaking": false, - "tada": true + "tada": false }, - "author": "rcoh", + "author": "ysaito1001", "references": [ - "smithy-rs#3385", - "aws-sdk-rust#1031" + "smithy-rs#3498" ], - "since-commit": "403580262f6089c62747b20b6ed1cfc7a09e79bc", - "age": 4 + "since-commit": "2561e01afca63a28b5034a99c610373f84545721", + "age": 5 }, { - "message": "Added impl `Display` to Enums.", + "message": "Ability to add an inline policy or a list of policy ARNs to the `WebIdentityTokenCredentialsProvider` builder.", "meta": { "bug": false, "breaking": false, - "tada": false + "tada": true }, - "author": "iampkmone", + "author": "mokhaled2992", "references": [ - "smithy-rs#3336", - "smithy-rs#3391" + "smithy-rs#3506" ], - "since-commit": "403580262f6089c62747b20b6ed1cfc7a09e79bc", + "since-commit": "f19a9da9b8f79a7c448246475539c03e1bb58d7e", "age": 4 }, { - "message": "Retry classifiers will now be sorted by priority. This change only affects requests\nthat are retried. Some requests that were previously been classified as transient\nerrors may now be classified as throttling errors.\n\nIf you were\n\n- configuring multiple custom retry classifiers\n- that would disagree on how to classify a response\n- that have differing priorities\n\nyou may see a behavior change in that classification for the same response is now\ndependent on the classifier priority instead of the order in which the classifier\nwas added.\n", + "message": "Make `BehaviorVersion` be future-proof by disallowing it to be constructed via the `BehaviorVersion {}` syntax.", "meta": { "bug": true, - "breaking": false, + "breaking": true, "tada": false }, - "author": "Velfi", + "author": "Ten0", "references": [ - "smithy-rs#3322" + "aws-sdk-rust#1111", + "smithy-rs#3513" ], - "since-commit": "403580262f6089c62747b20b6ed1cfc7a09e79bc", + "since-commit": "f19a9da9b8f79a7c448246475539c03e1bb58d7e", "age": 4 }, { - "message": "Cap the maximum jitter fraction for credentials cache refresh buffer time to 0.5. It was previously 1.0, and if the fraction was randomly set to 1.0, it was equivalent to disregarding the buffer time for cache refresh.", + "message": "Users may now set service-specific configuration in the environment. For more information, see [this discussion topic](https://github.com/smithy-lang/smithy-rs/discussions/3537).", "meta": { - "bug": true, + "bug": false, "breaking": false, - "tada": false + "tada": true }, - "author": "ysaito1001", + "author": "Velfi", "references": [ - "smithy-rs#3402" + "smithy-rs#3493" ], - "since-commit": "403580262f6089c62747b20b6ed1cfc7a09e79bc", + "since-commit": "f19a9da9b8f79a7c448246475539c03e1bb58d7e", "age": 4 }, { - "message": "Retain the SSO token cache between calls to `provide_credentials` when using IAM Identity Center SSO via the AWS config file.", + "message": "All requests are now retryable, even if they are deserialized successfully. Previously, this was not allowed.", "meta": { - "bug": true, + "bug": false, "breaking": false, "tada": false }, - "author": "jdisanti", + "author": "Velfi", "references": [ - "smithy-rs#3387" + "smithy-rs#3389" ], - "since-commit": "403580262f6089c62747b20b6ed1cfc7a09e79bc", + "since-commit": "f19a9da9b8f79a7c448246475539c03e1bb58d7e", "age": 4 }, { - "message": "Fix bug where timeout settings where not merged properly. This will add a default connect timeout of 3.1s seconds for most clients.\n\n[**For more details see the long-form changelog discussion**](https://github.com/smithy-lang/smithy-rs/discussions/3408).", + "message": "Add FIPS support to our Hyper 1.0-based client. Customers can enable this mode by enabling the `crypto-aws-lc-fips` on `aws-smithy-experimental`. To construct a client using the new client, consult this [example](https://github.com/awslabs/aws-sdk-rust/blob/release-2024-03-29/sdk/s3/tests/hyper-10.rs).\n\nPlease note that support for Hyper 1.0 remains experimental.", "meta": { - "bug": true, - "breaking": true, - "tada": false + "bug": false, + "breaking": false, + "tada": true }, "author": "rcoh", "references": [ - "smithy-rs#3405", - "smithy-rs#3400", - "smithy-rs#3258" + "smithy-rs#3539" ], - "since-commit": "403580262f6089c62747b20b6ed1cfc7a09e79bc", + "since-commit": "f19a9da9b8f79a7c448246475539c03e1bb58d7e", "age": 4 }, { - "message": "The MSRV has been increase to 1.74.1", + "message": "Fixes the identity resolver types (`credentials_provider()` and `token_provider()`) from `SdkConfig` to have\na consistent identity cache partition when re-used across different clients.\n", "meta": { - "bug": false, + "bug": true, "breaking": false, "tada": false }, - "author": "rcoh", + "author": "aajtodd", "references": [ - "smithy-rs#3410" + "smithy-rs#3427" ], - "since-commit": "bc1e019e9a9aba438d855e660d18b6ab7d8a903c", + "since-commit": "129b85d3187d61dbe4bac2a105ebc3411516a271", "age": 3 }, { - "message": "EKS Pod Identity is now supported as part of the default ECS credential provider.", + "message": "Stalled stream protection now supports request upload streams. It is currently off by default, but will be enabled by default in a future release. To enable it now, you can do the following:\n\n```rust\nlet config = aws_config::defaults(BehaviorVersion::latest())\n .stalled_stream_protection(StalledStreamProtectionConfig::enabled().build())\n .load()\n .await;\n```\n", "meta": { "bug": false, "breaking": false, "tada": true }, - "author": "jackkleeman", + "author": "jdisanti", "references": [ - "smithy-rs#3416" + "smithy-rs#3485" ], - "since-commit": "c9786d6f56357348714e6c85f3f345a30d8674d8", - "age": 2 + "since-commit": "129b85d3187d61dbe4bac2a105ebc3411516a271", + "age": 3 }, { - "message": "Add support for Lambda's `InvokeWithResponseStreaming` and Bedrock Agent Runtime's `InvokeAgent` operations.", + "message": "Stalled stream protection on downloads will now only trigger if the upstream source is too slow. Previously, stalled stream protection could be erroneously triggered if the user was slowly consuming the stream slower than the minimum speed limit.", "meta": { - "bug": false, + "bug": true, "breaking": false, - "tada": true + "tada": false }, "author": "jdisanti", "references": [ - "aws-sdk-rust#1075", - "aws-sdk-rust#1080", - "smithy-rs#3451" + "smithy-rs#3485" ], - "since-commit": "c9786d6f56357348714e6c85f3f345a30d8674d8", - "age": 2 + "since-commit": "129b85d3187d61dbe4bac2a105ebc3411516a271", + "age": 3 }, { - "message": "Added support for SSO bearer token authentication. The aws-sdk-codecatalyst crate can now send requests without erroring.", + "message": "Upgraded MSRV to Rust 1.75", "meta": { "bug": false, "breaking": false, - "tada": true + "tada": false }, "author": "jdisanti", "references": [ - "aws-sdk-rust#703", - "smithy-rs#3453" + "smithy-rs#3553" ], - "since-commit": "c9786d6f56357348714e6c85f3f345a30d8674d8", + "since-commit": "13c04dafcf5d0f6d65a3edf54b78193f00b44265", "age": 2 }, { - "message": "Add support for S3 Express One Zone. See [the user guide](https://github.com/awslabs/aws-sdk-rust/discussions/1091) for more details.", + "message": "Make `SigningSettings` and its fields implement `Clone` and `Copy`", "meta": { "bug": false, "breaking": false, - "tada": true + "tada": false }, - "author": "ysaito1001", + "author": "avandesa", "references": [ - "aws-sdk-rust#992", - "smithy-rs#3465" + "smithy-rs#3533" ], - "since-commit": "c9786d6f56357348714e6c85f3f345a30d8674d8", + "since-commit": "13c04dafcf5d0f6d65a3edf54b78193f00b44265", "age": 2 }, { - "message": "`aws_sigv4::http_request::settigns::SigningSettings` adds a new setting `session_token_name_override` to allow for an alternative session token name for SigV4 signing.", + "message": "Change some credentials related info log messages to debug.", "meta": { "bug": false, "breaking": false, "tada": false }, - "author": "ysaito1001", + "author": "orf", "references": [ - "smithy-rs#3465", - "smithy-rs#3477" + "smithy-rs#3546" ], - "since-commit": "c9786d6f56357348714e6c85f3f345a30d8674d8", + "since-commit": "13c04dafcf5d0f6d65a3edf54b78193f00b44265", "age": 2 }, { - "message": "`DefaultS3ExpressIdentityProvider` now uses `BehaviorVersion` threaded through from the outer S3 client, instead of always creating `BehaviorVersion::latest()` on the fly.", + "message": "Fix an S3 crate's dependency on `ahash` so the crate can be compiled for `wasm32-unknown-unknown`.", "meta": { "bug": true, "breaking": false, @@ -221,37 +211,58 @@ }, "author": "ysaito1001", "references": [ - "smithy-rs#3478" + "smithy-rs#3590", + "aws-sdk-rust#1131" ], - "since-commit": "2561e01afca63a28b5034a99c610373f84545721", + "since-commit": "13c04dafcf5d0f6d65a3edf54b78193f00b44265", + "age": 2 + }, + { + "message": "Added support for waiters. Services that model waiters now have a `Waiters` trait that adds\nsome methods prefixed with `wait_until` to the existing clients. These can be used to, for example\nin S3, wait for a newly created bucket to be ready, or in EC2, to wait for a started instance to\nhave the status OK.\n\nUsing a waiter looks like the following example for EC2:\n```rust\nuse aws_sdk_ec2::client::Waiters;\n\nlet result = ec2_client.wait_until_instance_status_ok()\n .instance_ids(\"some-instance-id\")\n .wait(Duration::from_secs(300))\n .await;\n```\n", + "meta": { + "bug": false, + "breaking": false, + "tada": true + }, + "author": "jdisanti", + "references": [ + "aws-sdk-rust#400", + "smithy-rs#3595", + "smithy-rs#3593", + "smithy-rs#3585", + "smithy-rs#3571", + "smithy-rs#3569" + ], + "since-commit": "d7be22025857da5d21a0a1c8f5753fcf48e8d0ac", "age": 1 }, { - "message": "Users may now set an endpoint URL from the env or profile file:\n\n- env: `AWS_ENDPOINT_URL=\"http://localhost\"`\n- profile: `endpoint_url = http://localhost`\n\nUsers may also ignore endpoint URLs sourced from the env and profile files:\n\n- env: `AWS_IGNORE_CONFIGURED_ENDPOINT_URLS=\"true\"`\n- profile: `ignore_configured_endpoint_urls = true`\n", + "message": "SDK crates now set the `rust-version` property in their Cargo.toml files to indicate the minimum supported Rust version.", "meta": { "bug": false, "breaking": false, "tada": true }, - "author": "Velfi", + "author": "jdisanti", "references": [ - "smithy-rs#3488" + "smithy-rs#3601" ], - "since-commit": "2561e01afca63a28b5034a99c610373f84545721", + "since-commit": "d7be22025857da5d21a0a1c8f5753fcf48e8d0ac", "age": 1 }, { - "message": "Fix a bug where a `sigv4-s3express` auth scheme was incorrectly positioned at the front of `auth_scheme_options` and was used when no auth schemes were available for an endpoint.", + "message": "`aws_config::default_provider::use_dual_stack_provider` is now public instead of `pub(crate)`", "meta": { - "bug": true, + "bug": false, "breaking": false, "tada": false }, - "author": "ysaito1001", + "author": "jdisanti", "references": [ - "smithy-rs#3498" + "aws-sdk-rust#879", + "smithy-rs#3611" ], - "since-commit": "2561e01afca63a28b5034a99c610373f84545721", + "since-commit": "d7be22025857da5d21a0a1c8f5753fcf48e8d0ac", "age": 1 } ], diff --git a/aws/SDK_README.md.hb b/aws/SDK_README.md.hb index 75d130b13d..e9d1ab9483 100644 --- a/aws/SDK_README.md.hb +++ b/aws/SDK_README.md.hb @@ -92,7 +92,10 @@ If you are interested in contributing to the SDK, please take a look at [CONTRIB ## Supported Rust Versions (MSRV) -The SDK currently requires a minimum of Rust {{msrv}}, and is not guaranteed to build on compiler versions earlier than that. While we are still in alpha, we will be keeping the minimum compiler version two releases behind the latest stable release where possible (so if the latest stable were 1.55, we would be on 1.53). However, we are not making any guarantees around this at present. Increases in minimum required Rust version will be called out in the Release Notes for new releases of the SDK. +The SDK currently requires a minimum of Rust {{msrv}}, and is not guaranteed to build on compiler versions +earlier than that. We keep the minimum compiler version two releases behind the latest stable release where +possible (so if the latest stable were 1.55, we would support 1.53). Increases in minimum required Rust +version will be called out in the Release Notes for new releases of the SDK. ## Additional Resources diff --git a/aws/rust-runtime/aws-config/Cargo.toml b/aws/rust-runtime/aws-config/Cargo.toml index 8ba7eb09e4..98f7458542 100644 --- a/aws/rust-runtime/aws-config/Cargo.toml +++ b/aws/rust-runtime/aws-config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aws-config" -version = "1.1.10" +version = "1.3.0" authors = [ "AWS Rust SDK Team ", "Russell Cohen ", diff --git a/aws/rust-runtime/aws-config/integration-tests/eks-credentials/package-lock.json b/aws/rust-runtime/aws-config/integration-tests/eks-credentials/package-lock.json index f9927e3212..e32e5da8a3 100644 --- a/aws/rust-runtime/aws-config/integration-tests/eks-credentials/package-lock.json +++ b/aws/rust-runtime/aws-config/integration-tests/eks-credentials/package-lock.json @@ -1,7 +1,7 @@ { "name": "eks-credentials", "version": "0.1.0", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { @@ -34,9 +34,9 @@ "dev": true }, "node_modules/@aws-cdk/asset-node-proxy-agent-v6": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.0.1.tgz", - "integrity": "sha512-DDt4SLdLOwWCjGtltH4VCST7hpOI5DzieuhGZsBpZ+AgJdSI2GCjklCXm0GCTwJG/SolkL5dtQXyUKgg9luBDg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.0.3.tgz", + "integrity": "sha512-twhuEG+JPOYCYPx/xy5uH2+VUsIEhPTzDY0F1KuB+ocjWWB/KEDiOVL19nHvbPCB6fhWnkykXEMJ4HHcKvjtvg==", "dev": true }, "node_modules/@aws-cdk/lambda-layer-kubectl-v28": { @@ -62,9 +62,9 @@ "dev": true }, "node_modules/aws-cdk": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.17.0.tgz", - "integrity": "sha512-gRPPpTONOjtQ40A8sc2SzXPGDzFlVbSPPts1pjOx4VBJ2S91A0ON3Fkby+XX/Xqdo1GITTWAk5Va4PnoYyUhmA==", + "version": "2.135.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.135.0.tgz", + "integrity": "sha512-id/kBxDvXQhcPYhkP/3fwhaKN0uD3raz1Z4RZcO9jJ4UoQV2RElQl+dYdmIrwNSoNVhtZeV1O4IdEtBHUhdShQ==", "dev": true, "bin": { "cdk": "bin/cdk" @@ -77,9 +77,9 @@ } }, "node_modules/aws-cdk-lib": { - "version": "2.128.0", - "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.128.0.tgz", - "integrity": "sha512-cAU1L4jtPXPQXpa9kS2/HhHdkg3xGc5GCqwRgivdoj/iLQF3dDwIouOkwDBY/S5pXMqOUC7IoVdIPPbIgfGlsQ==", + "version": "2.135.0", + "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.135.0.tgz", + "integrity": "sha512-0RcmhPqJyMFgXqjESv+LilL7TfOQ7uZ4G125hp5/sSoaM7IFz/L3KDAUKVW/01rrebOQo0NZR9M7WIU3JJ7ezQ==", "bundleDependencies": [ "@balena/dockerignore", "case", @@ -90,7 +90,8 @@ "punycode", "semver", "table", - "yaml" + "yaml", + "mime-types" ], "dev": true, "dependencies": { @@ -102,10 +103,11 @@ "fs-extra": "^11.2.0", "ignore": "^5.3.1", "jsonschema": "^1.4.1", + "mime-types": "^2.1.35", "minimatch": "^3.1.2", "punycode": "^2.3.1", - "semver": "^7.5.4", - "table": "^6.8.1", + "semver": "^7.6.0", + "table": "^6.8.2", "yaml": "1.10.2" }, "engines": { @@ -314,6 +316,27 @@ "node": ">=10" } }, + "node_modules/aws-cdk-lib/node_modules/mime-db": { + "version": "1.52.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/aws-cdk-lib/node_modules/mime-types": { + "version": "2.1.35", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/aws-cdk-lib/node_modules/minimatch": { "version": "3.1.2", "dev": true, @@ -345,7 +368,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/semver": { - "version": "7.5.4", + "version": "7.6.0", "dev": true, "inBundle": true, "license": "ISC", @@ -403,7 +426,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/table": { - "version": "6.8.1", + "version": "6.8.2", "dev": true, "inBundle": true, "license": "BSD-3-Clause", @@ -458,12 +481,12 @@ "dev": true }, "node_modules/constructs": { - "version": "10.0.98", - "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.0.98.tgz", - "integrity": "sha512-xhPAuudPnQg3RbAIsK/x1XFDM+x//lgCV7UJbt0rUqhkzo1gytS852dG3LQd2tYPy8TQT0hStQjskikXShBgSg==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.3.0.tgz", + "integrity": "sha512-vbK8i3rIb/xwZxSpTjz3SagHn1qq9BChLEfy5Hf6fB3/2eFbrwt2n9kHwQcS0CPTRBesreeAcsJfMq2229FnbQ==", "dev": true, "engines": { - "node": ">= 12.7.0" + "node": ">= 16.14.0" } }, "node_modules/create-require": { @@ -568,382 +591,5 @@ "node": ">=6" } } - }, - "dependencies": { - "@aws-cdk/asset-awscli-v1": { - "version": "2.2.202", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.202.tgz", - "integrity": "sha512-JqlF0D4+EVugnG5dAsNZMqhu3HW7ehOXm5SDMxMbXNDMdsF0pxtQKNHRl52z1U9igsHmaFpUgSGjbhAJ+0JONg==", - "dev": true - }, - "@aws-cdk/asset-kubectl-v20": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-kubectl-v20/-/asset-kubectl-v20-2.1.2.tgz", - "integrity": "sha512-3M2tELJOxQv0apCIiuKQ4pAbncz9GuLwnKFqxifWfe77wuMxyTRPmxssYHs42ePqzap1LT6GDcPygGs+hHstLg==", - "dev": true - }, - "@aws-cdk/asset-node-proxy-agent-v6": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.0.1.tgz", - "integrity": "sha512-DDt4SLdLOwWCjGtltH4VCST7hpOI5DzieuhGZsBpZ+AgJdSI2GCjklCXm0GCTwJG/SolkL5dtQXyUKgg9luBDg==", - "dev": true - }, - "@aws-cdk/lambda-layer-kubectl-v28": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@aws-cdk/lambda-layer-kubectl-v28/-/lambda-layer-kubectl-v28-2.2.0.tgz", - "integrity": "sha512-m7nMDn/Ff9S+gJ5Sok5NuYHBzgsj3Xz3dOo0BxXYJJNPl9UtD1HnPcKV56lHn9+BACJff/h8aPUMln0xCUPuIw==", - "dev": true, - "requires": {} - }, - "@types/node": { - "version": "10.17.27", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.27.tgz", - "integrity": "sha512-J0oqm9ZfAXaPdwNXMMgAhylw5fhmXkToJd06vuDUSAgEDZ/n/69/69UmyBZbc+zT34UnShuDSBqvim3SPnozJg==", - "dev": true - }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "aws-cdk": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.17.0.tgz", - "integrity": "sha512-gRPPpTONOjtQ40A8sc2SzXPGDzFlVbSPPts1pjOx4VBJ2S91A0ON3Fkby+XX/Xqdo1GITTWAk5Va4PnoYyUhmA==", - "dev": true, - "requires": { - "fsevents": "2.3.2" - } - }, - "aws-cdk-lib": { - "version": "2.128.0", - "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.128.0.tgz", - "integrity": "sha512-cAU1L4jtPXPQXpa9kS2/HhHdkg3xGc5GCqwRgivdoj/iLQF3dDwIouOkwDBY/S5pXMqOUC7IoVdIPPbIgfGlsQ==", - "dev": true, - "requires": { - "@aws-cdk/asset-awscli-v1": "^2.2.202", - "@aws-cdk/asset-kubectl-v20": "^2.1.2", - "@aws-cdk/asset-node-proxy-agent-v6": "^2.0.1", - "@balena/dockerignore": "^1.0.2", - "case": "1.6.3", - "fs-extra": "^11.2.0", - "ignore": "^5.3.1", - "jsonschema": "^1.4.1", - "minimatch": "^3.1.2", - "punycode": "^2.3.1", - "semver": "^7.5.4", - "table": "^6.8.1", - "yaml": "1.10.2" - }, - "dependencies": { - "@balena/dockerignore": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "ajv": { - "version": "8.12.0", - "bundled": true, - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ansi-regex": { - "version": "5.0.1", - "bundled": true, - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "bundled": true, - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "astral-regex": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "balanced-match": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "case": { - "version": "1.6.3", - "bundled": true, - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "bundled": true, - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "bundled": true, - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "bundled": true, - "dev": true - }, - "fs-extra": { - "version": "11.2.0", - "bundled": true, - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "graceful-fs": { - "version": "4.2.11", - "bundled": true, - "dev": true - }, - "ignore": { - "version": "5.3.1", - "bundled": true, - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "json-schema-traverse": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "bundled": true, - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "jsonschema": { - "version": "1.4.1", - "bundled": true, - "dev": true - }, - "lodash.truncate": { - "version": "4.4.2", - "bundled": true, - "dev": true - }, - "lru-cache": { - "version": "6.0.0", - "bundled": true, - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "punycode": { - "version": "2.3.1", - "bundled": true, - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "bundled": true, - "dev": true - }, - "semver": { - "version": "7.5.4", - "bundled": true, - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "slice-ansi": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "bundled": true, - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "table": { - "version": "6.8.1", - "bundled": true, - "dev": true, - "requires": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - } - }, - "universalify": { - "version": "2.0.1", - "bundled": true, - "dev": true - }, - "uri-js": { - "version": "4.4.1", - "bundled": true, - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "yallist": { - "version": "4.0.0", - "bundled": true, - "dev": true - }, - "yaml": { - "version": "1.10.2", - "bundled": true, - "dev": true - } - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "constructs": { - "version": "10.0.98", - "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.0.98.tgz", - "integrity": "sha512-xhPAuudPnQg3RbAIsK/x1XFDM+x//lgCV7UJbt0rUqhkzo1gytS852dG3LQd2tYPy8TQT0hStQjskikXShBgSg==", - "dev": true - }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", - "dev": true, - "requires": { - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" - } - }, - "typescript": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", - "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", - "dev": true - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true - } } } diff --git a/aws/rust-runtime/aws-config/src/credential_process.rs b/aws/rust-runtime/aws-config/src/credential_process.rs index 6aec2a9888..b1b6572354 100644 --- a/aws/rust-runtime/aws-config/src/credential_process.rs +++ b/aws/rust-runtime/aws-config/src/credential_process.rs @@ -207,19 +207,12 @@ pub(crate) fn parse_credential_process_json_credentials( } fn parse_expiration(expiration: impl AsRef) -> Result { - SystemTime::try_from( - OffsetDateTime::parse(expiration.as_ref(), &Rfc3339).map_err(|err| { - InvalidJsonCredentials::InvalidField { - field: "Expiration", - err: err.into(), - } - })?, - ) - .map_err(|_| { - InvalidJsonCredentials::Other( - "credential expiration time cannot be represented by a DateTime".into(), - ) - }) + OffsetDateTime::parse(expiration.as_ref(), &Rfc3339) + .map(SystemTime::from) + .map_err(|err| InvalidJsonCredentials::InvalidField { + field: "Expiration", + err: err.into(), + }) } #[cfg(test)] diff --git a/aws/rust-runtime/aws-config/src/default_provider/endpoint_url.rs b/aws/rust-runtime/aws-config/src/default_provider/endpoint_url.rs index a34ee29479..da3569385d 100644 --- a/aws/rust-runtime/aws-config/src/default_provider/endpoint_url.rs +++ b/aws/rust-runtime/aws-config/src/default_provider/endpoint_url.rs @@ -7,6 +7,7 @@ use crate::environment::parse_url; use crate::provider_config::ProviderConfig; use aws_runtime::env_config::EnvConfigValue; use aws_smithy_types::error::display::DisplayErrorContext; +use aws_types::origin::Origin; mod env { pub(super) const ENDPOINT_URL: &str = "AWS_ENDPOINT_URL"; @@ -37,6 +38,29 @@ pub async fn endpoint_url_provider(provider_config: &ProviderConfig) -> Option (Option, Origin) { + let env = provider_config.env(); + let profiles = provider_config.profile().await; + + EnvConfigValue::new() + .env(env::ENDPOINT_URL) + .profile(profile_key::ENDPOINT_URL) + .validate_and_return_origin(&env, profiles, parse_url) + .map_err( + |err| tracing::warn!(err = %DisplayErrorContext(&err), "invalid value for endpoint URL setting"), + ) + .unwrap_or_default() +} + #[cfg(test)] mod test { use super::endpoint_url_provider; diff --git a/aws/rust-runtime/aws-config/src/default_provider/use_dual_stack.rs b/aws/rust-runtime/aws-config/src/default_provider/use_dual_stack.rs index 5004938c08..a78be5ae0e 100644 --- a/aws/rust-runtime/aws-config/src/default_provider/use_dual_stack.rs +++ b/aws/rust-runtime/aws-config/src/default_provider/use_dual_stack.rs @@ -16,7 +16,14 @@ mod profile_key { pub(super) const USE_DUAL_STACK: &str = "use_dualstack_endpoint"; } -pub(crate) async fn use_dual_stack_provider(provider_config: &ProviderConfig) -> Option { +/// Load the value for "use dual-stack" +/// +/// This checks the following sources: +/// 1. The environment variable `AWS_USE_DUALSTACK_ENDPOINT=true/false` +/// 2. The profile key `use_dualstack_endpoint=true/false` +/// +/// If invalid values are found, the provider will return `None` and an error will be logged. +pub async fn use_dual_stack_provider(provider_config: &ProviderConfig) -> Option { let env = provider_config.env(); let profiles = provider_config.profile().await; diff --git a/aws/rust-runtime/aws-config/src/lib.rs b/aws/rust-runtime/aws-config/src/lib.rs index b97178be47..05bdf05f67 100644 --- a/aws/rust-runtime/aws-config/src/lib.rs +++ b/aws/rust-runtime/aws-config/src/lib.rs @@ -223,6 +223,7 @@ mod loader { use aws_smithy_types::timeout::TimeoutConfig; use aws_types::app_name::AppName; use aws_types::docs_for; + use aws_types::origin::Origin; use aws_types::os_shim_internal::{Env, Fs}; use aws_types::sdk_config::SharedHttpClient; use aws_types::SdkConfig; @@ -605,7 +606,6 @@ mod loader { /// /// ```no_run /// use aws_config::profile::{ProfileFileCredentialsProvider, ProfileFileRegionProvider}; - /// use aws_config::profile::profile_file::{ProfileFiles, ProfileFileKind}; /// /// # async fn example() { /// let sdk_config = aws_config::from_env() @@ -624,8 +624,8 @@ mod loader { /// exists to set a static endpoint for tools like `LocalStack`. When sending requests to /// production AWS services, this method should only be used for service-specific behavior. /// - /// When this method is used, the [`Region`](aws_types::region::Region) is only used for - /// signing; it is not used to route the request. + /// When this method is used, the [`Region`](aws_types::region::Region) is only used for signing; + /// It is **not** used to route the request. /// /// # Examples /// @@ -823,6 +823,7 @@ mod loader { // If an endpoint URL is set programmatically, then our work is done. let endpoint_url = if self.endpoint_url.is_some() { + builder.insert_origin("endpoint_url", Origin::shared_config()); self.endpoint_url } else { // Otherwise, check to see if we should ignore EP URLs set in the environment. @@ -840,7 +841,9 @@ mod loader { None } else { // Otherwise, attempt to resolve one. - endpoint_url::endpoint_url_provider(&conf).await + let (v, origin) = endpoint_url::endpoint_url_provider_with_origin(&conf).await; + builder.insert_origin("endpoint_url", origin); + v } }; builder.set_endpoint_url(endpoint_url); @@ -884,6 +887,7 @@ mod loader { use aws_smithy_runtime::client::http::test_util::{infallible_client_fn, NeverClient}; use aws_smithy_runtime::test_util::capture_test_logs::capture_test_logs; use aws_types::app_name::AppName; + use aws_types::origin::Origin; use aws_types::os_shim_internal::{Env, Fs}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; @@ -950,6 +954,78 @@ mod loader { .http_client(no_traffic_client()) } + #[tokio::test] + async fn test_origin_programmatic() { + let _ = tracing_subscriber::fmt::try_init(); + let loader = base_conf() + .test_credentials() + .profile_name("custom") + .profile_files( + #[allow(deprecated)] + ProfileFiles::builder() + .with_contents( + #[allow(deprecated)] + ProfileFileKind::Config, + "[profile custom]\nendpoint_url = http://localhost:8989", + ) + .build(), + ) + .endpoint_url("http://localhost:1111") + .load() + .await; + assert_eq!(Origin::shared_config(), loader.get_origin("endpoint_url")); + } + + #[tokio::test] + async fn test_origin_env() { + let _ = tracing_subscriber::fmt::try_init(); + let env = Env::from_slice(&[("AWS_ENDPOINT_URL", "http://localhost:7878")]); + let loader = base_conf() + .test_credentials() + .env(env) + .profile_name("custom") + .profile_files( + #[allow(deprecated)] + ProfileFiles::builder() + .with_contents( + #[allow(deprecated)] + ProfileFileKind::Config, + "[profile custom]\nendpoint_url = http://localhost:8989", + ) + .build(), + ) + .load() + .await; + assert_eq!( + Origin::shared_environment_variable(), + loader.get_origin("endpoint_url") + ); + } + + #[tokio::test] + async fn test_origin_fs() { + let _ = tracing_subscriber::fmt::try_init(); + let loader = base_conf() + .test_credentials() + .profile_name("custom") + .profile_files( + #[allow(deprecated)] + ProfileFiles::builder() + .with_contents( + #[allow(deprecated)] + ProfileFileKind::Config, + "[profile custom]\nendpoint_url = http://localhost:8989", + ) + .build(), + ) + .load() + .await; + assert_eq!( + Origin::shared_profile_file(), + loader.get_origin("endpoint_url") + ); + } + #[tokio::test] async fn load_fips() { let conf = base_conf().use_fips(true).load().await; diff --git a/aws/rust-runtime/aws-config/src/profile/credentials/exec.rs b/aws/rust-runtime/aws-config/src/profile/credentials/exec.rs index 10ba42d5b0..87f28df19c 100644 --- a/aws/rust-runtime/aws-config/src/profile/credentials/exec.rs +++ b/aws/rust-runtime/aws-config/src/profile/credentials/exec.rs @@ -160,12 +160,12 @@ impl ProviderChain { } } }; - tracing::info!(base = ?repr.base(), "first credentials will be loaded from {:?}", repr.base()); + tracing::debug!(base = ?repr.base(), "first credentials will be loaded from {:?}", repr.base()); let chain = repr .chain() .iter() .map(|role_arn| { - tracing::info!(role_arn = ?role_arn, "which will be used to assume a role"); + tracing::debug!(role_arn = ?role_arn, "which will be used to assume a role"); AssumeRoleProvider { role_arn: role_arn.role_arn.into(), external_id: role_arn.external_id.map(Into::into), diff --git a/aws/rust-runtime/aws-credential-types/Cargo.toml b/aws/rust-runtime/aws-credential-types/Cargo.toml index 8bd3a7068a..dbf70e9316 100644 --- a/aws/rust-runtime/aws-credential-types/Cargo.toml +++ b/aws/rust-runtime/aws-credential-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aws-credential-types" -version = "1.1.8" +version = "1.2.0" authors = ["AWS Rust SDK Team "] description = "Types for AWS SDK credentials." edition = "2021" diff --git a/aws/rust-runtime/aws-credential-types/src/provider/credentials.rs b/aws/rust-runtime/aws-credential-types/src/provider/credentials.rs index 5b63ad1547..39a46d40b5 100644 --- a/aws/rust-runtime/aws-credential-types/src/provider/credentials.rs +++ b/aws/rust-runtime/aws-credential-types/src/provider/credentials.rs @@ -72,7 +72,9 @@ construct credentials from hardcoded values. //! ``` use crate::Credentials; -use aws_smithy_runtime_api::client::identity::{Identity, IdentityFuture, ResolveIdentity}; +use aws_smithy_runtime_api::client::identity::{ + Identity, IdentityCachePartition, IdentityFuture, ResolveIdentity, +}; use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents; use aws_smithy_types::config_bag::{ConfigBag, Storable, StoreReplace}; use std::sync::Arc; @@ -124,7 +126,7 @@ impl ProvideCredentials for Arc { /// Newtype wrapper around ProvideCredentials that implements Clone using an internal /// Arc. #[derive(Clone, Debug)] -pub struct SharedCredentialsProvider(Arc); +pub struct SharedCredentialsProvider(Arc, IdentityCachePartition); impl SharedCredentialsProvider { /// Create a new SharedCredentials provider from `ProvideCredentials` @@ -132,7 +134,7 @@ impl SharedCredentialsProvider { /// The given provider will be wrapped in an internal `Arc`. If your /// provider is already in an `Arc`, use `SharedCredentialsProvider::from(provider)` instead. pub fn new(provider: impl ProvideCredentials + 'static) -> Self { - Self(Arc::new(provider)) + Self(Arc::new(provider), IdentityCachePartition::new()) } } @@ -144,7 +146,7 @@ impl AsRef for SharedCredentialsProvider { impl From> for SharedCredentialsProvider { fn from(provider: Arc) -> Self { - SharedCredentialsProvider(provider) + SharedCredentialsProvider(provider, IdentityCachePartition::new()) } } @@ -173,4 +175,28 @@ impl ResolveIdentity for SharedCredentialsProvider { fn fallback_on_interrupt(&self) -> Option { ProvideCredentials::fallback_on_interrupt(self).map(|creds| creds.into()) } + + fn cache_partition(&self) -> Option { + Some(self.1) + } +} + +#[cfg(test)] +mod tests { + use aws_smithy_runtime_api::client::identity::SharedIdentityResolver; + + use super::*; + + #[test] + fn reuses_cache_partition() { + let creds = Credentials::new("AKID", "SECRET", None, None, "test"); + let provider = SharedCredentialsProvider::new(creds); + let partition = provider.cache_partition(); + assert!(partition.is_some()); + + let identity_resolver = SharedIdentityResolver::new(provider); + let identity_partition = identity_resolver.cache_partition(); + + assert!(partition.unwrap() == identity_partition); + } } diff --git a/aws/rust-runtime/aws-credential-types/src/provider/token.rs b/aws/rust-runtime/aws-credential-types/src/provider/token.rs index e59ff7665c..bb2ddae3c6 100644 --- a/aws/rust-runtime/aws-credential-types/src/provider/token.rs +++ b/aws/rust-runtime/aws-credential-types/src/provider/token.rs @@ -14,7 +14,7 @@ use crate::{provider::error::TokenError, provider::future, Token}; use aws_smithy_runtime_api::client::{ - identity::{IdentityFuture, ResolveIdentity}, + identity::{IdentityCachePartition, IdentityFuture, ResolveIdentity}, runtime_components::RuntimeComponents, }; use aws_smithy_runtime_api::impl_shared_conversions; @@ -45,7 +45,7 @@ impl ProvideToken for Token { /// /// Newtype wrapper around [`ProvideToken`] that implements `Clone` using an internal `Arc`. #[derive(Clone, Debug)] -pub struct SharedTokenProvider(Arc); +pub struct SharedTokenProvider(Arc, IdentityCachePartition); impl SharedTokenProvider { /// Create a new [`SharedTokenProvider`] from [`ProvideToken`]. @@ -53,7 +53,7 @@ impl SharedTokenProvider { /// The given provider will be wrapped in an internal `Arc`. If your /// provider is already in an `Arc`, use `SharedTokenProvider::from(provider)` instead. pub fn new(provider: impl ProvideToken + 'static) -> Self { - Self(Arc::new(provider)) + Self(Arc::new(provider), IdentityCachePartition::new()) } } @@ -65,7 +65,7 @@ impl AsRef for SharedTokenProvider { impl From> for SharedTokenProvider { fn from(provider: Arc) -> Self { - SharedTokenProvider(provider) + SharedTokenProvider(provider, IdentityCachePartition::new()) } } @@ -86,6 +86,30 @@ impl ResolveIdentity for SharedTokenProvider { ) -> IdentityFuture<'a> { IdentityFuture::new(async move { Ok(self.provide_token().await?.into()) }) } + + fn cache_partition(&self) -> Option { + Some(self.1) + } } impl_shared_conversions!(convert SharedTokenProvider from ProvideToken using SharedTokenProvider::new); + +#[cfg(test)] +mod tests { + use aws_smithy_runtime_api::client::identity::SharedIdentityResolver; + + use super::*; + + #[test] + fn reuses_cache_partition() { + let token = Token::new("token", None); + let provider = SharedTokenProvider::new(token); + let partition = provider.cache_partition(); + assert!(partition.is_some()); + + let identity_resolver = SharedIdentityResolver::new(provider); + let identity_partition = identity_resolver.cache_partition(); + + assert!(partition.unwrap() == identity_partition); + } +} diff --git a/aws/rust-runtime/aws-inlineable/Cargo.toml b/aws/rust-runtime/aws-inlineable/Cargo.toml index 66e8f7ff0b..4d987fe62f 100644 --- a/aws/rust-runtime/aws-inlineable/Cargo.toml +++ b/aws/rust-runtime/aws-inlineable/Cargo.toml @@ -15,7 +15,7 @@ repository = "https://github.com/smithy-lang/smithy-rs" # Used by lru, and this forces it to be a later version that avoids # https://github.com/tkaitchuck/aHash/issues/200 # when built with `cargo update -Z minimal-versions` -ahash = "0.8.11" +ahash = { version = "0.8.11", default-features = false } aws-credential-types = { path = "../aws-credential-types" } aws-runtime = { path = "../aws-runtime", features = ["http-02x"] } aws-sigv4 = { path = "../aws-sigv4" } diff --git a/aws/rust-runtime/aws-runtime/Cargo.toml b/aws/rust-runtime/aws-runtime/Cargo.toml index ee56bfdd18..3862a04241 100644 --- a/aws/rust-runtime/aws-runtime/Cargo.toml +++ b/aws/rust-runtime/aws-runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aws-runtime" -version = "1.1.9" +version = "1.2.0" authors = ["AWS Rust SDK Team "] description = "Runtime support code for the AWS SDK. This crate isn't intended to be used directly." edition = "2021" diff --git a/aws/rust-runtime/aws-runtime/src/env_config.rs b/aws/rust-runtime/aws-runtime/src/env_config.rs index 55c8e8ed1d..d2cb9a1868 100644 --- a/aws/rust-runtime/aws-runtime/src/env_config.rs +++ b/aws/rust-runtime/aws-runtime/src/env_config.rs @@ -5,6 +5,7 @@ use crate::env_config::property::PropertiesKey; use crate::env_config::section::EnvConfigSections; +use aws_types::origin::Origin; use aws_types::os_shim_internal::Env; use aws_types::service_config::ServiceConfigKey; use std::borrow::Cow; @@ -81,6 +82,20 @@ pub struct EnvConfigSource<'a> { scope: Scope<'a>, } +#[allow(clippy::from_over_into)] +impl Into for &EnvConfigSource<'_> { + fn into(self) -> Origin { + match (&self.scope, &self.location) { + (Scope::Global, Location::Environment) => Origin::shared_environment_variable(), + (Scope::Global, Location::Profile { .. }) => Origin::shared_profile_file(), + (Scope::Service { .. }, Location::Environment) => { + Origin::service_environment_variable() + } + (Scope::Service { .. }, Location::Profile { .. }) => Origin::service_profile_file(), + } + } +} + impl<'a> EnvConfigSource<'a> { pub(crate) fn global_from_env(key: Cow<'a, str>) -> Self { Self { @@ -186,7 +201,7 @@ impl<'a> EnvConfigValue<'a> { self } - /// Load the value from `provider_config`, validating with `validator` + /// Load the value from the env or profile files, validating with `validator` pub fn validate( self, env: &Env, @@ -204,6 +219,30 @@ impl<'a> EnvConfigValue<'a> { .transpose() } + /// Load the value from the env or profile files, validating with `validator` + /// + /// This version of the function will also return the origin of the config. + pub fn validate_and_return_origin( + self, + env: &Env, + profiles: Option<&EnvConfigSections>, + validator: impl Fn(&str) -> Result, + ) -> Result<(Option, Origin), EnvConfigError> { + let value = self.load(env, profiles); + match value { + Some((v, ctx)) => { + let origin: Origin = (&ctx).into(); + validator(v.as_ref()) + .map_err(|err| EnvConfigError { + property_source: format!("{}", ctx), + err, + }) + .map(|value| (Some(value), origin)) + } + None => Ok((None, Origin::unknown())), + } + } + /// Load the value from the environment pub fn load( &self, @@ -222,9 +261,16 @@ impl<'a> EnvConfigValue<'a> { ) }); - let value = service_config.or(global_config); - tracing::trace!("ENV value = {value:?}"); - value + if let Some(v) = service_config { + tracing::trace!("(service env) {env_var} = {v:?}"); + Some(v) + } else if let Some(v) = global_config { + tracing::trace!("(global env) {env_var} = {v:?}"); + Some(v) + } else { + tracing::trace!("(env) no value set for {env_var}"); + None + } }); let profile_value = match (profiles, self.profile_key.as_ref()) { @@ -245,9 +291,16 @@ impl<'a> EnvConfigValue<'a> { ) }); - let value = service_config.or(global_config); - tracing::trace!("PROFILE value = {value:?}"); - value + if let Some(v) = service_config { + tracing::trace!("(service profile) {profile_key} = {v:?}"); + Some(v) + } else if let Some(v) = global_config { + tracing::trace!("(global profile) {profile_key} = {v:?}"); + Some(v) + } else { + tracing::trace!("(service profile) no value set for {profile_key}"); + None + } } _ => None, }; diff --git a/aws/rust-runtime/aws-sigv4/Cargo.toml b/aws/rust-runtime/aws-sigv4/Cargo.toml index 45f6e3a9fd..9a497c80e8 100644 --- a/aws/rust-runtime/aws-sigv4/Cargo.toml +++ b/aws/rust-runtime/aws-sigv4/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aws-sigv4" -version = "1.2.0" +version = "1.2.1" authors = ["AWS Rust SDK Team ", "David Barsky "] description = "SigV4 signer for HTTP requests and Event Stream messages." edition = "2021" diff --git a/aws/rust-runtime/aws-sigv4/src/http_request/settings.rs b/aws/rust-runtime/aws-sigv4/src/http_request/settings.rs index 9b51345866..bc8409b807 100644 --- a/aws/rust-runtime/aws-sigv4/src/http_request/settings.rs +++ b/aws/rust-runtime/aws-sigv4/src/http_request/settings.rs @@ -10,7 +10,7 @@ use std::time::Duration; const HEADER_NAME_X_RAY_TRACE_ID: &str = "x-amzn-trace-id"; /// HTTP-specific signing settings -#[derive(Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq)] #[non_exhaustive] pub struct SigningSettings { /// Specifies how to encode the request URL when signing. Some services do not decode @@ -45,7 +45,7 @@ pub struct SigningSettings { /// HTTP payload checksum type #[non_exhaustive] -#[derive(Debug, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum PayloadChecksumKind { /// Add x-amz-checksum-sha256 to the canonical request /// @@ -64,7 +64,7 @@ pub enum PayloadChecksumKind { /// do not decode the path prior to checking the signature, requiring clients to actually /// _double-encode_ the URI in creating the canonical request in order to pass a signature check. #[non_exhaustive] -#[derive(Debug, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum PercentEncodingMode { /// Re-encode the resulting URL (e.g. %30 becomes `%2530) Double, @@ -78,7 +78,7 @@ pub enum PercentEncodingMode { /// /// URI path normalization is performed based on . #[non_exhaustive] -#[derive(Debug, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum UriPathNormalizationMode { /// Normalize the URI path according to RFC3986 Enabled, @@ -100,7 +100,7 @@ impl From for UriPathNormalizationMode { /// Config value to specify whether X-Amz-Security-Token should be part of the canonical request. /// #[non_exhaustive] -#[derive(Debug, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum SessionTokenMode { /// Include in the canonical request before calculating the signature. Include, diff --git a/aws/rust-runtime/aws-types/Cargo.toml b/aws/rust-runtime/aws-types/Cargo.toml index 714425a5ac..d82b168d16 100644 --- a/aws/rust-runtime/aws-types/Cargo.toml +++ b/aws/rust-runtime/aws-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aws-types" -version = "1.1.9" +version = "1.2.0" authors = ["AWS Rust SDK Team ", "Russell Cohen "] description = "Cross-service types for the AWS SDK." edition = "2021" diff --git a/aws/rust-runtime/aws-types/src/lib.rs b/aws/rust-runtime/aws-types/src/lib.rs index 926b44dd78..6b6d62a474 100644 --- a/aws/rust-runtime/aws-types/src/lib.rs +++ b/aws/rust-runtime/aws-types/src/lib.rs @@ -20,6 +20,7 @@ pub mod app_name; pub mod build_metadata; pub mod endpoint_config; +pub mod origin; pub mod os_shim_internal; pub mod region; pub mod request_id; diff --git a/aws/rust-runtime/aws-types/src/origin.rs b/aws/rust-runtime/aws-types/src/origin.rs new file mode 100644 index 0000000000..0b5ee830bc --- /dev/null +++ b/aws/rust-runtime/aws-types/src/origin.rs @@ -0,0 +1,253 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +//! Types for tracking the origin of config values. + +use std::cmp::Ordering; +use std::fmt; + +/// A type for tracking the origin of config values. +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] +#[non_exhaustive] +pub struct Origin { + inner: Inner, +} + +impl fmt::Display for Origin { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use Inner::*; + + match self.inner { + Imds => write!(f, "IMDS"), + ProfileFile(Kind::Shared) => write!(f, "shared profile file"), + ProfileFile(Kind::Service) => write!(f, "service profile file"), + EnvironmentVariable(Kind::Shared) => write!(f, "shared environment variable"), + EnvironmentVariable(Kind::Service) => write!(f, "service environment variable"), + Programmatic(Kind::Shared) => write!(f, "shared client"), + Programmatic(Kind::Service) => write!(f, "service client"), + Unknown => write!(f, "unknown"), + } + } +} + +impl Origin { + /// The origin is unknown. + pub fn unknown() -> Self { + Self { + inner: Inner::Unknown, + } + } + + /// Set with IMDS. + pub fn imds() -> Self { + Self { inner: Inner::Imds } + } + + /// Set on a shared config struct. + pub fn shared_config() -> Self { + Self { + inner: Inner::Programmatic(Kind::Shared), + } + } + + /// Set on a service config struct. + pub fn service_config() -> Self { + Self { + inner: Inner::Programmatic(Kind::Service), + } + } + + /// Set by an environment variable. + pub fn shared_environment_variable() -> Self { + Self { + inner: Inner::EnvironmentVariable(Kind::Shared), + } + } + + /// Set by a service-specific environment variable. + pub fn service_environment_variable() -> Self { + Self { + inner: Inner::EnvironmentVariable(Kind::Service), + } + } + + /// Set in a profile file. + pub fn shared_profile_file() -> Self { + Self { + inner: Inner::ProfileFile(Kind::Shared), + } + } + + /// Service-specific, set in a profile file. + pub fn service_profile_file() -> Self { + Self { + inner: Inner::ProfileFile(Kind::Service), + } + } + + /// Return true if the origin was set programmatically i.e. on an `SdkConfig` or service `Config`. + pub fn is_client_config(&self) -> bool { + matches!( + self, + Origin { + inner: Inner::Programmatic(..), + .. + } + ) + } +} + +impl Default for Origin { + fn default() -> Self { + Self::unknown() + } +} + +#[derive(Debug, Clone, Copy)] +enum Inner { + Imds, + ProfileFile(Kind), + EnvironmentVariable(Kind), + Programmatic(Kind), + Unknown, +} + +impl Inner { + pub(self) fn is_unknown(&self) -> bool { + matches!(self, Inner::Unknown) + } +} + +// Unknown is like NaN. It's not equal to anything, not even itself. +impl PartialEq for Inner { + fn eq(&self, other: &Self) -> bool { + use Inner::*; + + match (self, other) { + (Imds, Imds) => true, + (Programmatic(a), Programmatic(b)) => a == b, + (EnvironmentVariable(a), EnvironmentVariable(b)) => a == b, + (ProfileFile(a), ProfileFile(b)) => a == b, + _ => false, + } + } +} + +impl PartialOrd for Inner { + fn partial_cmp(&self, other: &Self) -> Option { + use Inner::*; + + if self.is_unknown() || other.is_unknown() { + return None; + } + + match self { + // IMDS is the lowest priority + Imds => Some(Ordering::Less), + // ProfileFile is the second-lowest priority + ProfileFile(kind) => match other { + Imds => Some(Ordering::Greater), + ProfileFile(other_kind) => kind.partial_cmp(other_kind), + _ => Some(Ordering::Less), + }, + // EnvironmentVariable is the second-highest priority + EnvironmentVariable(kind) => match other { + Imds | ProfileFile(_) => Some(Ordering::Greater), + EnvironmentVariable(other_kind) => kind.partial_cmp(other_kind), + _ => Some(Ordering::Less), + }, + // Programmatic is the highest priority + Programmatic(kind) => match other { + Imds | EnvironmentVariable(_) | ProfileFile(_) => Some(Ordering::Greater), + Programmatic(other_kind) => kind.partial_cmp(other_kind), + _ => unreachable!( + "When we have something higher than programmatic we can update this case." + ), + }, + _ => unreachable!(), + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd)] +enum Kind { + Shared, + Service, +} + +#[cfg(test)] +mod test { + use super::Origin; + + #[test] + fn test_precedence_low_to_high() { + // Lowest to highest precedence + let list = [ + Origin::imds(), + Origin::shared_profile_file(), + Origin::service_profile_file(), + Origin::shared_environment_variable(), + Origin::service_environment_variable(), + Origin::shared_config(), + Origin::service_config(), + ]; + + for window in list.windows(2) { + let &[a, b] = window else { unreachable!() }; + assert!(a < b); + } + } + + #[test] + fn test_precedence_high_to_low() { + // Highest to lowest precedence + let list = [ + Origin::service_config(), + Origin::shared_config(), + Origin::service_environment_variable(), + Origin::shared_environment_variable(), + Origin::service_profile_file(), + Origin::shared_profile_file(), + Origin::imds(), + ]; + + for window in list.windows(2) { + let &[a, b] = window else { unreachable!() }; + assert!(a > b); + } + } + + #[test] + fn test_unknown_is_not_equal() { + assert_ne!(Origin::unknown(), Origin::imds()); + assert_ne!(Origin::unknown(), Origin::shared_config()); + assert_ne!(Origin::unknown(), Origin::service_config()); + assert_ne!(Origin::unknown(), Origin::shared_environment_variable()); + assert_ne!(Origin::unknown(), Origin::service_environment_variable()); + assert_ne!(Origin::unknown(), Origin::shared_profile_file()); + assert_ne!(Origin::unknown(), Origin::service_profile_file()); + assert_ne!(Origin::unknown(), Origin::unknown()); + } + + #[test] + fn test_self_equality() { + assert_eq!(Origin::imds(), Origin::imds()); + assert_eq!(Origin::shared_config(), Origin::shared_config()); + assert_eq!(Origin::service_config(), Origin::service_config()); + assert_eq!( + Origin::shared_environment_variable(), + Origin::shared_environment_variable() + ); + assert_eq!( + Origin::service_environment_variable(), + Origin::service_environment_variable() + ); + assert_eq!(Origin::shared_profile_file(), Origin::shared_profile_file()); + assert_eq!( + Origin::service_profile_file(), + Origin::service_profile_file() + ); + } +} diff --git a/aws/rust-runtime/aws-types/src/sdk_config.rs b/aws/rust-runtime/aws-types/src/sdk_config.rs index a8f0071f68..2515a2e4c5 100644 --- a/aws/rust-runtime/aws-types/src/sdk_config.rs +++ b/aws/rust-runtime/aws-types/src/sdk_config.rs @@ -11,9 +11,8 @@ use crate::app_name::AppName; use crate::docs_for; +use crate::origin::Origin; use crate::region::Region; -use std::sync::Arc; - use crate::service_config::LoadServiceConfig; use aws_credential_types::provider::token::SharedTokenProvider; pub use aws_credential_types::provider::SharedCredentialsProvider; @@ -28,6 +27,8 @@ pub use aws_smithy_runtime_api::client::stalled_stream_protection::StalledStream use aws_smithy_runtime_api::shared::IntoShared; pub use aws_smithy_types::retry::RetryConfig; pub use aws_smithy_types::timeout::TimeoutConfig; +use std::collections::HashMap; +use std::sync::Arc; /// Unified docstrings to keep crates in sync. Not intended for public use pub mod unified_docs { @@ -71,6 +72,7 @@ pub struct SdkConfig { use_dual_stack: Option, behavior_version: Option, service_config: Option>, + config_origins: HashMap<&'static str, Origin>, } /// Builder for AWS Shared Configuration @@ -96,6 +98,7 @@ pub struct Builder { use_dual_stack: Option, behavior_version: Option, service_config: Option>, + config_origins: HashMap<&'static str, Origin>, } impl Builder { @@ -633,6 +636,14 @@ impl Builder { self } + /// Set the origin of a setting. + /// + /// This is used internally to understand how to merge config structs while + /// respecting precedence of origins. + pub fn insert_origin(&mut self, setting: &'static str, origin: Origin) { + self.config_origins.insert(setting, origin); + } + /// Build a [`SdkConfig`] from this builder. pub fn build(self) -> SdkConfig { SdkConfig { @@ -652,6 +663,7 @@ impl Builder { behavior_version: self.behavior_version, stalled_stream_protection_config: self.stalled_stream_protection_config, service_config: self.service_config, + config_origins: self.config_origins, } } } @@ -822,6 +834,17 @@ impl SdkConfig { self.clone().into_builder() } + /// Get the origin of a setting. + /// + /// This is used internally to understand how to merge config structs while + /// respecting precedence of origins. + pub fn get_origin(&self, setting: &'static str) -> Origin { + self.config_origins + .get(setting) + .cloned() + .unwrap_or_default() + } + /// Convert this [`SdkConfig`] back to a builder to enable modification pub fn into_builder(self) -> Builder { Builder { @@ -841,6 +864,7 @@ impl SdkConfig { behavior_version: self.behavior_version, stalled_stream_protection_config: self.stalled_stream_protection_config, service_config: self.service_config, + config_origins: self.config_origins, } } } diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsFluentClientDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsFluentClientDecorator.kt index d2437a05aa..95e754ff0c 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsFluentClientDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/AwsFluentClientDecorator.kt @@ -155,10 +155,11 @@ private class AwsFluentClientDocs(private val codegenContext: ClientCodegenConte /// Client for $serviceName /// /// Client for invoking operations on $serviceName. Each operation on $serviceName is a method on this - /// this struct. `.send()` MUST be invoked on the generated operations to dispatch the request to the service.""", + /// this struct. `.send()` MUST be invoked on the generated operations to dispatch the request to the service.""", ) AwsDocs.clientConstructionDocs(codegenContext)(this) FluentClientDocs.clientUsageDocs(codegenContext)(this) + FluentClientDocs.waiterDocs(codegenContext)(this) } else -> emptySection diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/EndpointBuiltInsDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/EndpointBuiltInsDecorator.kt index 7900b1ca56..b177b6be73 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/EndpointBuiltInsDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/EndpointBuiltInsDecorator.kt @@ -114,7 +114,12 @@ fun Model.sdkConfigSetter( ParameterType.STRING -> writable { rust("|s|s.to_string()") } ParameterType.BOOLEAN -> null } - return SdkConfigCustomization.copyField(fieldName, map) + + return if (fieldName == "endpoint_url") { + SdkConfigCustomization.copyFieldAndCheckForServiceConfig(fieldName, map) + } else { + SdkConfigCustomization.copyField(fieldName, map) + } } /** diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/HttpRequestChecksumDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/HttpRequestChecksumDecorator.kt index d3d46916ab..2794fc0295 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/HttpRequestChecksumDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/HttpRequestChecksumDecorator.kt @@ -106,7 +106,7 @@ private fun HttpChecksumTrait.checksumAlgorithmToStr( } // This generator was implemented based on this spec: -// https://smithy-lang.github.io/smithy/1.0/spec/aws/aws-core.html#http-request-checksums +// https://smithy.io/2.0/aws/aws-core.html#http-request-checksums class HttpRequestChecksumCustomization( private val codegenContext: ClientCodegenContext, private val operationShape: OperationShape, diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/HttpResponseChecksumDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/HttpResponseChecksumDecorator.kt index f5d5f67bd4..16a4521679 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/HttpResponseChecksumDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/HttpResponseChecksumDecorator.kt @@ -68,7 +68,7 @@ class HttpResponseChecksumDecorator : ClientCodegenDecorator { } // This generator was implemented based on this spec: -// https://awslabs.github.io/smithy/1.0/spec/aws/aws-core.html#http-request-checksums +// https://smithy.io/2.0/aws/aws-core.html#http-request-checksums class HttpResponseChecksumCustomization( private val codegenContext: ClientCodegenContext, private val operationShape: OperationShape, diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/RegionDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/RegionDecorator.kt index 7f5ce13de8..366d310c57 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/RegionDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/RegionDecorator.kt @@ -104,15 +104,8 @@ class RegionDecorator : ClientCodegenDecorator { adhocCustomization { section -> rust( """ - ${section.serviceConfigBuilder}.set_region( - ${section.sdkConfig} - .service_config() - .and_then(|conf| { - conf.load_config(service_config_key($envKey, $profileKey)) - .map(Region::new) - }) - .or_else(|| ${section.sdkConfig}.region().cloned()), - ); + ${section.serviceConfigBuilder} = + ${section.serviceConfigBuilder}.region(${section.sdkConfig}.region().cloned()); """, ) } diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/SdkConfigDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/SdkConfigDecorator.kt index 2b1872c569..ab00d1fc67 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/SdkConfigDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/SdkConfigDecorator.kt @@ -54,6 +54,17 @@ object SdkConfigCustomization { fun copyField( fieldName: String, map: Writable?, + ) = adhocCustomization { section -> + val mapBlock = map?.let { writable { rust(".map(#W)", it) } } ?: writable { } + rustTemplate( + "${section.serviceConfigBuilder}.set_$fieldName(${section.sdkConfig}.$fieldName()#{map});", + "map" to mapBlock, + ) + } + + fun copyFieldAndCheckForServiceConfig( + fieldName: String, + map: Writable?, ) = adhocCustomization { section -> val mapBlock = map?.let { writable { rust(".map(#W)", it) } } ?: writable { } val envKey = "AWS_${fieldName.toSnakeCase().uppercase()}".dq() @@ -61,12 +72,16 @@ object SdkConfigCustomization { rustTemplate( """ - ${section.serviceConfigBuilder}.set_$fieldName( - ${section.sdkConfig} - .service_config() - .and_then(|conf| conf.load_config(service_config_key($envKey, $profileKey)).map(|it| it.parse().unwrap())) - .or_else(|| ${section.sdkConfig}.$fieldName()#{map}) - ); + if ${section.sdkConfig}.get_origin("endpoint_url").is_client_config() { + ${section.serviceConfigBuilder}.set_$fieldName(${section.sdkConfig}.$fieldName()#{map}); + } else { + ${section.serviceConfigBuilder}.set_$fieldName( + ${section.sdkConfig} + .service_config() + .and_then(|conf| conf.load_config(service_config_key($envKey, $profileKey)).map(|it| it.parse().unwrap())) + .or_else(|| ${section.sdkConfig}.$fieldName()#{map}) + ); + } """, "map" to mapBlock, ) diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/s3/S3Decorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/s3/S3Decorator.kt index 498a155a28..8af54cfe6e 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/s3/S3Decorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/s3/S3Decorator.kt @@ -28,21 +28,17 @@ import software.amazon.smithy.rust.codegen.client.smithy.generators.OperationGen import software.amazon.smithy.rust.codegen.client.smithy.generators.OperationSection import software.amazon.smithy.rust.codegen.client.smithy.protocols.ClientRestXmlFactory import software.amazon.smithy.rust.codegen.core.rustlang.Writable -import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustBlockTemplate import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType -import software.amazon.smithy.rust.codegen.core.smithy.customize.AdHocCustomization -import software.amazon.smithy.rust.codegen.core.smithy.customize.adhocCustomization import software.amazon.smithy.rust.codegen.core.smithy.protocols.ProtocolFunctions import software.amazon.smithy.rust.codegen.core.smithy.protocols.ProtocolMap import software.amazon.smithy.rust.codegen.core.smithy.protocols.RestXml import software.amazon.smithy.rust.codegen.core.smithy.traits.AllowInvalidXmlRoot import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.letIf -import software.amazon.smithy.rustsdk.SdkConfigSection import software.amazon.smithy.rustsdk.getBuiltIn import software.amazon.smithy.rustsdk.toWritable import java.util.logging.Logger @@ -158,33 +154,6 @@ class S3Decorator : ClientCodegenDecorator { } } - override fun extraSections(codegenContext: ClientCodegenContext): List { - return listOf( - adhocCustomization { section -> - rust( - """ - ${section.serviceConfigBuilder}.set_disable_multi_region_access_points( - ${section.sdkConfig} - .service_config() - .and_then(|conf| { - let str_config = conf.load_config(service_config_key("AWS_S3_DISABLE_MULTIREGION_ACCESS_POINTS", "s3_disable_multi_region_access_points")); - str_config.and_then(|it| it.parse::().ok()) - }), - ); - ${section.serviceConfigBuilder}.set_use_arn_region( - ${section.sdkConfig} - .service_config() - .and_then(|conf| { - let str_config = conf.load_config(service_config_key("AWS_S3_USE_ARN_REGION", "s3_use_arn_region")); - str_config.and_then(|it| it.parse::().ok()) - }), - ); - """, - ) - }, - ) - } - private fun isInInvalidXmlRootAllowList(shape: Shape): Boolean { return shape.isStructureShape && invalidXmlRootAllowList.contains(shape.id) } diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/timestream/TimestreamDecorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/timestream/TimestreamDecorator.kt index 3e4705a743..650730b146 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/timestream/TimestreamDecorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/timestream/TimestreamDecorator.kt @@ -63,7 +63,7 @@ class TimestreamDecorator : ClientCodegenDecorator { async fn resolve_endpoint(client: &crate::Client) -> Result<(#{Endpoint}, #{SystemTime}), #{BoxError}> { let describe_endpoints = client.describe_endpoints().send().await?; - let endpoint = describe_endpoints.endpoints().get(0).unwrap(); + let endpoint = describe_endpoints.endpoints().first().unwrap(); let expiry = client.config().time_source().expect("checked when ep discovery was enabled").now() + #{Duration}::from_secs(endpoint.cache_period_in_minutes() as u64 * 60); Ok(( diff --git a/aws/sdk/benchmarks/previous-release-comparison/Cargo.lock b/aws/sdk/benchmarks/previous-release-comparison/Cargo.lock index d606888f0d..7ea163c633 100644 --- a/aws/sdk/benchmarks/previous-release-comparison/Cargo.lock +++ b/aws/sdk/benchmarks/previous-release-comparison/Cargo.lock @@ -17,15 +17,34 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "anes" version = "0.1.6" @@ -34,9 +53,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "assert-json-diff" @@ -51,129 +70,103 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "aws-config" -version = "1.0.1" +version = "1.1.10" dependencies = [ - "aws-credential-types 1.0.1", - "aws-http 0.60.0", - "aws-runtime 1.0.1", + "aws-credential-types 1.1.8", + "aws-runtime 1.1.9", "aws-sdk-sso", "aws-sdk-ssooidc", "aws-sdk-sts", - "aws-smithy-async 1.0.1", - "aws-smithy-http 0.60.0", - "aws-smithy-json 0.60.0", - "aws-smithy-runtime 1.0.1", - "aws-smithy-runtime-api 1.0.1", - "aws-smithy-types 1.0.1", - "aws-types 1.0.1", + "aws-smithy-async 1.2.1", + "aws-smithy-http 0.60.7", + "aws-smithy-json 0.60.7", + "aws-smithy-runtime 1.3.0", + "aws-smithy-runtime-api 1.4.0", + "aws-smithy-types 1.1.8", + "aws-types 1.1.9", "bytes", "fastrand", "hex", - "http", + "http 0.2.12", "hyper", "ring", "time", "tokio", "tracing", + "url", "zeroize", ] [[package]] name = "aws-credential-types" -version = "1.0.1" +version = "1.1.8" dependencies = [ - "aws-smithy-async 1.0.1", - "aws-smithy-runtime-api 1.0.1", - "aws-smithy-types 1.0.1", + "aws-smithy-async 1.2.1", + "aws-smithy-runtime-api 1.4.0", + "aws-smithy-types 1.1.8", "zeroize", ] [[package]] name = "aws-credential-types" -version = "1.0.1" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1317e1a3514b103cf7d5828bbab3b4d30f56bd22d684f8568bc51b6cfbbb1c" +checksum = "fa8587ae17c8e967e4b05a62d495be2fb7701bec52a97f7acfe8a29f938384c8" dependencies = [ - "aws-smithy-async 1.0.2", - "aws-smithy-runtime-api 1.0.2", - "aws-smithy-types 1.0.2", + "aws-smithy-async 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-runtime-api 1.3.0", + "aws-smithy-types 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "zeroize", ] -[[package]] -name = "aws-http" -version = "0.60.0" -dependencies = [ - "aws-smithy-runtime-api 1.0.1", - "aws-smithy-types 1.0.1", - "aws-types 1.0.1", - "bytes", - "http", - "http-body", - "pin-project-lite", - "tracing", -] - -[[package]] -name = "aws-http" -version = "0.60.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "361c4310fdce94328cc2d1ca0c8a48c13f43009c61d3367585685a50ca8c66b6" -dependencies = [ - "aws-smithy-runtime-api 1.0.2", - "aws-smithy-types 1.0.2", - "aws-types 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes", - "http", - "http-body", - "pin-project-lite", - "tracing", -] - [[package]] name = "aws-runtime" -version = "1.0.1" -dependencies = [ - "aws-credential-types 1.0.1", - "aws-http 0.60.0", - "aws-sigv4 1.0.1", - "aws-smithy-async 1.0.1", - "aws-smithy-eventstream 0.60.0", - "aws-smithy-http 0.60.0", - "aws-smithy-runtime-api 1.0.1", - "aws-smithy-types 1.0.1", - "aws-types 1.0.1", +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b13dc54b4b49f8288532334bba8f87386a40571c47c37b1304979b556dc613c8" +dependencies = [ + "aws-credential-types 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-sigv4 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-async 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-eventstream 0.60.4 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-http 0.60.7 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-runtime-api 1.3.0", + "aws-smithy-types 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-types 1.1.8", + "bytes", "fastrand", - "http", + "http 0.2.12", + "http-body 0.4.6", "percent-encoding", + "pin-project-lite", "tracing", "uuid", ] [[package]] name = "aws-runtime" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ed7ef604a15fd0d4d9e43701295161ea6b504b63c44990ead352afea2bc15e9" -dependencies = [ - "aws-credential-types 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-http 0.60.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-sigv4 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-smithy-async 1.0.2", - "aws-smithy-eventstream 0.60.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-smithy-http 0.60.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-smithy-runtime-api 1.0.2", - "aws-smithy-types 1.0.2", - "aws-types 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +version = "1.1.9" +dependencies = [ + "aws-credential-types 1.1.8", + "aws-sigv4 1.2.0", + "aws-smithy-async 1.2.1", + "aws-smithy-eventstream 0.60.4", + "aws-smithy-http 0.60.7", + "aws-smithy-runtime-api 1.4.0", + "aws-smithy-types 1.1.8", + "aws-types 1.1.9", + "bytes", "fastrand", - "http", + "http 0.2.12", + "http-body 0.4.6", "percent-encoding", + "pin-project-lite", "tracing", "uuid", ] @@ -182,56 +175,66 @@ dependencies = [ name = "aws-sdk-s3" version = "0.0.0-local" dependencies = [ - "aws-credential-types 1.0.1", - "aws-http 0.60.0", - "aws-runtime 1.0.1", - "aws-sigv4 1.0.1", - "aws-smithy-async 1.0.1", - "aws-smithy-checksums 0.60.0", - "aws-smithy-eventstream 0.60.0", - "aws-smithy-http 0.60.0", - "aws-smithy-json 0.60.0", - "aws-smithy-runtime 1.0.1", - "aws-smithy-runtime-api 1.0.1", - "aws-smithy-types 1.0.1", - "aws-smithy-xml 0.60.0", - "aws-types 1.0.1", + "ahash", + "aws-credential-types 1.1.8", + "aws-runtime 1.1.9", + "aws-sigv4 1.2.0", + "aws-smithy-async 1.2.1", + "aws-smithy-checksums 0.60.7", + "aws-smithy-eventstream 0.60.4", + "aws-smithy-http 0.60.7", + "aws-smithy-json 0.60.7", + "aws-smithy-runtime 1.3.0", + "aws-smithy-runtime-api 1.4.0", + "aws-smithy-types 1.1.8", + "aws-smithy-xml 0.60.7", + "aws-types 1.1.9", "bytes", - "http", - "http-body", + "fastrand", + "hex", + "hmac", + "http 0.2.12", + "http-body 0.4.6", + "lru", "once_cell", "percent-encoding", "regex-lite", + "sha2", "tracing", "url", ] [[package]] name = "aws-sdk-s3" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dcafc2fe52cc30b2d56685e2fa6a879ba50d79704594852112337a472ddbd24" -dependencies = [ - "aws-credential-types 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-http 0.60.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-runtime 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-sigv4 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-smithy-async 1.0.2", - "aws-smithy-checksums 0.60.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-smithy-eventstream 0.60.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-smithy-http 0.60.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-smithy-json 0.60.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-smithy-runtime 1.0.2", - "aws-smithy-runtime-api 1.0.2", - "aws-smithy-types 1.0.2", - "aws-smithy-xml 0.60.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-types 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +version = "1.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc075ffee2a40cb1590bed35d7ec953589a564e768fa91947c565425cd569269" +dependencies = [ + "ahash", + "aws-credential-types 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-runtime 1.1.8", + "aws-sigv4 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-async 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-checksums 0.60.7 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-eventstream 0.60.4 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-http 0.60.7 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-json 0.60.7 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-runtime 1.2.1", + "aws-smithy-runtime-api 1.3.0", + "aws-smithy-types 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-xml 0.60.7 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-types 1.1.8", "bytes", - "http", - "http-body", + "fastrand", + "hex", + "hmac", + "http 0.2.12", + "http-body 0.4.6", + "lru", "once_cell", "percent-encoding", - "regex", + "regex-lite", + "sha2", "tracing", "url", ] @@ -240,18 +243,17 @@ dependencies = [ name = "aws-sdk-sso" version = "0.0.0-local" dependencies = [ - "aws-credential-types 1.0.1", - "aws-http 0.60.0", - "aws-runtime 1.0.1", - "aws-smithy-async 1.0.1", - "aws-smithy-http 0.60.0", - "aws-smithy-json 0.60.0", - "aws-smithy-runtime 1.0.1", - "aws-smithy-runtime-api 1.0.1", - "aws-smithy-types 1.0.1", - "aws-types 1.0.1", + "aws-credential-types 1.1.8", + "aws-runtime 1.1.9", + "aws-smithy-async 1.2.1", + "aws-smithy-http 0.60.7", + "aws-smithy-json 0.60.7", + "aws-smithy-runtime 1.3.0", + "aws-smithy-runtime-api 1.4.0", + "aws-smithy-types 1.1.8", + "aws-types 1.1.9", "bytes", - "http", + "http 0.2.12", "once_cell", "regex-lite", "tracing", @@ -261,18 +263,17 @@ dependencies = [ name = "aws-sdk-ssooidc" version = "0.0.0-local" dependencies = [ - "aws-credential-types 1.0.1", - "aws-http 0.60.0", - "aws-runtime 1.0.1", - "aws-smithy-async 1.0.1", - "aws-smithy-http 0.60.0", - "aws-smithy-json 0.60.0", - "aws-smithy-runtime 1.0.1", - "aws-smithy-runtime-api 1.0.1", - "aws-smithy-types 1.0.1", - "aws-types 1.0.1", + "aws-credential-types 1.1.8", + "aws-runtime 1.1.9", + "aws-smithy-async 1.2.1", + "aws-smithy-http 0.60.7", + "aws-smithy-json 0.60.7", + "aws-smithy-runtime 1.3.0", + "aws-smithy-runtime-api 1.4.0", + "aws-smithy-types 1.1.8", + "aws-types 1.1.9", "bytes", - "http", + "http 0.2.12", "once_cell", "regex-lite", "tracing", @@ -282,19 +283,18 @@ dependencies = [ name = "aws-sdk-sts" version = "0.0.0-local" dependencies = [ - "aws-credential-types 1.0.1", - "aws-http 0.60.0", - "aws-runtime 1.0.1", - "aws-smithy-async 1.0.1", - "aws-smithy-http 0.60.0", - "aws-smithy-json 0.60.0", + "aws-credential-types 1.1.8", + "aws-runtime 1.1.9", + "aws-smithy-async 1.2.1", + "aws-smithy-http 0.60.7", + "aws-smithy-json 0.60.7", "aws-smithy-query", - "aws-smithy-runtime 1.0.1", - "aws-smithy-runtime-api 1.0.1", - "aws-smithy-types 1.0.1", - "aws-smithy-xml 0.60.0", - "aws-types 1.0.1", - "http", + "aws-smithy-runtime 1.3.0", + "aws-smithy-runtime-api 1.4.0", + "aws-smithy-types 1.1.8", + "aws-smithy-xml 0.60.7", + "aws-types 1.1.9", + "http 0.2.12", "once_cell", "regex-lite", "tracing", @@ -302,19 +302,20 @@ dependencies = [ [[package]] name = "aws-sigv4" -version = "1.0.1" +version = "1.2.0" dependencies = [ - "aws-credential-types 1.0.1", - "aws-smithy-eventstream 0.60.0", - "aws-smithy-http 0.60.0", - "aws-smithy-runtime-api 1.0.1", - "aws-smithy-types 1.0.1", + "aws-credential-types 1.1.8", + "aws-smithy-eventstream 0.60.4", + "aws-smithy-http 0.60.7", + "aws-smithy-runtime-api 1.4.0", + "aws-smithy-types 1.1.8", "bytes", "crypto-bigint 0.5.5", "form_urlencoded", "hex", "hmac", - "http", + "http 0.2.12", + "http 1.1.0", "once_cell", "p256", "percent-encoding", @@ -328,25 +329,25 @@ dependencies = [ [[package]] name = "aws-sigv4" -version = "1.0.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380adcc8134ad8bbdfeb2ace7626a869914ee266322965276cbc54066186d236" +checksum = "11d6f29688a4be9895c0ba8bef861ad0c0dac5c15e9618b9b7a6c233990fc263" dependencies = [ - "aws-credential-types 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-smithy-eventstream 0.60.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-smithy-http 0.60.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-smithy-runtime-api 1.0.2", - "aws-smithy-types 1.0.2", + "aws-credential-types 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-eventstream 0.60.4 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-http 0.60.7 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-runtime-api 1.3.0", + "aws-smithy-types 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "bytes", "crypto-bigint 0.5.5", "form_urlencoded", "hex", "hmac", - "http", + "http 0.2.12", + "http 1.1.0", "once_cell", "p256", "percent-encoding", - "regex", "ring", "sha2", "subtle", @@ -357,7 +358,7 @@ dependencies = [ [[package]] name = "aws-smithy-async" -version = "1.0.1" +version = "1.2.1" dependencies = [ "futures-util", "pin-project-lite", @@ -366,9 +367,9 @@ dependencies = [ [[package]] name = "aws-smithy-async" -version = "1.0.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e37ca17d25fe1e210b6d4bdf59b81caebfe99f986201a1228cb5061233b4b13" +checksum = "62220bc6e97f946ddd51b5f1361f78996e704677afc518a4ff66b7a72ea1378c" dependencies = [ "futures-util", "pin-project-lite", @@ -377,16 +378,16 @@ dependencies = [ [[package]] name = "aws-smithy-checksums" -version = "0.60.0" +version = "0.60.7" dependencies = [ - "aws-smithy-http 0.60.0", - "aws-smithy-types 1.0.1", + "aws-smithy-http 0.60.7", + "aws-smithy-types 1.1.8", "bytes", "crc32c", "crc32fast", "hex", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "md-5", "pin-project-lite", "sha1", @@ -396,18 +397,18 @@ dependencies = [ [[package]] name = "aws-smithy-checksums" -version = "0.60.0" +version = "0.60.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5a373ec01aede3dd066ec018c1bc4e8f5dd11b2c11c59c8eef1a5c68101f397" +checksum = "83fa43bc04a6b2441968faeab56e68da3812f978a670a5db32accbdcafddd12f" dependencies = [ - "aws-smithy-http 0.60.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-smithy-types 1.0.2", + "aws-smithy-http 0.60.7 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-types 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "bytes", "crc32c", "crc32fast", "hex", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "md-5", "pin-project-lite", "sha1", @@ -417,36 +418,36 @@ dependencies = [ [[package]] name = "aws-smithy-eventstream" -version = "0.60.0" +version = "0.60.4" dependencies = [ - "aws-smithy-types 1.0.1", + "aws-smithy-types 1.1.8", "bytes", "crc32fast", ] [[package]] name = "aws-smithy-eventstream" -version = "0.60.0" +version = "0.60.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c669e1e5fc0d79561bf7a122b118bd50c898758354fe2c53eb8f2d31507cbc3" +checksum = "e6363078f927f612b970edf9d1903ef5cef9a64d1e8423525ebb1f0a1633c858" dependencies = [ - "aws-smithy-types 1.0.2", + "aws-smithy-types 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "bytes", "crc32fast", ] [[package]] name = "aws-smithy-http" -version = "0.60.0" +version = "0.60.7" dependencies = [ - "aws-smithy-eventstream 0.60.0", - "aws-smithy-runtime-api 1.0.1", - "aws-smithy-types 1.0.1", + "aws-smithy-eventstream 0.60.4", + "aws-smithy-runtime-api 1.4.0", + "aws-smithy-types 1.1.8", "bytes", "bytes-utils", "futures-core", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "once_cell", "percent-encoding", "pin-project-lite", @@ -456,18 +457,18 @@ dependencies = [ [[package]] name = "aws-smithy-http" -version = "0.60.0" +version = "0.60.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b1de8aee22f67de467b2e3d0dd0fb30859dc53f579a63bd5381766b987db644" +checksum = "3f10fa66956f01540051b0aa7ad54574640f748f9839e843442d99b970d3aff9" dependencies = [ - "aws-smithy-eventstream 0.60.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-smithy-runtime-api 1.0.2", - "aws-smithy-types 1.0.2", + "aws-smithy-eventstream 0.60.4 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-runtime-api 1.3.0", + "aws-smithy-types 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "bytes", "bytes-utils", "futures-core", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "once_cell", "percent-encoding", "pin-project-lite", @@ -477,27 +478,27 @@ dependencies = [ [[package]] name = "aws-smithy-json" -version = "0.60.0" +version = "0.60.7" dependencies = [ - "aws-smithy-types 1.0.1", + "aws-smithy-types 1.1.8", ] [[package]] name = "aws-smithy-json" -version = "0.60.0" +version = "0.60.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a46dd338dc9576d6a6a5b5a19bd678dcad018ececee11cf28ecd7588bd1a55c" +checksum = "4683df9469ef09468dad3473d129960119a0d3593617542b7d52086c8486f2d6" dependencies = [ - "aws-smithy-types 1.0.2", + "aws-smithy-types 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "aws-smithy-protocol-test" -version = "0.60.0" +version = "0.60.7" dependencies = [ "assert-json-diff", - "aws-smithy-runtime-api 1.0.1", - "http", + "aws-smithy-runtime-api 1.4.0", + "http 0.2.12", "pretty_assertions", "regex-lite", "roxmltree", @@ -507,15 +508,15 @@ dependencies = [ [[package]] name = "aws-smithy-protocol-test" -version = "0.60.0" +version = "0.60.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ad76ca454230a5540a47e44ba903a910ae09f2c39a86cd249f2f8c87da83eb" +checksum = "a31e8279cb24640c7349f2bda6ca818d5fcc85129386bd73c1d0999430d6ddf2" dependencies = [ "assert-json-diff", - "aws-smithy-runtime-api 1.0.2", - "http", + "aws-smithy-runtime-api 1.3.0", + "http 0.2.12", "pretty_assertions", - "regex", + "regex-lite", "roxmltree", "serde_json", "thiserror", @@ -523,27 +524,32 @@ dependencies = [ [[package]] name = "aws-smithy-query" -version = "0.60.0" +version = "0.60.7" dependencies = [ - "aws-smithy-types 1.0.1", + "aws-smithy-types 1.1.8", "urlencoding", ] [[package]] name = "aws-smithy-runtime" -version = "1.0.1" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c53572b4cd934ee5e8461ad53caa36e9d246aaef42166e3ac539e206a925d330" dependencies = [ - "aws-smithy-async 1.0.1", - "aws-smithy-http 0.60.0", - "aws-smithy-protocol-test 0.60.0", - "aws-smithy-runtime-api 1.0.1", - "aws-smithy-types 1.0.1", + "aws-smithy-async 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-http 0.60.7 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-protocol-test 0.60.7 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-runtime-api 1.3.0", + "aws-smithy-types 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "bytes", "fastrand", - "http", - "http-body", + "h2", + "http 0.2.12", + "http-body 0.4.6", + "http-body 1.0.0", "hyper", "hyper-rustls", + "indexmap", "once_cell", "pin-project-lite", "pin-utils", @@ -557,22 +563,22 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "273479291efc55e7b0bce985b139d86b6031adb8e50f65c1f712f20ba38f6388" +version = "1.3.0" dependencies = [ - "aws-smithy-async 1.0.2", - "aws-smithy-http 0.60.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-smithy-protocol-test 0.60.0 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-smithy-runtime-api 1.0.2", - "aws-smithy-types 1.0.2", + "aws-smithy-async 1.2.1", + "aws-smithy-http 0.60.7", + "aws-smithy-protocol-test 0.60.7", + "aws-smithy-runtime-api 1.4.0", + "aws-smithy-types 1.1.8", "bytes", "fastrand", "h2", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", + "http-body 1.0.0", "hyper", "hyper-rustls", + "indexmap", "once_cell", "pin-project-lite", "pin-utils", @@ -586,12 +592,15 @@ dependencies = [ [[package]] name = "aws-smithy-runtime-api" -version = "1.0.1" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccb2b3a7030dc9a3c9a08ce0b25decea5130e9db19619d4dffbbff34f75fe850" dependencies = [ - "aws-smithy-async 1.0.1", - "aws-smithy-types 1.0.1", + "aws-smithy-async 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-types 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "bytes", - "http", + "http 0.2.12", + "http 1.1.0", "pin-project-lite", "tokio", "tracing", @@ -600,29 +609,32 @@ dependencies = [ [[package]] name = "aws-smithy-runtime-api" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6cebff0d977b6b6feed2fd07db52aac58ba3ccaf26cdd49f1af4add5061bef9" +version = "1.4.0" dependencies = [ - "aws-smithy-async 1.0.2", - "aws-smithy-types 1.0.2", + "aws-smithy-async 1.2.1", + "aws-smithy-types 1.1.8", "bytes", - "http", + "http 0.2.12", + "http 1.1.0", "pin-project-lite", "tokio", "tracing", + "zeroize", ] [[package]] name = "aws-smithy-types" -version = "1.0.1" +version = "1.1.8" dependencies = [ "base64-simd", "bytes", "bytes-utils", "futures-core", - "http", - "http-body", + "http 0.2.12", + "http 1.1.0", + "http-body 0.4.6", + "http-body 1.0.0", + "http-body-util", "itoa", "num-integer", "pin-project-lite", @@ -636,16 +648,19 @@ dependencies = [ [[package]] name = "aws-smithy-types" -version = "1.0.2" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f48b3f27ddb40ab19892a5abda331f403e3cb877965e4e51171447807104af" +checksum = "abe14dceea1e70101d38fbf2a99e6a34159477c0fb95e68e05c66bd7ae4c3729" dependencies = [ "base64-simd", "bytes", "bytes-utils", "futures-core", - "http", - "http-body", + "http 0.2.12", + "http 1.1.0", + "http-body 0.4.6", + "http-body 1.0.0", + "http-body-util", "itoa", "num-integer", "pin-project-lite", @@ -659,53 +674,53 @@ dependencies = [ [[package]] name = "aws-smithy-xml" -version = "0.60.0" +version = "0.60.7" dependencies = [ "xmlparser", ] [[package]] name = "aws-smithy-xml" -version = "0.60.0" +version = "0.60.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec40d74a67fd395bc3f6b4ccbdf1543672622d905ef3f979689aea5b730cb95" +checksum = "872c68cf019c0e4afc5de7753c4f7288ce4b71663212771bf5e4542eb9346ca9" dependencies = [ "xmlparser", ] [[package]] name = "aws-types" -version = "1.0.1" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dbf2f3da841a8930f159163175cf6a3d16ddde517c1b0fba7aa776822800f40" dependencies = [ - "aws-credential-types 1.0.1", - "aws-smithy-async 1.0.1", - "aws-smithy-runtime-api 1.0.1", - "aws-smithy-types 1.0.1", - "http", + "aws-credential-types 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-async 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aws-smithy-runtime-api 1.3.0", + "aws-smithy-types 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.12", "rustc_version", "tracing", ] [[package]] name = "aws-types" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8403fc56b1f3761e8efe45771ddc1165e47ec3417c68e68a4519b5cb030159ca" +version = "1.1.9" dependencies = [ - "aws-credential-types 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "aws-smithy-async 1.0.2", - "aws-smithy-runtime-api 1.0.2", - "aws-smithy-types 1.0.2", - "http", + "aws-credential-types 1.1.8", + "aws-smithy-async 1.2.1", + "aws-smithy-runtime-api 1.4.0", + "aws-smithy-types 1.1.8", + "http 0.2.12", "rustc_version", "tracing", ] [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -724,9 +739,9 @@ checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64-simd" @@ -750,12 +765,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bitflags" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" - [[package]] name = "block-buffer" version = "0.10.4" @@ -767,15 +776,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "bytes-utils" @@ -795,12 +804,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.83" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" [[package]] name = "cfg-if" @@ -810,9 +816,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "ciborium" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ "ciborium-io", "ciborium-ll", @@ -821,15 +827,15 @@ dependencies = [ [[package]] name = "ciborium-io" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] name = "ciborium-ll" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", "half", @@ -837,18 +843,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.10" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fffed7514f420abec6d183b1d3acfd9099c79c3a10a06ade4f8203f1411272" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.4.9" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63361bae7eef3771745f02d8d892bec2fee5f6e34af316ba556e7f97a7069ff1" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstyle", "clap_lex", @@ -856,21 +862,21 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "const-oid" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -878,33 +884,33 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] [[package]] name = "crc32c" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8f48d60e5b4d2c53d5c2b1d8a58c849a70ae5e5509b08a48d047e3b65714a74" +checksum = "89254598aa9b9fa608de44b3ae54c810f0f06d755e24c50177f1f8f31ff50ce2" dependencies = [ "rustc_version", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] @@ -949,36 +955,34 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" @@ -1024,9 +1028,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", ] @@ -1062,9 +1066,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "elliptic-curve" @@ -1092,16 +1096,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" -[[package]] -name = "errno" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - [[package]] name = "extend" version = "0.1.2" @@ -1116,9 +1110,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "ff" @@ -1147,9 +1141,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -1161,9 +1155,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1171,33 +1165,33 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-core", "futures-sink", @@ -1218,9 +1212,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -1246,16 +1240,16 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.22" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.12", "indexmap", "slab", "tokio", @@ -1265,21 +1259,29 @@ dependencies = [ [[package]] name = "half" -version = "1.8.2" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +checksum = "b5eceaaeec696539ddaf7b333340f1af35a5aa87ae3e4f3ead0532f72affab2e" +dependencies = [ + "cfg-if", + "crunchy", +] [[package]] name = "hashbrown" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", + "allocator-api2", +] [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -1298,9 +1300,20 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -1309,12 +1322,35 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http 1.1.0", + "http-body 1.0.0", "pin-project-lite", ] @@ -1332,22 +1368,22 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", "h2", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2", "tokio", "tower-service", "tracing", @@ -1361,7 +1397,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http", + "http 0.2.12", "hyper", "log", "rustls", @@ -1382,23 +1418,24 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown", + "serde", ] [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" dependencies = [ "hermit-abi", - "rustix", - "windows-sys 0.48.0", + "libc", + "windows-sys 0.52.0", ] [[package]] @@ -1412,15 +1449,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1433,21 +1470,33 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] -name = "linux-raw-sys" -version = "0.4.11" +name = "log" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] -name = "log" -version = "0.4.20" +name = "lru" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +dependencies = [ + "hashbrown", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] [[package]] name = "md-5" @@ -1461,33 +1510,24 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.9" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", @@ -1504,21 +1544,26 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] @@ -1535,18 +1580,18 @@ dependencies = [ [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oorandom" @@ -1591,9 +1636,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -1660,13 +1705,13 @@ name = "previous-release-comparison" version = "0.1.0" dependencies = [ "aws-config", - "aws-credential-types 1.0.1", + "aws-credential-types 1.1.8", "aws-sdk-s3 0.0.0-local", - "aws-sdk-s3 1.4.0", - "aws-smithy-runtime 1.0.1", - "aws-smithy-runtime 1.0.2", + "aws-sdk-s3 1.21.0", + "aws-smithy-runtime 1.2.1", + "aws-smithy-runtime 1.3.0", "criterion", - "http", + "http 0.2.12", "tokio", ] @@ -1696,18 +1741,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -1723,9 +1768,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -1733,9 +1778,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -1743,25 +1788,34 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", ] [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.3", ] [[package]] @@ -1772,9 +1826,15 @@ checksum = "30b661b2f27137bdbc16f00eda72866a92bb28af1753ffbd56744fb6e2e9cd8e" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "rfc6979" @@ -1789,16 +1849,17 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.6" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "684d5e6e18f669ccebf64a92236bb7db9a34f07be010e3627368182027180866" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", "spin", "untrusted", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1825,24 +1886,11 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.38.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" -dependencies = [ - "bitflags 2.4.1", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.48.0", -] - [[package]] name = "rustls" -version = "0.21.9" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", "ring", @@ -1883,9 +1931,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "same-file" @@ -1898,19 +1946,13 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - [[package]] name = "sct" version = "0.7.1" @@ -1937,11 +1979,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ - "bitflags 1.3.2", + "bitflags", "core-foundation", "core-foundation-sys", "libc", @@ -1950,9 +1992,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" dependencies = [ "core-foundation-sys", "libc", @@ -1960,36 +2002,37 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.58", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ + "indexmap", "itoa", "ryu", "serde", @@ -2056,28 +2099,18 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" - -[[package]] -name = "socket2" -version = "0.4.10" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2115,9 +2148,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" dependencies = [ "proc-macro2", "quote", @@ -2126,29 +2159,29 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.58", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -2156,11 +2189,12 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ "deranged", + "num-conv", "powerfmt", "serde", "time-core", @@ -2175,10 +2209,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" dependencies = [ + "num-conv", "time-core", ] @@ -2209,9 +2244,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.34.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -2220,7 +2255,7 @@ dependencies = [ "num_cpus", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.5", + "socket2", "tokio-macros", "windows-sys 0.48.0", ] @@ -2233,7 +2268,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.58", ] [[package]] @@ -2285,7 +2320,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.58", ] [[package]] @@ -2325,12 +2360,16 @@ version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ + "matchers", "nu-ansi-term", + "once_cell", + "regex", "serde", "serde_json", "sharded-slab", "smallvec", "thread_local", + "tracing", "tracing-core", "tracing-log", "tracing-serde", @@ -2338,9 +2377,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" @@ -2350,9 +2389,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -2362,9 +2401,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -2394,9 +2433,9 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] name = "uuid" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" [[package]] name = "valuable" @@ -2418,9 +2457,9 @@ checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -2443,9 +2482,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2453,24 +2492,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.58", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2478,28 +2517,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.58", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -2551,7 +2590,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.4", ] [[package]] @@ -2571,17 +2610,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] @@ -2592,9 +2631,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" @@ -2604,9 +2643,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" @@ -2616,9 +2655,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" @@ -2628,9 +2667,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" @@ -2640,9 +2679,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" @@ -2652,9 +2691,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" @@ -2664,9 +2703,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "xmlparser" @@ -2680,6 +2719,26 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + [[package]] name = "zeroize" version = "1.7.0" diff --git a/aws/sdk/benchmarks/s3-express/Cargo.lock b/aws/sdk/benchmarks/s3-express/Cargo.lock new file mode 100644 index 0000000000..caa6ae9c9b --- /dev/null +++ b/aws/sdk/benchmarks/s3-express/Cargo.lock @@ -0,0 +1,2205 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "anstyle" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "aws-config" +version = "1.1.10" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-sdk-sso", + "aws-sdk-ssooidc", + "aws-sdk-sts", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand", + "hex", + "http 0.2.11", + "hyper", + "ring", + "time", + "tokio", + "tracing", + "url", + "zeroize", +] + +[[package]] +name = "aws-credential-types" +version = "1.1.8" +dependencies = [ + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "zeroize", +] + +[[package]] +name = "aws-runtime" +version = "1.1.9" +dependencies = [ + "aws-credential-types", + "aws-sigv4", + "aws-smithy-async", + "aws-smithy-eventstream", + "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand", + "http 0.2.11", + "http-body 0.4.6", + "percent-encoding", + "pin-project-lite", + "tracing", + "uuid", +] + +[[package]] +name = "aws-sdk-s3" +version = "0.0.0-local" +dependencies = [ + "ahash", + "aws-credential-types", + "aws-runtime", + "aws-sigv4", + "aws-smithy-async", + "aws-smithy-checksums", + "aws-smithy-eventstream", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-smithy-xml", + "aws-types", + "bytes", + "fastrand", + "hex", + "hmac", + "http 0.2.11", + "http-body 0.4.6", + "lru", + "once_cell", + "percent-encoding", + "regex-lite", + "sha2", + "tracing", + "url", +] + +[[package]] +name = "aws-sdk-sso" +version = "0.0.0-local" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "http 0.2.11", + "once_cell", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sdk-ssooidc" +version = "0.0.0-local" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "http 0.2.11", + "once_cell", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sdk-sts" +version = "0.0.0-local" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-query", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-smithy-xml", + "aws-types", + "http 0.2.11", + "once_cell", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sigv4" +version = "1.2.0" +dependencies = [ + "aws-credential-types", + "aws-smithy-eventstream", + "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "crypto-bigint 0.5.5", + "form_urlencoded", + "hex", + "hmac", + "http 0.2.11", + "http 1.0.0", + "once_cell", + "p256", + "percent-encoding", + "ring", + "sha2", + "subtle", + "time", + "tracing", + "zeroize", +] + +[[package]] +name = "aws-smithy-async" +version = "1.2.1" +dependencies = [ + "futures-util", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "aws-smithy-checksums" +version = "0.60.7" +dependencies = [ + "aws-smithy-http", + "aws-smithy-types", + "bytes", + "crc32c", + "crc32fast", + "hex", + "http 0.2.11", + "http-body 0.4.6", + "md-5", + "pin-project-lite", + "sha1", + "sha2", + "tracing", +] + +[[package]] +name = "aws-smithy-eventstream" +version = "0.60.4" +dependencies = [ + "aws-smithy-types", + "bytes", + "crc32fast", +] + +[[package]] +name = "aws-smithy-http" +version = "0.60.7" +dependencies = [ + "aws-smithy-eventstream", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "bytes-utils", + "futures-core", + "http 0.2.11", + "http-body 0.4.6", + "once_cell", + "percent-encoding", + "pin-project-lite", + "pin-utils", + "tracing", +] + +[[package]] +name = "aws-smithy-json" +version = "0.60.7" +dependencies = [ + "aws-smithy-types", +] + +[[package]] +name = "aws-smithy-query" +version = "0.60.7" +dependencies = [ + "aws-smithy-types", + "urlencoding", +] + +[[package]] +name = "aws-smithy-runtime" +version = "1.3.0" +dependencies = [ + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "fastrand", + "h2", + "http 0.2.11", + "http-body 0.4.6", + "http-body 1.0.0", + "hyper", + "hyper-rustls", + "once_cell", + "pin-project-lite", + "pin-utils", + "rustls", + "tokio", + "tracing", +] + +[[package]] +name = "aws-smithy-runtime-api" +version = "1.4.0" +dependencies = [ + "aws-smithy-async", + "aws-smithy-types", + "bytes", + "http 0.2.11", + "http 1.0.0", + "pin-project-lite", + "tokio", + "tracing", + "zeroize", +] + +[[package]] +name = "aws-smithy-types" +version = "1.1.8" +dependencies = [ + "base64-simd", + "bytes", + "bytes-utils", + "futures-core", + "http 0.2.11", + "http 1.0.0", + "http-body 0.4.6", + "http-body 1.0.0", + "http-body-util", + "itoa", + "num-integer", + "pin-project-lite", + "pin-utils", + "ryu", + "serde", + "time", + "tokio", + "tokio-util", +] + +[[package]] +name = "aws-smithy-xml" +version = "0.60.7" +dependencies = [ + "xmlparser", +] + +[[package]] +name = "aws-types" +version = "1.1.9" +dependencies = [ + "aws-credential-types", + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "http 0.2.11", + "rustc_version", + "tracing", +] + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" +dependencies = [ + "outref", + "vsimd", +] + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3b1be7772ee4501dba05acbe66bb1e8760f6a6c474a36035631638e4415f130" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "bytes-utils" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35" +dependencies = [ + "bytes", + "either", +] + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cc" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clap" +version = "4.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32c" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89254598aa9b9fa608de44b3ae54c810f0f06d755e24c50177f1f8f31ff50ce2" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "crc32fast" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "criterion" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "futures", + "is-terminal", + "itertools", + "num-traits", + "once_cell", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "tokio", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der", + "elliptic-curve", + "rfc6979", + "signature", +] + +[[package]] +name = "either" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct", + "crypto-bigint 0.4.9", + "der", + "digest", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "h2" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.11", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "half" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hermit-abi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "http" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.11", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.0.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http 1.0.0", + "http-body 1.0.0", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http 0.2.11", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.11", + "hyper", + "log", + "rustls", + "rustls-native-certs", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "is-terminal" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "js-sys" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "lru" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +dependencies = [ + "hashbrown", +] + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "outref" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a" + +[[package]] +name = "p256" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" +dependencies = [ + "ecdsa", + "elliptic-curve", + "sha2", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "plotters" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" + +[[package]] +name = "plotters-svg" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "regex" +version = "1.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-lite" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b661b2f27137bdbc16f00eda72866a92bb28af1753ffbd56744fb6e2e9cd8e" + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint 0.4.9", + "hmac", + "zeroize", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustls" +version = "0.21.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "s3-express" +version = "0.1.0" +dependencies = [ + "aws-config", + "aws-sdk-s3", + "criterion", + "futures-util", + "tokio", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "socket2" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "2.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "time" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] +name = "uuid" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" + +[[package]] +name = "web-sys" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "xmlparser" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/aws/sdk/benchmarks/s3-express/Cargo.toml b/aws/sdk/benchmarks/s3-express/Cargo.toml new file mode 100644 index 0000000000..5bdf83bcff --- /dev/null +++ b/aws/sdk/benchmarks/s3-express/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "s3-express" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +aws-config = { path = "../../build/aws-sdk/sdk/aws-config", features = ["behavior-version-latest"] } +aws-sdk-s3 = { path = "../../build/aws-sdk/sdk/s3", features = ["behavior-version-latest"] } +criterion = { version = "0.5", features = ["async_tokio"] } +futures-util = { version = "0.3.29", default-features = false, features = ["alloc"] } +tokio = { version = "1.23.1", features = ["macros", "test-util", "rt-multi-thread"] } + +[[bench]] +name = "concurrent_put_get" +harness = false + +[[bench]] +name = "get_object" +harness = false + +[[bench]] +name = "put_get_delete" +harness = false + +[[bench]] +name = "put_object" +harness = false + +[profile.bench] +debug = true diff --git a/aws/sdk/benchmarks/s3-express/README.md b/aws/sdk/benchmarks/s3-express/README.md new file mode 100644 index 0000000000..cae5b88c81 --- /dev/null +++ b/aws/sdk/benchmarks/s3-express/README.md @@ -0,0 +1,62 @@ +# S3 Express Benchmark + +This directory contains S3 Express One Zone benchmarks that measure end-to-end throughput when using the AWS Rust SDK to put, get, and delete objects to/from S3 Express One Zone buckets. We use [`Criterion`](https://github.com/bheisler/criterion.rs) for benchmarks. A sibling directory `s3-throughput` also measures throughput to put and get objects to/from S3 but currently does not support generating benchmark results with a given confidence interval, which is why we have this separate benchmark suite. + +Performance numbers will vary depending on the benchmarking environment, but relative performance should still be accurate (i.e. regular S3 bucket vs. S3 Express bucket or comparing with a previous release of the Rust SDK). + +## Benchmark targets +- `get_object`: Invoke `GetObject` the specified number of times (20 by default) against a given set of buckets, using both 64KB and 1MB objects. +- `put_object`: Invoke `PutObject` the specified number of times (20 by default) against a given set of buckets, using both 64KB and 1MB objects. +- `put_get_delete`: `PutObject`, `GetObject`, and `DeleteObject` using sequential invocations (20 by default) of operations across different buckets, switching buckets on every request and using both 64KB and 1MB objects. +- `concurrent_put_get`: Schedule the equal number of async tasks of `PutObject` (20 by default) to different buckets, wait for completion, then schedule the equal number of async tasks of `GetObject` to different buckets, and wait for completion, using the 64KB objects. + +## Running benchmarks +Example of running the `put_object` benchmark in local dev environment: + +```bash +export BUCKETS=test0--usw2-az1--x-s3,test1--usw2-az1--x-s3 +cargo bench --bench put_object +``` +To configure how the benchmark is run, set the following environment variables: +#### required +- `BUCKETS`: a list of comma separated bucket names + +#### optional +- `CONFIDENCE_LEVEL`: the confidence level for benchmarks in a group (0.99 by default) +- `NUMBER_OF_ITERATIONS`: the number of times a set of operations runs for measurement (20 by default) +- `SAMPLE_SIZE`: the size of the sample for benchmarks in a group (10 by default) + +### Flamegraph generation +Use [`flamegraph`](https://github.com/flamegraph-rs/flamegraph) to generate one for a target bench, for instance: +```bash +export BUCKETS=test0--usw2-az1--x-s3,test1--usw2-az1--x-s3 +cargo flamegraph --bench put_get_delete -- --bench +``` + +The resulting flamegraph `flamegraph.svg` should be generated in the current directory. + + +## Limitation +Benchmarks currently measure end-to-end throughput of operations, including both the Rust SDK latency and the server side latency. To detect regressions in the Rust SDK reliably, we should only capture the time taken before sending a request and after receiving a response. + +## Baseline +As of b172a1e, here are performance numbers for the targets `get_object` and `put_object` run against a single express bucket within the `us-west-2` region (showing additional outputs to display config parameters). The benchmarks are measured on Amazon Linux 2 x86_64 5.10 Kernel with a host type c5.4xlarge. +``` +[src/lib.rs:30] sample_size = 10 +[src/lib.rs:14] confidence_level = 0.99 +[src/lib.rs:23] number_of_iterations = 20 +measuring 20 of GetObject against [ + "s3express-rust-sdk-benchmark--usw2-az1--x-s3", +], switching buckets on every operation if more than one bucket is specified +get_object/size/65536 time: [304.20 ms 311.62 ms 317.62 ms] +get_object/size/1048576 time: [283.94 ms 289.16 ms 293.42 ms] + +[src/lib.rs:30] sample_size = 10 +[src/lib.rs:14] confidence_level = 0.99 +[src/lib.rs:23] number_of_iterations = 20 +measuring 20 of PutObject against [ + "s3express-rust-sdk-benchmark--usw2-az1--x-s3", +], switching buckets on every operation if more than one bucket is specified +put_object/size/65536 time: [163.01 ms 172.76 ms 185.16 ms] +put_object/size/1048576 time: [356.49 ms 368.64 ms 383.51 ms] +``` diff --git a/aws/sdk/benchmarks/s3-express/benches/concurrent_put_get.rs b/aws/sdk/benchmarks/s3-express/benches/concurrent_put_get.rs new file mode 100644 index 0000000000..df39aae87b --- /dev/null +++ b/aws/sdk/benchmarks/s3-express/benches/concurrent_put_get.rs @@ -0,0 +1,97 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use aws_config::BehaviorVersion; +use aws_sdk_s3::primitives::ByteStream; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; +use s3_express::{confidence_level, number_of_iterations, sample_size}; +use tokio::runtime::Runtime; +use tokio::task; + +pub fn concurrent_put_get(c: &mut Criterion) { + let buckets = if let Ok(buckets) = std::env::var("BUCKETS") { + buckets.split(",").map(String::from).collect::>() + } else { + panic!("required environment variable `BUCKETS` should be set: e.g. `BUCKETS=\"bucket1,bucket2\"`") + }; + + let number_of_iterations = number_of_iterations(); + + println!( + "measuring {number_of_iterations} concurrent PutObject followed by \ + {number_of_iterations} concurrent GetObject against \ + {buckets:#?}, with each bucket being assigned equal number of operations\n" + ); + + let client = Runtime::new().unwrap().block_on(async { + let config = aws_config::load_defaults(BehaviorVersion::latest()).await; + aws_sdk_s3::Client::new(&config) + }); + + const KB: usize = 1024; + const SIZE: usize = 64 * KB; + let object: Vec = vec![0; SIZE]; + let mut group = c.benchmark_group("concurrent_put_delete"); + group.bench_with_input(BenchmarkId::new("size", SIZE), &SIZE, |b, _| { + b.to_async(Runtime::new().unwrap()).iter(|| async { + let put_futures = (0..number_of_iterations) + .map({ + let client = client.clone(); + let buckets = buckets.clone(); + let object = object.clone(); + move |i| { + task::spawn({ + let client = client.clone(); + let buckets = buckets.clone(); + let object = object.clone(); + async move { + client + .put_object() + .bucket(&buckets[i % buckets.len()]) + .key(&format!("test{i}")) + .body(ByteStream::from(object)) + .send() + .await + .unwrap(); + } + }) + } + }) + .collect::>(); + ::futures_util::future::join_all(put_futures).await; + + let get_futures = (0..number_of_iterations) + .map({ + let client = client.clone(); + let buckets = buckets.clone(); + move |i| { + task::spawn({ + let client = client.clone(); + let buckets = buckets.clone(); + async move { + client + .get_object() + .bucket(&buckets[i % buckets.len()]) + .key(&format!("test{i}")) + .send() + .await + .unwrap(); + } + }) + } + }) + .collect::>(); + ::futures_util::future::join_all(get_futures).await; + }); + }); + group.finish(); +} + +criterion_group!( + name = benches; + config = Criterion::default().sample_size(sample_size()).confidence_level(confidence_level()); + targets = concurrent_put_get +); +criterion_main!(benches); diff --git a/aws/sdk/benchmarks/s3-express/benches/get_object.rs b/aws/sdk/benchmarks/s3-express/benches/get_object.rs new file mode 100644 index 0000000000..14181f4739 --- /dev/null +++ b/aws/sdk/benchmarks/s3-express/benches/get_object.rs @@ -0,0 +1,99 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use aws_config::BehaviorVersion; +use aws_sdk_s3::primitives::ByteStream; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; +use s3_express::{confidence_level, number_of_iterations, sample_size}; +use tokio::runtime::Runtime; + +async fn prepare_test_objects>(buckets: &[T], object_sizes: &[usize]) { + let config = aws_config::load_defaults(BehaviorVersion::latest()).await; + let client = aws_sdk_s3::Client::new(&config); + + for size in object_sizes { + let object: Vec = vec![0; *size]; + for bucket in buckets.as_ref() { + client + .put_object() + .bucket(bucket.as_ref()) + .key(&format!("test-{size}")) + .body(ByteStream::from(object.clone())) + .send() + .await + .unwrap(); + } + } +} + +pub fn get_object(c: &mut Criterion) { + let buckets = if let Ok(buckets) = std::env::var("BUCKETS") { + buckets.split(",").map(String::from).collect::>() + } else { + panic!("required environment variable `BUCKETS` should be set: e.g. `BUCKETS=\"bucket1,bucket2\"`") + }; + + let number_of_iterations = number_of_iterations(); + + println!( + "measuring {number_of_iterations} of GetObject against {buckets:#?}, \ + switching buckets on every operation if more than one bucket is specified\n" + ); + + const KB: usize = 1024; + let sizes = [64 * KB, KB * KB]; + + let client = Runtime::new().unwrap().block_on(async { + prepare_test_objects(&buckets, &sizes).await; + + // Return a new client that has an empty identity cache + let config = aws_config::load_defaults(BehaviorVersion::latest()).await; + aws_sdk_s3::Client::new(&config) + }); + + let mut group = c.benchmark_group("get_object"); + + for size in sizes.iter() { + let key = format!("test-{size}"); + group.bench_with_input(BenchmarkId::new("size", size), size, |b, _| { + b.to_async(Runtime::new().unwrap()).iter(|| async { + for i in 0..number_of_iterations { + let bucket = &buckets[i % buckets.len()]; + client + .get_object() + .bucket(bucket) + .key(&key) + .send() + .await + .unwrap(); + } + }); + }); + } + group.finish(); + + // Clean up test objects + Runtime::new().unwrap().block_on(async { + for size in sizes { + let key = format!("test-{size}"); + for bucket in &buckets { + client + .delete_object() + .bucket(bucket) + .key(&key) + .send() + .await + .unwrap(); + } + } + }); +} + +criterion_group!( + name = benches; + config = Criterion::default().sample_size(sample_size()).confidence_level(confidence_level()); + targets = get_object +); +criterion_main!(benches); diff --git a/aws/sdk/benchmarks/s3-express/benches/put_get_delete.rs b/aws/sdk/benchmarks/s3-express/benches/put_get_delete.rs new file mode 100644 index 0000000000..741d39b2d1 --- /dev/null +++ b/aws/sdk/benchmarks/s3-express/benches/put_get_delete.rs @@ -0,0 +1,78 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use aws_config::BehaviorVersion; +use aws_sdk_s3::primitives::ByteStream; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; +use s3_express::{confidence_level, number_of_iterations, sample_size}; +use tokio::runtime::Runtime; + +pub fn put_get_delete(c: &mut Criterion) { + let buckets = if let Ok(buckets) = std::env::var("BUCKETS") { + buckets.split(",").map(String::from).collect::>() + } else { + panic!("required environment variable `BUCKETS` should be set: e.g. `BUCKETS=\"bucket1,bucket2\"`") + }; + + let number_of_iterations = number_of_iterations(); + + println!( + "measuring {number_of_iterations} sequences of \ + PutObject -> GetObject -> DeleteObject against \ + {buckets:#?}, switching buckets on every sequence of operations if more than one bucket is specified\n" + ); + + let client = Runtime::new().unwrap().block_on(async { + let config = aws_config::load_defaults(BehaviorVersion::latest()).await; + aws_sdk_s3::Client::new(&config) + }); + + let mut group = c.benchmark_group("put_get_delete"); + + const KB: usize = 1024; + for size in [64 * KB, KB * KB].iter() { + let object: Vec = vec![0; *size]; + group.bench_with_input(BenchmarkId::new("size", size), size, |b, _| { + b.to_async(Runtime::new().unwrap()).iter(|| async { + for i in 0..number_of_iterations { + let bucket = &buckets[i % buckets.len()]; + let key = "test"; + client + .put_object() + .bucket(bucket) + .key(key) + .body(ByteStream::from(object.clone())) + .send() + .await + .unwrap(); + + client + .get_object() + .bucket(bucket) + .key(key) + .send() + .await + .unwrap(); + + client + .delete_object() + .bucket(bucket) + .key(key) + .send() + .await + .unwrap(); + } + }); + }); + } + group.finish(); +} + +criterion_group!( + name = benches; + config = Criterion::default().sample_size(sample_size()).confidence_level(confidence_level()); + targets = put_get_delete +); +criterion_main!(benches); diff --git a/aws/sdk/benchmarks/s3-express/benches/put_object.rs b/aws/sdk/benchmarks/s3-express/benches/put_object.rs new file mode 100644 index 0000000000..4496608945 --- /dev/null +++ b/aws/sdk/benchmarks/s3-express/benches/put_object.rs @@ -0,0 +1,74 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use aws_config::BehaviorVersion; +use aws_sdk_s3::primitives::ByteStream; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; +use s3_express::{confidence_level, number_of_iterations, sample_size}; +use tokio::runtime::Runtime; + +pub fn put_object(c: &mut Criterion) { + let buckets = if let Ok(buckets) = std::env::var("BUCKETS") { + buckets.split(",").map(String::from).collect::>() + } else { + panic!("required environment variable `BUCKETS` should be set: e.g. `BUCKETS=\"bucket1,bucket2\"`") + }; + + let number_of_iterations = number_of_iterations(); + + println!( + "measuring {number_of_iterations} of PutObject against {buckets:#?}, \ + switching buckets on every operation if more than one bucket is specified\n" + ); + + let client = Runtime::new().unwrap().block_on(async { + let config = aws_config::load_defaults(BehaviorVersion::latest()).await; + aws_sdk_s3::Client::new(&config) + }); + + let mut group = c.benchmark_group("put_object"); + + let key = "test"; + const KB: usize = 1024; + for size in [64 * KB, KB * KB].iter() { + let object: Vec = vec![0; *size]; + group.bench_with_input(BenchmarkId::new("size", size), size, |b, _| { + b.to_async(Runtime::new().unwrap()).iter(|| async { + for i in 0..number_of_iterations { + let bucket = &buckets[i % buckets.len()]; + client + .put_object() + .bucket(bucket) + .key(key) + .body(ByteStream::from(object.clone())) + .send() + .await + .unwrap(); + } + }); + }); + } + group.finish(); + + // Clean up test objects + Runtime::new().unwrap().block_on(async { + for bucket in buckets { + client + .delete_object() + .bucket(bucket) + .key(key) + .send() + .await + .unwrap(); + } + }); +} + +criterion_group!( + name = benches; + config = Criterion::default().sample_size(sample_size()).confidence_level(confidence_level()); + targets = put_object +); +criterion_main!(benches); diff --git a/aws/sdk/benchmarks/s3-express/src/lib.rs b/aws/sdk/benchmarks/s3-express/src/lib.rs new file mode 100644 index 0000000000..40037fb30a --- /dev/null +++ b/aws/sdk/benchmarks/s3-express/src/lib.rs @@ -0,0 +1,31 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +const DEFAULT_CONFIDENCE_LEVEL: f64 = 0.99; +const DEFAULT_NUMBER_OF_ITERATIONS: usize = 20; +const DEFAULT_SAMPLE_SIZE: usize = 10; + +/// Configures the confidence level for benchmarks +pub fn confidence_level() -> f64 { + let confidence_level = std::env::var("CONFIDENCE_LEVEL") + .map_or(DEFAULT_CONFIDENCE_LEVEL, |s| s.parse::().unwrap()); + dbg!(confidence_level) +} + +/// Configures the number of times operations run for measurement +pub fn number_of_iterations() -> usize { + let number_of_iterations = std::env::var("NUMBER_OF_ITERATIONS") + .map_or(DEFAULT_NUMBER_OF_ITERATIONS, |n| { + n.parse::().unwrap() + }); + dbg!(number_of_iterations) +} + +/// Configures the sample size for benchmarks +pub fn sample_size() -> usize { + let sample_size = + std::env::var("SAMPLE_SIZE").map_or(DEFAULT_SAMPLE_SIZE, |s| s.parse::().unwrap()); + dbg!(sample_size) +} diff --git a/aws/sdk/benchmarks/s3-throughput/benchmark/Cargo.lock b/aws/sdk/benchmarks/s3-throughput/benchmark/Cargo.lock index 4479f62204..137ec9cffb 100644 --- a/aws/sdk/benchmarks/s3-throughput/benchmark/Cargo.lock +++ b/aws/sdk/benchmarks/s3-throughput/benchmark/Cargo.lock @@ -17,26 +17,45 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" -version = "1.0.5" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "anstyle" -version = "1.0.2" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "async-trait" -version = "0.1.73" +version = "0.1.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" dependencies = [ "proc-macro2", "quote", @@ -45,224 +64,224 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "aws-config" -version = "0.55.3" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcdcf0d683fe9c23d32cf5b53c9918ea0a500375a9fb20109802552658e576c9" +checksum = "297b64446175a73987cedc3c438d79b2a654d0fff96f65ff530fbe039347644c" dependencies = [ "aws-credential-types", - "aws-http", + "aws-runtime", "aws-sdk-sso", + "aws-sdk-ssooidc", "aws-sdk-sts", "aws-smithy-async", - "aws-smithy-client", "aws-smithy-http", - "aws-smithy-http-tower", "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", "aws-smithy-types", "aws-types", "bytes", "fastrand", "hex", - "http", + "http 0.2.12", "hyper", "ring", "time", "tokio", - "tower", "tracing", + "url", "zeroize", ] [[package]] name = "aws-credential-types" -version = "0.55.3" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fcdb2f7acbc076ff5ad05e7864bdb191ca70a6fd07668dc3a1a8bcd051de5ae" +checksum = "fa8587ae17c8e967e4b05a62d495be2fb7701bec52a97f7acfe8a29f938384c8" dependencies = [ "aws-smithy-async", + "aws-smithy-runtime-api", "aws-smithy-types", - "fastrand", - "tokio", - "tracing", "zeroize", ] [[package]] -name = "aws-endpoint" -version = "0.55.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cce1c41a6cfaa726adee9ebb9a56fcd2bbfd8be49fd8a04c5e20fd968330b04" -dependencies = [ - "aws-smithy-http", - "aws-smithy-types", - "aws-types", - "http", - "regex", - "tracing", -] - -[[package]] -name = "aws-http" -version = "0.55.3" +name = "aws-runtime" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aadbc44e7a8f3e71c8b374e03ecd972869eb91dd2bc89ed018954a52ba84bc44" +checksum = "b13dc54b4b49f8288532334bba8f87386a40571c47c37b1304979b556dc613c8" dependencies = [ "aws-credential-types", + "aws-sigv4", + "aws-smithy-async", + "aws-smithy-eventstream", "aws-smithy-http", + "aws-smithy-runtime-api", "aws-smithy-types", "aws-types", "bytes", - "http", - "http-body", - "lazy_static", + "fastrand", + "http 0.2.12", + "http-body 0.4.6", "percent-encoding", "pin-project-lite", "tracing", + "uuid", ] [[package]] name = "aws-sdk-s3" -version = "0.28.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fba197193cbb4bcb6aad8d99796b2291f36fa89562ded5d4501363055b0de89f" +checksum = "bc075ffee2a40cb1590bed35d7ec953589a564e768fa91947c565425cd569269" dependencies = [ + "ahash", "aws-credential-types", - "aws-endpoint", - "aws-http", - "aws-sig-auth", + "aws-runtime", "aws-sigv4", "aws-smithy-async", "aws-smithy-checksums", - "aws-smithy-client", "aws-smithy-eventstream", "aws-smithy-http", - "aws-smithy-http-tower", "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", "aws-smithy-types", "aws-smithy-xml", "aws-types", "bytes", - "http", - "http-body", + "fastrand", + "hex", + "hmac", + "http 0.2.12", + "http-body 0.4.6", + "lru", "once_cell", "percent-encoding", - "regex", - "tokio-stream", - "tower", + "regex-lite", + "sha2", "tracing", "url", ] [[package]] name = "aws-sdk-sso" -version = "0.28.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8b812340d86d4a766b2ca73f740dfd47a97c2dff0c06c8517a16d88241957e4" +checksum = "019a07902c43b03167ea5df0182f0cb63fae89f9a9682c44d18cf2e4a042cb34" dependencies = [ "aws-credential-types", - "aws-endpoint", - "aws-http", - "aws-sig-auth", + "aws-runtime", "aws-smithy-async", - "aws-smithy-client", "aws-smithy-http", - "aws-smithy-http-tower", "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", "aws-smithy-types", "aws-types", "bytes", - "http", - "regex", - "tokio-stream", - "tower", + "http 0.2.12", + "once_cell", + "regex-lite", "tracing", ] [[package]] -name = "aws-sdk-sts" -version = "0.28.0" +name = "aws-sdk-ssooidc" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "265fac131fbfc188e5c3d96652ea90ecc676a934e3174eaaee523c6cec040b3b" +checksum = "04c46ee08a48a7f4eaa4ad201dcc1dd537b49c50859d14d4510e00ad9d3f9af2" dependencies = [ "aws-credential-types", - "aws-endpoint", - "aws-http", - "aws-sig-auth", + "aws-runtime", "aws-smithy-async", - "aws-smithy-client", "aws-smithy-http", - "aws-smithy-http-tower", "aws-smithy-json", - "aws-smithy-query", + "aws-smithy-runtime", + "aws-smithy-runtime-api", "aws-smithy-types", - "aws-smithy-xml", "aws-types", "bytes", - "http", - "regex", - "tower", + "http 0.2.12", + "once_cell", + "regex-lite", "tracing", ] [[package]] -name = "aws-sig-auth" -version = "0.55.3" +name = "aws-sdk-sts" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b94acb10af0c879ecd5c7bdf51cda6679a0a4f4643ce630905a77673bfa3c61" +checksum = "f752ac730125ca6017f72f9db5ec1772c9ecc664f87aa7507a7d81b023c23713" dependencies = [ "aws-credential-types", - "aws-sigv4", - "aws-smithy-eventstream", + "aws-runtime", + "aws-smithy-async", "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-query", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-smithy-xml", "aws-types", - "http", + "http 0.2.12", + "once_cell", + "regex-lite", "tracing", ] [[package]] name = "aws-sigv4" -version = "0.55.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d2ce6f507be68e968a33485ced670111d1cbad161ddbbab1e313c03d37d8f4c" +checksum = "11d6f29688a4be9895c0ba8bef861ad0c0dac5c15e9618b9b7a6c233990fc263" dependencies = [ + "aws-credential-types", "aws-smithy-eventstream", "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", "bytes", + "crypto-bigint 0.5.5", "form_urlencoded", "hex", "hmac", - "http", + "http 0.2.12", + "http 1.1.0", "once_cell", + "p256", "percent-encoding", - "regex", + "ring", "sha2", + "subtle", "time", "tracing", + "zeroize", ] [[package]] name = "aws-smithy-async" -version = "0.55.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13bda3996044c202d75b91afeb11a9afae9db9a721c6a7a427410018e286b880" +checksum = "62220bc6e97f946ddd51b5f1361f78996e704677afc518a4ff66b7a72ea1378c" dependencies = [ "futures-util", "pin-project-lite", "tokio", - "tokio-stream", ] [[package]] name = "aws-smithy-checksums" -version = "0.55.3" +version = "0.60.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ed8b96d95402f3f6b8b57eb4e0e45ee365f78b1a924faf20ff6e97abf1eae6" +checksum = "83fa43bc04a6b2441968faeab56e68da3812f978a670a5db32accbdcafddd12f" dependencies = [ "aws-smithy-http", "aws-smithy-types", @@ -270,8 +289,8 @@ dependencies = [ "crc32c", "crc32fast", "hex", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "md-5", "pin-project-lite", "sha1", @@ -279,35 +298,11 @@ dependencies = [ "tracing", ] -[[package]] -name = "aws-smithy-client" -version = "0.55.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a86aa6e21e86c4252ad6a0e3e74da9617295d8d6e374d552be7d3059c41cedd" -dependencies = [ - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-http-tower", - "aws-smithy-types", - "bytes", - "fastrand", - "http", - "http-body", - "hyper", - "hyper-rustls", - "lazy_static", - "pin-project-lite", - "rustls", - "tokio", - "tower", - "tracing", -] - [[package]] name = "aws-smithy-eventstream" -version = "0.55.3" +version = "0.60.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460c8da5110835e3d9a717c61f5556b20d03c32a1dec57f8fc559b360f733bb8" +checksum = "e6363078f927f612b970edf9d1903ef5cef9a64d1e8423525ebb1f0a1633c858" dependencies = [ "aws-smithy-types", "bytes", @@ -316,105 +311,142 @@ dependencies = [ [[package]] name = "aws-smithy-http" -version = "0.55.3" +version = "0.60.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b3b693869133551f135e1f2c77cb0b8277d9e3e17feaf2213f735857c4f0d28" +checksum = "3f10fa66956f01540051b0aa7ad54574640f748f9839e843442d99b970d3aff9" dependencies = [ "aws-smithy-eventstream", + "aws-smithy-runtime-api", "aws-smithy-types", "bytes", "bytes-utils", "futures-core", - "http", - "http-body", - "hyper", + "http 0.2.12", + "http-body 0.4.6", "once_cell", "percent-encoding", "pin-project-lite", "pin-utils", - "tokio", - "tokio-util", "tracing", ] [[package]] -name = "aws-smithy-http-tower" -version = "0.55.3" +name = "aws-smithy-json" +version = "0.60.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae4f6c5798a247fac98a867698197d9ac22643596dc3777f0c76b91917616b9" +checksum = "4683df9469ef09468dad3473d129960119a0d3593617542b7d52086c8486f2d6" dependencies = [ - "aws-smithy-http", "aws-smithy-types", - "bytes", - "http", - "http-body", - "pin-project-lite", - "tower", - "tracing", ] [[package]] -name = "aws-smithy-json" -version = "0.55.3" +name = "aws-smithy-query" +version = "0.60.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23f9f42fbfa96d095194a632fbac19f60077748eba536eb0b9fecc28659807f8" +checksum = "f2fbd61ceb3fe8a1cb7352e42689cec5335833cd9f94103a61e98f9bb61c64bb" dependencies = [ "aws-smithy-types", + "urlencoding", ] [[package]] -name = "aws-smithy-query" -version = "0.55.3" +name = "aws-smithy-runtime" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98819eb0b04020a1c791903533b638534ae6c12e2aceda3e6e6fba015608d51d" +checksum = "c53572b4cd934ee5e8461ad53caa36e9d246aaef42166e3ac539e206a925d330" dependencies = [ + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-runtime-api", "aws-smithy-types", - "urlencoding", + "bytes", + "fastrand", + "h2", + "http 0.2.12", + "http-body 0.4.6", + "http-body 1.0.0", + "hyper", + "hyper-rustls", + "once_cell", + "pin-project-lite", + "pin-utils", + "rustls", + "tokio", + "tracing", +] + +[[package]] +name = "aws-smithy-runtime-api" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccb2b3a7030dc9a3c9a08ce0b25decea5130e9db19619d4dffbbff34f75fe850" +dependencies = [ + "aws-smithy-async", + "aws-smithy-types", + "bytes", + "http 0.2.12", + "http 1.1.0", + "pin-project-lite", + "tokio", + "tracing", + "zeroize", ] [[package]] name = "aws-smithy-types" -version = "0.55.3" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16a3d0bf4f324f4ef9793b86a1701d9700fbcdbd12a846da45eed104c634c6e8" +checksum = "abe14dceea1e70101d38fbf2a99e6a34159477c0fb95e68e05c66bd7ae4c3729" dependencies = [ "base64-simd", + "bytes", + "bytes-utils", + "futures-core", + "http 0.2.12", + "http 1.1.0", + "http-body 0.4.6", + "http-body 1.0.0", + "http-body-util", "itoa", "num-integer", + "pin-project-lite", + "pin-utils", "ryu", + "serde", "time", + "tokio", + "tokio-util", ] [[package]] name = "aws-smithy-xml" -version = "0.55.3" +version = "0.60.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1b9d12875731bd07e767be7baad95700c3137b56730ec9ddeedb52a5e5ca63b" +checksum = "872c68cf019c0e4afc5de7753c4f7288ce4b71663212771bf5e4542eb9346ca9" dependencies = [ "xmlparser", ] [[package]] name = "aws-types" -version = "0.55.3" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd209616cc8d7bfb82f87811a5c655dc97537f592689b18743bddf5dc5c4829" +checksum = "0dbf2f3da841a8930f159163175cf6a3d16ddde517c1b0fba7aa776822800f40" dependencies = [ "aws-credential-types", "aws-smithy-async", - "aws-smithy-client", - "aws-smithy-http", + "aws-smithy-runtime-api", "aws-smithy-types", - "http", + "http 0.2.12", "rustc_version", "tracing", ] [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -425,11 +457,17 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + [[package]] name = "base64" -version = "0.21.3" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64-simd" @@ -441,6 +479,12 @@ dependencies = [ "vsimd", ] +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "benchmark" version = "0.1.0" @@ -448,8 +492,6 @@ dependencies = [ "async-trait", "aws-config", "aws-sdk-s3", - "aws-smithy-client", - "aws-smithy-http", "clap", "hyper", "tokio", @@ -472,23 +514,17 @@ dependencies = [ "generic-array", ] -[[package]] -name = "bumpalo" -version = "3.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" - [[package]] name = "bytes" -version = "1.4.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "bytes-utils" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e47d3a8076e283f3acd27400535992edb3ba4b5bb72f8891ad8fbe7932a7d4b9" +checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35" dependencies = [ "bytes", "either", @@ -496,12 +532,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" [[package]] name = "cfg-if" @@ -511,9 +544,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.4.2" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a13b88d2c62ff462f88e4a121f17a82c1af05693a2f192b5c38d14de73c19f6" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", "clap_derive", @@ -521,9 +554,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.2" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstyle", "clap_lex", @@ -531,9 +564,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ "heck", "proc-macro2", @@ -543,15 +576,21 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "const-oid" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -559,37 +598,59 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] [[package]] name = "crc32c" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8f48d60e5b4d2c53d5c2b1d8a58c849a70ae5e5509b08a48d047e3b65714a74" +checksum = "89254598aa9b9fa608de44b3ae54c810f0f06d755e24c50177f1f8f31ff50ce2" dependencies = [ "rustc_version", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "rand_core", + "subtle", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -600,11 +661,24 @@ dependencies = [ "typenum", ] +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", + "zeroize", +] + [[package]] name = "deranged" -version = "0.3.8" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] [[package]] name = "digest" @@ -617,19 +691,64 @@ dependencies = [ "subtle", ] +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der", + "elliptic-curve", + "rfc6979", + "signature", +] + [[package]] name = "either" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct", + "crypto-bigint 0.4.9", + "der", + "digest", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "fastrand" -version = "1.9.0" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" + +[[package]] +name = "ff" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" dependencies = [ - "instant", + "rand_core", + "subtle", ] [[package]] @@ -640,45 +759,45 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-core", "futures-task", @@ -696,24 +815,46 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "group" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff", + "rand_core", + "subtle", +] [[package]] name = "h2" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.12", "indexmap", "slab", "tokio", @@ -723,21 +864,25 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", + "allocator-api2", +] [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -756,9 +901,20 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -767,12 +923,35 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http 1.1.0", + "http-body 1.0.0", "pin-project-lite", ] @@ -790,22 +969,22 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", "h2", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2", "tokio", "tower-service", "tracing", @@ -814,11 +993,12 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.23.2" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ - "http", + "futures-util", + "http 0.2.12", "hyper", "log", "rustls", @@ -829,9 +1009,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -839,37 +1019,19 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.3" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ - "autocfg", + "equivalent", "hashbrown", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - [[package]] name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "js-sys" -version = "0.3.64" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" -dependencies = [ - "wasm-bindgen", -] +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "lazy_static" @@ -879,15 +1041,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -895,9 +1057,18 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "lru" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +dependencies = [ + "hashbrown", +] [[package]] name = "matchers" @@ -910,37 +1081,38 @@ dependencies = [ [[package]] name = "md-5" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ + "cfg-if", "digest", ] [[package]] name = "memchr" -version = "2.6.3" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -953,21 +1125,26 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] @@ -984,18 +1161,18 @@ dependencies = [ [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl-probe" @@ -1015,6 +1192,17 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "p256" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" +dependencies = [ + "ecdsa", + "elliptic-curve", + "sha2", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -1027,92 +1215,97 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] -name = "pin-project" -version = "1.1.3" +name = "pin-project-lite" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" -dependencies = [ - "pin-project-internal", -] +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] -name = "pin-project-internal" -version = "1.1.3" +name = "pin-utils" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "pin-project-lite" -version = "0.2.13" +name = "pkcs8" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der", + "spki", +] [[package]] -name = "pin-utils" -version = "0.1.0" +name = "powerfmt" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.9.5" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.8", - "regex-syntax 0.7.5", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", ] [[package]] @@ -1126,15 +1319,21 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.8" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.5", + "regex-syntax 0.8.3", ] +[[package]] +name = "regex-lite" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b661b2f27137bdbc16f00eda72866a92bb28af1753ffbd56744fb6e2e9cd8e" + [[package]] name = "regex-syntax" version = "0.6.29" @@ -1143,23 +1342,34 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "rfc6979" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint 0.4.9", + "hmac", + "zeroize", +] [[package]] name = "ring" -version = "0.16.20" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", + "getrandom", "libc", - "once_cell", "spin", "untrusted", - "web-sys", - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -1179,14 +1389,14 @@ dependencies = [ [[package]] name = "rustls" -version = "0.20.9" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", "ring", + "rustls-webpki", "sct", - "webpki", ] [[package]] @@ -1203,26 +1413,36 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ "base64", ] +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1233,19 +1453,33 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sct" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ "ring", "untrusted", ] +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "security-framework" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags", "core-foundation", @@ -1256,9 +1490,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" dependencies = [ "core-foundation-sys", "libc", @@ -1266,24 +1500,24 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.18" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.188" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", @@ -1292,9 +1526,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", @@ -1303,9 +1537,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -1314,9 +1548,9 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] @@ -1330,6 +1564,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest", + "rand_core", +] + [[package]] name = "slab" version = "0.4.9" @@ -1341,35 +1585,35 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.4.9" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "winapi", + "windows-sys 0.52.0", ] [[package]] -name = "socket2" -version = "0.5.3" +name = "spin" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" -dependencies = [ - "libc", - "windows-sys", -] +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] -name = "spin" -version = "0.5.2" +name = "spki" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der", +] [[package]] name = "subtle" @@ -1379,9 +1623,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" -version = "2.0.31" +version = "2.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" dependencies = [ "proc-macro2", "quote", @@ -1390,9 +1634,9 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -1400,11 +1644,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.28" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ "deranged", + "num-conv", + "powerfmt", "serde", "time-core", "time-macros", @@ -1412,16 +1658,17 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.14" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a942f44339478ef67935ab2bbaec2fb0322496cf3cbe84b261e06ac3814c572" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" dependencies = [ + "num-conv", "time-core", ] @@ -1442,9 +1689,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.32.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -1454,16 +1701,16 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.3", + "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", @@ -1472,31 +1719,19 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.23.4" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ "rustls", "tokio", - "webpki", -] - -[[package]] -name = "tokio-stream" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", ] [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", @@ -1506,28 +1741,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-layer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - [[package]] name = "tower-service" version = "0.3.2" @@ -1536,12 +1749,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", - "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -1549,9 +1760,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", @@ -1560,9 +1771,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -1570,20 +1781,20 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term", @@ -1599,48 +1810,48 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] [[package]] name = "untrusted" -version = "0.7.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -1653,6 +1864,12 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" +[[package]] +name = "uuid" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" + [[package]] name = "valuable" version = "0.1.0" @@ -1686,80 +1903,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasm-bindgen" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" - -[[package]] -name = "web-sys" -version = "0.3.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0e74f82d49d545ad128049b7e88f6576df2da6b02e9ce565c6f533be576957e" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "winapi" version = "0.3.9" @@ -1788,7 +1931,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.4", ] [[package]] @@ -1797,13 +1949,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] @@ -1812,50 +1979,112 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + [[package]] name = "xmlparser" -version = "0.13.5" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" + +[[package]] +name = "zerocopy" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d25c75bf9ea12c4040a97f829154768bbbce366287e2dc044af160cd79a13fd" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "zeroize" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/aws/sdk/benchmarks/s3-throughput/benchmark/Cargo.toml b/aws/sdk/benchmarks/s3-throughput/benchmark/Cargo.toml index d15d7823ef..71c0f81a8c 100644 --- a/aws/sdk/benchmarks/s3-throughput/benchmark/Cargo.toml +++ b/aws/sdk/benchmarks/s3-throughput/benchmark/Cargo.toml @@ -9,10 +9,8 @@ repository = "https://github.com/smithy-lang/smithy-rs" publish = false [dependencies] -aws-config = "0.55.3" -aws-sdk-s3 = "0.28.0" -aws-smithy-http = "0.55.3" -aws-smithy-client= { version = "0.55.3", features = ["client-hyper"] } +aws-config = { version = "1", features = ["behavior-version-latest"] } +aws-sdk-s3 = "1" clap = { version = "4.3.2", default-features = false, features = ["derive", "std", "help"] } tokio = { version = "1.28.2", features = ["full"] } tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } diff --git a/aws/sdk/benchmarks/s3-throughput/benchmark/src/main.rs b/aws/sdk/benchmarks/s3-throughput/benchmark/src/main.rs index ad9e6aefb1..2b7146dc87 100644 --- a/aws/sdk/benchmarks/s3-throughput/benchmark/src/main.rs +++ b/aws/sdk/benchmarks/s3-throughput/benchmark/src/main.rs @@ -202,7 +202,7 @@ async fn benchmark_get_object(client: &SdkConfig, args: &Args) -> Result Self::Setup { - Client::new(&conf) + Client::new(conf) } async fn do_get( diff --git a/aws/sdk/benchmarks/s3-throughput/benchmark/src/multipart_get.rs b/aws/sdk/benchmarks/s3-throughput/benchmark/src/multipart_get.rs index 10e209776e..28144bcb38 100644 --- a/aws/sdk/benchmarks/s3-throughput/benchmark/src/multipart_get.rs +++ b/aws/sdk/benchmarks/s3-throughput/benchmark/src/multipart_get.rs @@ -7,8 +7,8 @@ use crate::{Args, BoxError, BENCH_KEY}; use async_trait::async_trait; use aws_config::SdkConfig; use aws_sdk_s3 as s3; +use aws_sdk_s3::primitives::AggregatedBytes; use aws_sdk_s3::Client; -use aws_smithy_types::byte_stream::AggregatedBytes; use std::fmt; use std::fs::File; use std::os::unix::fs::FileExt; @@ -34,7 +34,7 @@ impl GetBenchmark for GetObjectMultipart { type Setup = Vec; async fn prepare(&self, conf: &SdkConfig) -> Self::Setup { - let clients = (0..32).map(|_| Client::new(&conf)).collect::>(); + let clients = (0..32).map(|_| Client::new(conf)).collect::>(); for client in &clients { let _ = client.list_buckets().send().await; } @@ -59,22 +59,19 @@ pub async fn get_object_multipart( bucket: &str, key: &str, ) -> Result<(), BoxError> { - let mut part_count = (args.size_bytes / args.part_size_bytes + 1) as u64; - let mut size_of_last_part = (args.size_bytes % args.part_size_bytes) as u64; + let mut part_count = args.size_bytes / args.part_size_bytes + 1; + let mut size_of_last_part = args.size_bytes % args.part_size_bytes; if size_of_last_part == 0 { - size_of_last_part = args.part_size_bytes as u64; + size_of_last_part = args.part_size_bytes; part_count -= 1; } let ranges = (0..part_count).map(|i| { if i == part_count - 1 { - let start = i * args.part_size_bytes as u64; + let start = i * args.part_size_bytes; ContentRange::new(start, start + size_of_last_part - 1) } else { - ContentRange::new( - i * args.part_size_bytes as u64, - (i + 1) * args.part_size_bytes as u64 - 1, - ) + ContentRange::new(i * args.part_size_bytes, (i + 1) * args.part_size_bytes - 1) } }); diff --git a/aws/sdk/benchmarks/s3-throughput/benchmark/src/multipart_put.rs b/aws/sdk/benchmarks/s3-throughput/benchmark/src/multipart_put.rs index d5bc8c8a97..895b6adeb6 100644 --- a/aws/sdk/benchmarks/s3-throughput/benchmark/src/multipart_put.rs +++ b/aws/sdk/benchmarks/s3-throughput/benchmark/src/multipart_put.rs @@ -8,8 +8,8 @@ use crate::{Args, BoxError, BENCH_KEY}; use async_trait::async_trait; use aws_config::SdkConfig; use aws_sdk_s3 as s3; +use aws_sdk_s3::primitives::ByteStream; use aws_sdk_s3::Client; -use aws_smithy_types::byte_stream::ByteStream; use s3::types::CompletedMultipartUpload; use s3::types::CompletedPart; use std::io::SeekFrom; @@ -29,7 +29,7 @@ impl PutBenchmark for PutObjectMultipart { type Setup = Vec; async fn prepare(&self, conf: &SdkConfig) -> Self::Setup { - let clients = (0..32).map(|_| Client::new(&conf)).collect::>(); + let clients = (0..32).map(|_| Client::new(conf)).collect::>(); for client in &clients { let _ = client.list_buckets().send().await; } @@ -112,6 +112,7 @@ pub async fn put_object_multipart( Ok(()) } +#[allow(clippy::too_many_arguments)] async fn upload_part_retry_on_timeout( permit: OwnedSemaphorePermit, client: s3::Client, diff --git a/aws/sdk/benchmarks/s3-throughput/infrastructure/package-lock.json b/aws/sdk/benchmarks/s3-throughput/infrastructure/package-lock.json index 4e749c56b5..c5fb64fdda 100644 --- a/aws/sdk/benchmarks/s3-throughput/infrastructure/package-lock.json +++ b/aws/sdk/benchmarks/s3-throughput/infrastructure/package-lock.json @@ -1,7 +1,7 @@ { "name": "infrastructure", "version": "1.0.0", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { @@ -24,55 +24,65 @@ "typescript": "^5.1.3" } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "peer": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@aws-cdk/asset-awscli-v1": { - "version": "2.2.186", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.186.tgz", - "integrity": "sha512-2wSuOWQlrWc0AFuPCzXYn2Y8oK2vTfpNrVa8dxBxfswbwUrXMAirhpsP1f1J/4KEhA/4Hs4l27dKiC/IcDrvIQ==", + "version": "2.2.202", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.202.tgz", + "integrity": "sha512-JqlF0D4+EVugnG5dAsNZMqhu3HW7ehOXm5SDMxMbXNDMdsF0pxtQKNHRl52z1U9igsHmaFpUgSGjbhAJ+0JONg==", "dev": true }, "node_modules/@aws-cdk/asset-kubectl-v20": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-kubectl-v20/-/asset-kubectl-v20-2.1.1.tgz", - "integrity": "sha512-U1ntiX8XiMRRRH5J1IdC+1t5CE89015cwyt5U63Cpk0GnMlN5+h9WsWMlKlPXZR4rdq/m806JRlBMRpBUB2Dhw==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-kubectl-v20/-/asset-kubectl-v20-2.1.2.tgz", + "integrity": "sha512-3M2tELJOxQv0apCIiuKQ4pAbncz9GuLwnKFqxifWfe77wuMxyTRPmxssYHs42ePqzap1LT6GDcPygGs+hHstLg==", "dev": true }, - "node_modules/@aws-cdk/asset-node-proxy-agent-v5": { - "version": "2.0.155", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v5/-/asset-node-proxy-agent-v5-2.0.155.tgz", - "integrity": "sha512-Q+Ny25hUPINlBbS6lmbUr4m6Tr6ToEJBla7sXA3FO3JUD0Z69ddcgbhuEBF8Rh1a2xmPONm89eX77kwK2fb4vQ==", + "node_modules/@aws-cdk/asset-node-proxy-agent-v6": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.0.3.tgz", + "integrity": "sha512-twhuEG+JPOYCYPx/xy5uH2+VUsIEhPTzDY0F1KuB+ocjWWB/KEDiOVL19nHvbPCB6fhWnkykXEMJ4HHcKvjtvg==", "dev": true }, "node_modules/@babel/code-frame": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", - "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", "dev": true, "peer": true, "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.3.tgz", - "integrity": "sha512-aNtko9OPOwVESUFp3MZfD8Uzxl7JzSeJpd7npIoxCasU37PFbAQRpKglkaKwlHOyeJdrREpo8TW8ldrkYWwvIQ==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", + "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", "dev": true, "peer": true, "engines": { @@ -80,27 +90,27 @@ } }, "node_modules/@babel/core": { - "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.1.tgz", - "integrity": "sha512-Hkqu7J4ynysSXxmAahpN1jjRwVJ+NdpraFLIWflgjpVob3KNyK3/tIUc7Q7szed8WMp0JNa7Qtd1E9Oo22F9gA==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", + "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", "dev": true, "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.22.0", - "@babel/helper-compilation-targets": "^7.22.1", - "@babel/helper-module-transforms": "^7.22.1", - "@babel/helpers": "^7.22.0", - "@babel/parser": "^7.22.0", - "@babel/template": "^7.21.9", - "@babel/traverse": "^7.22.1", - "@babel/types": "^7.22.0", - "convert-source-map": "^1.7.0", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.4", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.24.4", + "@babel/parser": "^7.24.4", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -110,23 +120,26 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "peer": true + "peer": true, + "bin": { + "semver": "bin/semver.js" + } }, "node_modules/@babel/generator": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.3.tgz", - "integrity": "sha512-C17MW4wlk//ES/CJDL51kPNwl+qiBQyN7b9SKyVp11BLGFeSPoVaHrv+MNt8jwQFhQWowW88z1eeBx3pFz9v8A==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", + "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", "dev": true, "peer": true, "dependencies": { - "@babel/types": "^7.22.3", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { @@ -134,29 +147,36 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.1.tgz", - "integrity": "sha512-Rqx13UM3yVB5q0D/KwQ8+SPfX/+Rnsy1Lw1k/UwOC4KC6qrzIQoY3lYnBu5EHKBlEHHcj0M0W8ltPSkD8rqfsQ==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dev": true, "peer": true, "dependencies": { - "@babel/compat-data": "^7.22.0", - "@babel/helper-validator-option": "^7.21.0", - "browserslist": "^4.21.3", + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", "lru-cache": "^5.1.1", - "semver": "^6.3.0" + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.1.tgz", - "integrity": "sha512-Z2tgopurB/kTbidvzeBrc2To3PUP/9i5MUe+fU6QJCQDyPwSH2oRapkLw3KGECDYSjhQZCNxEvNvZlLw8JjGwA==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, "peer": true, "engines": { @@ -164,69 +184,69 @@ } }, "node_modules/@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "peer": true, "dependencies": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, "peer": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", - "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", "dev": true, "peer": true, "dependencies": { - "@babel/types": "^7.21.4" + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.1.tgz", - "integrity": "sha512-dxAe9E7ySDGbQdCVOY/4+UcD8M9ZFqZcZhSPsPacvCG4M+9lwtDDQfI2EoaSvmf7W/8yCBkGU0m7Pvt1ru3UZw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, "peer": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.1", - "@babel/helper-module-imports": "^7.21.4", - "@babel/helper-simple-access": "^7.21.5", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.21.9", - "@babel/traverse": "^7.22.1", - "@babel/types": "^7.22.0" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.21.5.tgz", - "integrity": "sha512-0WDaIlXKOX/3KfBK/dwP1oQGiPh6rjMkT7HIRv7i5RR2VUMwrx5ZL0dwBkKx7+SW1zwNdgjHd34IMk5ZjTeHVg==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", "dev": true, "peer": true, "engines": { @@ -234,35 +254,35 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz", - "integrity": "sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dev": true, "peer": true, "dependencies": { - "@babel/types": "^7.21.5" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "peer": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz", - "integrity": "sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", "dev": true, "peer": true, "engines": { @@ -270,9 +290,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, "peer": true, "engines": { @@ -280,9 +300,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, "peer": true, "engines": { @@ -290,30 +310,31 @@ } }, "node_modules/@babel/helpers": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.3.tgz", - "integrity": "sha512-jBJ7jWblbgr7r6wYZHMdIqKc73ycaTcCaWRq4/2LpuPHcx7xMlZvpGQkOYc9HeSjn6rcx15CPlgVcBtZ4WZJ2w==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz", + "integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==", "dev": true, "peer": true, "dependencies": { - "@babel/template": "^7.21.9", - "@babel/traverse": "^7.22.1", - "@babel/types": "^7.22.3" + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", "dev": true, "peer": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -398,9 +419,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.4.tgz", - "integrity": "sha512-VLLsx06XkEYqBtE5YGPwfSGwfrjnyPP5oiGty3S8pQLFDFLaS8VwWSIxkTXpcvr5zeYLE6+MBNl2npl/YnfofA==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", + "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", "dev": true, "peer": true, "bin": { @@ -476,13 +497,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz", - "integrity": "sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", + "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", "dev": true, "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -586,13 +607,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.21.4.tgz", - "integrity": "sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", + "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", "dev": true, "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -602,51 +623,61 @@ } }, "node_modules/@babel/template": { - "version": "7.21.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.21.9.tgz", - "integrity": "sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "dev": true, "peer": true, "dependencies": { - "@babel/code-frame": "^7.21.4", - "@babel/parser": "^7.21.9", - "@babel/types": "^7.21.5" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.22.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.4.tgz", - "integrity": "sha512-Tn1pDsjIcI+JcLKq1AVlZEr4226gpuAQTsLMorsYg9tuS/kG7nuwwJ4AB8jfQuEgb/COBwR/DqJxmoiYFu5/rQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", "dev": true, "peer": true, "dependencies": { - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.22.3", - "@babel/helper-environment-visitor": "^7.22.1", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.22.4", - "@babel/types": "^7.22.4", - "debug": "^4.1.0", + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/types": { - "version": "7.22.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.4.tgz", - "integrity": "sha512-Tx9x3UBHTTsMSW85WB2kphxYQVvrZ/t1FxD88IpSgIjiUJlCm9z+xWIDwyo1vffTwSqteqyznB8ZE9vYYk16zA==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", "dev": true, "peer": true, "dependencies": { - "@babel/helper-string-parser": "^7.21.5", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -698,23 +729,23 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", - "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.2", + "espree": "^9.6.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -729,68 +760,23 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@eslint/js": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz", - "integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { @@ -811,9 +797,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { @@ -833,6 +819,96 @@ "node": ">=8" } }, + "node_modules/@istanbuljs/load-nyc-config/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, + "peer": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/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, + "peer": true, + "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.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "peer": true, + "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", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "peer": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/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, + "peer": true, + "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", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "peer": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/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, + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", @@ -844,17 +920,17 @@ } }, "node_modules/@jest/console": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", - "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0" }, "engines": { @@ -862,38 +938,38 @@ } }, "node_modules/@jest/core": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.5.0.tgz", - "integrity": "sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, "peer": true, "dependencies": { - "@jest/console": "^29.5.0", - "@jest/reporters": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.5.0", - "jest-config": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-resolve-dependencies": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "jest-watcher": "^29.5.0", + "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.5.0", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -910,95 +986,95 @@ } }, "node_modules/@jest/environment": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.5.0.tgz", - "integrity": "sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "peer": true, "dependencies": { - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.5.0" + "jest-mock": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, "peer": true, "dependencies": { - "expect": "^29.5.0", - "jest-snapshot": "^29.5.0" + "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.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", - "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, "peer": true, "dependencies": { - "jest-get-type": "^29.4.3" + "jest-get-type": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.5.0.tgz", - "integrity": "sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.5.0.tgz", - "integrity": "sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, "peer": true, "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/types": "^29.5.0", - "jest-mock": "^29.5.0" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.5.0.tgz", - "integrity": "sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, "peer": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", @@ -1006,13 +1082,13 @@ "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -1031,25 +1107,25 @@ } }, "node_modules/@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.25.16" + "@sinclair/typebox": "^0.27.8" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/source-map": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.3.tgz", - "integrity": "sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "peer": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.15", + "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" }, @@ -1058,14 +1134,14 @@ } }, "node_modules/@jest/test-result": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.5.0.tgz", - "integrity": "sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, "peer": true, "dependencies": { - "@jest/console": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, @@ -1074,15 +1150,15 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz", - "integrity": "sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, "peer": true, "dependencies": { - "@jest/test-result": "^29.5.0", + "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.7.0", "slash": "^3.0.0" }, "engines": { @@ -1090,23 +1166,23 @@ } }, "node_modules/@jest/transform": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", - "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "peer": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -1117,12 +1193,12 @@ } }, "node_modules/@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -1134,33 +1210,33 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "peer": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "peer": true, "engines": { @@ -1174,23 +1250,16 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "peer": true, "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true, - "peer": true - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1227,15 +1296,15 @@ } }, "node_modules/@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true }, "node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dev": true, "peer": true, "dependencies": { @@ -1243,9 +1312,9 @@ } }, "node_modules/@sinonjs/fake-timers": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.2.0.tgz", - "integrity": "sha512-OPwQlEdg40HAj5KNF8WW6q2KG4Z+cBCZb3m4ninfTZKaBmbIJodviQsDBoYMPHkOyJJMHnOJo5j2+LKDOhOACg==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, "peer": true, "dependencies": { @@ -1253,9 +1322,9 @@ } }, "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", "dev": true }, "node_modules/@tsconfig/node12": { @@ -1277,9 +1346,9 @@ "dev": true }, "node_modules/@types/babel__core": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", - "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "peer": true, "dependencies": { @@ -1291,9 +1360,9 @@ } }, "node_modules/@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", "dev": true, "peer": true, "dependencies": { @@ -1301,9 +1370,9 @@ } }, "node_modules/@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, "peer": true, "dependencies": { @@ -1312,9 +1381,9 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", - "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", "dev": true, "peer": true, "dependencies": { @@ -1322,9 +1391,9 @@ } }, "node_modules/@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", "dev": true, "peer": true, "dependencies": { @@ -1332,33 +1401,33 @@ } }, "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", "dev": true }, "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", "dev": true, "dependencies": { "@types/istanbul-lib-report": "*" } }, "node_modules/@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "node_modules/@types/node": { @@ -1367,53 +1436,46 @@ "integrity": "sha512-WCuw/o4GSwDGMoonES8rcvwsig77dGCMbZDrZr2x4ZZiNW4P/gcoZXe/0twgtobcTkmg9TuKflxYL/DuwDyJzg==", "dev": true }, - "node_modules/@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true, - "peer": true - }, "node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "dev": true, "peer": true }, "node_modules/@types/yargs": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", "dev": true, "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.9.tgz", - "integrity": "sha512-4uQIBq1ffXd2YvF7MAvehWKW3zVv/w+mSfRAu+8cKbfj3nwzyqJLNcZJpQ/WZ1HLbJDiowwmQ6NO+63nCA+fqA==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/type-utils": "5.59.9", - "@typescript-eslint/utils": "5.59.9", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", + "graphemer": "^1.4.0", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", "semver": "^7.3.7", @@ -1436,48 +1498,15 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@typescript-eslint/parser": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.9.tgz", - "integrity": "sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/typescript-estree": "5.59.9", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", "debug": "^4.3.4" }, "engines": { @@ -1497,13 +1526,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.9.tgz", - "integrity": "sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/visitor-keys": "5.59.9" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1514,13 +1543,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.9.tgz", - "integrity": "sha512-ksEsT0/mEHg9e3qZu98AlSrONAQtrSTljL3ow9CGej8eRo7pe+yaC/mvTjptp23Xo/xIf2mLZKC6KPv4Sji26Q==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.59.9", - "@typescript-eslint/utils": "5.59.9", + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1541,9 +1570,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.9.tgz", - "integrity": "sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1554,13 +1583,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz", - "integrity": "sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/visitor-keys": "5.59.9", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1580,51 +1609,18 @@ } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@typescript-eslint/utils": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.9.tgz", - "integrity": "sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/typescript-estree": "5.59.9", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -1639,82 +1635,33 @@ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" }, "engines": { - "node": ">=8.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/utils/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.9.tgz", - "integrity": "sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.59.9", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -1733,9 +1680,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", "dev": true, "engines": { "node": ">=0.4.0" @@ -1773,6 +1720,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -1818,14 +1778,10 @@ "dev": true }, "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, - "peer": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/array-union": { "version": "2.1.0", @@ -1837,9 +1793,9 @@ } }, "node_modules/aws-cdk": { - "version": "2.82.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.82.0.tgz", - "integrity": "sha512-4uAhKN8HMdxxM10Th8aMQJLSINO6evYV9UKTPL0hbVQ6dh6+i5LbSejcvDRw0HfBoP6qV1LNV8P8XGLYIC3tyQ==", + "version": "2.135.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.135.0.tgz", + "integrity": "sha512-id/kBxDvXQhcPYhkP/3fwhaKN0uD3raz1Z4RZcO9jJ4UoQV2RElQl+dYdmIrwNSoNVhtZeV1O4IdEtBHUhdShQ==", "dev": true, "bin": { "cdk": "bin/cdk" @@ -1852,9 +1808,9 @@ } }, "node_modules/aws-cdk-lib": { - "version": "2.82.0", - "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.82.0.tgz", - "integrity": "sha512-icLhHvoxxo5mu9z8oplSHF+A7scbRiXYoRp2hyFkYSCoY9H+eBeIVXKA2S5YPpJfJO4SeORbCQnsyXBbz31XXw==", + "version": "2.135.0", + "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.135.0.tgz", + "integrity": "sha512-0RcmhPqJyMFgXqjESv+LilL7TfOQ7uZ4G125hp5/sSoaM7IFz/L3KDAUKVW/01rrebOQo0NZR9M7WIU3JJ7ezQ==", "bundleDependencies": [ "@balena/dockerignore", "case", @@ -1865,22 +1821,24 @@ "punycode", "semver", "table", - "yaml" + "yaml", + "mime-types" ], "dev": true, "dependencies": { - "@aws-cdk/asset-awscli-v1": "^2.2.177", - "@aws-cdk/asset-kubectl-v20": "^2.1.1", - "@aws-cdk/asset-node-proxy-agent-v5": "^2.0.148", + "@aws-cdk/asset-awscli-v1": "^2.2.202", + "@aws-cdk/asset-kubectl-v20": "^2.1.2", + "@aws-cdk/asset-node-proxy-agent-v6": "^2.0.1", "@balena/dockerignore": "^1.0.2", "case": "1.6.3", - "fs-extra": "^11.1.1", - "ignore": "^5.2.4", + "fs-extra": "^11.2.0", + "ignore": "^5.3.1", "jsonschema": "^1.4.1", + "mime-types": "^2.1.35", "minimatch": "^3.1.2", - "punycode": "^2.3.0", - "semver": "^7.5.1", - "table": "^6.8.1", + "punycode": "^2.3.1", + "semver": "^7.6.0", + "table": "^6.8.2", "yaml": "1.10.2" }, "engines": { @@ -2007,7 +1965,7 @@ "license": "MIT" }, "node_modules/aws-cdk-lib/node_modules/fs-extra": { - "version": "11.1.1", + "version": "11.2.0", "dev": true, "inBundle": true, "license": "MIT", @@ -2027,7 +1985,7 @@ "license": "ISC" }, "node_modules/aws-cdk-lib/node_modules/ignore": { - "version": "5.2.4", + "version": "5.3.1", "dev": true, "inBundle": true, "license": "MIT", @@ -2089,6 +2047,27 @@ "node": ">=10" } }, + "node_modules/aws-cdk-lib/node_modules/mime-db": { + "version": "1.52.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/aws-cdk-lib/node_modules/mime-types": { + "version": "2.1.35", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/aws-cdk-lib/node_modules/minimatch": { "version": "3.1.2", "dev": true, @@ -2102,7 +2081,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/punycode": { - "version": "2.3.0", + "version": "2.3.1", "dev": true, "inBundle": true, "license": "MIT", @@ -2120,7 +2099,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/semver": { - "version": "7.5.1", + "version": "7.6.0", "dev": true, "inBundle": true, "license": "ISC", @@ -2178,7 +2157,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/table": { - "version": "6.8.1", + "version": "6.8.2", "dev": true, "inBundle": true, "license": "BSD-3-Clause", @@ -2194,7 +2173,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/universalify": { - "version": "2.0.0", + "version": "2.0.1", "dev": true, "inBundle": true, "license": "MIT", @@ -2227,16 +2206,16 @@ } }, "node_modules/babel-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz", - "integrity": "sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, "peer": true, "dependencies": { - "@jest/transform": "^29.5.0", + "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.5.0", + "babel-preset-jest": "^29.6.3", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -2265,10 +2244,37 @@ "node": ">=8" } }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/babel-plugin-jest-hoist": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", - "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, "peer": true, "dependencies": { @@ -2306,13 +2312,13 @@ } }, "node_modules/babel-preset-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", - "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, "peer": true, "dependencies": { - "babel-plugin-jest-hoist": "^29.5.0", + "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { @@ -2351,9 +2357,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.7.tgz", - "integrity": "sha512-BauCXrQ7I2ftSqd2mvKHGo85XR0u7Ru3C/Hxsy/0TkfCtjrmAbPdzLGasmoiBxplpDXlPvdjX9u7srIMfgasNA==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, "funding": [ { @@ -2371,10 +2377,10 @@ ], "peer": true, "dependencies": { - "caniuse-lite": "^1.0.30001489", - "electron-to-chromium": "^1.4.411", - "node-releases": "^2.0.12", - "update-browserslist-db": "^1.0.11" + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" }, "bin": { "browserslist": "cli.js" @@ -2431,9 +2437,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001495", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001495.tgz", - "integrity": "sha512-F6x5IEuigtUfU5ZMQK2jsy5JqUUlEFRVZq8bO2a+ysq5K7jD6PPc9YXZj78xDNS3uNchesp1Jw47YXEqr+Viyg==", + "version": "1.0.30001605", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001605.tgz", + "integrity": "sha512-nXwGlFWo34uliI9z3n6Qc0wZaf7zaZWA1CPZ169La5mV3I/gem7bst0vr5XQH5TJXZIMfDeZyOrZnSlVzKxxHQ==", "dev": true, "funding": [ { @@ -2478,9 +2484,9 @@ } }, "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, "funding": [ { @@ -2493,9 +2499,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true, "peer": true }, @@ -2526,9 +2532,9 @@ } }, "node_modules/collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true, "peer": true }, @@ -2557,9 +2563,9 @@ "dev": true }, "node_modules/constructs": { - "version": "10.2.44", - "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.2.44.tgz", - "integrity": "sha512-7v4KnradGM1JeOuuhey4m9t6pLkwc0XOlgO1TrjB8HLRbfxDHeJ10Tt6IfxihgkrDjYN1SOMmpeVFzLLNjGRQw==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.3.0.tgz", + "integrity": "sha512-vbK8i3rIb/xwZxSpTjz3SagHn1qq9BChLEfy5Hf6fB3/2eFbrwt2n9kHwQcS0CPTRBesreeAcsJfMq2229FnbQ==", "dev": true, "engines": { "node": ">= 16.14.0" @@ -2572,6 +2578,28 @@ "dev": true, "peer": true }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -2610,11 +2638,19 @@ } }, "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", "dev": true, - "peer": true + "peer": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } }, "node_modules/deep-is": { "version": "0.1.4", @@ -2652,9 +2688,9 @@ } }, "node_modules/diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, "peer": true, "engines": { @@ -2686,9 +2722,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.422", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.422.tgz", - "integrity": "sha512-OQMid0IRbJv27BhlPiBK8CfGzjeq4ZCBSmpwNi1abyS8w17/BajOUu7hBI49ptDTBCz9NRFbORhWvt41dF7dwg==", + "version": "1.4.725", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.725.tgz", + "integrity": "sha512-OGkMXLY7XH6ykHE5ZOVVIMHaGAvvxqw98cswTKB683dntBJre7ufm9wouJ0ExDm0VXhHenU8mREvxIbV5nNoVQ==", "dev": true, "peer": true }, @@ -2723,9 +2759,9 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "peer": true, "engines": { @@ -2733,37 +2769,40 @@ } }, "node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "peer": true, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz", - "integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.42.0", - "@humanwhocodes/config-array": "^0.11.10", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.5.2", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2773,7 +2812,6 @@ "globals": "^13.19.0", "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", @@ -2783,9 +2821,8 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" }, "bin": { @@ -2799,9 +2836,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", - "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", + "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" @@ -2811,25 +2848,22 @@ } }, "node_modules/eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "estraverse": "^4.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=8.0.0" } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2838,116 +2872,38 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "dependencies": { - "p-limit": "^3.0.2" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4.0" } }, "node_modules/espree": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "dependencies": { - "acorn": "^8.8.0", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" }, @@ -2984,11 +2940,20 @@ "node": ">=0.10" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -2996,7 +2961,7 @@ "node": ">=4.0" } }, - "node_modules/estraverse": { + "node_modules/esrecurse/node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", @@ -3005,6 +2970,15 @@ "node": ">=4.0" } }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -3049,17 +3023,17 @@ } }, "node_modules/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, "peer": true, "dependencies": { - "@jest/expect-utils": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0" + "@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" @@ -3072,9 +3046,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -3112,9 +3086,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -3155,26 +3129,29 @@ } }, "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==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, - "peer": true, "dependencies": { - "locate-path": "^5.0.0", + "locate-path": "^6.0.0", "path-exists": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { @@ -3182,9 +3159,9 @@ } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "node_modules/fs.realpath": { @@ -3208,11 +3185,14 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, - "peer": true + "peer": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/gensync": { "version": "1.0.0-beta.2", @@ -3290,13 +3270,18 @@ } }, "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, - "peer": true, + "dependencies": { + "type-fest": "^0.20.2" + }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globby": { @@ -3325,31 +3310,12 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "peer": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -3359,6 +3325,19 @@ "node": ">=8" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "peer": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -3377,9 +3356,9 @@ } }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" @@ -3401,15 +3380,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", @@ -3463,13 +3433,13 @@ "peer": true }, "node_modules/is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "peer": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3554,9 +3524,9 @@ "dev": true }, "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "peer": true, "engines": { @@ -3564,35 +3534,35 @@ } }, "node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", + "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", "dev": true, "peer": true, "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" + "semver": "^7.5.4" }, "engines": { - "node": ">=8" + "node": ">=10" } }, "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "peer": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, "node_modules/istanbul-lib-source-maps": { @@ -3611,9 +3581,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, "peer": true, "dependencies": { @@ -3625,16 +3595,16 @@ } }, "node_modules/jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", - "integrity": "sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "peer": true, "dependencies": { - "@jest/core": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", "import-local": "^3.0.2", - "jest-cli": "^29.5.0" + "jest-cli": "^29.7.0" }, "bin": { "jest": "bin/jest.js" @@ -3652,13 +3622,14 @@ } }, "node_modules/jest-changed-files": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", - "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, "peer": true, "dependencies": { "execa": "^5.0.0", + "jest-util": "^29.7.0", "p-limit": "^3.1.0" }, "engines": { @@ -3666,29 +3637,29 @@ } }, "node_modules/jest-circus": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.5.0.tgz", - "integrity": "sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, "peer": true, "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "dedent": "^0.7.0", + "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.5.0", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "p-limit": "^3.1.0", - "pretty-format": "^29.5.0", + "pretty-format": "^29.7.0", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" @@ -3698,23 +3669,22 @@ } }, "node_modules/jest-cli": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.5.0.tgz", - "integrity": "sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dev": true, "peer": true, "dependencies": { - "@jest/core": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", + "create-jest": "^29.7.0", "exit": "^0.1.2", - "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "prompts": "^2.0.1", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "yargs": "^17.3.1" }, "bin": { @@ -3733,32 +3703,32 @@ } }, "node_modules/jest-config": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.5.0.tgz", - "integrity": "sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, "peer": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.5.0", - "@jest/types": "^29.5.0", - "babel-jest": "^29.5.0", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.5.0", - "jest-environment-node": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.5.0", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -3779,25 +3749,25 @@ } }, "node_modules/jest-diff": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", - "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "peer": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-docblock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", - "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, "peer": true, "dependencies": { @@ -3808,44 +3778,44 @@ } }, "node_modules/jest-each": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.5.0.tgz", - "integrity": "sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "jest-util": "^29.5.0", - "pretty-format": "^29.5.0" + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.5.0.tgz", - "integrity": "sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, "peer": true, "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.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-get-type": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, "peer": true, "engines": { @@ -3853,21 +3823,21 @@ } }, "node_modules/jest-haste-map": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.5.0.tgz", - "integrity": "sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -3879,49 +3849,49 @@ } }, "node_modules/jest-leak-detector": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz", - "integrity": "sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, "peer": true, "dependencies": { - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", - "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, "peer": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", - "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, "peer": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -3930,15 +3900,15 @@ } }, "node_modules/jest-mock": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.5.0.tgz", - "integrity": "sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-util": "^29.5.0" + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3963,9 +3933,9 @@ } }, "node_modules/jest-regex-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", - "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, "peer": true, "engines": { @@ -3973,18 +3943,18 @@ } }, "node_modules/jest-resolve": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.5.0.tgz", - "integrity": "sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, "peer": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.7.0", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" @@ -3994,45 +3964,45 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz", - "integrity": "sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, "peer": true, "dependencies": { - "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.5.0" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.5.0.tgz", - "integrity": "sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, "peer": true, "dependencies": { - "@jest/console": "^29.5.0", - "@jest/environment": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-leak-detector": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-resolve": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-util": "^29.5.0", - "jest-watcher": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -4052,32 +4022,32 @@ } }, "node_modules/jest-runtime": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.5.0.tgz", - "integrity": "sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "dev": true, "peer": true, "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/globals": "^29.5.0", - "@jest/source-map": "^29.4.3", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -4086,9 +4056,9 @@ } }, "node_modules/jest-snapshot": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.5.0.tgz", - "integrity": "sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, "peer": true, "dependencies": { @@ -4096,73 +4066,34 @@ "@babel/generator": "^7.7.2", "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/babel__traverse": "^7.0.6", - "@types/prettier": "^2.1.5", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.5.0", + "expect": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "natural-compare": "^1.4.0", - "pretty-format": "^29.5.0", - "semver": "^7.3.5" + "pretty-format": "^29.7.0", + "semver": "^7.5.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-snapshot/node_modules/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, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", - "dev": true, - "peer": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jest-snapshot/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "peer": true - }, "node_modules/jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -4174,18 +4105,18 @@ } }, "node_modules/jest-validate": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.5.0.tgz", - "integrity": "sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", + "jest-get-type": "^29.6.3", "leven": "^3.1.0", - "pretty-format": "^29.5.0" + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -4205,19 +4136,19 @@ } }, "node_modules/jest-watcher": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.5.0.tgz", - "integrity": "sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, "peer": true, "dependencies": { - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.5.0", + "jest-util": "^29.7.0", "string-length": "^4.0.1" }, "engines": { @@ -4225,14 +4156,14 @@ } }, "node_modules/jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "peer": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.5.0", + "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -4264,14 +4195,12 @@ "peer": true }, "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "peer": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" @@ -4290,6 +4219,12 @@ "node": ">=4" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -4321,6 +4256,15 @@ "node": ">=6" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -4362,16 +4306,18 @@ "peer": true }, "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==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, - "peer": true, "dependencies": { - "p-locate": "^4.1.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash.memoize": { @@ -4397,16 +4343,16 @@ } }, "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "peer": true, "dependencies": { - "semver": "^6.0.0" + "semver": "^7.5.3" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4505,9 +4451,9 @@ "peer": true }, "node_modules/node-releases": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", - "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true, "peer": true }, @@ -4560,17 +4506,17 @@ } }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "type-check": "^0.4.0" }, "engines": { "node": ">= 0.8.0" @@ -4592,29 +4538,15 @@ } }, "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, - "peer": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, - "peer": true, "dependencies": { - "p-try": "^2.0.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4724,9 +4656,9 @@ } }, "node_modules/pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "dev": true, "peer": true, "engines": { @@ -4746,6 +4678,62 @@ "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, + "peer": true, + "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, + "peer": true, + "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, + "peer": true, + "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, + "peer": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4771,13 +4759,13 @@ } }, "node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "peer": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -4813,18 +4801,18 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/pure-rand": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", - "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", "dev": true, "funding": [ { @@ -4876,13 +4864,13 @@ } }, "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "peer": true, "dependencies": { - "is-core-module": "^2.11.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -4906,7 +4894,7 @@ "node": ">=8" } }, - "node_modules/resolve-from": { + "node_modules/resolve-cwd/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==", @@ -4916,13 +4904,22 @@ "node": ">=8" } }, - "node_modules/resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true, - "peer": true, - "engines": { + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "peer": true, + "engines": { "node": ">=10" } }, @@ -4975,15 +4972,38 @@ } }, "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, - "peer": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -5067,6 +5087,16 @@ "node": ">=10" } }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -5216,9 +5246,9 @@ } }, "node_modules/ts-jest": { - "version": "29.1.0", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz", - "integrity": "sha512-ZhNr7Z4PcYa+JjMl62ir+zPiNJfXJN6E8hSLnaUKhOgqcn8vb3e537cpkd0FuAfRK3sR1LSqM1MOhliXNgOFPA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", + "integrity": "sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==", "dev": true, "dependencies": { "bs-logger": "0.x", @@ -5227,14 +5257,14 @@ "json5": "^2.2.3", "lodash.memoize": "4.x", "make-error": "1.x", - "semver": "7.x", + "semver": "^7.5.3", "yargs-parser": "^21.0.1" }, "bin": { "ts-jest": "cli.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.10.0 || ^18.0.0 || >=20.0.0" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", @@ -5258,43 +5288,10 @@ } } }, - "node_modules/ts-jest/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ts-jest/node_modules/semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ts-jest/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", @@ -5378,11 +5375,10 @@ } }, "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, - "peer": true, "engines": { "node": ">=10" }, @@ -5391,9 +5387,9 @@ } }, "node_modules/typescript": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", - "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", + "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -5404,9 +5400,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "dev": true, "funding": [ { @@ -5450,27 +5446,20 @@ "dev": true }, "node_modules/v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", "dev": true, "peer": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" + "convert-source-map": "^2.0.0" }, "engines": { "node": ">=10.12.0" } }, - "node_modules/v8-to-istanbul/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true, - "peer": true - }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -5496,15 +5485,6 @@ "node": ">= 8" } }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -5609,4149 +5589,5 @@ "url": "https://github.com/sponsors/sindresorhus" } } - }, - "dependencies": { - "@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", - "dev": true, - "peer": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@aws-cdk/asset-awscli-v1": { - "version": "2.2.186", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.186.tgz", - "integrity": "sha512-2wSuOWQlrWc0AFuPCzXYn2Y8oK2vTfpNrVa8dxBxfswbwUrXMAirhpsP1f1J/4KEhA/4Hs4l27dKiC/IcDrvIQ==", - "dev": true - }, - "@aws-cdk/asset-kubectl-v20": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-kubectl-v20/-/asset-kubectl-v20-2.1.1.tgz", - "integrity": "sha512-U1ntiX8XiMRRRH5J1IdC+1t5CE89015cwyt5U63Cpk0GnMlN5+h9WsWMlKlPXZR4rdq/m806JRlBMRpBUB2Dhw==", - "dev": true - }, - "@aws-cdk/asset-node-proxy-agent-v5": { - "version": "2.0.155", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v5/-/asset-node-proxy-agent-v5-2.0.155.tgz", - "integrity": "sha512-Q+Ny25hUPINlBbS6lmbUr4m6Tr6ToEJBla7sXA3FO3JUD0Z69ddcgbhuEBF8Rh1a2xmPONm89eX77kwK2fb4vQ==", - "dev": true - }, - "@babel/code-frame": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", - "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", - "dev": true, - "peer": true, - "requires": { - "@babel/highlight": "^7.18.6" - } - }, - "@babel/compat-data": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.3.tgz", - "integrity": "sha512-aNtko9OPOwVESUFp3MZfD8Uzxl7JzSeJpd7npIoxCasU37PFbAQRpKglkaKwlHOyeJdrREpo8TW8ldrkYWwvIQ==", - "dev": true, - "peer": true - }, - "@babel/core": { - "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.1.tgz", - "integrity": "sha512-Hkqu7J4ynysSXxmAahpN1jjRwVJ+NdpraFLIWflgjpVob3KNyK3/tIUc7Q7szed8WMp0JNa7Qtd1E9Oo22F9gA==", - "dev": true, - "peer": true, - "requires": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.22.0", - "@babel/helper-compilation-targets": "^7.22.1", - "@babel/helper-module-transforms": "^7.22.1", - "@babel/helpers": "^7.22.0", - "@babel/parser": "^7.22.0", - "@babel/template": "^7.21.9", - "@babel/traverse": "^7.22.1", - "@babel/types": "^7.22.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" - }, - "dependencies": { - "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true, - "peer": true - } - } - }, - "@babel/generator": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.3.tgz", - "integrity": "sha512-C17MW4wlk//ES/CJDL51kPNwl+qiBQyN7b9SKyVp11BLGFeSPoVaHrv+MNt8jwQFhQWowW88z1eeBx3pFz9v8A==", - "dev": true, - "peer": true, - "requires": { - "@babel/types": "^7.22.3", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.1.tgz", - "integrity": "sha512-Rqx13UM3yVB5q0D/KwQ8+SPfX/+Rnsy1Lw1k/UwOC4KC6qrzIQoY3lYnBu5EHKBlEHHcj0M0W8ltPSkD8rqfsQ==", - "dev": true, - "peer": true, - "requires": { - "@babel/compat-data": "^7.22.0", - "@babel/helper-validator-option": "^7.21.0", - "browserslist": "^4.21.3", - "lru-cache": "^5.1.1", - "semver": "^6.3.0" - } - }, - "@babel/helper-environment-visitor": { - "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.1.tgz", - "integrity": "sha512-Z2tgopurB/kTbidvzeBrc2To3PUP/9i5MUe+fU6QJCQDyPwSH2oRapkLw3KGECDYSjhQZCNxEvNvZlLw8JjGwA==", - "dev": true, - "peer": true - }, - "@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", - "dev": true, - "peer": true, - "requires": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", - "dev": true, - "peer": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-module-imports": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", - "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", - "dev": true, - "peer": true, - "requires": { - "@babel/types": "^7.21.4" - } - }, - "@babel/helper-module-transforms": { - "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.1.tgz", - "integrity": "sha512-dxAe9E7ySDGbQdCVOY/4+UcD8M9ZFqZcZhSPsPacvCG4M+9lwtDDQfI2EoaSvmf7W/8yCBkGU0m7Pvt1ru3UZw==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-environment-visitor": "^7.22.1", - "@babel/helper-module-imports": "^7.21.4", - "@babel/helper-simple-access": "^7.21.5", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.21.9", - "@babel/traverse": "^7.22.1", - "@babel/types": "^7.22.0" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.21.5.tgz", - "integrity": "sha512-0WDaIlXKOX/3KfBK/dwP1oQGiPh6rjMkT7HIRv7i5RR2VUMwrx5ZL0dwBkKx7+SW1zwNdgjHd34IMk5ZjTeHVg==", - "dev": true, - "peer": true - }, - "@babel/helper-simple-access": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz", - "integrity": "sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg==", - "dev": true, - "peer": true, - "requires": { - "@babel/types": "^7.21.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "dev": true, - "peer": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-string-parser": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz", - "integrity": "sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==", - "dev": true, - "peer": true - }, - "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "dev": true, - "peer": true - }, - "@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", - "dev": true, - "peer": true - }, - "@babel/helpers": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.3.tgz", - "integrity": "sha512-jBJ7jWblbgr7r6wYZHMdIqKc73ycaTcCaWRq4/2LpuPHcx7xMlZvpGQkOYc9HeSjn6rcx15CPlgVcBtZ4WZJ2w==", - "dev": true, - "peer": true, - "requires": { - "@babel/template": "^7.21.9", - "@babel/traverse": "^7.22.1", - "@babel/types": "^7.22.3" - } - }, - "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "peer": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "peer": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "peer": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "peer": true - }, - "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, - "peer": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "peer": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "peer": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/parser": { - "version": "7.22.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.4.tgz", - "integrity": "sha512-VLLsx06XkEYqBtE5YGPwfSGwfrjnyPP5oiGty3S8pQLFDFLaS8VwWSIxkTXpcvr5zeYLE6+MBNl2npl/YnfofA==", - "dev": true, - "peer": true - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-jsx": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz", - "integrity": "sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-typescript": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.21.4.tgz", - "integrity": "sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/template": { - "version": "7.21.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.21.9.tgz", - "integrity": "sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ==", - "dev": true, - "peer": true, - "requires": { - "@babel/code-frame": "^7.21.4", - "@babel/parser": "^7.21.9", - "@babel/types": "^7.21.5" - } - }, - "@babel/traverse": { - "version": "7.22.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.4.tgz", - "integrity": "sha512-Tn1pDsjIcI+JcLKq1AVlZEr4226gpuAQTsLMorsYg9tuS/kG7nuwwJ4AB8jfQuEgb/COBwR/DqJxmoiYFu5/rQ==", - "dev": true, - "peer": true, - "requires": { - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.22.3", - "@babel/helper-environment-visitor": "^7.22.1", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.22.4", - "@babel/types": "^7.22.4", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.22.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.4.tgz", - "integrity": "sha512-Tx9x3UBHTTsMSW85WB2kphxYQVvrZ/t1FxD88IpSgIjiUJlCm9z+xWIDwyo1vffTwSqteqyznB8ZE9vYYk16zA==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-string-parser": "^7.21.5", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" - } - }, - "@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true, - "peer": true - }, - "@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "dependencies": { - "@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - } - } - }, - "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - } - }, - "@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", - "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.5.2", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "@eslint/js": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz", - "integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==", - "dev": true - }, - "@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "peer": true, - "requires": { - "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" - } - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "peer": true - }, - "@jest/console": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", - "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", - "dev": true, - "peer": true, - "requires": { - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "slash": "^3.0.0" - } - }, - "@jest/core": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.5.0.tgz", - "integrity": "sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==", - "dev": true, - "peer": true, - "requires": { - "@jest/console": "^29.5.0", - "@jest/reporters": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.5.0", - "jest-config": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-resolve-dependencies": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "jest-watcher": "^29.5.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "@jest/environment": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.5.0.tgz", - "integrity": "sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==", - "dev": true, - "peer": true, - "requires": { - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "jest-mock": "^29.5.0" - } - }, - "@jest/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==", - "dev": true, - "peer": true, - "requires": { - "expect": "^29.5.0", - "jest-snapshot": "^29.5.0" - } - }, - "@jest/expect-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", - "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", - "dev": true, - "peer": true, - "requires": { - "jest-get-type": "^29.4.3" - } - }, - "@jest/fake-timers": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.5.0.tgz", - "integrity": "sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==", - "dev": true, - "peer": true, - "requires": { - "@jest/types": "^29.5.0", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" - } - }, - "@jest/globals": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.5.0.tgz", - "integrity": "sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==", - "dev": true, - "peer": true, - "requires": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/types": "^29.5.0", - "jest-mock": "^29.5.0" - } - }, - "@jest/reporters": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.5.0.tgz", - "integrity": "sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==", - "dev": true, - "peer": true, - "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - } - }, - "@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.25.16" - } - }, - "@jest/source-map": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.3.tgz", - "integrity": "sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w==", - "dev": true, - "peer": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.15", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - } - }, - "@jest/test-result": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.5.0.tgz", - "integrity": "sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==", - "dev": true, - "peer": true, - "requires": { - "@jest/console": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/test-sequencer": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz", - "integrity": "sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==", - "dev": true, - "peer": true, - "requires": { - "@jest/test-result": "^29.5.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "slash": "^3.0.0" - } - }, - "@jest/transform": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", - "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", - "dev": true, - "peer": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - } - }, - "@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", - "dev": true, - "requires": { - "@jest/schemas": "^29.4.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "peer": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "peer": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", - "dev": true, - "peer": true, - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - }, - "dependencies": { - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true, - "peer": true - } - } - }, - "@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, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@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 - }, - "@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, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", - "dev": true - }, - "@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", - "dev": true, - "peer": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.2.0.tgz", - "integrity": "sha512-OPwQlEdg40HAj5KNF8WW6q2KG4Z+cBCZb3m4ninfTZKaBmbIJodviQsDBoYMPHkOyJJMHnOJo5j2+LKDOhOACg==", - "dev": true, - "peer": true, - "requires": { - "@sinonjs/commons": "^3.0.0" - } - }, - "@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true - }, - "@types/babel__core": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", - "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", - "dev": true, - "peer": true, - "requires": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, - "peer": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "peer": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@types/babel__traverse": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", - "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", - "dev": true, - "peer": true, - "requires": { - "@babel/types": "^7.20.7" - } - }, - "@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", - "dev": true, - "peer": true, - "requires": { - "@types/node": "*" - } - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*" - } - }, - "@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "requires": { - "@types/istanbul-lib-report": "*" - } - }, - "@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", - "dev": true - }, - "@types/node": { - "version": "20.1.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.7.tgz", - "integrity": "sha512-WCuw/o4GSwDGMoonES8rcvwsig77dGCMbZDrZr2x4ZZiNW4P/gcoZXe/0twgtobcTkmg9TuKflxYL/DuwDyJzg==", - "dev": true - }, - "@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true, - "peer": true - }, - "@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true - }, - "@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true, - "peer": true - }, - "@types/yargs": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.9.tgz", - "integrity": "sha512-4uQIBq1ffXd2YvF7MAvehWKW3zVv/w+mSfRAu+8cKbfj3nwzyqJLNcZJpQ/WZ1HLbJDiowwmQ6NO+63nCA+fqA==", - "dev": true, - "requires": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/type-utils": "5.59.9", - "@typescript-eslint/utils": "5.59.9", - "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "@typescript-eslint/parser": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.9.tgz", - "integrity": "sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/typescript-estree": "5.59.9", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.9.tgz", - "integrity": "sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/visitor-keys": "5.59.9" - } - }, - "@typescript-eslint/type-utils": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.9.tgz", - "integrity": "sha512-ksEsT0/mEHg9e3qZu98AlSrONAQtrSTljL3ow9CGej8eRo7pe+yaC/mvTjptp23Xo/xIf2mLZKC6KPv4Sji26Q==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "5.59.9", - "@typescript-eslint/utils": "5.59.9", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/types": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.9.tgz", - "integrity": "sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz", - "integrity": "sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/visitor-keys": "5.59.9", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "@typescript-eslint/utils": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.9.tgz", - "integrity": "sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/typescript-estree": "5.59.9", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "dependencies": { - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "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, - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.9.tgz", - "integrity": "sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.59.9", - "eslint-visitor-keys": "^3.3.0" - } - }, - "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "peer": true, - "requires": { - "type-fest": "^0.21.3" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "peer": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "peer": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "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 - }, - "aws-cdk": { - "version": "2.82.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.82.0.tgz", - "integrity": "sha512-4uAhKN8HMdxxM10Th8aMQJLSINO6evYV9UKTPL0hbVQ6dh6+i5LbSejcvDRw0HfBoP6qV1LNV8P8XGLYIC3tyQ==", - "dev": true, - "requires": { - "fsevents": "2.3.2" - } - }, - "aws-cdk-lib": { - "version": "2.82.0", - "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.82.0.tgz", - "integrity": "sha512-icLhHvoxxo5mu9z8oplSHF+A7scbRiXYoRp2hyFkYSCoY9H+eBeIVXKA2S5YPpJfJO4SeORbCQnsyXBbz31XXw==", - "dev": true, - "requires": { - "@aws-cdk/asset-awscli-v1": "^2.2.177", - "@aws-cdk/asset-kubectl-v20": "^2.1.1", - "@aws-cdk/asset-node-proxy-agent-v5": "^2.0.148", - "@balena/dockerignore": "^1.0.2", - "case": "1.6.3", - "fs-extra": "^11.1.1", - "ignore": "^5.2.4", - "jsonschema": "^1.4.1", - "minimatch": "^3.1.2", - "punycode": "^2.3.0", - "semver": "^7.5.1", - "table": "^6.8.1", - "yaml": "1.10.2" - }, - "dependencies": { - "@balena/dockerignore": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "ajv": { - "version": "8.12.0", - "bundled": true, - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ansi-regex": { - "version": "5.0.1", - "bundled": true, - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "bundled": true, - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "astral-regex": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "balanced-match": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "case": { - "version": "1.6.3", - "bundled": true, - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "bundled": true, - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "bundled": true, - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "bundled": true, - "dev": true - }, - "fs-extra": { - "version": "11.1.1", - "bundled": true, - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "graceful-fs": { - "version": "4.2.11", - "bundled": true, - "dev": true - }, - "ignore": { - "version": "5.2.4", - "bundled": true, - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "bundled": true, - "dev": true - }, - "json-schema-traverse": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "bundled": true, - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "jsonschema": { - "version": "1.4.1", - "bundled": true, - "dev": true - }, - "lodash.truncate": { - "version": "4.4.2", - "bundled": true, - "dev": true - }, - "lru-cache": { - "version": "6.0.0", - "bundled": true, - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "punycode": { - "version": "2.3.0", - "bundled": true, - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "bundled": true, - "dev": true - }, - "semver": { - "version": "7.5.1", - "bundled": true, - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "slice-ansi": { - "version": "4.0.0", - "bundled": true, - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "bundled": true, - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "table": { - "version": "6.8.1", - "bundled": true, - "dev": true, - "requires": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - } - }, - "universalify": { - "version": "2.0.0", - "bundled": true, - "dev": true - }, - "uri-js": { - "version": "4.4.1", - "bundled": true, - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "yallist": { - "version": "4.0.0", - "bundled": true, - "dev": true - }, - "yaml": { - "version": "1.10.2", - "bundled": true, - "dev": true - } - } - }, - "babel-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz", - "integrity": "sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==", - "dev": true, - "peer": true, - "requires": { - "@jest/transform": "^29.5.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.5.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - } - }, - "babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "peer": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - } - }, - "babel-plugin-jest-hoist": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", - "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", - "dev": true, - "peer": true, - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "peer": true, - "requires": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - } - }, - "babel-preset-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", - "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", - "dev": true, - "peer": true, - "requires": { - "babel-plugin-jest-hoist": "^29.5.0", - "babel-preset-current-node-syntax": "^1.0.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browserslist": { - "version": "4.21.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.7.tgz", - "integrity": "sha512-BauCXrQ7I2ftSqd2mvKHGo85XR0u7Ru3C/Hxsy/0TkfCtjrmAbPdzLGasmoiBxplpDXlPvdjX9u7srIMfgasNA==", - "dev": true, - "peer": true, - "requires": { - "caniuse-lite": "^1.0.30001489", - "electron-to-chromium": "^1.4.411", - "node-releases": "^2.0.12", - "update-browserslist-db": "^1.0.11" - } - }, - "bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "requires": { - "fast-json-stable-stringify": "2.x" - } - }, - "bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "peer": true, - "requires": { - "node-int64": "^0.4.0" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "peer": true - }, - "caniuse-lite": { - "version": "1.0.30001495", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001495.tgz", - "integrity": "sha512-F6x5IEuigtUfU5ZMQK2jsy5JqUUlEFRVZq8bO2a+ysq5K7jD6PPc9YXZj78xDNS3uNchesp1Jw47YXEqr+Viyg==", - "dev": true, - "peer": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, - "peer": true - }, - "ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true - }, - "cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", - "dev": true, - "peer": true - }, - "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, - "peer": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, - "peer": true - }, - "collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true, - "peer": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "constructs": { - "version": "10.2.44", - "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.2.44.tgz", - "integrity": "sha512-7v4KnradGM1JeOuuhey4m9t6pLkwc0XOlgO1TrjB8HLRbfxDHeJ10Tt6IfxihgkrDjYN1SOMmpeVFzLLNjGRQw==", - "dev": true - }, - "convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "peer": true - }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true, - "peer": true - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "peer": true - }, - "detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "peer": true - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", - "dev": true, - "peer": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "electron-to-chromium": { - "version": "1.4.422", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.422.tgz", - "integrity": "sha512-OQMid0IRbJv27BhlPiBK8CfGzjeq4ZCBSmpwNi1abyS8w17/BajOUu7hBI49ptDTBCz9NRFbORhWvt41dF7dwg==", - "dev": true, - "peer": true - }, - "emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true, - "peer": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "peer": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "peer": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "peer": true - }, - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "peer": true - }, - "eslint": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz", - "integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.42.0", - "@humanwhocodes/config-array": "^0.11.10", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.5.2", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "eslint-config-prettier": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", - "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", - "dev": true, - "requires": {} - }, - "eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", - "dev": true - }, - "espree": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", - "dev": true, - "requires": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "peer": true - }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "peer": true, - "requires": { - "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" - } - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true, - "peer": true - }, - "expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", - "dev": true, - "peer": true, - "requires": { - "@jest/expect-utils": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0" - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "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, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "peer": true, - "requires": { - "bser": "2.1.1" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "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, - "peer": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true, - "peer": true - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "peer": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "peer": true - }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "peer": true - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "peer": true - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "peer": true - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "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" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "peer": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true, - "peer": true - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "peer": true - }, - "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } - } - }, - "import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "peer": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, - "peer": true - }, - "is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", - "dev": true, - "peer": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "peer": true - }, - "is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, - "peer": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "peer": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, - "peer": true - }, - "istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "peer": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - } - }, - "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "peer": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "peer": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - } - }, - "istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "peer": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", - "integrity": "sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==", - "dev": true, - "peer": true, - "requires": { - "@jest/core": "^29.5.0", - "@jest/types": "^29.5.0", - "import-local": "^3.0.2", - "jest-cli": "^29.5.0" - } - }, - "jest-changed-files": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", - "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", - "dev": true, - "peer": true, - "requires": { - "execa": "^5.0.0", - "p-limit": "^3.1.0" - } - }, - "jest-circus": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.5.0.tgz", - "integrity": "sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==", - "dev": true, - "peer": true, - "requires": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.5.0", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.5.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - } - }, - "jest-cli": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.5.0.tgz", - "integrity": "sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==", - "dev": true, - "peer": true, - "requires": { - "@jest/core": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "prompts": "^2.0.1", - "yargs": "^17.3.1" - } - }, - "jest-config": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.5.0.tgz", - "integrity": "sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==", - "dev": true, - "peer": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.5.0", - "@jest/types": "^29.5.0", - "babel-jest": "^29.5.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.5.0", - "jest-environment-node": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.5.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - } - }, - "jest-diff": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", - "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", - "dev": true, - "peer": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" - } - }, - "jest-docblock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", - "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", - "dev": true, - "peer": true, - "requires": { - "detect-newline": "^3.0.0" - } - }, - "jest-each": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.5.0.tgz", - "integrity": "sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA==", - "dev": true, - "peer": true, - "requires": { - "@jest/types": "^29.5.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "jest-util": "^29.5.0", - "pretty-format": "^29.5.0" - } - }, - "jest-environment-node": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.5.0.tgz", - "integrity": "sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw==", - "dev": true, - "peer": true, - "requires": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" - } - }, - "jest-get-type": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", - "dev": true, - "peer": true - }, - "jest-haste-map": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.5.0.tgz", - "integrity": "sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA==", - "dev": true, - "peer": true, - "requires": { - "@jest/types": "^29.5.0", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - } - }, - "jest-leak-detector": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz", - "integrity": "sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==", - "dev": true, - "peer": true, - "requires": { - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" - } - }, - "jest-matcher-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", - "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", - "dev": true, - "peer": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" - } - }, - "jest-message-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", - "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", - "dev": true, - "peer": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.5.0", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - } - }, - "jest-mock": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.5.0.tgz", - "integrity": "sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==", - "dev": true, - "peer": true, - "requires": { - "@jest/types": "^29.5.0", - "@types/node": "*", - "jest-util": "^29.5.0" - } - }, - "jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "peer": true, - "requires": {} - }, - "jest-regex-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", - "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", - "dev": true, - "peer": true - }, - "jest-resolve": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.5.0.tgz", - "integrity": "sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w==", - "dev": true, - "peer": true, - "requires": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - } - }, - "jest-resolve-dependencies": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz", - "integrity": "sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==", - "dev": true, - "peer": true, - "requires": { - "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.5.0" - } - }, - "jest-runner": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.5.0.tgz", - "integrity": "sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==", - "dev": true, - "peer": true, - "requires": { - "@jest/console": "^29.5.0", - "@jest/environment": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-leak-detector": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-resolve": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-util": "^29.5.0", - "jest-watcher": "^29.5.0", - "jest-worker": "^29.5.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "dependencies": { - "source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "peer": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - } - } - }, - "jest-runtime": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.5.0.tgz", - "integrity": "sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==", - "dev": true, - "peer": true, - "requires": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/globals": "^29.5.0", - "@jest/source-map": "^29.4.3", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - } - }, - "jest-snapshot": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.5.0.tgz", - "integrity": "sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==", - "dev": true, - "peer": true, - "requires": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/babel__traverse": "^7.0.6", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.5.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.5.0", - "semver": "^7.3.5" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "peer": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", - "dev": true, - "peer": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "peer": true - } - } - }, - "jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", - "dev": true, - "requires": { - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-validate": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.5.0.tgz", - "integrity": "sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ==", - "dev": true, - "peer": true, - "requires": { - "@jest/types": "^29.5.0", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "leven": "^3.1.0", - "pretty-format": "^29.5.0" - }, - "dependencies": { - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "peer": true - } - } - }, - "jest-watcher": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.5.0.tgz", - "integrity": "sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==", - "dev": true, - "peer": true, - "requires": { - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.5.0", - "string-length": "^4.0.1" - } - }, - "jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", - "dev": true, - "peer": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.5.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "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, - "peer": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "peer": true - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "peer": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "peer": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "peer": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - }, - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "peer": true - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "peer": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "peer": true - }, - "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, - "peer": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "peer": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "peer": true, - "requires": { - "semver": "^6.0.0" - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "peer": true, - "requires": { - "tmpl": "1.0.5" - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "peer": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "peer": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, - "node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true, - "peer": true - }, - "node-releases": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", - "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==", - "dev": true, - "peer": true - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "peer": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "peer": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "peer": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "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, - "peer": true, - "requires": { - "p-limit": "^2.2.0" - }, - "dependencies": { - "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, - "peer": true, - "requires": { - "p-try": "^2.0.0" - } - } - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "peer": true - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "peer": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "peer": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true, - "peer": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true, - "peer": true - }, - "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, - "peer": true, - "requires": { - "find-up": "^4.0.0" - } - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true - }, - "pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", - "dev": true, - "peer": true, - "requires": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "dependencies": { - "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, - "peer": true - } - } - }, - "prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "peer": true, - "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - } - }, - "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true - }, - "pure-rand": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", - "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", - "dev": true, - "peer": true - }, - "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 - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true, - "peer": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "peer": true - }, - "resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", - "dev": true, - "peer": true, - "requires": { - "is-core-module": "^2.11.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "peer": true, - "requires": { - "resolve-from": "^5.0.0" - } - }, - "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, - "peer": true - }, - "resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true, - "peer": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "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, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "peer": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "peer": true - }, - "sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true, - "peer": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, - "peer": true - }, - "stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "peer": true, - "requires": { - "escape-string-regexp": "^2.0.0" - } - }, - "string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "peer": true, - "requires": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "peer": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "peer": true - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "peer": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "peer": true - }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "peer": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true, - "peer": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "peer": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "ts-jest": { - "version": "29.1.0", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz", - "integrity": "sha512-ZhNr7Z4PcYa+JjMl62ir+zPiNJfXJN6E8hSLnaUKhOgqcn8vb3e537cpkd0FuAfRK3sR1LSqM1MOhliXNgOFPA==", - "dev": true, - "requires": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^29.0.0", - "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "7.x", - "yargs-parser": "^21.0.1" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "requires": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "peer": true - }, - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "peer": true - }, - "typescript": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", - "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", - "dev": true - }, - "update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", - "dev": true, - "peer": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", - "dev": true, - "peer": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - }, - "dependencies": { - "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true, - "peer": true - } - } - }, - "walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "peer": true, - "requires": { - "makeerror": "1.0.12" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "peer": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "peer": true, - "requires": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "peer": true - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "peer": true - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "peer": true, - "requires": { - "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" - } - }, - "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 - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } } } diff --git a/aws/sdk/build.gradle.kts b/aws/sdk/build.gradle.kts index bcc25bbe49..2b9ecf94b3 100644 --- a/aws/sdk/build.gradle.kts +++ b/aws/sdk/build.gradle.kts @@ -116,6 +116,7 @@ fun generateSmithyBuild(services: AwsServices): String { ${service.examplesUri(project)?.let { """"examples": "$it",""" } ?: ""} "moduleRepository": "https://github.com/awslabs/aws-sdk-rust", "license": "Apache-2.0", + "minimumSupportedRustVersion": "${getRustMSRV()}", "customizationConfig": { "awsSdk": { "awsSdkBuild": true, @@ -140,6 +141,9 @@ fun generateSmithyBuild(services: AwsServices): String { """ } +/** + * Task to generate smithyBuild.json dynamically + */ tasks.register("generateSmithyBuild") { description = "generate smithy-build.json" inputs.property("servicelist", awsServices.services.toString()) @@ -150,6 +154,7 @@ tasks.register("generateSmithyBuild") { doFirst { layout.buildDirectory.file("smithy-build.json").get().asFile.writeText(generateSmithyBuild(awsServices)) } + // TODO(https://github.com/smithy-lang/smithy-rs/issues/3599) outputs.upToDateWhen { false } } diff --git a/aws/sdk/integration-tests/dynamodb/tests/shared-config.rs b/aws/sdk/integration-tests/dynamodb/tests/shared-config.rs index a0a26bc0e2..02786fe0af 100644 --- a/aws/sdk/integration-tests/dynamodb/tests/shared-config.rs +++ b/aws/sdk/integration-tests/dynamodb/tests/shared-config.rs @@ -3,10 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -use aws_runtime::env_config::file::{EnvConfigFileKind, EnvConfigFiles}; -use aws_sdk_dynamodb::config::{ - BehaviorVersion, Credentials, Region, StalledStreamProtectionConfig, -}; +use aws_sdk_dynamodb::config::{Credentials, Region, StalledStreamProtectionConfig}; use aws_smithy_runtime::client::http::test_util::capture_request; use http::Uri; @@ -30,39 +27,3 @@ async fn shared_config_testbed() { &Uri::from_static("http://localhost:8000") ); } - -#[tokio::test] -async fn service_config_from_profile() { - let _ = tracing_subscriber::fmt::try_init(); - - let config = r#" -[profile custom] -aws_access_key_id = test-access-key-id -aws_secret_access_key = test-secret-access-key -aws_session_token = test-session-token -region = us-east-1 -services = custom - -[services custom] -dynamodb = - region = us-west-1 -"# - .trim(); - - let shared_config = aws_config::ConfigLoader::default() - .behavior_version(BehaviorVersion::latest()) - .profile_name("custom") - .profile_files( - EnvConfigFiles::builder() - .with_contents(EnvConfigFileKind::Config, config) - .build(), - ) - .load() - .await; - let service_config = aws_sdk_dynamodb::Config::from(&shared_config); - - assert_eq!( - service_config.region().unwrap(), - &Region::from_static("us-west-1") - ); -} diff --git a/aws/sdk/integration-tests/ec2/Cargo.toml b/aws/sdk/integration-tests/ec2/Cargo.toml index b019cd5014..f9778a75a4 100644 --- a/aws/sdk/integration-tests/ec2/Cargo.toml +++ b/aws/sdk/integration-tests/ec2/Cargo.toml @@ -8,11 +8,11 @@ publish = false [dev-dependencies] aws-credential-types = { path = "../../build/aws-sdk/sdk/aws-credential-types", features = ["test-util"] } -aws-smithy-async = { path = "../../build/aws-sdk/sdk/aws-smithy-async" } +aws-smithy-async = { path = "../../build/aws-sdk/sdk/aws-smithy-async", features = ["test-util"] } aws-smithy-runtime = { path = "../../build/aws-sdk/sdk/aws-smithy-runtime", features = ["client", "test-util"] } aws-smithy-runtime-api = { path = "../../build/aws-sdk/sdk/aws-smithy-runtime-api", features = ["client", "http-02x"] } aws-smithy-types = { path = "../../build/aws-sdk/sdk/aws-smithy-types" } -aws-sdk-ec2 = { path = "../../build/aws-sdk/sdk/ec2", features = ["behavior-version-latest"] } +aws-sdk-ec2 = { path = "../../build/aws-sdk/sdk/ec2", features = ["test-util"] } tokio = { version = "1.23.1", features = ["full"]} http = "0.2.0" tokio-stream = "0.1.5" diff --git a/aws/sdk/integration-tests/ec2/tests/instance-status-ok-waiter-success.json b/aws/sdk/integration-tests/ec2/tests/instance-status-ok-waiter-success.json new file mode 100644 index 0000000000..f45e0aa337 --- /dev/null +++ b/aws/sdk/integration-tests/ec2/tests/instance-status-ok-waiter-success.json @@ -0,0 +1,588 @@ +{ + "events": [ + { + "connection_id": 0, + "action": { + "Request": { + "request": { + "uri": "https://ec2.us-west-2.amazonaws.com/", + "headers": { + "content-type": [ + "application/x-www-form-urlencoded" + ], + "content-length": [ + "73" + ], + "amz-sdk-request": [ + "attempt=1; max=3" + ] + }, + "method": "POST" + } + } + } + }, + { + "connection_id": 0, + "action": { + "Data": { + "data": { + "Utf8": "Action=StartInstances&Version=2016-11-15&InstanceId.1=i-09fb4224219ac6902" + }, + "direction": "Request" + } + } + }, + { + "connection_id": 0, + "action": { + "Eof": { + "ok": true, + "direction": "Request" + } + } + }, + { + "connection_id": 0, + "action": { + "Response": { + "response": { + "Ok": { + "status": 200, + "headers": { + "x-amzn-requestid": [ + "bec35864-7ea6-430e-864e-229454f8b80d" + ], + "cache-control": [ + "no-cache, no-store" + ], + "strict-transport-security": [ + "max-age=31536000; includeSubDomains" + ], + "content-type": [ + "text/xml;charset=UTF-8" + ], + "content-length": [ + "579" + ], + "date": [ + "Fri, 19 Apr 2024 00:26:55 GMT" + ], + "server": [ + "AmazonEC2" + ] + } + } + } + } + } + }, + { + "connection_id": 0, + "action": { + "Data": { + "data": { + "Utf8": "\n\n bec35864-7ea6-430e-864e-229454f8b80d\n \n \n i-09fb4224219ac6902\n \n 0\n pending\n \n \n 80\n stopped\n \n \n \n\n" + }, + "direction": "Response" + } + } + }, + { + "connection_id": 0, + "action": { + "Eof": { + "ok": true, + "direction": "Response" + } + } + }, + { + "connection_id": 1, + "action": { + "Request": { + "request": { + "uri": "https://ec2.us-west-2.amazonaws.com/", + "headers": { + "content-type": [ + "application/x-www-form-urlencoded" + ], + "content-length": [ + "81" + ], + "amz-sdk-request": [ + "attempt=1; max=3" + ] + }, + "method": "POST" + } + } + } + }, + { + "connection_id": 1, + "action": { + "Data": { + "data": { + "Utf8": "Action=DescribeInstanceStatus&Version=2016-11-15&InstanceId.1=i-09fb4224219ac6902" + }, + "direction": "Request" + } + } + }, + { + "connection_id": 1, + "action": { + "Eof": { + "ok": true, + "direction": "Request" + } + } + }, + { + "connection_id": 1, + "action": { + "Response": { + "response": { + "Ok": { + "status": 200, + "headers": { + "x-amzn-requestid": [ + "02147aa0-b2d0-41a3-afd7-570bb2d75151" + ], + "cache-control": [ + "no-cache, no-store" + ], + "strict-transport-security": [ + "max-age=31536000; includeSubDomains" + ], + "content-type": [ + "text/xml;charset=UTF-8" + ], + "content-length": [ + "243" + ], + "date": [ + "Fri, 19 Apr 2024 00:26:56 GMT" + ], + "server": [ + "AmazonEC2" + ] + } + } + } + } + } + }, + { + "connection_id": 1, + "action": { + "Data": { + "data": { + "Utf8": "\n\n 02147aa0-b2d0-41a3-afd7-570bb2d75151\n \n" + }, + "direction": "Response" + } + } + }, + { + "connection_id": 1, + "action": { + "Eof": { + "ok": true, + "direction": "Response" + } + } + }, + { + "connection_id": 2, + "action": { + "Request": { + "request": { + "uri": "https://ec2.us-west-2.amazonaws.com/", + "headers": { + "content-type": [ + "application/x-www-form-urlencoded" + ], + "content-length": [ + "81" + ], + "amz-sdk-request": [ + "attempt=1; max=3" + ] + }, + "method": "POST" + } + } + } + }, + { + "connection_id": 2, + "action": { + "Data": { + "data": { + "Utf8": "Action=DescribeInstanceStatus&Version=2016-11-15&InstanceId.1=i-09fb4224219ac6902" + }, + "direction": "Request" + } + } + }, + { + "connection_id": 2, + "action": { + "Eof": { + "ok": true, + "direction": "Request" + } + } + }, + { + "connection_id": 2, + "action": { + "Response": { + "response": { + "Ok": { + "status": 200, + "headers": { + "x-amzn-requestid": [ + "4ddc4e65-50f4-42f9-a327-ad1c1fa717c8" + ], + "cache-control": [ + "no-cache, no-store" + ], + "strict-transport-security": [ + "max-age=31536000; includeSubDomains" + ], + "content-type": [ + "text/xml;charset=UTF-8" + ], + "content-length": [ + "1171" + ], + "date": [ + "Fri, 19 Apr 2024 00:27:11 GMT" + ], + "server": [ + "AmazonEC2" + ] + } + } + } + } + } + }, + { + "connection_id": 2, + "action": { + "Data": { + "data": { + "Utf8": "\n\n 4ddc4e65-50f4-42f9-a327-ad1c1fa717c8\n \n \n i-09fb4224219ac6902\n us-west-2d\n \n 16\n running\n \n \n initializing\n
\n \n reachability\n initializing\n \n
\n
\n \n initializing\n
\n \n reachability\n initializing\n \n
\n
\n
\n
\n
" + }, + "direction": "Response" + } + } + }, + { + "connection_id": 2, + "action": { + "Eof": { + "ok": true, + "direction": "Response" + } + } + }, + { + "connection_id": 3, + "action": { + "Request": { + "request": { + "uri": "https://ec2.us-west-2.amazonaws.com/", + "headers": { + "content-type": [ + "application/x-www-form-urlencoded" + ], + "content-length": [ + "81" + ], + "amz-sdk-request": [ + "attempt=1; max=3" + ] + }, + "method": "POST" + } + } + } + }, + { + "connection_id": 3, + "action": { + "Data": { + "data": { + "Utf8": "Action=DescribeInstanceStatus&Version=2016-11-15&InstanceId.1=i-09fb4224219ac6902" + }, + "direction": "Request" + } + } + }, + { + "connection_id": 3, + "action": { + "Eof": { + "ok": true, + "direction": "Request" + } + } + }, + { + "connection_id": 3, + "action": { + "Response": { + "response": { + "Ok": { + "status": 200, + "headers": { + "x-amzn-requestid": [ + "78adf8db-74c8-462e-98c5-17db37544534" + ], + "cache-control": [ + "no-cache, no-store" + ], + "strict-transport-security": [ + "max-age=31536000; includeSubDomains" + ], + "content-type": [ + "text/xml;charset=UTF-8" + ], + "content-length": [ + "1171" + ], + "date": [ + "Fri, 19 Apr 2024 00:27:39 GMT" + ], + "server": [ + "AmazonEC2" + ] + } + } + } + } + } + }, + { + "connection_id": 3, + "action": { + "Data": { + "data": { + "Utf8": "\n\n 78adf8db-74c8-462e-98c5-17db37544534\n \n \n i-09fb4224219ac6902\n us-west-2d\n \n 16\n running\n \n \n initializing\n
\n \n reachability\n initializing\n \n
\n
\n \n initializing\n
\n \n reachability\n initializing\n \n
\n
\n
\n
\n
" + }, + "direction": "Response" + } + } + }, + { + "connection_id": 3, + "action": { + "Eof": { + "ok": true, + "direction": "Response" + } + } + }, + { + "connection_id": 4, + "action": { + "Request": { + "request": { + "uri": "https://ec2.us-west-2.amazonaws.com/", + "headers": { + "content-type": [ + "application/x-www-form-urlencoded" + ], + "content-length": [ + "81" + ], + "amz-sdk-request": [ + "attempt=1; max=3" + ] + }, + "method": "POST" + } + } + } + }, + { + "connection_id": 4, + "action": { + "Data": { + "data": { + "Utf8": "Action=DescribeInstanceStatus&Version=2016-11-15&InstanceId.1=i-09fb4224219ac6902" + }, + "direction": "Request" + } + } + }, + { + "connection_id": 4, + "action": { + "Eof": { + "ok": true, + "direction": "Request" + } + } + }, + { + "connection_id": 4, + "action": { + "Response": { + "response": { + "Ok": { + "status": 200, + "headers": { + "x-amzn-requestid": [ + "48fb29e8-5b25-4854-a127-586f1b0ff62c" + ], + "cache-control": [ + "no-cache, no-store" + ], + "strict-transport-security": [ + "max-age=31536000; includeSubDomains" + ], + "content-type": [ + "text/xml;charset=UTF-8" + ], + "content-length": [ + "1171" + ], + "date": [ + "Fri, 19 Apr 2024 00:28:34 GMT" + ], + "server": [ + "AmazonEC2" + ] + } + } + } + } + } + }, + { + "connection_id": 4, + "action": { + "Data": { + "data": { + "Utf8": "\n\n 48fb29e8-5b25-4854-a127-586f1b0ff62c\n \n \n i-09fb4224219ac6902\n us-west-2d\n \n 16\n running\n \n \n initializing\n
\n \n reachability\n initializing\n \n
\n
\n \n initializing\n
\n \n reachability\n initializing\n \n
\n
\n
\n
\n
" + }, + "direction": "Response" + } + } + }, + { + "connection_id": 4, + "action": { + "Eof": { + "ok": true, + "direction": "Response" + } + } + }, + { + "connection_id": 5, + "action": { + "Request": { + "request": { + "uri": "https://ec2.us-west-2.amazonaws.com/", + "headers": { + "content-type": [ + "application/x-www-form-urlencoded" + ], + "content-length": [ + "81" + ], + "amz-sdk-request": [ + "attempt=1; max=3" + ] + }, + "method": "POST" + } + } + } + }, + { + "connection_id": 5, + "action": { + "Data": { + "data": { + "Utf8": "Action=DescribeInstanceStatus&Version=2016-11-15&InstanceId.1=i-09fb4224219ac6902" + }, + "direction": "Request" + } + } + }, + { + "connection_id": 5, + "action": { + "Eof": { + "ok": true, + "direction": "Request" + } + } + }, + { + "connection_id": 5, + "action": { + "Response": { + "response": { + "Ok": { + "status": 200, + "headers": { + "x-amzn-requestid": [ + "c9b9b2a0-ddbc-4ea8-a76a-4339a9a99de4" + ], + "cache-control": [ + "no-cache, no-store" + ], + "strict-transport-security": [ + "max-age=31536000; includeSubDomains" + ], + "content-type": [ + "text/xml;charset=UTF-8" + ], + "content-length": [ + "1139" + ], + "date": [ + "Fri, 19 Apr 2024 00:29:53 GMT" + ], + "server": [ + "AmazonEC2" + ] + } + } + } + } + } + }, + { + "connection_id": 5, + "action": { + "Data": { + "data": { + "Utf8": "\n\n c9b9b2a0-ddbc-4ea8-a76a-4339a9a99de4\n \n \n i-09fb4224219ac6902\n us-west-2d\n \n 16\n running\n \n \n ok\n
\n \n reachability\n passed\n \n
\n
\n \n ok\n
\n \n reachability\n passed\n \n
\n
\n
\n
\n
" + }, + "direction": "Response" + } + } + }, + { + "connection_id": 5, + "action": { + "Eof": { + "ok": true, + "direction": "Response" + } + } + } + ], + "docs": "traffic recording of EC2 start_instance followed by EC2 wait_until_instance_status_ok being successful", + "version": "V0" +} diff --git a/aws/sdk/integration-tests/ec2/tests/waiters.rs b/aws/sdk/integration-tests/ec2/tests/waiters.rs new file mode 100644 index 0000000000..88d725f0b3 --- /dev/null +++ b/aws/sdk/integration-tests/ec2/tests/waiters.rs @@ -0,0 +1,87 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use aws_sdk_ec2::{client::Waiters, config::Region, error::DisplayErrorContext, Client}; +use aws_smithy_async::test_util::tick_advance_sleep::{ + tick_advance_time_and_sleep, TickAdvanceTime, +}; +use aws_smithy_runtime::{ + client::http::test_util::dvr::ReplayingClient, test_util::capture_test_logs::show_test_logs, +}; +use aws_smithy_runtime_api::client::waiters::error::WaiterError; +use aws_smithy_types::retry::RetryConfig; +use std::time::Duration; + +async fn prerequisites() -> (Client, ReplayingClient, TickAdvanceTime) { + let (time_source, sleep_impl) = tick_advance_time_and_sleep(); + let client = + ReplayingClient::from_file("tests/instance-status-ok-waiter-success.json").unwrap(); + let config = aws_sdk_ec2::Config::builder() + .with_test_defaults() + .http_client(client.clone()) + .time_source(time_source.clone()) + .sleep_impl(sleep_impl) + .region(Region::new("us-west-2")) + .retry_config(RetryConfig::standard()) + .build(); + (aws_sdk_ec2::Client::from_conf(config), client, time_source) +} + +#[tokio::test] +async fn waiters_success() { + let _logs = show_test_logs(); + + let (ec2, http_client, time_source) = prerequisites().await; + + ec2.start_instances() + .instance_ids("i-09fb4224219ac6902") + .send() + .await + .unwrap(); + + let waiter_task = tokio::spawn( + ec2.wait_until_instance_status_ok() + .instance_ids("i-09fb4224219ac6902") + .wait(Duration::from_secs(300)), + ); + + // The responses in the test data will make the waiter poll a few times, so it will take some time + // to complete. If successful, it shouldn't take a full 300 seconds. However, in the event it isn't successful, + // waiting the full 300 seconds will result in a max time exceeded error instead of a never ending test. + time_source.tick(Duration::from_secs(305)).await; + waiter_task.await.unwrap().unwrap(); + + http_client.full_validate("application/xml").await.unwrap(); +} + +#[tokio::test] +async fn waiters_exceed_max_wait_time() { + let _logs = show_test_logs(); + + let (ec2, _, time_source) = prerequisites().await; + + ec2.start_instances() + .instance_ids("i-09fb4224219ac6902") + .send() + .await + .unwrap(); + + let waiter_task = tokio::spawn( + ec2.wait_until_instance_status_ok() + .instance_ids("i-09fb4224219ac6902") + .wait(Duration::from_secs(30)), + ); + + time_source.tick(Duration::from_secs(35)).await; + let err = waiter_task.await.unwrap().err().expect("should fail"); + match err { + WaiterError::ExceededMaxWait(context) => { + assert_eq!(30, context.max_wait().as_secs()); + assert_eq!(30, context.elapsed().as_secs()); + assert_eq!(3, context.poll_count()); + } + err => panic!("unexpected error: {}", DisplayErrorContext(&err)), + } +} diff --git a/aws/sdk/integration-tests/s3/Cargo.toml b/aws/sdk/integration-tests/s3/Cargo.toml index 50ce1ae5c0..0d8ec0a9bc 100644 --- a/aws/sdk/integration-tests/s3/Cargo.toml +++ b/aws/sdk/integration-tests/s3/Cargo.toml @@ -48,3 +48,6 @@ tracing-subscriber = { version = "0.3.15", features = ["env-filter", "json"] } # If you're writing a test with this, take heed! `no-env-filter` means you'll be capturing # logs from everything that speaks, so be specific with your asserts. tracing-test = { version = "0.2.4", features = ["no-env-filter"] } + +[dependencies] +pin-project-lite = "0.2.13" diff --git a/aws/sdk/integration-tests/s3/tests/body_size_hint.rs b/aws/sdk/integration-tests/s3/tests/body_size_hint.rs new file mode 100644 index 0000000000..97e9ac7234 --- /dev/null +++ b/aws/sdk/integration-tests/s3/tests/body_size_hint.rs @@ -0,0 +1,89 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +//! Body wrappers must pass through size_hint + +use aws_config::SdkConfig; +use aws_sdk_s3::{ + config::{Credentials, Region, SharedCredentialsProvider}, + primitives::{ByteStream, SdkBody}, + Client, +}; +use aws_smithy_runtime::client::http::test_util::{capture_request, infallible_client_fn}; +use http_body::Body; + +#[tokio::test] +async fn download_body_size_hint_check() { + let test_body_content = b"hello"; + let test_body = || SdkBody::from(&test_body_content[..]); + assert_eq!( + Some(test_body_content.len() as u64), + (test_body)().size_hint().exact(), + "pre-condition check" + ); + + let http_client = infallible_client_fn(move |_| { + http::Response::builder() + .status(200) + .body((test_body)()) + .unwrap() + }); + let sdk_config = SdkConfig::builder() + .credentials_provider(SharedCredentialsProvider::new(Credentials::for_tests())) + .region(Region::new("us-east-1")) + .http_client(http_client) + .build(); + let client = Client::new(&sdk_config); + let response = client + .get_object() + .bucket("foo") + .key("foo") + .send() + .await + .unwrap(); + assert_eq!( + ( + test_body_content.len() as u64, + Some(test_body_content.len() as u64), + ), + response.body.size_hint(), + "the size hint should be passed through all the default body wrappers" + ); +} + +#[tokio::test] +async fn upload_body_size_hint_check() { + let test_body_content = b"hello"; + + let (http_client, rx) = capture_request(None); + let sdk_config = SdkConfig::builder() + .credentials_provider(SharedCredentialsProvider::new(Credentials::for_tests())) + .region(Region::new("us-east-1")) + .http_client(http_client) + .build(); + let client = Client::new(&sdk_config); + let body = ByteStream::from_static(test_body_content); + assert_eq!( + ( + test_body_content.len() as u64, + Some(test_body_content.len() as u64), + ), + body.size_hint(), + "pre-condition check" + ); + let _response = client + .put_object() + .bucket("foo") + .key("foo") + .body(body) + .send() + .await; + let captured_request = rx.expect_request(); + assert_eq!( + Some(test_body_content.len() as u64), + captured_request.body().size_hint().exact(), + "the size hint should be passed through all the default body wrappers" + ); +} diff --git a/aws/sdk/integration-tests/s3/tests/identity-cache.rs b/aws/sdk/integration-tests/s3/tests/identity-cache.rs new file mode 100644 index 0000000000..9fc7a2fa6c --- /dev/null +++ b/aws/sdk/integration-tests/s3/tests/identity-cache.rs @@ -0,0 +1,119 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use std::sync::atomic::{AtomicI32, Ordering}; +use std::sync::Arc; + +use aws_config::{identity::IdentityCache, BehaviorVersion, Region}; +use aws_credential_types::{ + provider::{future::ProvideCredentials as ProvideCredentialsFuture, ProvideCredentials}, + Credentials, +}; +use aws_sdk_s3::Client; +use aws_smithy_runtime::client::http::test_util::infallible_client_fn; + +// NOTE: These tests are _not_ S3 specific and would apply to any AWS SDK but due to the need to consume `aws-config` +// (which depends on relocated runtime crates) we can't make this an `awsSdkIntegrationTest(..)`. + +#[tokio::test] +async fn test_identity_cache_reused_by_default() { + let http_client = + infallible_client_fn(|_req| http::Response::builder().status(200).body("OK!").unwrap()); + + let provider = TestCredProvider::new(); + let cache = IdentityCache::lazy().build(); + let config = aws_config::defaults(BehaviorVersion::latest()) + .http_client(http_client) + .credentials_provider(provider.clone()) + // TODO(rfc-43) - remove adding a cache when this is the new default + .identity_cache(cache) + .region(Region::new("us-west-2")) + .load() + .await; + + let c1 = Client::new(&config); + let _ = c1.list_buckets().send().await; + assert_eq!(1, provider.invoke_count.load(Ordering::SeqCst)); + + let c2 = Client::new(&config); + let _ = c2.list_buckets().send().await; + assert_eq!(1, provider.invoke_count.load(Ordering::SeqCst)); +} + +// TODO(rfc-43) - add no_identity_cache() to ConfigLoader and re-enable test +// #[tokio::test] +// async fn test_identity_cache_explicit_unset() { +// let http_client = +// infallible_client_fn(|_req| http::Response::builder().status(200).body("OK!").unwrap()); +// +// let provider = TestCredProvider::new(); +// +// let config = aws_config::defaults(BehaviorVersion::latest()) +// .no_identity_cache() +// .http_client(http_client) +// .credentials_provider(provider.clone()) +// .region(Region::new("us-west-2")) +// .load() +// .await; +// +// let c1 = Client::new(&config); +// let _ = c1.list_buckets().send().await; +// assert_eq!(1, provider.invoke_count.load(Ordering::SeqCst)); +// +// let c2 = Client::new(&config); +// let _ = c2.list_buckets().send().await; +// assert_eq!(2, provider.invoke_count.load(Ordering::SeqCst)); +// } + +#[tokio::test] +async fn test_identity_cache_ga_behavior_version() { + let http_client = + infallible_client_fn(|_req| http::Response::builder().status(200).body("OK!").unwrap()); + + let provider = TestCredProvider::new(); + + // no cache is defined in this behavior version by default so each client should get their own + let config = aws_config::defaults(BehaviorVersion::v2023_11_09()) + .http_client(http_client) + .credentials_provider(provider.clone()) + .region(Region::new("us-west-2")) + .load() + .await; + + let c1 = Client::new(&config); + let _ = c1.list_buckets().send().await; + assert_eq!(1, provider.invoke_count.load(Ordering::SeqCst)); + + let c2 = Client::new(&config); + let _ = c2.list_buckets().send().await; + assert_eq!(2, provider.invoke_count.load(Ordering::SeqCst)); +} + +#[derive(Clone, Debug)] +struct TestCredProvider { + invoke_count: Arc, + creds: Credentials, +} + +impl TestCredProvider { + fn new() -> Self { + TestCredProvider { + invoke_count: Arc::new(AtomicI32::default()), + creds: Credentials::for_tests(), + } + } +} + +impl ProvideCredentials for TestCredProvider { + fn provide_credentials<'a>( + &'a self, + ) -> aws_credential_types::provider::future::ProvideCredentials<'a> + where + Self: 'a, + { + self.invoke_count.fetch_add(1, Ordering::SeqCst); + ProvideCredentialsFuture::ready(Ok(self.creds.clone())) + } +} diff --git a/aws/sdk/integration-tests/s3/tests/stalled-stream-protection.rs b/aws/sdk/integration-tests/s3/tests/stalled-stream-protection.rs index af38678f70..c40563ed4a 100644 --- a/aws/sdk/integration-tests/s3/tests/stalled-stream-protection.rs +++ b/aws/sdk/integration-tests/s3/tests/stalled-stream-protection.rs @@ -4,27 +4,90 @@ */ use aws_credential_types::Credentials; -use aws_sdk_s3::config::{Region, StalledStreamProtectionConfig}; -use aws_sdk_s3::primitives::ByteStream; +use aws_sdk_s3::{ + config::{Region, StalledStreamProtectionConfig}, + error::BoxError, +}; +use aws_sdk_s3::{error::DisplayErrorContext, primitives::ByteStream}; use aws_sdk_s3::{Client, Config}; -use bytes::BytesMut; +use aws_smithy_runtime::{assert_str_contains, test_util::capture_test_logs::capture_test_logs}; +use aws_smithy_types::body::SdkBody; +use bytes::{Bytes, BytesMut}; +use http_body::Body; use std::error::Error; -use std::future::Future; -use std::net::SocketAddr; use std::time::Duration; +use std::{future::Future, task::Poll}; +use std::{net::SocketAddr, pin::Pin, task::Context}; +use tokio::{ + net::{TcpListener, TcpStream}, + time::sleep, +}; use tracing::debug; -// This test doesn't work because we can't count on `hyper` to poll the body, -// regardless of whether we schedule a wake. To make this functionality work, -// we'd have to integrate more closely with the orchestrator. -// -// I'll leave this test here because we do eventually want to support stalled -// stream protection for uploads. -#[ignore] +enum SlowBodyState { + Wait(Pin + Send + Sync + 'static>>), + Send, + Taken, +} + +struct SlowBody { + state: SlowBodyState, +} + +impl SlowBody { + fn new() -> Self { + Self { + state: SlowBodyState::Send, + } + } +} + +impl Body for SlowBody { + type Data = Bytes; + type Error = BoxError; + + fn poll_data( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll>> { + loop { + let mut state = SlowBodyState::Taken; + std::mem::swap(&mut state, &mut self.state); + match state { + SlowBodyState::Wait(mut fut) => match fut.as_mut().poll(cx) { + Poll::Ready(_) => self.state = SlowBodyState::Send, + Poll::Pending => { + self.state = SlowBodyState::Wait(fut); + return Poll::Pending; + } + }, + SlowBodyState::Send => { + self.state = SlowBodyState::Wait(Box::pin(sleep(Duration::from_micros(100)))); + return Poll::Ready(Some(Ok(Bytes::from_static( + b"data_data_data_data_data_data_data_data_data_data_data_data_\ + data_data_data_data_data_data_data_data_data_data_data_data_\ + data_data_data_data_data_data_data_data_data_data_data_data_\ + data_data_data_data_data_data_data_data_data_data_data_data_", + )))); + } + SlowBodyState::Taken => unreachable!(), + } + } + } + + fn poll_trailers( + self: Pin<&mut Self>, + _cx: &mut Context<'_>, + ) -> Poll, Self::Error>> { + Poll::Ready(Ok(None)) + } +} + #[tokio::test] async fn test_stalled_stream_protection_defaults_for_upload() { - // We spawn a faulty server that will close the connection after - // writing half of the response body. + let _logs = capture_test_logs(); + + // We spawn a faulty server that will stop all request processing after reading half of the request body. let (server, server_addr) = start_faulty_upload_server().await; let _ = tokio::spawn(server); @@ -32,7 +95,8 @@ async fn test_stalled_stream_protection_defaults_for_upload() { .credentials_provider(Credentials::for_tests()) .region(Region::new("us-east-1")) .endpoint_url(format!("http://{server_addr}")) - // .stalled_stream_protection(StalledStreamProtectionConfig::enabled().build()) + // TODO(https://github.com/smithy-lang/smithy-rs/issues/3510): make stalled stream protection enabled by default with BMV and remove this line + .stalled_stream_protection(StalledStreamProtectionConfig::enabled().build()) .build(); let client = Client::from_conf(conf); @@ -40,22 +104,19 @@ async fn test_stalled_stream_protection_defaults_for_upload() { .put_object() .bucket("a-test-bucket") .key("stalled-stream-test.txt") - .body(ByteStream::from_static(b"Hello")) + .body(ByteStream::new(SdkBody::from_body_0_4(SlowBody::new()))) .send() .await .expect_err("upload stream stalled out"); - let err = err.source().expect("inner error exists"); - assert_eq!( - err.to_string(), + let err_msg = DisplayErrorContext(&err).to_string(); + assert_str_contains!( + err_msg, "minimum throughput was specified at 1 B/s, but throughput of 0 B/s was observed" ); } async fn start_faulty_upload_server() -> (impl Future, SocketAddr) { - use tokio::net::{TcpListener, TcpStream}; - use tokio::time::sleep; - let listener = TcpListener::bind("0.0.0.0:0") .await .expect("socket is free"); @@ -65,12 +126,7 @@ async fn start_faulty_upload_server() -> (impl Future, SocketAddr) let mut buf = BytesMut::new(); let mut time_to_stall = false; - loop { - if time_to_stall { - debug!("faulty server has read partial request, now getting stuck"); - break; - } - + while !time_to_stall { match socket.try_read_buf(&mut buf) { Ok(0) => { unreachable!( @@ -79,12 +135,7 @@ async fn start_faulty_upload_server() -> (impl Future, SocketAddr) } Ok(n) => { debug!("read {n} bytes from the socket"); - - // Check to see if we've received some headers if buf.len() >= 128 { - let s = String::from_utf8_lossy(&buf); - debug!("{s}"); - time_to_stall = true; } } @@ -98,6 +149,7 @@ async fn start_faulty_upload_server() -> (impl Future, SocketAddr) } } + debug!("faulty server has read partial request, now getting stuck"); loop { tokio::task::yield_now().await } @@ -240,9 +292,6 @@ async fn test_stalled_stream_protection_for_downloads_is_enabled_by_default() { } async fn start_faulty_download_server() -> (impl Future, SocketAddr) { - use tokio::net::{TcpListener, TcpStream}; - use tokio::time::sleep; - let listener = TcpListener::bind("0.0.0.0:0") .await .expect("socket is free"); diff --git a/aws/sdk/integration-tests/s3/tests/streaming-response.rs b/aws/sdk/integration-tests/s3/tests/streaming-response.rs index df25bca384..f8104ef68d 100644 --- a/aws/sdk/integration-tests/s3/tests/streaming-response.rs +++ b/aws/sdk/integration-tests/s3/tests/streaming-response.rs @@ -20,7 +20,7 @@ use tracing::debug; // TODO(https://github.com/smithy-lang/smithy-rs/issues/3523): Unignore this test #[tokio::test] -#[should_panic] +#[ignore] async fn test_too_short_body_causes_an_error() { // this is almost impossible to reproduce with Hyper—you need to do stuff like run each request // in its own async runtime. But there's no reason a customer couldn't run their _own_ HttpClient diff --git a/aws/sdk/integration-tests/test.sh b/aws/sdk/integration-tests/test.sh index 88026f6d7c..6d230a73c6 100755 --- a/aws/sdk/integration-tests/test.sh +++ b/aws/sdk/integration-tests/test.sh @@ -16,7 +16,10 @@ for f in *; do else # The webassembly tests use a custom runner set in config.toml that # is not picked up when running the tests outside of the package - cd webassembly && cargo component test --all-features --all-targets && cd .. + # The tests are written for `wasm32-wasi` but the manifest config also specifies + # `wasm32-unknown-unknown` so we can ensure the test build on that platform as well. + # For executing the tests, however, we explicitly choose a target `wasm32-wasi`. + cd webassembly && cargo component test --all-features --target wasm32-wasi && cd .. fi fi done diff --git a/aws/sdk/integration-tests/webassembly/.cargo/config.toml b/aws/sdk/integration-tests/webassembly/.cargo/config.toml index 06b75c8e09..37f9ac58f5 100644 --- a/aws/sdk/integration-tests/webassembly/.cargo/config.toml +++ b/aws/sdk/integration-tests/webassembly/.cargo/config.toml @@ -1,5 +1,5 @@ [build] -target = "wasm32-wasi" +target = ["wasm32-unknown-unknown", "wasm32-wasi"] [target.wasm32-wasi] rustflags = ["-C", "opt-level=1"] diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientRustModule.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientRustModule.kt index 9d33c1b1c5..2da355cb5c 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientRustModule.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientRustModule.kt @@ -102,6 +102,8 @@ object ClientRustModule { /** crate::types::error */ val Error = RustModule.public("error", parent = self) } + + val waiters = RustModule.public("waiters") } class ClientModuleDocProvider( @@ -127,6 +129,7 @@ class ClientModuleDocProvider( ClientRustModule.Primitives.EventStream -> strDoc("Event stream related primitives such as `Message` or `Header`.") ClientRustModule.types -> strDoc("Data structures used by operation inputs/outputs.") ClientRustModule.Types.Error -> strDoc("Error types that $serviceName can respond with.") + ClientRustModule.waiters -> strDoc("Supporting types for waiters.\n\nNote: to use waiters, import the [`Waiters`](crate::client::Waiters) trait, which adds methods prefixed with `wait_until` to the client.") else -> TODO("Document this module: $module") } } @@ -140,6 +143,7 @@ class ClientModuleDocProvider( writeClientConstructionDocs(this) FluentClientDocs.clientUsageDocs(codegenContext)(this) + FluentClientDocs.waiterDocs(codegenContext)(this) } private fun customizeModuleDoc(): Writable = diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientRustSettings.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientRustSettings.kt index ebb5db6a0a..ab3bb2bedd 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientRustSettings.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/ClientRustSettings.kt @@ -37,6 +37,7 @@ data class ClientRustSettings( override val codegenConfig: ClientCodegenConfig, override val license: String?, override val examplesUri: String?, + override val minimumSupportedRustVersion: String? = null, override val customizationConfig: ObjectNode?, ) : CoreRustSettings( service, @@ -49,6 +50,7 @@ data class ClientRustSettings( codegenConfig, license, examplesUri, + minimumSupportedRustVersion, customizationConfig, ) { companion object { @@ -70,6 +72,7 @@ data class ClientRustSettings( codegenConfig = ClientCodegenConfig.fromCodegenConfigAndNode(coreCodegenConfig, codegenSettingsNode), license = coreRustSettings.license, examplesUri = coreRustSettings.examplesUri, + minimumSupportedRustVersion = coreRustSettings.minimumSupportedRustVersion, customizationConfig = coreRustSettings.customizationConfig, ) } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/rulesgen/StdLib.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/rulesgen/StdLib.kt index f9a55ae847..68eda8b854 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/rulesgen/StdLib.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/endpoint/rulesgen/StdLib.kt @@ -55,6 +55,7 @@ class AwsPartitionResolver(runtimeConfig: RuntimeConfig, private val partitionsD arrayOf( "PartitionResolver" to EndpointsLib.partitionResolver(runtimeConfig), "Lazy" to CargoDependency.OnceCell.toType().resolve("sync::Lazy"), + "tracing" to RuntimeType.Tracing, ) override fun structFieldInit() = @@ -70,7 +71,19 @@ class AwsPartitionResolver(runtimeConfig: RuntimeConfig, private val partitionsD // Loading the partition JSON is expensive since it involves many regex compilations, // so cache the result so that it only need to be paid for the first constructed client. pub(crate) static DEFAULT_PARTITION_RESOLVER: #{Lazy}<#{PartitionResolver}> = - #{Lazy}::new(|| #{PartitionResolver}::new_from_json(b$json).expect("valid JSON")); + #{Lazy}::new(|| { + match std::env::var("SMITHY_CLIENT_SDK_CUSTOM_PARTITION") { + Ok(partitions) => { + #{tracing}::debug!("loading custom partitions located at {partitions}"); + let partition_dot_json = std::fs::read_to_string(partitions).expect("should be able to read a custom partition JSON"); + #{PartitionResolver}::new_from_json(partition_dot_json.as_bytes()).expect("valid JSON") + }, + _ => { + #{tracing}::debug!("loading default partitions"); + #{PartitionResolver}::new_from_json(b$json).expect("valid JSON") + } + } + }); """, *codegenScope, ) diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentBuilderGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentBuilderGenerator.kt new file mode 100644 index 0000000000..e6429eb9f9 --- /dev/null +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentBuilderGenerator.kt @@ -0,0 +1,430 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package software.amazon.smithy.rust.codegen.client.smithy.generators.client + +import software.amazon.smithy.model.shapes.MemberShape +import software.amazon.smithy.model.shapes.OperationShape +import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext +import software.amazon.smithy.rust.codegen.client.smithy.ClientRustModule +import software.amazon.smithy.rust.codegen.client.smithy.generators.PaginatorGenerator +import software.amazon.smithy.rust.codegen.core.rustlang.Attribute +import software.amazon.smithy.rust.codegen.core.rustlang.RustType +import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter +import software.amazon.smithy.rust.codegen.core.rustlang.Writable +import software.amazon.smithy.rust.codegen.core.rustlang.asArgument +import software.amazon.smithy.rust.codegen.core.rustlang.asOptional +import software.amazon.smithy.rust.codegen.core.rustlang.deprecatedShape +import software.amazon.smithy.rust.codegen.core.rustlang.docs +import software.amazon.smithy.rust.codegen.core.rustlang.documentShape +import software.amazon.smithy.rust.codegen.core.rustlang.rust +import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock +import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate +import software.amazon.smithy.rust.codegen.core.rustlang.stripOuter +import software.amazon.smithy.rust.codegen.core.rustlang.writable +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope +import software.amazon.smithy.rust.codegen.core.smithy.customize.writeCustomizations +import software.amazon.smithy.rust.codegen.core.smithy.expectRustMetadata +import software.amazon.smithy.rust.codegen.core.smithy.generators.getterName +import software.amazon.smithy.rust.codegen.core.smithy.generators.setterName +import software.amazon.smithy.rust.codegen.core.smithy.rustType +import software.amazon.smithy.rust.codegen.core.util.inputShape +import software.amazon.smithy.rust.codegen.core.util.outputShape + +/** + * Codegen configuration for the fluent builder generator. + * + * Null values indicate "use the default", and defaults are oriented towards + * the main fluent builders used by the client. + * + * These can be overridden for secondary fluent builders, such as used by + * waiters. + */ +interface FluentBuilderConfig { + /** Top-level documentation for the builder struct */ + fun documentBuilder(): Writable? = null + + /** `send()` (and friends) method on the builder */ + fun sendMethods(): Writable? = null + + /** Whether to include paginators or not */ + fun includePaginators(): Boolean = true + + /** Whether to include config override or not */ + fun includeConfigOverride(): Boolean = true +} + +private fun FluentBuilderConfig.sendOverridden(): Boolean = sendMethods() != null + +/** Default fluent builder generator config */ +class DefaultFluentBuilderConfig : FluentBuilderConfig + +/** + * Generates the fluent builders returned by the generated client. + */ +class FluentBuilderGenerator( + private val codegenContext: ClientCodegenContext, + private val operation: OperationShape, + private val customizations: List = emptyList(), + private val builderName: String = operation.fluentBuilderType(codegenContext.symbolProvider).name, + private val config: FluentBuilderConfig = DefaultFluentBuilderConfig(), +) { + private val runtimeConfig = codegenContext.runtimeConfig + private val symbolProvider = codegenContext.symbolProvider + private val model = codegenContext.model + + private val inputShape = operation.inputShape(model) + private val inputBuilderType = symbolProvider.symbolForBuilder(inputShape) + + private val outputType = symbolProvider.toSymbol(operation.outputShape(model)) + private val errorType = symbolProvider.symbolForOperationError(operation) + private val operationType = symbolProvider.toSymbol(operation) + + private val scope = + arrayOf( + *preludeScope, + "Arc" to RuntimeType.Arc, + "CustomizableOperation" to + ClientRustModule.Client.customize.toType() + .resolve("CustomizableOperation"), + "HttpResponse" to + RuntimeType.smithyRuntimeApiClient(runtimeConfig) + .resolve("client::orchestrator::HttpResponse"), + "InputBuilder" to inputBuilderType, + "Operation" to operationType, + "OperationError" to errorType, + "OperationOutput" to outputType, + "SdkError" to RuntimeType.sdkError(runtimeConfig), + "RuntimePlugins" to RuntimeType.runtimePlugins(runtimeConfig), + "SendResult" to + ClientRustModule.Client.customize.toType() + .resolve("internal::SendResult"), + ) + + fun render(writer: RustWriter) { + if (!config.sendOverridden()) { + writer.renderInputBuilderImpls() + } + writer.renderStruct() + if (!config.sendOverridden()) { + writer.renderTraitImpls() + } + writer.renderImpl() + } + + private fun defaultDocumentBuilder(): Writable = + writable { + docs("Fluent builder constructing a request to `${operationType.name}`.\n") + documentShape(operation, model, autoSuppressMissingDocs = false) + } + + private fun defaultSend(): Writable = + writable { + rustTemplate( + """ + /// Sends the request and returns the response. + /// + /// If an error occurs, an `SdkError` will be returned with additional details that + /// can be matched against. + /// + /// By default, any retryable failures will be retried twice. Retry behavior + /// is configurable with the [RetryConfig](aws_smithy_types::retry::RetryConfig), which can be + /// set when configuring the client. + pub async fn send(self) -> #{Result}<#{OperationOutput}, #{SdkError}<#{OperationError}, #{HttpResponse}>> { + let input = self.inner.build().map_err(#{SdkError}::construction_failure)?; + let runtime_plugins = #{Operation}::operation_runtime_plugins( + self.handle.runtime_plugins.clone(), + &self.handle.conf, + self.config_override, + ); + #{Operation}::orchestrate(&runtime_plugins, input).await + } + + /// Consumes this builder, creating a customizable operation that can be modified before being sent. + pub fn customize( + self, + ) -> #{CustomizableOperation}<#{OperationOutput}, #{OperationError}, Self> { + #{CustomizableOperation}::new(self) + } + """, + *scope, + ) + } + + private fun RustWriter.renderStruct() { + // Filter out any derive that isn't Clone. Then add a Debug derive input name + val derives = + symbolProvider.toSymbol(inputShape).expectRustMetadata().derives.let { baseDerives -> + baseDerives.filter { it == RuntimeType.Clone } + RuntimeType.Debug + } + + (config.documentBuilder() ?: defaultDocumentBuilder())() + deprecatedShape(operation) + Attribute(Attribute.derive(derives.toSet())).render(this) + val configOverride = + when (config.includeConfigOverride()) { + true -> "\nconfig_override: #{Option}," + else -> "" + } + rustTemplate( + """ + pub struct $builderName { + handle: #{Arc}, + inner: #{InputBuilder},$configOverride + } + """, + *scope, + ) + } + + private fun RustWriter.renderImpl() { + rustBlock("impl $builderName") { + val configOverride = + when (config.includeConfigOverride()) { + true -> "\nconfig_override: #{None}," + else -> "" + } + rustTemplate( + """ + /// Creates a new `$builderName`. + pub(crate) fn new(handle: #{Arc}) -> Self { + Self { + handle, + inner: #{Default}::default(),$configOverride + } + } + """, + *scope, + ) + + rustTemplate( + """ + /// Access the ${operationType.name} as a reference. + pub fn as_input(&self) -> &#{InputBuilder} { + &self.inner + } + """, + *scope, + ) + + // Output the send method + (config.sendMethods() ?: defaultSend())() + + if (config.includeConfigOverride()) { + rustTemplate( + """ + pub(crate) fn config_override( + mut self, + config_override: impl #{Into}, + ) -> Self { + self.set_config_override(#{Some}(config_override.into())); + self + } + + pub(crate) fn set_config_override( + &mut self, + config_override: #{Option}, + ) -> &mut Self { + self.config_override = config_override; + self + } + """, + *scope, + ) + } + + if (config.includePaginators()) { + PaginatorGenerator.paginatorType(codegenContext, operation) + ?.also { paginatorType -> + rustTemplate( + """ + /// Create a paginator for this request + /// + /// Paginators are used by calling [`send().await`](#{Paginator}::send) which returns a [`PaginationStream`](aws_smithy_async::future::pagination_stream::PaginationStream). + pub fn into_paginator(self) -> #{Paginator} { + #{Paginator}::new(self.handle, self.inner) + } + """, + "Paginator" to paginatorType, + ) + } + } + + writeCustomizations( + customizations, + FluentClientSection.FluentBuilderImpl(operation, errorType), + ) + + inputShape.members().forEach { member -> + val memberName = symbolProvider.toMemberName(member) + // All fields in the builder are optional + val memberSymbol = symbolProvider.toSymbol(member) + val outerType = memberSymbol.rustType() + when (val coreType = outerType.stripOuter()) { + is RustType.Vec -> renderVecHelper(member, memberName, coreType) + is RustType.HashMap -> renderMapHelper(member, memberName, coreType) + else -> renderInputHelper(member, memberName, coreType) + } + // pure setter + val setterName = member.setterName() + val optionalInputType = outerType.asOptional() + renderInputHelper(member, setterName, optionalInputType) + + val getterName = member.getterName() + renderGetterHelper(member, getterName, optionalInputType) + } + } + } + + private fun RustWriter.renderTraitImpls() { + rustTemplate( + """ + impl + crate::client::customize::internal::CustomizableSend< + #{OperationOutput}, + #{OperationError}, + > for $builderName + { + fn send( + self, + config_override: crate::config::Builder, + ) -> crate::client::customize::internal::BoxFuture< + crate::client::customize::internal::SendResult< + #{OperationOutput}, + #{OperationError}, + >, + > { + #{Box}::pin(async move { self.config_override(config_override).send().await }) + } + } + """, + *scope, + ) + } + + private fun RustWriter.renderInputBuilderImpls() { + FluentClientGenerator.clientOperationFnName(operation, symbolProvider).also { fnName -> + rustTemplate( + """ + impl #{InputBuilder} { + /// Sends a request with this input using the given client. + pub async fn send_with(self, client: &crate::Client) -> #{Result}< + #{OperationOutput}, + #{SdkError}< + #{OperationError}, + #{HttpResponse} + > + > { + let mut fluent_builder = client.$fnName(); + fluent_builder.inner = self; + fluent_builder.send().await + } + } + """, + *scope, + ) + } + } + + /** Generate and write Rust code for a builder method that sets a Vec */ + private fun RustWriter.renderVecHelper( + member: MemberShape, + memberName: String, + coreType: RustType.Vec, + ) { + docs( + """ + Appends an item to `${member.memberName}`. + + To override the contents of this collection use [`${member.setterName()}`](Self::${member.setterName()}). + """, + ) + documentShape(member, model) + deprecatedShape(member) + coreType.member.asArgument("input").also { input -> + rust( + """ + pub fn $memberName(mut self, ${input.argument}) -> Self { + self.inner = self.inner.$memberName(${input.value}); + self + } + """, + ) + } + } + + /** Generate and write Rust code for a builder method that sets a HashMap */ + private fun RustWriter.renderMapHelper( + member: MemberShape, + memberName: String, + coreType: RustType.HashMap, + ) { + val k = coreType.key.asArgument("k") + val v = coreType.member.asArgument("v") + + docs( + """ + Adds a key-value pair to `${member.memberName}`. + + To override the contents of this collection use [`${member.setterName()}`](Self::${member.setterName()}). + """, + ) + documentShape(member, model) + deprecatedShape(member) + rust( + """ + pub fn $memberName(mut self, ${k.argument}, ${v.argument}) -> Self { + self.inner = self.inner.$memberName(${k.value}, ${v.value}); + self + } + """, + ) + } + + /** + * Generate and write Rust code for a builder method that sets an input. Can be used for setter methods as well e.g. + * + * `renderInputHelper(memberShape, "foo", RustType.String)` -> `pub fn foo(mut self, input: impl Into) -> Self { ... }` + * `renderInputHelper(memberShape, "set_bar", RustType.Option)` -> `pub fn set_bar(mut self, input: Option) -> Self { ... }` + */ + private fun RustWriter.renderInputHelper( + member: MemberShape, + memberName: String, + coreType: RustType, + ) { + val functionInput = coreType.asArgument("input") + + documentShape(member, model) + deprecatedShape(member) + rust( + """ + pub fn $memberName(mut self, ${functionInput.argument}) -> Self { + self.inner = self.inner.$memberName(${functionInput.value}); + self + } + """, + ) + } + + /** + * Generate and write Rust code for a getter method that returns a reference to the inner data. + */ + private fun RustWriter.renderGetterHelper( + member: MemberShape, + memberName: String, + coreType: RustType, + ) { + documentShape(member, model) + deprecatedShape(member) + rustTemplate( + """ + pub fn $memberName(&self) -> &#{CoreType} { + self.inner.$memberName() + } + """, + "CoreType" to coreType, + ) + } +} diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientCore.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientCore.kt deleted file mode 100644 index b997142a99..0000000000 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientCore.kt +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -package software.amazon.smithy.rust.codegen.client.smithy.generators.client - -import software.amazon.smithy.model.Model -import software.amazon.smithy.model.shapes.MemberShape -import software.amazon.smithy.rust.codegen.core.rustlang.RustType -import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter -import software.amazon.smithy.rust.codegen.core.rustlang.asArgument -import software.amazon.smithy.rust.codegen.core.rustlang.deprecatedShape -import software.amazon.smithy.rust.codegen.core.rustlang.docs -import software.amazon.smithy.rust.codegen.core.rustlang.documentShape -import software.amazon.smithy.rust.codegen.core.rustlang.rust -import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock -import software.amazon.smithy.rust.codegen.core.rustlang.withBlockTemplate -import software.amazon.smithy.rust.codegen.core.smithy.generators.setterName - -class FluentClientCore(private val model: Model) { - /** Generate and write Rust code for a builder method that sets a Vec */ - fun RustWriter.renderVecHelper( - member: MemberShape, - memberName: String, - coreType: RustType.Vec, - ) { - docs("Appends an item to `${member.memberName}`.") - rust("///") - docs("To override the contents of this collection use [`${member.setterName()}`](Self::${member.setterName()}).") - rust("///") - val input = coreType.member.asArgument("input") - - documentShape(member, model) - deprecatedShape(member) - rustBlock("pub fn $memberName(mut self, ${input.argument}) -> Self") { - write("self.inner = self.inner.$memberName(${input.value});") - write("self") - } - } - - /** Generate and write Rust code for a builder method that sets a HashMap */ - fun RustWriter.renderMapHelper( - member: MemberShape, - memberName: String, - coreType: RustType.HashMap, - ) { - docs("Adds a key-value pair to `${member.memberName}`.") - rust("///") - docs("To override the contents of this collection use [`${member.setterName()}`](Self::${member.setterName()}).") - rust("///") - val k = coreType.key.asArgument("k") - val v = coreType.member.asArgument("v") - - documentShape(member, model) - deprecatedShape(member) - rustBlock("pub fn $memberName(mut self, ${k.argument}, ${v.argument}) -> Self") { - write("self.inner = self.inner.$memberName(${k.value}, ${v.value});") - write("self") - } - } - - /** - * Generate and write Rust code for a builder method that sets an input. Can be used for setter methods as well e.g. - * - * `renderInputHelper(memberShape, "foo", RustType.String)` -> `pub fn foo(mut self, input: impl Into) -> Self { ... }` - * `renderInputHelper(memberShape, "set_bar", RustType.Option)` -> `pub fn set_bar(mut self, input: Option) -> Self { ... }` - */ - fun RustWriter.renderInputHelper( - member: MemberShape, - memberName: String, - coreType: RustType, - ) { - val functionInput = coreType.asArgument("input") - - documentShape(member, model) - deprecatedShape(member) - rustBlock("pub fn $memberName(mut self, ${functionInput.argument}) -> Self") { - write("self.inner = self.inner.$memberName(${functionInput.value});") - write("self") - } - } - - /** - * Generate and write Rust code for a getter method that returns a reference to the inner data. - */ - fun RustWriter.renderGetterHelper( - member: MemberShape, - memberName: String, - coreType: RustType, - ) { - documentShape(member, model) - deprecatedShape(member) - withBlockTemplate("pub fn $memberName(&self) -> &#{CoreType} {", "}", "CoreType" to coreType) { - write("self.inner.$memberName()") - } - } -} diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientDecorator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientDecorator.kt index 2a2c0c1353..8a57a5996e 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientDecorator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientDecorator.kt @@ -22,6 +22,15 @@ import software.amazon.smithy.rust.codegen.core.smithy.generators.LibRsCustomiza import software.amazon.smithy.rust.codegen.core.smithy.generators.LibRsSection import software.amazon.smithy.rust.codegen.core.util.serviceNameOrDefault +/** + * Generates the client via codegen decorator. + * + * > Why is this a decorator instead of a normal generator that gets called from the codegen visitor? + * + * The AWS SDK needs to make significant changes from what smithy-rs generates for generic clients, + * and the easiest way to do that is to completely replace the client generator. With this as + * a decorator, it can be excluded entirely and replaced in the sdk-codegen plugin. + */ class FluentClientDecorator : ClientCodegenDecorator { override val name: String = "FluentClient" override val order: Byte = 0 @@ -101,6 +110,7 @@ class GenericFluentClient(private val codegenContext: ClientCodegenContext) : Fl ) FluentClientDocs.clientConstructionDocs(codegenContext)(this) FluentClientDocs.clientUsageDocs(codegenContext)(this) + FluentClientDocs.waiterDocs(codegenContext)(this) } else -> emptySection } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientDocs.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientDocs.kt index be499c6ca6..1ceaf043cc 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientDocs.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientDocs.kt @@ -5,13 +5,17 @@ package software.amazon.smithy.rust.codegen.client.smithy.generators.client +import software.amazon.smithy.model.knowledge.TopDownIndex import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext +import software.amazon.smithy.rust.codegen.core.rustlang.docs import software.amazon.smithy.rust.codegen.core.rustlang.docsTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable +import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.inputShape import software.amazon.smithy.rust.codegen.core.util.serviceNameOrDefault +import software.amazon.smithy.waiters.WaitableTrait object FluentClientDocs { fun clientConstructionDocs(codegenContext: ClientCodegenContext) = @@ -99,4 +103,30 @@ object FluentClientDocs { } } } + + fun waiterDocs(codegenContext: ClientCodegenContext) = + writable { + val operations = TopDownIndex.of(codegenContext.model).getContainedOperations(codegenContext.serviceShape) + if (operations.any { it.hasTrait() }) { + docs( + """ + ## Waiters + + This client provides `wait_until` methods behind the [`Waiters`](crate::client::Waiters) trait. + To use them, simply import the trait, and then call one of the `wait_until` methods. This will + return a waiter fluent builder that takes various parameters, which are documented on the builder + type. Once parameters have been provided, the `wait` method can be called to initiate waiting. + + For example, if there was a `wait_until_thing` method, it could look like: + ```rust,ignore + let result = client.wait_until_thing() + .thing_id("someId") + .wait(Duration::from_secs(120)) + .await; + ``` + """.trimIndent(), + trimStart = false, + ) + } + } } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGenerator.kt index 3cc9816cdc..a9f75f066a 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/client/FluentClientGenerator.kt @@ -14,10 +14,8 @@ import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.model.traits.DocumentationTrait import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext import software.amazon.smithy.rust.codegen.client.smithy.ClientRustModule -import software.amazon.smithy.rust.codegen.client.smithy.generators.PaginatorGenerator import software.amazon.smithy.rust.codegen.client.smithy.generators.isPaginated -import software.amazon.smithy.rust.codegen.core.rustlang.Attribute -import software.amazon.smithy.rust.codegen.core.rustlang.Attribute.Companion.derive +import software.amazon.smithy.rust.codegen.client.smithy.generators.waiters.WaitableGenerator import software.amazon.smithy.rust.codegen.core.rustlang.CargoDependency import software.amazon.smithy.rust.codegen.core.rustlang.EscapeFor import software.amazon.smithy.rust.codegen.core.rustlang.Feature @@ -26,30 +24,22 @@ import software.amazon.smithy.rust.codegen.core.rustlang.RustReservedWords import software.amazon.smithy.rust.codegen.core.rustlang.RustType import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.asArgumentType -import software.amazon.smithy.rust.codegen.core.rustlang.asOptional import software.amazon.smithy.rust.codegen.core.rustlang.deprecatedShape import software.amazon.smithy.rust.codegen.core.rustlang.docLink -import software.amazon.smithy.rust.codegen.core.rustlang.docs -import software.amazon.smithy.rust.codegen.core.rustlang.documentShape import software.amazon.smithy.rust.codegen.core.rustlang.escape import software.amazon.smithy.rust.codegen.core.rustlang.featureGatedBlock -import software.amazon.smithy.rust.codegen.core.rustlang.implBlock import software.amazon.smithy.rust.codegen.core.rustlang.normalizeHtml import software.amazon.smithy.rust.codegen.core.rustlang.qualifiedName import software.amazon.smithy.rust.codegen.core.rustlang.render -import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.stripOuter -import software.amazon.smithy.rust.codegen.core.rustlang.withBlockTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope import software.amazon.smithy.rust.codegen.core.smithy.RustCrate import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.customize.writeCustomizations -import software.amazon.smithy.rust.codegen.core.smithy.expectRustMetadata -import software.amazon.smithy.rust.codegen.core.smithy.generators.getterName import software.amazon.smithy.rust.codegen.core.smithy.generators.setterName import software.amazon.smithy.rust.codegen.core.smithy.rustType import software.amazon.smithy.rust.codegen.core.util.dq @@ -87,7 +77,6 @@ class FluentClientGenerator( private val symbolProvider = codegenContext.symbolProvider private val model = codegenContext.model private val runtimeConfig = codegenContext.runtimeConfig - private val core = FluentClientCore(model) fun render(crate: RustCrate) { renderFluentClient(crate) @@ -95,11 +84,13 @@ class FluentClientGenerator( val customizableOperationGenerator = CustomizableOperationGenerator(codegenContext) operations.forEach { operation -> crate.withModule(symbolProvider.moduleForBuilder(operation)) { - renderFluentBuilder(operation) + FluentBuilderGenerator(codegenContext, operation, customizations).render(this) } } customizableOperationGenerator.render(crate) + + WaitableGenerator(codegenContext, operations).render(crate) } private fun renderFluentClient(crate: RustCrate) { @@ -246,225 +237,6 @@ class FluentClientGenerator( } } } - - private fun RustWriter.renderFluentBuilder(operation: OperationShape) { - val outputType = symbolProvider.toSymbol(operation.outputShape(model)) - val errorType = symbolProvider.symbolForOperationError(operation) - val operationSymbol = symbolProvider.toSymbol(operation) - - val input = operation.inputShape(model) - val baseDerives = symbolProvider.toSymbol(input).expectRustMetadata().derives - // Filter out any derive that isn't Clone. Then add a Debug derive - // input name - val fnName = clientOperationFnName(operation, symbolProvider) - implBlock(symbolProvider.symbolForBuilder(input)) { - rustTemplate( - """ - /// Sends a request with this input using the given client. - pub async fn send_with(self, client: &crate::Client) -> #{Result}< - #{OperationOutput}, - #{SdkError}< - #{OperationError}, - #{RawResponseType} - > - > { - let mut fluent_builder = client.$fnName(); - fluent_builder.inner = self; - fluent_builder.send().await - } - """, - *preludeScope, - "RawResponseType" to - RuntimeType.smithyRuntimeApiClient(runtimeConfig).resolve("client::orchestrator::HttpResponse"), - "Operation" to operationSymbol, - "OperationError" to errorType, - "OperationOutput" to outputType, - "SdkError" to RuntimeType.sdkError(runtimeConfig), - ) - } - - val derives = baseDerives.filter { it == RuntimeType.Clone } + RuntimeType.Debug - docs("Fluent builder constructing a request to `${operationSymbol.name}`.\n") - - val builderName = operation.fluentBuilderType(symbolProvider).name - documentShape(operation, model, autoSuppressMissingDocs = false) - deprecatedShape(operation) - Attribute(derive(derives.toSet())).render(this) - withBlockTemplate( - "pub struct $builderName {", - "}", - ) { - rustTemplate( - """ - handle: #{Arc}, - inner: #{Inner}, - """, - "Inner" to symbolProvider.symbolForBuilder(input), - "Arc" to RuntimeType.Arc, - ) - rustTemplate("config_override: #{Option},", *preludeScope) - } - - rustTemplate( - """ - impl - crate::client::customize::internal::CustomizableSend< - #{OperationOutput}, - #{OperationError}, - > for $builderName - { - fn send( - self, - config_override: crate::config::Builder, - ) -> crate::client::customize::internal::BoxFuture< - crate::client::customize::internal::SendResult< - #{OperationOutput}, - #{OperationError}, - >, - > { - #{Box}::pin(async move { self.config_override(config_override).send().await }) - } - } - """, - *preludeScope, - "OperationError" to errorType, - "OperationOutput" to outputType, - "SdkError" to RuntimeType.sdkError(runtimeConfig), - ) - - rustBlock("impl $builderName") { - rust("/// Creates a new `${operationSymbol.name}`.") - withBlockTemplate( - "pub(crate) fn new(handle: #{Arc}) -> Self {", - "}", - "Arc" to RuntimeType.Arc, - ) { - withBlockTemplate( - "Self {", - "}", - ) { - rustTemplate("handle, inner: #{Default}::default(),", *preludeScope) - rustTemplate("config_override: #{None},", *preludeScope) - } - } - - rust("/// Access the ${operationSymbol.name} as a reference.\n") - withBlockTemplate( - "pub fn as_input(&self) -> &#{Inner} {", "}", - "Inner" to symbolProvider.symbolForBuilder(input), - ) { - write("&self.inner") - } - - val orchestratorScope = - arrayOf( - *preludeScope, - "CustomizableOperation" to - ClientRustModule.Client.customize.toType() - .resolve("CustomizableOperation"), - "HttpResponse" to - RuntimeType.smithyRuntimeApiClient(runtimeConfig) - .resolve("client::orchestrator::HttpResponse"), - "Operation" to operationSymbol, - "OperationError" to errorType, - "OperationOutput" to outputType, - "RuntimePlugins" to RuntimeType.runtimePlugins(runtimeConfig), - "SendResult" to - ClientRustModule.Client.customize.toType() - .resolve("internal::SendResult"), - "SdkError" to RuntimeType.sdkError(runtimeConfig), - ) - rustTemplate( - """ - /// Sends the request and returns the response. - /// - /// If an error occurs, an `SdkError` will be returned with additional details that - /// can be matched against. - /// - /// By default, any retryable failures will be retried twice. Retry behavior - /// is configurable with the [RetryConfig](aws_smithy_types::retry::RetryConfig), which can be - /// set when configuring the client. - pub async fn send(self) -> #{Result}<#{OperationOutput}, #{SdkError}<#{OperationError}, #{HttpResponse}>> { - let input = self.inner.build().map_err(#{SdkError}::construction_failure)?; - let runtime_plugins = #{Operation}::operation_runtime_plugins( - self.handle.runtime_plugins.clone(), - &self.handle.conf, - self.config_override, - ); - #{Operation}::orchestrate(&runtime_plugins, input).await - } - - /// Consumes this builder, creating a customizable operation that can be modified before being sent. - pub fn customize( - self, - ) -> #{CustomizableOperation}<#{OperationOutput}, #{OperationError}, Self> { - #{CustomizableOperation}::new(self) - } - """, - *orchestratorScope, - ) - - rustTemplate( - """ - pub(crate) fn config_override( - mut self, - config_override: impl Into, - ) -> Self { - self.set_config_override(Some(config_override.into())); - self - } - - pub(crate) fn set_config_override( - &mut self, - config_override: Option, - ) -> &mut Self { - self.config_override = config_override; - self - } - """, - ) - - PaginatorGenerator.paginatorType(codegenContext, operation) - ?.also { paginatorType -> - rustTemplate( - """ - /// Create a paginator for this request - /// - /// Paginators are used by calling [`send().await`](#{Paginator}::send) which returns a [`PaginationStream`](aws_smithy_async::future::pagination_stream::PaginationStream). - pub fn into_paginator(self) -> #{Paginator} { - #{Paginator}::new(self.handle, self.inner) - } - """, - "Paginator" to paginatorType, - ) - } - writeCustomizations( - customizations, - FluentClientSection.FluentBuilderImpl( - operation, - symbolProvider.symbolForOperationError(operation), - ), - ) - input.members().forEach { member -> - val memberName = symbolProvider.toMemberName(member) - // All fields in the builder are optional - val memberSymbol = symbolProvider.toSymbol(member) - val outerType = memberSymbol.rustType() - when (val coreType = outerType.stripOuter()) { - is RustType.Vec -> with(core) { renderVecHelper(member, memberName, coreType) } - is RustType.HashMap -> with(core) { renderMapHelper(member, memberName, coreType) } - else -> with(core) { renderInputHelper(member, memberName, coreType) } - } - // pure setter - val setterName = member.setterName() - val optionalInputType = outerType.asOptional() - with(core) { renderInputHelper(member, setterName, optionalInputType) } - - val getterName = member.getterName() - with(core) { renderGetterHelper(member, getterName, optionalInputType) } - } - } - } } private fun baseClientRuntimePluginsFn( diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/StalledStreamProtectionConfigCustomization.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/StalledStreamProtectionConfigCustomization.kt index 83c3b6dd6b..8304efc2c4 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/StalledStreamProtectionConfigCustomization.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/config/StalledStreamProtectionConfigCustomization.kt @@ -120,15 +120,12 @@ class StalledStreamProtectionOperationCustomization( is OperationSection.AdditionalInterceptors -> { val stalledStreamProtectionModule = RuntimeType.smithyRuntime(rc).resolve("client::stalled_stream_protection") section.registerInterceptor(rc, this) { - // Currently, only response bodies are protected/supported because - // we can't count on hyper to poll a request body on wake. rustTemplate( """ - #{StalledStreamProtectionInterceptor}::new(#{Kind}::ResponseBody) + #{StalledStreamProtectionInterceptor}::default() """, *preludeScope, "StalledStreamProtectionInterceptor" to stalledStreamProtectionModule.resolve("StalledStreamProtectionInterceptor"), - "Kind" to stalledStreamProtectionModule.resolve("StalledStreamProtectionInterceptorKind"), ) } } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/error/ServiceErrorGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/error/ServiceErrorGenerator.kt index 0f8789d4e6..48f924c4e8 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/error/ServiceErrorGenerator.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/error/ServiceErrorGenerator.kt @@ -24,7 +24,6 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustBlockTemplate import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext -import software.amazon.smithy.rust.codegen.core.smithy.CodegenTarget import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope @@ -33,6 +32,8 @@ import software.amazon.smithy.rust.codegen.core.smithy.customize.writeCustomizat import software.amazon.smithy.rust.codegen.core.smithy.generators.operationBuildError import software.amazon.smithy.rust.codegen.core.smithy.transformers.allErrors import software.amazon.smithy.rust.codegen.core.smithy.transformers.eventStreamErrors +import software.amazon.smithy.rust.codegen.core.util.hasTrait +import software.amazon.smithy.waiters.WaitableTrait /** * Each service defines its own "top-level" error combining all possible errors that a service can emit. @@ -77,6 +78,30 @@ class ServiceErrorGenerator( // operation errors renderImplFrom(symbolProvider.symbolForOperationError(operationShape), operationShape.errors) } + // Every waiter error can be converted into service::Error + if (operations.any { it.hasTrait() }) { + rustTemplate( + """ + impl #{From}<#{WaiterError}> for Error + where + O: #{Debug} + #{Send} + #{Sync} + 'static, + E: #{StdError} + #{Send} + #{Sync} + 'static, + { + fn from(err: #{WaiterError}) -> Self { + Error::Unhandled(#{Unhandled} { + meta: #{Default}::default(), + source: err.into(), + }) + } + } + """, + *preludeScope, + "Debug" to RuntimeType.Debug, + "StdError" to RuntimeType.StdError, + "WaiterError" to RuntimeType.smithyRuntimeApiClient(codegenContext.runtimeConfig).resolve("client::waiters::error::WaiterError"), + "Unhandled" to unhandledError(codegenContext.runtimeConfig), + ) + } // event stream errors operations.map { it.eventStreamErrors(codegenContext.model) } .flatMap { it.entries } @@ -145,52 +170,50 @@ class ServiceErrorGenerator( errorSymbol: Symbol, errors: List, ) { - if (errors.isNotEmpty() || CodegenTarget.CLIENT == codegenContext.target) { - val operationErrors = errors.map { model.expectShape(it) } - rustBlock( - "impl From<#T<#T, R>> for Error where R: Send + Sync + std::fmt::Debug + 'static", - sdkError, - errorSymbol, + val operationErrors = errors.map { model.expectShape(it) } + rustBlock( + "impl From<#T<#T, R>> for Error where R: Send + Sync + std::fmt::Debug + 'static", + sdkError, + errorSymbol, + ) { + rustBlockTemplate( + "fn from(err: #{SdkError}<#{OpError}, R>) -> Self", + "SdkError" to sdkError, + "OpError" to errorSymbol, ) { - rustBlockTemplate( - "fn from(err: #{SdkError}<#{OpError}, R>) -> Self", - "SdkError" to sdkError, - "OpError" to errorSymbol, - ) { - rustBlock("match err") { - rust("#T::ServiceError(context) => Self::from(context.into_err()),", sdkError) - rustTemplate( - """ - _ => Error::Unhandled( - #{Unhandled} { - meta: #{ProvideErrorMetadata}::meta(&err).clone(), - source: err.into(), - } - ), - """, - "Unhandled" to unhandledError(codegenContext.runtimeConfig), - "ProvideErrorMetadata" to RuntimeType.provideErrorMetadataTrait(codegenContext.runtimeConfig), - ) - } + rustBlock("match err") { + rust("#T::ServiceError(context) => Self::from(context.into_err()),", sdkError) + rustTemplate( + """ + _ => Error::Unhandled( + #{Unhandled} { + meta: #{ProvideErrorMetadata}::meta(&err).clone(), + source: err.into(), + } + ), + """, + "Unhandled" to unhandledError(codegenContext.runtimeConfig), + "ProvideErrorMetadata" to RuntimeType.provideErrorMetadataTrait(codegenContext.runtimeConfig), + ) } } + } - rustBlock("impl From<#T> for Error", errorSymbol) { - rustBlock("fn from(err: #T) -> Self", errorSymbol) { - rustBlock("match err") { - operationErrors.forEach { errorShape -> - val errSymbol = symbolProvider.toSymbol(errorShape) - rust( - "#T::${errSymbol.name}(inner) => Error::${errSymbol.name}(inner),", - errorSymbol, - ) - } - rustTemplate( - "#{errorSymbol}::Unhandled(inner) => Error::Unhandled(inner),", - "errorSymbol" to errorSymbol, - "unhandled" to unhandledError(codegenContext.runtimeConfig), + rustBlock("impl From<#T> for Error", errorSymbol) { + rustBlock("fn from(err: #T) -> Self", errorSymbol) { + rustBlock("match err") { + operationErrors.forEach { errorShape -> + val errSymbol = symbolProvider.toSymbol(errorShape) + rust( + "#T::${errSymbol.name}(inner) => Error::${errSymbol.name}(inner),", + errorSymbol, ) } + rustTemplate( + "#{errorSymbol}::Unhandled(inner) => Error::Unhandled(inner),", + "errorSymbol" to errorSymbol, + "unhandled" to unhandledError(codegenContext.runtimeConfig), + ) } } } diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/waiters/RustJmespathShapeTraversalGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/waiters/RustJmespathShapeTraversalGenerator.kt new file mode 100644 index 0000000000..2e588d0f53 --- /dev/null +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/waiters/RustJmespathShapeTraversalGenerator.kt @@ -0,0 +1,891 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package software.amazon.smithy.rust.codegen.client.smithy.generators.waiters + +import software.amazon.smithy.jmespath.ExpressionSerializer +import software.amazon.smithy.jmespath.JmespathExpression +import software.amazon.smithy.jmespath.ast.AndExpression +import software.amazon.smithy.jmespath.ast.BinaryExpression +import software.amazon.smithy.jmespath.ast.ComparatorExpression +import software.amazon.smithy.jmespath.ast.CurrentExpression +import software.amazon.smithy.jmespath.ast.ExpressionTypeExpression +import software.amazon.smithy.jmespath.ast.FieldExpression +import software.amazon.smithy.jmespath.ast.FilterProjectionExpression +import software.amazon.smithy.jmespath.ast.FlattenExpression +import software.amazon.smithy.jmespath.ast.FunctionExpression +import software.amazon.smithy.jmespath.ast.IndexExpression +import software.amazon.smithy.jmespath.ast.LiteralExpression +import software.amazon.smithy.jmespath.ast.MultiSelectHashExpression +import software.amazon.smithy.jmespath.ast.MultiSelectListExpression +import software.amazon.smithy.jmespath.ast.NotExpression +import software.amazon.smithy.jmespath.ast.ObjectProjectionExpression +import software.amazon.smithy.jmespath.ast.OrExpression +import software.amazon.smithy.jmespath.ast.ProjectionExpression +import software.amazon.smithy.jmespath.ast.SliceExpression +import software.amazon.smithy.jmespath.ast.Subexpression +import software.amazon.smithy.model.Model +import software.amazon.smithy.model.shapes.BooleanShape +import software.amazon.smithy.model.shapes.CollectionShape +import software.amazon.smithy.model.shapes.EnumShape +import software.amazon.smithy.model.shapes.MapShape +import software.amazon.smithy.model.shapes.NumberShape +import software.amazon.smithy.model.shapes.Shape +import software.amazon.smithy.model.shapes.StringShape +import software.amazon.smithy.model.shapes.StructureShape +import software.amazon.smithy.model.traits.EnumTrait +import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext +import software.amazon.smithy.rust.codegen.core.rustlang.RustType +import software.amazon.smithy.rust.codegen.core.rustlang.SafeNamer +import software.amazon.smithy.rust.codegen.core.rustlang.Writable +import software.amazon.smithy.rust.codegen.core.rustlang.asRef +import software.amazon.smithy.rust.codegen.core.rustlang.plus +import software.amazon.smithy.rust.codegen.core.rustlang.render +import software.amazon.smithy.rust.codegen.core.rustlang.rust +import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock +import software.amazon.smithy.rust.codegen.core.rustlang.rustBlockTemplate +import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate +import software.amazon.smithy.rust.codegen.core.rustlang.stripOuter +import software.amazon.smithy.rust.codegen.core.rustlang.withBlock +import software.amazon.smithy.rust.codegen.core.rustlang.withBlockTemplate +import software.amazon.smithy.rust.codegen.core.rustlang.writable +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope +import software.amazon.smithy.rust.codegen.core.smithy.isOptional +import software.amazon.smithy.rust.codegen.core.smithy.rustType +import software.amazon.smithy.rust.codegen.core.util.dq +import software.amazon.smithy.rust.codegen.core.util.hasTrait +import software.amazon.smithy.rust.codegen.core.util.orNull +import java.text.NumberFormat + +/** + * This needs to exist since there are computed values where there is no modeled + * shape for the result of the evaluated expression. For example, the multi-select + * list `['foo', 'baz']` is a list of string, but it isn't modeled anywhere, + * so there is no Smithy shape to represent it. However, information is still + * needed about the original shape in order to correctly generate code. + */ +sealed class TraversedShape { + abstract val shape: Shape? + + data class Array(override val shape: Shape?, val member: TraversedShape) : TraversedShape() + + data class Object(override val shape: Shape?) : TraversedShape() + + data class Bool(override val shape: Shape?) : TraversedShape() + + data class Enum(override val shape: Shape?) : TraversedShape() + + data class Number(override val shape: Shape?) : TraversedShape() + + data class String(override val shape: Shape?) : TraversedShape() + + companion object { + fun from( + model: Model, + shape: Shape, + ): TraversedShape = + when { + shape is MapShape || shape is StructureShape -> Object(shape) + shape is CollectionShape -> Array(shape, from(model, model.expectShape(shape.member.target))) + shape is BooleanShape -> Bool(shape) + shape is EnumShape || shape.hasTrait() -> Enum(shape) + shape is NumberShape -> Number(shape) + shape is StringShape -> String(shape) + else -> TODO() + } + } +} + +/** + * Contains information about the output of a visited [JmespathExpression]. + */ +data class GeneratedExpression( + /** The name of the identifier that this expression's evaluation is placed into */ + val identifier: String, + /** The TraversedShape for the output of the expression evaluation. */ + val outputShape: TraversedShape, + /** + * The Rust type for the evaluated expression. + * + * For the most part, the code generator operates on output types rather than output shapes + * since there will always be an output type, whereas there will only sometimes be an output + * shape. Output shapes are only really used for handling enums and projections. + */ + val outputType: RustType, + /** Writable to output this expression's generated code. */ + val output: Writable, +) { + internal fun isArray(): Boolean = outputShape is TraversedShape.Array + + internal fun isBool(): Boolean = outputShape is TraversedShape.Bool + + internal fun isEnum(): Boolean = outputShape is TraversedShape.Enum + + internal fun isNumber(): Boolean = outputShape is TraversedShape.Number + + internal fun isString(): Boolean = outputShape is TraversedShape.String + + internal fun isStringOrEnum(): Boolean = isString() || isEnum() + + /** Dereferences this expression if it is a reference. */ + internal fun dereference(namer: SafeNamer): GeneratedExpression = + if (outputType is RustType.Reference) { + namer.safeName("_tmp").let { tmp -> + copy( + identifier = tmp, + outputType = outputType.member, + output = + output + + writable { + rust("let $tmp = *$identifier;") + }, + ) + } + } else { + this + } + + /** Converts this expression into a &str. */ + internal fun convertToStrRef(namer: SafeNamer): GeneratedExpression = + if (outputType.isDoubleReference()) { + dereference(namer).convertToStrRef(namer) + } else if (isEnum()) { + namer.safeName("_tmp").let { tmp -> + GeneratedExpression( + identifier = tmp, + outputType = RustType.Reference(null, RustType.Opaque("str")), + outputShape = TraversedShape.String(null), + output = + output + + writable { + rust("let $tmp = $identifier.as_str();") + }, + ).convertToStrRef(namer) + } + } else if (!outputType.isString()) { + namer.safeName("_tmp").let { tmp -> + GeneratedExpression( + identifier = tmp, + outputType = RustType.String, + outputShape = TraversedShape.String(null), + output = + output + + writable { + rust("let $tmp = $identifier.to_string();") + }, + ).convertToStrRef(namer) + } + } else if (!outputType.isStr()) { + namer.safeName("_tmp").let { tmp -> + GeneratedExpression( + identifier = tmp, + outputType = RustType.Reference(null, RustType.Opaque("str")), + outputShape = TraversedShape.String(null), + output = + output + + writable { + rust("let $tmp = $identifier.as_str();") + }, + ).convertToStrRef(namer) + } + } else { + this + } + + /** Converts a number expression into a specific number type */ + internal fun convertToNumberPrimitive( + namer: SafeNamer, + desiredPrimitive: RustType, + ): GeneratedExpression { + check(isNumber() && desiredPrimitive.isNumber()) { + "this function only works on number types" + } + + return when { + desiredPrimitive is RustType.Reference -> convertToNumberPrimitive(namer, desiredPrimitive.member) + outputType is RustType.Reference -> dereference(namer).convertToNumberPrimitive(namer, desiredPrimitive) + outputType != desiredPrimitive -> + namer.safeName("_tmp").let { tmp -> + GeneratedExpression( + identifier = tmp, + outputType = desiredPrimitive, + outputShape = this.outputShape, + output = + output + + writable { + rust("let $tmp = $identifier as ${desiredPrimitive.render()};") + }, + ) + } + + else -> this + } + } +} + +/** + * Identifier binding for JmesPath expressions. + */ +sealed class TraversalBinding { + /** The name of this binding in the generated Rust code */ + abstract val rustName: String + + /** The Smithy shape behind this binding */ + abstract val shape: TraversedShape + + /** Binds the given shape to the global namespace such that all its members are globally available */ + data class Global( + override val rustName: String, + override val shape: TraversedShape, + ) : TraversalBinding() + + /** Binds a shape to a name */ + data class Named( + /** What this binding is referred to in JmesPath expressions */ + val jmespathName: String, + override val rustName: String, + override val shape: TraversedShape, + ) : TraversalBinding() +} + +typealias TraversalBindings = List + +/** + * Indicates a feature that's part of the JmesPath spec, but that we explicitly decided + * not to support in smithy-rs due to the complexity of code generating it for Rust. + */ +class UnsupportedJmesPathException(msg: String?, what: Throwable? = null) : RuntimeException(msg, what) + +/** Code can't be generated for the combination of the Smithy shape and the JmesPath expression. */ +class InvalidJmesPathTraversalException(msg: String?, what: Throwable? = null) : RuntimeException(msg, what) + +/** This indicates a bug in the code generator itself that should be fixed. */ +class JmesPathTraversalCodegenBugException(msg: String?, what: Throwable? = null) : RuntimeException(msg, what) + +/** + * Generates code from a JmesPath expression to traverse generated Smithy shapes. + * + * This generator implements a subset of the JmesPath spec since the full spec has more features + * than are needed for real-world Smithy waiters, and some of those features are very complex + * to code generate for Rust. + * + * Specifically, the following Jmespath features are supported: + * - Fields + * - Sub-expressions + * - Comparisons + * - Filter projections + * - Object projections + * - Multi-select lists (but only when every item in the list is the exact same type) + * - And/or/not boolean operations + * - Functions `contains` and `length`. The `keys` function may be supported in the future. + */ +class RustJmespathShapeTraversalGenerator( + codegenContext: ClientCodegenContext, +) { + private val model = codegenContext.model + private val symbolProvider = codegenContext.symbolProvider + private val safeNamer = SafeNamer() + + fun generate( + expr: JmespathExpression, + bindings: TraversalBindings, + ): GeneratedExpression { + fun String.attachExpression() = + this.substringBefore("\nExpression:") + "\nExpression: ${ExpressionSerializer().serialize(expr)}" + try { + val result = + when (expr) { + is ComparatorExpression -> generateComparator(expr, bindings) + is FunctionExpression -> generateFunction(expr, bindings) + is FieldExpression -> generateField(expr, bindings) + is LiteralExpression -> generateLiteral(expr) + is MultiSelectListExpression -> generateMultiSelectList(expr, bindings) + is AndExpression -> generateAnd(expr, bindings) + is OrExpression -> generateOr(expr, bindings) + is NotExpression -> generateNot(expr, bindings) + is ObjectProjectionExpression -> generateObjectProjection(expr, bindings) + is FilterProjectionExpression -> generateFilterProjection(expr, bindings) + is ProjectionExpression -> generateProjection(expr, bindings) + is Subexpression -> generateSubexpression(expr, bindings) + is CurrentExpression -> throw JmesPathTraversalCodegenBugException("current expression must be handled in each expression type that can have one") + is ExpressionTypeExpression -> throw UnsupportedJmesPathException("Expression type expressions are not supported by smithy-rs") + is IndexExpression -> throw UnsupportedJmesPathException("Index expressions are not supported by smithy-rs") + is MultiSelectHashExpression -> throw UnsupportedJmesPathException("Multi-select hash expressions are not supported by smithy-rs") + is SliceExpression -> throw UnsupportedJmesPathException("Slice expressions are not supported by smithy-rs") + else -> throw UnsupportedJmesPathException("${expr.javaClass.name} expression type not supported by smithy-rs") + } + return result.copy( + output = + writable { + result.output(this) + if (debugMode) { + rust("// ${result.identifier} = ${ExpressionSerializer().serialize(expr)}") + } + }, + ) + } catch (ex: UnsupportedJmesPathException) { + throw UnsupportedJmesPathException(ex.message?.attachExpression(), ex) + } catch (ex: InvalidJmesPathTraversalException) { + throw InvalidJmesPathTraversalException(ex.message?.attachExpression(), ex) + } catch (ex: Exception) { + throw JmesPathTraversalCodegenBugException(ex.message?.attachExpression(), ex) + } + } + + private fun generateComparator( + expr: ComparatorExpression, + bindings: TraversalBindings, + ): GeneratedExpression { + val left = generate(expr.left, bindings) + val right = generate(expr.right, bindings) + return generateCompare(safeNamer, left, right, expr.comparator.toString()) + } + + private fun generateFunction( + expr: FunctionExpression, + bindings: TraversalBindings, + ): GeneratedExpression { + val ident = safeNamer.safeName("_ret") + return when (expr.name) { + "length" -> { + if (expr.arguments.size != 1) { + throw InvalidJmesPathTraversalException("Length function takes exactly one argument") + } + val arg = generate(expr.arguments[0], bindings) + if (!arg.isArray() && !arg.isString()) { + throw InvalidJmesPathTraversalException("Argument to `length` function must be a collection or string type") + } + GeneratedExpression( + identifier = ident, + outputType = RustType.Integer(64), + outputShape = TraversedShape.Number(null), + output = + writable { + arg.output(this) + rust("let $ident = ${arg.identifier}.len() as i64;") + }, + ) + } + + "contains" -> { + if (expr.arguments.size != 2) { + throw InvalidJmesPathTraversalException("Contains function takes exactly two arguments") + } + val left = generate(expr.arguments[0], bindings) + if (!left.isArray() && !left.isString()) { + throw InvalidJmesPathTraversalException("First argument to `contains` function must be a collection or string type") + } + if (expr.arguments[1].isLiteralNull()) { + throw UnsupportedJmesPathException("Checking for null with `contains` is not supported in smithy-rs") + } + val right = generate(expr.arguments[1], bindings) + if (!right.isBool() && !right.isNumber() && !right.isString() && !right.isEnum()) { + throw UnsupportedJmesPathException("Checking for anything other than booleans, numbers, strings, or enums in the `contains` function is not supported in smithy-rs") + } + if (left.isString()) { + return GeneratedExpression( + identifier = ident, + outputType = RustType.Bool, + outputShape = TraversedShape.Bool(null), + output = + left.output + + writable { + val rightStr = right.convertToStrRef(safeNamer).also { it.output(this) } + rust("let $ident = ${left.identifier}.contains(${rightStr.identifier});") + }, + ) + } else { + return GeneratedExpression( + identifier = ident, + outputType = RustType.Bool, + outputShape = TraversedShape.Bool(null), + output = + left.output + right.output + + writable { + withBlockTemplate("let $ident = ${left.identifier}.iter().any(|_v| {", "});") { + val compare = + generateCompare( + safeNamer, + GeneratedExpression( + identifier = "_v", + outputShape = (left.outputShape as TraversedShape.Array).member, + outputType = + RustType.Reference( + lifetime = null, + member = left.outputType.collectionValue(), + ), + output = writable {}, + ), + // Clear the output since we already wrote the right and don't want to duplicate it + right.copy(output = writable {}), + "==", + ).also { it.output(this) } + + rust(compare.identifier) + } + }, + ) + } + } + + else -> throw UnsupportedJmesPathException("The `${expr.name}` function is not supported by smithy-rs") + } + } + + private fun generateField( + expr: FieldExpression, + bindings: TraversalBindings, + ): GeneratedExpression { + val globalBinding = bindings.find { it is TraversalBinding.Global } + val namedBinding = bindings.find { it is TraversalBinding.Named && it.jmespathName == expr.name } + if (namedBinding != null && namedBinding.shape is TraversedShape.Object) { + // If there's a named binding that matches, then immediately return it + return GeneratedExpression( + identifier = namedBinding.rustName, + outputShape = namedBinding.shape, + outputType = symbolProvider.toSymbol(namedBinding.shape.shape!!).rustType().asRef(), + output = writable { }, + ) + } else if (globalBinding != null && globalBinding.shape is TraversedShape.Object) { + // Otherwise, look in the global binding (if available) + val member = + globalBinding.shape.shape?.getMember(expr.name)?.orNull() + ?: throw InvalidJmesPathTraversalException("Member `${expr.name}` doesn't exist on ${globalBinding.shape.shape?.id}") + val memberSym = symbolProvider.toSymbol(member) + + val target = model.expectShape(member.target) + val targetSym = symbolProvider.toSymbol(target) + + val ident = safeNamer.safeName("_fld") + return GeneratedExpression( + identifier = ident, + outputShape = TraversedShape.from(model, target), + outputType = targetSym.rustType().asRef(), + output = + writable { + rust( + if (memberSym.isOptional()) { + "let $ident = ${globalBinding.rustName}.${memberSym.name}.as_ref()?;" + } else { + "let $ident = &${globalBinding.rustName}.${memberSym.name};" + }, + ) + }, + ) + } else if (namedBinding != null || globalBinding != null) { + throw InvalidJmesPathTraversalException("Cannot look up fields in non-struct shapes") + } else { + throw JmesPathTraversalCodegenBugException("Missing jmespath traversal binding for ${expr.name}; available bindings: $bindings") + } + } + + private fun generateLiteral(expr: LiteralExpression): GeneratedExpression { + val (outputShape, outputType) = + when (expr.value) { + is Boolean -> TraversedShape.Bool(null) to RustType.Reference(lifetime = null, member = RustType.Bool) + is Double -> + TraversedShape.Number(null) to + RustType.Reference( + lifetime = null, + member = RustType.Float(64), + ) + + is String -> + TraversedShape.String(null) to + RustType.Reference( + lifetime = null, + member = RustType.Opaque("str"), + ) + + null -> throw UnsupportedJmesPathException("Literal nulls are not supported by smithy-rs") + else -> throw UnsupportedJmesPathException("Literal expression '${ExpressionSerializer().serialize(expr)}' is not supported by smithy-rs") + } + + fun fmtFloating(floating: Number) = + NumberFormat.getInstance().apply { minimumFractionDigits = 1 }.format(floating) + + return safeNamer.safeName("_lit").uppercase().let { ident -> + GeneratedExpression( + identifier = ident, + outputType = outputType, + outputShape = outputShape, + output = + writable { + when (val value = expr.value) { + is Boolean -> rust("const $ident: &bool = &$value;") + is Double -> { + rust("const $ident: #T = &${fmtFloating(value)};", outputType) + } + + is String -> rust("const $ident: &str = ${value.dq()};") + else -> throw RuntimeException("unreachable") + } + }, + ) + } + } + + private fun generateMultiSelectList( + expr: MultiSelectListExpression, + bindings: TraversalBindings, + ): GeneratedExpression { + val expressions = + expr.expressions.map { subexpr -> + generate(subexpr, bindings) + } + // If we wanted to support mixed-types, we would need to use tuples, add tuple support to RustType, + // and update supported functions such as `contains` to operate on tuples. + for (pair in expressions.map { it.outputType }.windowed(2)) { + if (pair[0] != pair[1]) { + throw UnsupportedJmesPathException("Mixed-type multi-select lists are not supported by smithy-rs") + } + } + + return safeNamer.safeName("_msl").let { ident -> + GeneratedExpression( + identifier = ident, + outputType = RustType.Vec(expressions[0].outputType), + outputShape = TraversedShape.Array(null, expressions[0].outputShape), + output = + writable { + expressions.forEach { it.output(this) } + rust("let $ident = vec![${expressions.map { it.identifier }.joinToString(", ")}];") + }, + ) + } + } + + private fun generateAnd( + expr: AndExpression, + bindings: TraversalBindings, + ): GeneratedExpression = generateBooleanOp(expr, "&&", bindings) + + private fun generateOr( + expr: OrExpression, + bindings: TraversalBindings, + ): GeneratedExpression = generateBooleanOp(expr, "||", bindings) + + private fun generateBooleanOp( + expr: BinaryExpression, + op: String, + bindings: TraversalBindings, + ): GeneratedExpression { + val left = generate(expr.left, bindings) + val right = generate(expr.right, bindings) + if (!left.isBool() || !right.isBool()) { + throw UnsupportedJmesPathException("Applying the `$op` operation doesn't support non-boolean types in smithy-rs") + } + + return safeNamer.safeName("_bo").let { ident -> + GeneratedExpression( + identifier = ident, + outputType = RustType.Bool, + outputShape = TraversedShape.Bool(null), + output = + writable { + val leftBool = left.dereference(safeNamer).also { it.output(this) } + val rightBool = right.dereference(safeNamer).also { it.output(this) } + rust("let $ident = ${leftBool.identifier} $op ${rightBool.identifier};") + }, + ) + } + } + + private fun generateNot( + expr: NotExpression, + bindings: TraversalBindings, + ): GeneratedExpression { + val inner = generate(expr.expression, bindings) + if (!inner.isBool()) { + throw UnsupportedJmesPathException("Negation of a non-boolean type is not supported by smithy-rs") + } + + return safeNamer.safeName("_not").let { ident -> + GeneratedExpression( + identifier = ident, + outputType = RustType.Bool, + outputShape = TraversedShape.Bool(null), + output = + inner.output + + writable { + rust("let $ident = !${inner.identifier};") + }, + ) + } + } + + private fun generateProjection( + expr: ProjectionExpression, + bindings: TraversalBindings, + ): GeneratedExpression { + val maybeFlatten = expr.left + if (maybeFlatten is SliceExpression) { + throw UnsupportedJmesPathException("Slice expressions are not supported by smithy-rs") + } + if (maybeFlatten !is FlattenExpression) { + throw UnsupportedJmesPathException("Only projection expressions with flattens are supported by smithy-rs") + } + val left = generate(maybeFlatten.expression, bindings) + val leftTarget = + ( + left.outputShape as? TraversedShape.Array + ?: throw InvalidJmesPathTraversalException("Left side of the flatten projection MUST resolve to a list or set shape") + ).member + val leftTargetSym: Any = (leftTarget.shape?.let { symbolProvider.toSymbol(it) }) ?: left.outputType + + // Short-circuit in the case where the projection is unnecessary + if (left.isArray() && expr.right is CurrentExpression) { + return left + } + + val right = generate(expr.right, listOf(TraversalBinding.Global("v", leftTarget))) + + // If the right expression results in a collection type, then the resulting vec will need to get flattened. + // Otherwise, you'll get `Vec<&Vec>` instead of `Vec<&T>`, which causes later projections to fail to compile. + val (projectionType, flattenNeeded) = + when { + right.isArray() -> right.outputType.stripOuter() to true + else -> RustType.Vec(right.outputType.asRef()) to false + } + + return safeNamer.safeName("_prj").let { ident -> + GeneratedExpression( + identifier = ident, + outputShape = right.outputShape, + outputType = projectionType, + output = + left.output + + writable { + rust("let $ident = ${left.identifier}.iter()") + withBlock(".flat_map(|v| {", "})") { + rustBlockTemplate( + "fn map(v: &#{Left}) -> #{Option}<#{Right}>", + *preludeScope, + "Left" to leftTargetSym, + "Right" to right.outputType, + ) { + right.output(this) + rustTemplate("#{Some}(${right.identifier})", *preludeScope) + } + rust("map(v)") + } + if (flattenNeeded) { + rust(".flatten()") + } + rustTemplate(".collect::<#{Vec}<_>>();", *preludeScope) + }, + ) + } + } + + private fun generateFilterProjection( + expr: FilterProjectionExpression, + bindings: TraversalBindings, + ): GeneratedExpression { + val left = generate(expr.left, bindings) + if (!left.isArray()) { + throw UnsupportedJmesPathException("Filter projections can only be done on lists or sets in smithy-rs") + } + + val leftTarget = (left.outputShape as TraversedShape.Array).member + val leftTargetSym = symbolProvider.toSymbol(leftTarget.shape) + + val right = + if (expr.right is CurrentExpression) { + left.copy( + outputType = left.outputType.collectionValue().asRef(), + output = writable {}, + ) + } else { + generate(expr.right, listOf(TraversalBinding.Global("_v", leftTarget))) + } + + val comparison = generate(expr.comparison, listOf(TraversalBinding.Global("_v", leftTarget))) + if (!comparison.isBool()) { + throw InvalidJmesPathTraversalException("The filter expression comparison must result in a boolean") + } + + return safeNamer.safeName("_fprj").let { ident -> + GeneratedExpression( + identifier = ident, + outputShape = TraversedShape.Array(null, right.outputShape), + outputType = RustType.Vec(right.outputType), + output = + left.output + + writable { + rust("let $ident = ${left.identifier}.iter()") + withBlock(".filter({", "})") { + rustBlockTemplate( + "fn filter(_v: &#{Arg}) -> #{Option}", + "Arg" to leftTargetSym, + *preludeScope, + ) { + val toBool = comparison.dereference(safeNamer).also { it.output(this) } + rustTemplate("#{Some}(${toBool.identifier})", *preludeScope) + } + rust("|v| filter(v).unwrap_or_default()") + } + if (expr.right !is CurrentExpression) { + withBlock(".flat_map({", "})") { + rustBlockTemplate( + "fn map(_v: &#{Left}) -> #{Option}<#{Right}>", + *preludeScope, + "Left" to leftTargetSym, + "Right" to right.outputType, + ) { + right.output(this) + rustTemplate("#{Some}(${right.identifier})", *preludeScope) + } + rust("map") + } + } + rustTemplate(".collect::<#{Vec}<_>>();", *preludeScope) + }, + ) + } + } + + private fun generateObjectProjection( + expr: ObjectProjectionExpression, + bindings: TraversalBindings, + ): GeneratedExpression { + if (expr.left is CurrentExpression) { + throw UnsupportedJmesPathException("Object projection cannot be done on computed maps in smithy-rs") + } + val left = generate(expr.left, bindings) + if (!left.outputType.isMap()) { + throw UnsupportedJmesPathException("Object projection is only supported on map types in smithy-rs") + } + if (left.outputShape.shape == null) { + throw UnsupportedJmesPathException("Object projection cannot be done on computed maps in smithy-rs") + } + + val leftTarget = model.expectShape((left.outputShape.shape as MapShape).value.target) + val leftTargetSym = symbolProvider.toSymbol(leftTarget) + + val right = + if (expr.right is CurrentExpression) { + left.copy( + outputType = left.outputType.collectionValue().asRef(), + output = writable {}, + ) + } else { + generate(expr.right, listOf(TraversalBinding.Global("_v", TraversedShape.from(model, leftTarget)))) + } + + val ident = safeNamer.safeName("_oprj") + return GeneratedExpression( + identifier = ident, + outputShape = TraversedShape.Array(null, right.outputShape), + outputType = RustType.Vec(right.outputType), + output = + left.output + + writable { + if (expr.right is CurrentExpression) { + rustTemplate("let $ident = ${left.identifier}.values().collect::<#{Vec}<_>>();", *preludeScope) + } else { + rustBlock("let $ident = ${left.identifier}.values().flat_map(") { + rustBlockTemplate( + "fn map(_v: &#{Left}) -> #{Option}<#{Right}>", + *preludeScope, + "Left" to leftTargetSym, + "Right" to right.outputType, + ) { + right.output(this) + rustTemplate("#{Some}(${right.identifier})", *preludeScope) + } + rust("map") + } + rustTemplate(").collect::<#{Vec}<_>>();", *preludeScope) + } + }, + ) + } + + private fun generateSubexpression( + expr: Subexpression, + bindings: TraversalBindings, + ): GeneratedExpression { + val left = generate(expr.left, bindings) + val right = generate(expr.right, listOf(TraversalBinding.Global(left.identifier, left.outputShape))) + return GeneratedExpression( + identifier = right.identifier, + outputShape = right.outputShape, + outputType = right.outputType, + output = left.output + right.output, + ) + } +} + +internal fun generateCompare( + safeNamer: SafeNamer, + left: GeneratedExpression, + right: GeneratedExpression, + op: String, +): GeneratedExpression = + if (left.outputType.isDoubleReference()) { + generateCompare(safeNamer, left.dereference(safeNamer), right, op) + } else if (right.outputType.isDoubleReference()) { + generateCompare(safeNamer, left, right.dereference(safeNamer), op) + } else { + safeNamer.safeName("_cmp").let { ident -> + return GeneratedExpression( + identifier = ident, + outputType = RustType.Bool, + outputShape = TraversedShape.Bool(null), + output = + if (left.isStringOrEnum() && right.isStringOrEnum()) { + writable { + val leftStr = left.convertToStrRef(safeNamer).also { it.output(this) } + val rightStr = right.convertToStrRef(safeNamer).also { it.output(this) } + rust("let $ident = ${leftStr.identifier} $op ${rightStr.identifier};") + } + } else if (left.isNumber() && right.isNumber()) { + writable { + val leftPrim = + left.convertToNumberPrimitive(safeNamer, left.outputType).also { it.output(this) } + val rightPrim = + right.convertToNumberPrimitive(safeNamer, left.outputType).also { it.output(this) } + rust("let $ident = ${leftPrim.identifier} $op ${rightPrim.identifier};") + } + } else if (left.isBool() && right.isBool()) { + writable { + val leftPrim = left.dereference(safeNamer).also { it.output(this) } + val rightPrim = right.dereference(safeNamer).also { it.output(this) } + rust("let $ident = ${leftPrim.identifier} $op ${rightPrim.identifier};") + } + } else { + throw UnsupportedJmesPathException("Comparison of ${left.outputType.render()} with ${right.outputType.render()} is not supported by smithy-rs") + }, + ) + } + } + +private fun RustType.dereference(): RustType = + if (this is RustType.Reference) { + this.member.dereference() + } else { + this + } + +private fun RustType.isMap(): Boolean = this.dereference() is RustType.HashMap + +private fun RustType.isString(): Boolean = this.dereference().let { it is RustType.String || it.isStr() } + +private fun RustType.isStr(): Boolean = this.dereference().let { it is RustType.Opaque && it.name == "str" } + +private fun RustType.isNumber(): Boolean = this.dereference().let { it is RustType.Integer || it is RustType.Float } + +private fun RustType.isDoubleReference(): Boolean = this is RustType.Reference && this.member is RustType.Reference + +private fun RustType.collectionValue(): RustType = + when (this) { + is RustType.Reference -> member.collectionValue() + is RustType.Vec -> member + is RustType.HashSet -> member + is RustType.HashMap -> member + else -> throw RuntimeException("expected collection type") + } + +private fun JmespathExpression.isLiteralNull(): Boolean = this == LiteralExpression.NULL diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/waiters/RustWaiterMatcherGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/waiters/RustWaiterMatcherGenerator.kt new file mode 100644 index 0000000000..23123eb6dc --- /dev/null +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/waiters/RustWaiterMatcherGenerator.kt @@ -0,0 +1,277 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package software.amazon.smithy.rust.codegen.client.smithy.generators.waiters + +import software.amazon.smithy.codegen.core.CodegenException +import software.amazon.smithy.codegen.core.Symbol +import software.amazon.smithy.jmespath.JmespathExpression +import software.amazon.smithy.model.node.Node +import software.amazon.smithy.model.shapes.Shape +import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext +import software.amazon.smithy.rust.codegen.client.smithy.ClientRustModule +import software.amazon.smithy.rust.codegen.core.rustlang.Attribute +import software.amazon.smithy.rust.codegen.core.rustlang.RustModule +import software.amazon.smithy.rust.codegen.core.rustlang.RustType +import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter +import software.amazon.smithy.rust.codegen.core.rustlang.SafeNamer +import software.amazon.smithy.rust.codegen.core.rustlang.docs +import software.amazon.smithy.rust.codegen.core.rustlang.replaceLifetimes +import software.amazon.smithy.rust.codegen.core.rustlang.rust +import software.amazon.smithy.rust.codegen.core.rustlang.rustBlockTemplate +import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate +import software.amazon.smithy.rust.codegen.core.rustlang.writable +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope +import software.amazon.smithy.rust.codegen.core.util.dq +import software.amazon.smithy.rust.codegen.core.util.toSnakeCase +import software.amazon.smithy.waiters.Matcher +import software.amazon.smithy.waiters.Matcher.ErrorTypeMember +import software.amazon.smithy.waiters.Matcher.InputOutputMember +import software.amazon.smithy.waiters.Matcher.OutputMember +import software.amazon.smithy.waiters.Matcher.SuccessMember +import software.amazon.smithy.waiters.PathComparator +import java.security.MessageDigest + +private typealias Scope = Array> + +/** True if the waiter matcher requires the operation input in its implementation */ +fun Matcher<*>.requiresInput(): Boolean = this is InputOutputMember + +/** + * Generates the Rust code for the Smithy waiter "matcher union". + * See https://smithy.io/2.0/additional-specs/waiters.html#matcher-union + */ +class RustWaiterMatcherGenerator( + private val codegenContext: ClientCodegenContext, + private val operationName: String, + private val inputShape: Shape, + private val outputShape: Shape, +) { + private val model = codegenContext.model + private val runtimeConfig = codegenContext.runtimeConfig + private val module = + RustModule.pubCrate( + "matchers", + ClientRustModule.waiters, + additionalAttributes = + listOf( + Attribute.AllowClippyNeedlessLifetimes, + Attribute.AllowClippyLetAndReturn, + ), + ) + private val inputSymbol = codegenContext.symbolProvider.toSymbol(inputShape) + private val outputSymbol = codegenContext.symbolProvider.toSymbol(outputShape) + + fun generate( + errorSymbol: Symbol, + matcher: Matcher<*>, + ): RuntimeType { + val fnName = fnName(operationName, matcher) + val scope = + arrayOf( + *preludeScope, + "Input" to inputSymbol, + "Output" to outputSymbol, + "Error" to errorSymbol, + "ProvideErrorMetadata" to RuntimeType.provideErrorMetadataTrait(runtimeConfig), + ) + return RuntimeType.forInlineFun(fnName, module) { + val inputArg = + when { + matcher.requiresInput() -> "_input: &#{Input}, " + else -> "" + } + docs("Matcher union: " + Node.printJson(matcher.toNode())) + rustBlockTemplate( + "pub(crate) fn $fnName(${inputArg}_result: #{Result}<&#{Output}, &#{Error}>) -> bool", + *scope, + ) { + when (matcher) { + is OutputMember -> generateOutputMember(outputShape, matcher, scope) + is InputOutputMember -> generateInputOutputMember(matcher, scope) + is SuccessMember -> generateSuccessMember(matcher) + is ErrorTypeMember -> generateErrorTypeMember(matcher, scope) + else -> throw CodegenException("Unknown waiter matcher type: $matcher") + } + } + } + } + + private fun RustWriter.generateOutputMember( + outputShape: Shape, + matcher: OutputMember, + scope: Scope, + ) { + val pathExpression = JmespathExpression.parse(matcher.value.path) + val pathTraversal = + RustJmespathShapeTraversalGenerator(codegenContext).generate( + pathExpression, + listOf(TraversalBinding.Global("_output", TraversedShape.from(model, outputShape))), + ) + + generatePathTraversalMatcher( + pathTraversal, + matcher.value.expected, + matcher.value.comparator, + scope, + matcher.requiresInput(), + ) + } + + private fun RustWriter.generateInputOutputMember( + matcher: InputOutputMember, + scope: Scope, + ) { + val pathExpression = JmespathExpression.parse(matcher.value.path) + val pathTraversal = + RustJmespathShapeTraversalGenerator(codegenContext).generate( + pathExpression, + listOf( + TraversalBinding.Named("input", "_input", TraversedShape.from(model, inputShape)), + TraversalBinding.Named("output", "_output", TraversedShape.from(model, outputShape)), + ), + ) + + generatePathTraversalMatcher( + pathTraversal, + matcher.value.expected, + matcher.value.comparator, + scope, + matcher.requiresInput(), + ) + } + + private fun RustWriter.generatePathTraversalMatcher( + pathTraversal: GeneratedExpression, + expected: String, + comparatorKind: PathComparator, + scope: Scope, + requiresInput: Boolean, + ) { + val comparator = + writable { + val leftIsIterString = + listOf(PathComparator.ALL_STRING_EQUALS, PathComparator.ANY_STRING_EQUALS).contains(comparatorKind) + val left = + GeneratedExpression( + identifier = "value", + outputType = + when { + leftIsIterString -> RustType.Reference(null, RustType.String) + else -> pathTraversal.outputType + }, + outputShape = + when { + leftIsIterString -> (pathTraversal.outputShape as? TraversedShape.Array)?.member ?: pathTraversal.outputShape + else -> pathTraversal.outputShape + }, + output = writable {}, + ) + val rightIsString = PathComparator.BOOLEAN_EQUALS != comparatorKind + val right = + GeneratedExpression( + identifier = "right", + outputType = + when { + rightIsString -> RustType.Reference(null, RustType.Opaque("str")) + else -> RustType.Bool + }, + outputShape = + when { + rightIsString -> TraversedShape.String(null) + else -> TraversedShape.Bool(null) + }, + output = + writable { + rust( + "let right = " + + when { + rightIsString -> expected.dq() + else -> expected + } + ";", + ) + }, + ) + rustTemplate( + when (comparatorKind) { + PathComparator.ALL_STRING_EQUALS -> "!value.is_empty() && value.iter().all(|value| { #{comparison} })" + PathComparator.ANY_STRING_EQUALS -> "value.iter().any(|value| { #{comparison} })" + PathComparator.STRING_EQUALS -> "#{comparison}" + PathComparator.BOOLEAN_EQUALS -> "#{comparison}" + else -> throw CodegenException("Unknown path matcher comparator: $comparatorKind") + }, + "comparison" to + writable { + val compare = generateCompare(SafeNamer(), left, right, "==") + compare.output(this) + rust(compare.identifier) + }, + ) + } + + val (inputArgDecl, inputArg) = + when { + requiresInput -> "_input: &'a #{Input}, " to "_input, " + else -> "" to "" + } + rustTemplate( + """ + fn path_traversal<'a>(${inputArgDecl}_output: &'a #{Output}) -> #{Option}<#{TraversalOutput}> { + #{traversal} + #{Some}(${pathTraversal.identifier}) + } + _result.as_ref() + .ok() + .and_then(|output| path_traversal(${inputArg}output)) + .map(|value| { #{comparator} }) + .unwrap_or_default() + """, + *scope, + "traversal" to pathTraversal.output, + "TraversalOutput" to pathTraversal.outputType.replaceLifetimes("a"), + "comparator" to comparator, + ) + } + + private fun RustWriter.generateSuccessMember(matcher: SuccessMember) { + rust( + if (matcher.value) { + "_result.is_ok()" + } else { + "_result.is_err()" + }, + ) + } + + private fun RustWriter.generateErrorTypeMember( + matcher: ErrorTypeMember, + scope: Scope, + ) { + rustTemplate( + """ + if let #{Err}(err) = _result { + if let #{Some}(code) = #{ProvideErrorMetadata}::code(err) { + return code == ${matcher.value.dq()}; + } + } + false + """, + *scope, + ) + } + + private fun fnName( + operationName: String, + matcher: Matcher<*>, + ): String { + // Smithy models don't give us anything useful to name these functions with, so just + // SHA-256 hash the matcher JSON and truncate it to a reasonable length. This will have + // a nice side-effect of de-duplicating identical matchers within a given operation. + val jsonValue = Node.printJson(matcher.toNode()) + val bytes = MessageDigest.getInstance("SHA-256").digest(jsonValue.toByteArray()) + val hex = bytes.map { byte -> String.format("%02x", byte) }.joinToString("") + return "match_${operationName.toSnakeCase()}_${hex.substring(0..16)}" + } +} diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/waiters/WaitableGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/waiters/WaitableGenerator.kt new file mode 100644 index 0000000000..00c715b56b --- /dev/null +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/waiters/WaitableGenerator.kt @@ -0,0 +1,265 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.rust.codegen.client.smithy.generators.waiters + +import software.amazon.smithy.model.shapes.OperationShape +import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext +import software.amazon.smithy.rust.codegen.client.smithy.ClientRustModule +import software.amazon.smithy.rust.codegen.client.smithy.generators.client.FluentBuilderConfig +import software.amazon.smithy.rust.codegen.client.smithy.generators.client.FluentBuilderGenerator +import software.amazon.smithy.rust.codegen.core.rustlang.EscapeFor +import software.amazon.smithy.rust.codegen.core.rustlang.RustModule +import software.amazon.smithy.rust.codegen.core.rustlang.RustReservedWords +import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter +import software.amazon.smithy.rust.codegen.core.rustlang.Writable +import software.amazon.smithy.rust.codegen.core.rustlang.docs +import software.amazon.smithy.rust.codegen.core.rustlang.rust +import software.amazon.smithy.rust.codegen.core.rustlang.rustBlockTemplate +import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate +import software.amazon.smithy.rust.codegen.core.rustlang.writable +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope +import software.amazon.smithy.rust.codegen.core.smithy.RustCrate +import software.amazon.smithy.rust.codegen.core.util.getTrait +import software.amazon.smithy.rust.codegen.core.util.orNull +import software.amazon.smithy.rust.codegen.core.util.outputShape +import software.amazon.smithy.rust.codegen.core.util.toPascalCase +import software.amazon.smithy.rust.codegen.core.util.toSnakeCase +import software.amazon.smithy.waiters.WaitableTrait +import software.amazon.smithy.waiters.Waiter + +/** + * Generates waiters for the Smithy @waitable trait. + * + * This will place waiter-specific fluent builders into individual waiter submodules of the `crate::waiter` module, + * and place a `Waiters` trait in the client module that can be imported to initiate waiters. + */ +class WaitableGenerator( + private val codegenContext: ClientCodegenContext, + allOperations: List, +) { + private data class WaitableOp( + val shape: OperationShape, + val waiters: List, + ) + + private data class WaiterSpec( + val waiterName: String, + val waiter: Waiter, + val fluentBuilder: RuntimeType, + ) + + private val operations = + allOperations.mapNotNull { op -> + op.getTrait()?.let { + WaitableOp( + op, + it.waiters.entries.map { (name, waiter) -> + WaiterSpec( + name, + waiter, + waiterFluentBuilder(name, waiter, op), + ) + }, + ) + } + } + .sortedBy { it.shape.id } + + fun render(crate: RustCrate) { + if (operations.isEmpty()) { + return + } + + crate.withModule(ClientRustModule.client) { + docs( + """ + Waiter functions for the client. + + Import this trait to get `wait_until` methods on the client. + """, + ) + rustBlockTemplate("pub trait Waiters") { + for (op in operations) { + for (spec in op.waiters) { + val waiterDocs = spec.waiter.documentation.orNull() ?: "Wait for `${spec.waiterName.toSnakeCase()}`" + docs(waiterDocs) + renderWaiterFnDeclaration(spec) + rust(";") + } + } + } + + rustBlockTemplate("impl Waiters for Client") { + for (op in operations) { + for (spec in op.waiters) { + renderWaiterFnDeclaration(spec) + rustTemplate( + "{ #{FluentBuilder}::new(self.handle.clone()) }", + "FluentBuilder" to spec.fluentBuilder, + ) + } + } + } + } + } + + private fun RustWriter.renderWaiterFnDeclaration(spec: WaiterSpec) { + val fnName = "wait_until_${spec.waiterName.toSnakeCase()}" + rustTemplate( + "fn $fnName(&self) -> #{FluentBuilder}", + "FluentBuilder" to spec.fluentBuilder, + ) + } + + private fun waiterModule(waiterName: String): RustModule = + RustModule.public( + RustReservedWords.escapeIfNeeded(waiterName.toSnakeCase(), EscapeFor.ModuleName), + ClientRustModule.waiters, + documentationOverride = "Supporting types for the `${waiterName.toSnakeCase()}` waiter.", + ) + + private fun waiterFluentBuilder( + waiterName: String, + waiter: Waiter, + operation: OperationShape, + ): RuntimeType { + val builderName = "${waiterName.toPascalCase()}FluentBuilder" + val waiterModule = waiterModule(waiterName) + return RuntimeType.forInlineFun(builderName, waiterModule) { + FluentBuilderGenerator( + codegenContext, + operation, + builderName = builderName, + config = WaiterFluentBuilderConfig(codegenContext, operation, waiter, waiterName, waiterModule), + ).render(this) + } + } +} + +private class WaiterFluentBuilderConfig( + private val codegenContext: ClientCodegenContext, + private val operation: OperationShape, + private val waiter: Waiter, + private val waiterName: String, + private val waiterModule: RustModule, +) : FluentBuilderConfig { + private val model = codegenContext.model + private val runtimeConfig = codegenContext.runtimeConfig + private val symbolProvider = codegenContext.symbolProvider + + private val scope = + arrayOf( + *preludeScope, + "ConfigBag" to RuntimeType.configBag(runtimeConfig), + "Duration" to RuntimeType.Duration, + "Error" to RuntimeType.smithyRuntimeApi(runtimeConfig).resolve("client::interceptors::context::Error"), + "FinalPoll" to RuntimeType.smithyRuntimeApiClient(runtimeConfig).resolve("client::waiters::FinalPoll"), + "HttpResponse" to + RuntimeType.smithyRuntimeApiClient(runtimeConfig) + .resolve("client::orchestrator::HttpResponse"), + "Operation" to symbolProvider.toSymbol(operation), + "OperationError" to symbolProvider.symbolForOperationError(operation), + "OperationOutput" to symbolProvider.toSymbol(operation.outputShape(model)), + "SdkError" to RuntimeType.sdkError(runtimeConfig), + "WaiterError" to + RuntimeType.smithyRuntimeApiClient(runtimeConfig) + .resolve("client::waiters::error::WaiterError"), + "WaiterOrchestrator" to RuntimeType.smithyRuntime(runtimeConfig).resolve("client::waiters::WaiterOrchestrator"), + "attach_waiter_tracing_span" to RuntimeType.smithyRuntime(runtimeConfig).resolve("client::waiters::attach_waiter_tracing_span"), + ) + + override fun includeConfigOverride(): Boolean = false + + override fun includePaginators(): Boolean = false + + override fun documentBuilder(): Writable = + writable { + docs( + """ + Fluent builder for the `${waiterName.toSnakeCase()}` waiter. + + This builder is intended to be used similar to the other fluent builders for + normal operations on the client. However, instead of a `send` method, it has + a `wait` method that takes a maximum amount of time to wait. + + Construct this fluent builder using the client by importing the + [`Waiters`](crate::client::Waiters) trait and calling the methods + prefixed with `wait_until`. + """, + ) + } + + override fun sendMethods(): Writable = + writable { + val waiterDocs = waiter.documentation.orNull() ?: "Wait for `${waiterName.toSnakeCase()}`" + docs(waiterDocs) + rustTemplate( + """ + pub async fn wait(self, max_wait: #{Duration}) -> #{Result}<#{FinalPollAlias}, #{WaiterErrorAlias}> { + let input = self.inner.build() + .map_err(#{WaiterError}::construction_failure)?; + let runtime_plugins = #{Operation}::operation_runtime_plugins( + self.handle.runtime_plugins.clone(), + &self.handle.conf, + #{None}, + ); + let mut cfg = #{ConfigBag}::base(); + let runtime_components_builder = runtime_plugins.apply_client_configuration(&mut cfg) + .map_err(#{WaiterError}::construction_failure)?; + let time_components = runtime_components_builder.into_time_components(); + let sleep_impl = time_components.sleep_impl().expect("a sleep impl is required by waiters"); + let time_source = time_components.time_source().expect("a time source is required by waiters"); + + #{acceptor} + let operation = move || { + let input = input.clone(); + let runtime_plugins = runtime_plugins.clone(); + async move { + #{Operation}::orchestrate(&runtime_plugins, input).await + } + }; + let orchestrator = #{WaiterOrchestrator}::builder() + .min_delay(#{Duration}::from_secs(${waiter.minDelay})) + .max_delay(#{Duration}::from_secs(${waiter.maxDelay})) + .max_wait(max_wait) + .time_source(time_source) + .sleep_impl(sleep_impl) + .acceptor(acceptor) + .operation(operation) + .build(); + #{attach_waiter_tracing_span}(orchestrator.orchestrate()).await + } + """, + *scope, + "acceptor" to + writable { + WaiterAcceptorGenerator(codegenContext, operation, waiter, "input").render(this) + }, + "FinalPollAlias" to finalPollTypeAlias(), + "WaiterErrorAlias" to waiterErrorTypeAlias(), + ) + } + + private fun finalPollTypeAlias(): RuntimeType = + "${waiterName.toPascalCase()}FinalPoll".let { name -> + RuntimeType.forInlineFun(name, waiterModule) { + docs("Successful return type for the `${waiterName.toSnakeCase()}` waiter.") + rustTemplate( + "pub type $name = #{FinalPoll}<#{OperationOutput}, #{SdkError}<#{OperationError}, #{HttpResponse}>>;", + *scope, + ) + } + } + + private fun waiterErrorTypeAlias(): RuntimeType = + "WaitUntil${waiterName.toPascalCase()}Error".let { name -> + RuntimeType.forInlineFun(name, waiterModule) { + docs("Error type for the `${waiterName.toSnakeCase()}` waiter.") + rustTemplate("pub type $name = #{WaiterError}<#{OperationOutput}, #{OperationError}>;", *scope) + } + } +} diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/waiters/WaiterAcceptorGenerator.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/waiters/WaiterAcceptorGenerator.kt new file mode 100644 index 0000000000..1476061d7e --- /dev/null +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/waiters/WaiterAcceptorGenerator.kt @@ -0,0 +1,97 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package software.amazon.smithy.rust.codegen.client.smithy.generators.waiters + +import software.amazon.smithy.model.node.Node +import software.amazon.smithy.model.shapes.OperationShape +import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext +import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter +import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate +import software.amazon.smithy.rust.codegen.core.rustlang.writable +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope +import software.amazon.smithy.rust.codegen.core.util.inputShape +import software.amazon.smithy.rust.codegen.core.util.outputShape +import software.amazon.smithy.waiters.AcceptorState +import software.amazon.smithy.waiters.Waiter + +class WaiterAcceptorGenerator( + private val codegenContext: ClientCodegenContext, + operation: OperationShape, + private val waiter: Waiter, + private val inputName: String, +) { + private val symbolProvider = codegenContext.symbolProvider + private val runtimeConfig = codegenContext.runtimeConfig + private val model = codegenContext.model + + private val operationName = symbolProvider.toSymbol(operation).name + private val inputShape = operation.inputShape(model) + private val outputShape = operation.outputShape(model) + private val errorType = symbolProvider.symbolForOperationError(operation) + + private val scope = + arrayOf( + *preludeScope, + "AcceptorState" to RuntimeType.smithyRuntime(runtimeConfig).resolve("client::waiters::AcceptorState"), + "Output" to symbolProvider.toSymbol(outputShape), + "Error" to errorType, + ) + + fun render(writer: RustWriter) { + val matchers = + waiter.acceptors.map { acceptor -> + acceptor to + RustWaiterMatcherGenerator(codegenContext, operationName, inputShape, outputShape).generate( + errorType, + acceptor.matcher, + ) + } + + val anyRequiresInput = matchers.any { it.first.matcher.requiresInput() } + val inputPrep = + when { + anyRequiresInput -> "let acceptor_input = $inputName.clone();" + else -> "" + } + writer.rustTemplate( + """ + $inputPrep + let acceptor = move |result: #{Result}<&#{Output}, &#{Error}>| { + #{acceptors} + }; + """, + *scope, + "acceptors" to + writable { + for ((acceptor, matcherFn) in matchers) { + val condition = + when { + acceptor.matcher.requiresInput() -> "#{matcher_fn}(&acceptor_input, result)" + else -> "#{matcher_fn}(result)" + } + val matcherComment = Node.printJson(acceptor.matcher.toNode()) + val acceptorState = "#{AcceptorState}::${acceptor.state.rustName()}" + rustTemplate( + """ + // Matches: $matcherComment + if $condition { return $acceptorState; } + """, + *scope, + "matcher_fn" to matcherFn, + ) + } + rustTemplate("#{AcceptorState}::NoAcceptorsMatched", *scope) + }, + ) + } + + private fun AcceptorState.rustName(): String = + when (this) { + AcceptorState.SUCCESS -> "Success" + AcceptorState.FAILURE -> "Failure" + AcceptorState.RETRY -> "Retry" + } +} diff --git a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestHelpers.kt b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestHelpers.kt index e4b9e11ac5..b087d5078e 100644 --- a/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestHelpers.kt +++ b/codegen-client/src/main/kotlin/software/amazon/smithy/rust/codegen/client/testutil/TestHelpers.kt @@ -36,6 +36,7 @@ fun testClientRustSettings( codegenConfig: ClientCodegenConfig = ClientCodegenConfig(), license: String? = null, examplesUri: String? = null, + minimumSupportedRustVersion: String? = null, customizationConfig: ObjectNode? = null, ) = ClientRustSettings( service, @@ -48,6 +49,7 @@ fun testClientRustSettings( codegenConfig, license, examplesUri, + minimumSupportedRustVersion, customizationConfig, ) diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/waiters/RustJmespathShapeTraversalGeneratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/waiters/RustJmespathShapeTraversalGeneratorTest.kt new file mode 100644 index 0000000000..20d7d4b181 --- /dev/null +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/waiters/RustJmespathShapeTraversalGeneratorTest.kt @@ -0,0 +1,670 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package software.amazon.smithy.rust.codegen.client.smithy.generators.waiters + +import io.kotest.matchers.string.shouldContain +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.fail +import software.amazon.smithy.jmespath.JmespathExpression +import software.amazon.smithy.model.shapes.OperationShape +import software.amazon.smithy.model.shapes.Shape +import software.amazon.smithy.model.shapes.StructureShape +import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext +import software.amazon.smithy.rust.codegen.client.smithy.ClientRustModule +import software.amazon.smithy.rust.codegen.client.testutil.clientIntegrationTest +import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter +import software.amazon.smithy.rust.codegen.core.rustlang.replaceLifetimes +import software.amazon.smithy.rust.codegen.core.rustlang.rust +import software.amazon.smithy.rust.codegen.core.rustlang.rustBlockTemplate +import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope +import software.amazon.smithy.rust.codegen.core.smithy.RustCrate +import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel +import software.amazon.smithy.rust.codegen.core.testutil.unitTest +import software.amazon.smithy.rust.codegen.core.util.dq +import software.amazon.smithy.rust.codegen.core.util.inputShape +import software.amazon.smithy.rust.codegen.core.util.lookup +import software.amazon.smithy.rust.codegen.core.util.outputShape + +class RustJmespathShapeTraversalGeneratorTest { + private class TestCase( + private val codegenContext: ClientCodegenContext, + private val rustCrate: RustCrate, + ) { + private val model = codegenContext.model + private val symbolProvider = codegenContext.symbolProvider + + private val inputShape = + model.lookup("test#TestOperation") + .inputShape(model) + private val outputShape = + model.lookup("test#TestOperation") + .outputShape(model) + val input = symbolProvider.toSymbol(inputShape) + val output = symbolProvider.toSymbol(outputShape) + val entityPrimitives = symbolProvider.toSymbol(model.lookup("test#EntityPrimitives")) + val entityLists = symbolProvider.toSymbol(model.lookup("test#EntityLists")) + val entityMaps = symbolProvider.toSymbol(model.lookup("test#EntityMaps")) + val enum = symbolProvider.toSymbol(model.lookup("test#Enum")) + val struct = symbolProvider.toSymbol(model.lookup("test#Struct")) + + val testInputDataFn: RuntimeType + val testOutputDataFn: RuntimeType + + init { + testInputDataFn = + RuntimeType.forInlineFun("test_input_data", ClientRustModule.root) { + rustTemplate( + """ + ##[allow(dead_code)] + fn test_input_data() -> #{Input} { + #{Input}::builder() + .name("foobaz") + .true_bool(true) + .false_bool(false) + .build() + .unwrap() + } + """, + "Input" to input, + ) + } + + testOutputDataFn = + RuntimeType.forInlineFun("test_output_data", ClientRustModule.root) { + rustTemplate( + """ + ##[allow(dead_code)] + fn test_output_data() -> #{Output} { + let primitives = #{EntityPrimitives}::builder() + .required_boolean(true) + .required_string("required-test") + .boolean(true) + .string("test") + .byte(1) + .short(2) + .integer(4) + .long(8) + .float(4.0) + .double(8.0) + .r##enum(#{Enum}::One) + .int_enum(1) + .build() + .unwrap(); + #{Output}::builder() + .primitives(primitives.clone()) + .lists(#{EntityLists}::builder() + .booleans(true) + .shorts(1).shorts(2) + .integers(3).integers(4) + .longs(5).longs(6) + .floats(7.0).floats(8.0) + .doubles(9.0).doubles(10.0) + .strings("one").strings("two") + .enums(#{Enum}::Two) + .int_enums(2) + .structs(#{Struct}::builder() + .primitives(primitives.clone()) + .build()) + .build()) + .maps(#{EntityMaps}::builder() + .strings("foo", "foo_oo") + .strings("bar", "bar_ar") + .booleans("foo", true) + .booleans("bar", false) + .structs("foo", #{Struct}::builder().integer(5).build()) + .build()) + .build() + } + """, + "Output" to output, + "EntityPrimitives" to entityPrimitives, + "EntityLists" to entityLists, + "EntityMaps" to entityMaps, + "Enum" to enum, + "Struct" to struct, + ) + } + } + + fun testCase( + testName: String, + expression: String, + assertions: RustWriter.() -> Unit, + inputData: RuntimeType = testInputDataFn, + outputData: RuntimeType = testOutputDataFn, + dualBinding: Boolean = false, + ) { + val generator = RustJmespathShapeTraversalGenerator(codegenContext) + val parsed = JmespathExpression.parse(expression) + val bindings = + when { + dualBinding -> + listOf( + TraversalBinding.Named("input", "_input", TraversedShape.from(model, inputShape)), + TraversalBinding.Named("output", "_output", TraversedShape.from(model, outputShape)), + ) + + else -> listOf(TraversalBinding.Global("_output", TraversedShape.from(model, outputShape))) + } + val generated = generator.generate(parsed, bindings) + rustCrate.unitTest(testName) { + rust("// jmespath: $expression") + rust("// jmespath parsed: $parsed") + rustBlockTemplate( + "fn inner<'a>(_input: &'a #{Input}, _output: &'a #{Output}) -> #{Option}<#{Ret}>", + "Input" to input, + "Output" to output, + "Ret" to generated.outputType.replaceLifetimes("a"), + *preludeScope, + ) { + generated.output(this) + rustTemplate("#{Some}(${generated.identifier})", *preludeScope) + } + rustTemplate("let (input, output) = (#{in}(), #{out}());", "in" to inputData, "out" to outputData) + rust("""println!("test data: {output:##?}");""") + rust("""println!("jmespath: {}", ${expression.dq()});""") + rust("let result = inner(&input, &output);") + rust("""println!("result: {result:##?}");""") + rust("let result = result.unwrap();") + assertions() + // Unused variable suppression + rust("let _ = result;") + } + } + + fun invalid( + expression: String, + contains: String, + dualBinding: Boolean = false, + ) { + try { + val generator = RustJmespathShapeTraversalGenerator(codegenContext) + val parsed = JmespathExpression.parse(expression) + val bindings = + when { + dualBinding -> + listOf( + TraversalBinding.Named("input", "_input", TraversedShape.from(model, inputShape)), + TraversalBinding.Named("output", "_output", TraversedShape.from(model, outputShape)), + ) + + else -> listOf(TraversalBinding.Global("_output", TraversedShape.from(model, outputShape))) + } + generator.generate(parsed, bindings).output(RustWriter.forModule("unsupported")) + fail("expression '$expression' should have thrown InvalidJmesPathTraversalException") + } catch (ex: InvalidJmesPathTraversalException) { + ex.message shouldContain contains + } + } + + fun unsupported( + expression: String, + contains: String, + ) { + try { + val generator = RustJmespathShapeTraversalGenerator(codegenContext) + val parsed = JmespathExpression.parse(expression) + generator.generate( + parsed, + listOf(TraversalBinding.Global("_output", TraversedShape.from(model, outputShape))), + ).output(RustWriter.forModule("unsupported")) + fail("expression '$expression' should have thrown UnsupportedJmesPathException") + } catch (ex: UnsupportedJmesPathException) { + ex.message shouldContain contains + } + } + } + + private fun integrationTest(testCases: TestCase.() -> Unit) { + clientIntegrationTest(testModel()) { codegenContext, rustCrate -> + TestCase(codegenContext, rustCrate).testCases() + } + } + + private fun simple(assertion: String): RustWriter.() -> Unit = + { + rust(assertion) + } + + private val expectFalse = simple("assert_eq!(false, result);") + private val expectTrue = simple("assert!(result);") + private val itCompiles = simple("") + + @Test + fun all() = + integrationTest { + fieldExpressions() + subExpressions() + namedBindings() + flattenExpressions() + literalTypes() + functions() + comparisons() + objectProjections() + filterProjections() + booleanOperations() + multiSelectLists() + complexCombinationsOfFeatures() + + unsupported("&('foo')", "Expression type expressions") + unsupported("lists.integers[0]", "Index expressions") + unsupported("""{"foo": primitives, "bar": integer}""", "Multi-select hash expressions") + unsupported("lists.integers[0:2]", "Slice expressions") + } + + private fun TestCase.fieldExpressions() { + fun test( + expression: String, + assertions: RustWriter.() -> Unit, + ) = testCase("traverse_field_$expression", expression, assertions) + + test("primitives") { + rust("assert!(std::ptr::eq(output.primitives.as_ref().unwrap(), result));") + rust("""assert_eq!("test", result.string.as_deref().unwrap());""") + } + test("lists") { + rust("assert!(std::ptr::eq(output.lists.as_ref().unwrap(), result));") + } + test("maps") { + rust("assert!(std::ptr::eq(output.maps.as_ref().unwrap(), result));") + } + + invalid("doesNotExist", "Member `doesNotExist` doesn't exist") + } + + private fun TestCase.subExpressions() { + fun test( + name: String, + expression: String, + assertions: RustWriter.() -> Unit, + ) = testCase("traverse_subexpression_$name", expression, assertions) + + test("boolean", "primitives.boolean", expectTrue) + test("string", "primitives.string", simple("assert_eq!(\"test\", result);")) + test("byte", "primitives.byte", simple("assert_eq!(1i8, *result);")) + test("short", "primitives.short", simple("assert_eq!(2i16, *result);")) + test("integer", "primitives.integer", simple("assert_eq!(4i32, *result);")) + test("long", "primitives.long", simple("assert_eq!(8i64, *result);")) + test("float", "primitives.float", simple("assert_eq!(4f32, *result);")) + test("double", "primitives.double", simple("assert_eq!(8f64, *result);")) + test("enum", "primitives.enum") { + rust("assert_eq!(#T::One, *result);", enum) + } + test("int_enum", "primitives.intEnum", simple("assert_eq!(1, *result);")) + + invalid("primitives.integer.foo", "Cannot look up fields in non-struct shapes") + + test("required_boolean", "primitives.requiredBoolean", expectTrue) + test("required_string", "primitives.requiredString", simple("assert_eq!(\"required-test\", result);")) + } + + private fun TestCase.namedBindings() { + fun test( + name: String, + expression: String, + assertions: RustWriter.() -> Unit, + ) = testCase("named_bindings_$name", expression, assertions, dualBinding = true) + + test("input_and_output_bool_true", "input.trueBool && output.primitives.boolean", expectTrue) + test("input_and_output_bool_false", "input.falseBool && output.primitives.boolean", expectFalse) + + invalid( + "input.doesNotExist && output.primitives.boolean", + "Member `doesNotExist` doesn't exist", + dualBinding = true, + ) + } + + private fun TestCase.flattenExpressions() { + fun test( + name: String, + expression: String, + assertions: RustWriter.() -> Unit, + ) = testCase("traverse_flatten_$name", expression, assertions) + + test("shortcircuit", "lists.structs[]") { + rust("assert!(std::ptr::eq(output.lists.as_ref().unwrap().structs.as_ref().unwrap(), result));") + } + test("no_shortcircuit", "lists.structs[].primitives.string") { + rust("assert_eq!(1, result.len());") + rust("assert_eq!(\"test\", result[0]);") + } + test("nested_flattens", "lists.structs[].subStructs[].subStructPrimitives.string") { + // it should compile + } + + invalid("primitives.integer[]", "Left side of the flatten") + } + + private fun TestCase.literalTypes() { + fun test( + name: String, + expression: String, + assertions: RustWriter.() -> Unit, + ) = testCase("traverse_literal_$name", expression, assertions) + + test("bool", "`true`", expectTrue) + test("int", "`0`", simple("assert_eq!(0f64, *result);")) + test("float", "`1.5`", simple("assert_eq!(1.5f64, *result);")) + test("string", "`\"foo\"`", simple("assert_eq!(\"foo\", result);")) + + unsupported("`null`", "Literal nulls") + unsupported("`{}`", "Literal expression '`{}`'") + unsupported("`[]`", "Literal expression '`[]`'") + } + + private fun TestCase.functions() { + fun test( + name: String, + expression: String, + assertions: RustWriter.() -> Unit, + ) = testCase("traverse_fn_$name", expression, assertions) + + test("list_length", "length(lists.structs[])", simple("assert_eq!(1, result);")) + test("string_length", "length(primitives.string)", simple("assert_eq!(4, result);")) + + test("string_contains_false", "contains(primitives.string, 'foo')", expectFalse) + test("string_contains_true", "contains(primitives.string, 'st')", expectTrue) + + test("strings_contains_false", "contains(lists.strings, 'foo')", expectFalse) + test("strings_contains_true", "contains(lists.strings, 'two')", expectTrue) + + test("bools_contains_false", "contains(lists.booleans, `false`)", expectFalse) + test("bools_contains_true", "contains(lists.booleans, `true`)", expectTrue) + + test("i16s_contains_false", "contains(lists.shorts, `0`)", expectFalse) + test("i16s_contains_true", "contains(lists.shorts, `1`)", expectTrue) + + test("i32s_contains_false", "contains(lists.integers, `0`)", expectFalse) + test("i32s_contains_true", "contains(lists.integers, `3`)", expectTrue) + + test("i64s_contains_false", "contains(lists.longs, `0`)", expectFalse) + test("i64s_contains_true", "contains(lists.longs, `5`)", expectTrue) + + test("f32s_contains_false", "contains(lists.floats, `0`)", expectFalse) + test("f32s_contains_true", "contains(lists.floats, `7.0`)", expectTrue) + + test("f64s_contains_false", "contains(lists.doubles, `0`)", expectFalse) + test("f64s_contains_true", "contains(lists.doubles, `9.0`)", expectTrue) + + test("enums_contains_false", "contains(lists.enums, 'one')", expectFalse) + test("enums_contains_true", "contains(lists.enums, 'two')", expectTrue) + + test("intenums_contains_false", "contains(lists.intEnums, `1`)", expectFalse) + test("intenums_contains_true", "contains(lists.intEnums, `2`)", expectTrue) + + test("stringlit_contains_stringlit_false", "contains('foo', 'o0')", expectFalse) + test("stringlit_contains_stringlit_true", "contains('foo', 'oo')", expectTrue) + + test("strings_contains_string", "contains(lists.strings, primitives.string)", expectFalse) + test("i32s_contains_i32", "contains(lists.integers, primitives.integer)", expectTrue) + test("i32s_contains_i16", "contains(lists.integers, primitives.short)", expectFalse) + test("f32s_contains_f32", "contains(lists.floats, primitives.float)", expectFalse) + + invalid("length()", "Length function takes exactly one argument") + invalid("length(primitives.integer)", "Argument to `length` function") + invalid("contains('foo')", "Contains function takes exactly two arguments") + invalid("contains(primitives.integer, 'foo')", "First argument to `contains`") + unsupported("contains(lists.structs, `null`)", "Checking for null with `contains`") + unsupported("contains(lists.structs, lists)", "Checking for anything other than") + unsupported("abs(`-1`)", "The `abs` function is not supported") + unsupported("contains(lists.floats, primitives.string)", "Comparison of &f32 with &::std::string::String") + } + + private fun TestCase.comparisons() { + fun test( + name: String, + expression: String, + assertions: RustWriter.() -> Unit, + ) = testCase("traverse_compare_$name", expression, assertions) + + test("eq_boollit_w_boollit", "`true` == `true`", expectTrue) + test("neq_boollit_w_boollit", "`true` != `true`", expectFalse) + test("boollit_w_boollit", "`true` != `true`", expectFalse) + test("bool_w_boollit", "primitives.boolean != `true`", expectFalse) + test("bool_w_bool", "primitives.boolean == primitives.boolean", expectTrue) + test("eq_integerlit_w_integerlit", "`0` == `0`", expectTrue) + test("neq_integerlit_w_integerlit", "`0` != `0`", expectFalse) + test("lt_integerlit_w_integerlit_false", "`0` < `0`", expectFalse) + test("lt_integerlit_w_integerlit_true", "`0` < `1`", expectTrue) + test("integer_w_integerlit", "primitives.integer != `0`", expectTrue) + test("integer_w_integer", "primitives.integer == primitives.integer", expectTrue) + test("float_w_integer_true", "primitives.float == primitives.integer", expectTrue) + test("integer_w_float_true", "primitives.integer == primitives.float", expectTrue) + test("float_w_integer_false", "primitives.float != primitives.integer", expectFalse) + test("integer_w_float_false", "primitives.integer != primitives.float", expectFalse) + test("eq_stringlit_w_stringlit", "'foo' == 'foo'", expectTrue) + test("neq_stringlit_w_stringlit", "'bar' != 'foo'", expectTrue) + test("string_w_stringlit_false", "primitives.string == 'foo'", expectFalse) + test("string_w_stringlit_true", "primitives.string == 'test'", expectTrue) + test("string_w_string", "primitives.string == primitives.string", expectTrue) + test("enum_w_stringlit_false", "primitives.enum == 'one'", expectTrue) + test("enum_w_stringlit_true", "primitives.enum == 'two'", expectFalse) + test("enum_w_string", "primitives.enum == primitives.string", expectFalse) + test("fn_w_number", "length(lists.structs[]) > `0`", expectTrue) + + unsupported("'foo' == `1`", "Comparison of &str with &f64") + unsupported("primitives.string == primitives.integer", "Comparison of &::std::string::String with &i32") + } + + private fun TestCase.objectProjections() { + fun test( + name: String, + expression: String, + assertions: RustWriter.() -> Unit, + ) = testCase("traverse_obj_projection_$name", expression, assertions) + + test("traverse_obj_projection_simple", "maps.booleans.*") { + rust("assert_eq!(2, result.len());") + // Order is non-deterministic because we're getting the values of a hash map + rust("assert_eq!(1, result.iter().filter(|&&&b| b == true).count());") + rust("assert_eq!(1, result.iter().filter(|&&&b| b == false).count());") + } + test("traverse_obj_projection_continued", "maps.structs.*.integer") { + rust("assert_eq!(1, result.len());") + rust("assert_eq!(5, **result.get(0).unwrap());") + } + test("traverse_obj_projection_complex", "length(maps.structs.*.strings) == `0`", expectTrue) + + unsupported("primitives.integer.*", "Object projection is only supported on map types") + unsupported("lists.structs[?`true`].*", "Object projection cannot be done on computed maps") + } + + private fun TestCase.filterProjections() { + fun test( + name: String, + expression: String, + assertions: RustWriter.() -> Unit, + ) = testCase("traverse_filter_projection_$name", expression, assertions) + + test("boollit", "lists.structs[?`true`]") { + rust("assert_eq!(1, result.len());") + } + test("intcmp", "lists.structs[?primitives.integer > `0`]") { + rust("assert_eq!(1, result.len());") + } + test("boollit_continued_empty", "lists.structs[?`true`].integer") { + rust("assert_eq!(0, result.len());") + } + test("boollit_continued", "lists.structs[?`true`].primitives.integer") { + rust("assert_eq!(1, result.len());") + } + test("intcmp_continued", "lists.structs[?primitives.integer > `0`].primitives.integer") { + rust("assert_eq!(1, result.len());") + rust("assert_eq!(4, **result.get(0).unwrap());") + } + test("intcmp_continued_filtered", "lists.structs[?primitives.integer == `0`].primitives.integer") { + rust("assert_eq!(0, result.len());") + } + + unsupported("primitives.integer[?`true`]", "Filter projections can only be done on lists") + invalid("lists.structs[?`5`]", "The filter expression comparison must result in a bool") + } + + private fun TestCase.booleanOperations() { + fun test( + name: String, + expression: String, + assertions: RustWriter.() -> Unit, + ) = testCase("traverse_boolean_ops_$name", expression, assertions) + + test("lit_not", "!`true`", expectFalse) + test("bool_not", "!(primitives.boolean)", expectFalse) + test("lit_and_lit", "`true` && `false`", expectFalse) + test("lit_or_lit", "`true` || `false`", expectTrue) + test("bool_and_lit", "primitives.boolean && `true`", expectTrue) + test("bool_or_lit", "primitives.boolean || `false`", expectTrue) + test("bool_and_bool", "primitives.boolean && primitives.boolean", expectTrue) + test("bool_or_bool", "primitives.boolean || primitives.boolean", expectTrue) + test("paren_expressions", "(`true` || `false`) && `true`", expectTrue) + + unsupported("`5` || `true`", "Applying the `||` operation doesn't support non-bool") + unsupported("`5` && `true`", "Applying the `&&` operation doesn't support non-bool") + unsupported("!`5`", "Negation of a non-boolean type") + } + + private fun TestCase.multiSelectLists() { + fun test( + name: String, + expression: String, + assertions: RustWriter.() -> Unit, + ) = testCase("traverse_multiselectlists_$name", expression, assertions) + + test("intlist_contains", "contains([`1`, `2`, `3`], `1`)", expectTrue) + test("stringlist_contains", "contains(['foo', 'bar'], 'foo')", expectTrue) + test("primitive_int_list_contains", "contains(primitives.[integer, integer], primitives.integer)", expectTrue) + test("primitive_bools", "primitives.[boolean, boolean]") { + rust("assert_eq!(2, result.len());") + rust("assert!(*result[0]);") + rust("assert!(*result[1]);") + } + test("primitive_strings_contain", "contains(primitives.[string, string], primitives.string)", expectTrue) + } + + private fun TestCase.complexCombinationsOfFeatures() { + fun test( + name: String, + expression: String, + assertions: RustWriter.() -> Unit, + ) = testCase("traverse_complex_combos_$name", expression, assertions) + + test( + "1", + "(length(lists.structs[?!(integer < `0`) && integer >= `0` || `false`]) == `5`) == contains(lists.integers, length(maps.structs.*.strings))", + itCompiles, + ) + } + + private fun testModel() = + """ + ${'$'}version: "2" + namespace test + + @aws.protocols#awsJson1_0 + service TestService { + operations: [TestOperation], + } + + operation TestOperation { + input: GetEntityRequest, + output: GetEntityResponse, + errors: [], + } + + structure GetEntityRequest { + @required + name: String + trueBool: Boolean + falseBool: Boolean + } + + structure GetEntityResponse { + primitives: EntityPrimitives, + lists: EntityLists, + maps: EntityMaps, + } + + structure EntityPrimitives { + boolean: Boolean, + string: String, + byte: Byte, + short: Short, + integer: Integer, + long: Long, + float: Float, + double: Double, + enum: Enum, + intEnum: IntEnum, + + @required requiredBoolean: Boolean, + @required requiredString: String, + } + + structure EntityLists { + booleans: BooleanList, + strings: StringList, + shorts: ShortList + integers: IntegerList, + longs: LongList + floats: FloatList, + doubles: DoubleList, + enums: EnumList, + intEnums: IntEnumList, + structs: StructList, + } + + structure EntityMaps { + booleans: BooleanMap, + strings: StringMap, + integers: IntegerMap, + enums: EnumMap, + intEnums: IntEnumMap, + structs: StructMap, + } + + enum Enum { + ONE = "one", + TWO = "two", + } + + intEnum IntEnum { + ONE = 1, + TWO = 2, + } + + structure Struct { + primitives: EntityPrimitives, + strings: StringList, + integer: Integer, + string: String, + enums: EnumList, + subStructs: SubStructList, + } + + structure SubStruct { + subStructPrimitives: EntityPrimitives, + } + + list BooleanList { member: Boolean } + list StringList { member: String } + list ShortList { member: Short } + list IntegerList { member: Integer } + list LongList { member: Long } + list FloatList { member: Float } + list DoubleList { member: Double } + list EnumList { member: Enum } + list IntEnumList { member: IntEnum } + list StructList { member: Struct } + list SubStructList { member: SubStruct } + map BooleanMap { key: String, value: Boolean } + map StringMap { key: String, value: String } + map IntegerMap { key: String, value: Integer } + map EnumMap { key: String, value: Enum } + map IntEnumMap { key: String, value: IntEnum } + map StructMap { key: String, value: Struct } + """.asSmithyModel() +} diff --git a/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/waiters/RustWaiterMatcherGeneratorTest.kt b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/waiters/RustWaiterMatcherGeneratorTest.kt new file mode 100644 index 0000000000..b099b234d5 --- /dev/null +++ b/codegen-client/src/test/kotlin/software/amazon/smithy/rust/codegen/client/smithy/generators/waiters/RustWaiterMatcherGeneratorTest.kt @@ -0,0 +1,379 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +package software.amazon.smithy.rust.codegen.client.smithy.generators.waiters + +import org.junit.jupiter.api.Test +import software.amazon.smithy.model.node.Node +import software.amazon.smithy.model.shapes.EnumShape +import software.amazon.smithy.model.shapes.OperationShape +import software.amazon.smithy.model.shapes.StructureShape +import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext +import software.amazon.smithy.rust.codegen.client.testutil.clientIntegrationTest +import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter +import software.amazon.smithy.rust.codegen.core.rustlang.Writable +import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate +import software.amazon.smithy.rust.codegen.core.rustlang.writable +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.preludeScope +import software.amazon.smithy.rust.codegen.core.smithy.RustCrate +import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel +import software.amazon.smithy.rust.codegen.core.util.dq +import software.amazon.smithy.rust.codegen.core.util.inputShape +import software.amazon.smithy.rust.codegen.core.util.lookup +import software.amazon.smithy.rust.codegen.core.util.outputShape +import software.amazon.smithy.waiters.Matcher.SuccessMember + +private typealias Scope = Array> + +class RustWaiterMatcherGeneratorTest { + class TestCase( + codegenContext: ClientCodegenContext, + private val rustCrate: RustCrate, + matcherJson: String, + ) { + val operationShape = codegenContext.model.lookup("test#TestOperation") + val inputShape = operationShape.inputShape(codegenContext.model) + val outputShape = operationShape.outputShape(codegenContext.model) + val errorShape = codegenContext.model.lookup("test#SomeError") + val inputSymbol = codegenContext.symbolProvider.toSymbol(inputShape) + val outputSymbol = codegenContext.symbolProvider.toSymbol(outputShape) + val errorSymbol = codegenContext.symbolProvider.toSymbol(errorShape) + + val matcher = SuccessMember.fromNode(Node.parse(matcherJson)) + val matcherFn = + RustWaiterMatcherGenerator(codegenContext, "TestOperation", inputShape, outputShape) + .generate(errorSymbol, matcher) + + val scope = + arrayOf( + *preludeScope, + "Input" to inputSymbol, + "Output" to outputSymbol, + "Error" to errorSymbol, + "ErrorMetadata" to RuntimeType.errorMetadata(codegenContext.runtimeConfig), + "SomeEnum" to codegenContext.symbolProvider.toSymbol(codegenContext.model.lookup("test#SomeEnum")), + "matcher_fn" to matcherFn, + ) + + fun renderTest( + name: String, + writeTest: TestCase.() -> Writable, + ) { + rustCrate.lib { + rustTemplate( + """ + /// Make the unit test public and document it so that compiler + /// doesn't complain about dead code. + pub fn ${name}_test_case() { + #{test} + } + ##[cfg(test)] + ##[test] + fn $name() { + ${name}_test_case(); + } + """, + *scope, + "test" to writeTest(), + ) + } + } + } + + @Test + fun tests() { + clientIntegrationTest(testModel()) { codegenContext, rustCrate -> + successMatcher(codegenContext, rustCrate) + errorMatcher(codegenContext, rustCrate) + outputPathMatcher(codegenContext, rustCrate) + inputOutputPathMatcher(codegenContext, rustCrate) + } + } + + private fun testCase( + codegenContext: ClientCodegenContext, + rustCrate: RustCrate, + name: String, + matcherJson: String, + writeFn: RustWriter.(Scope) -> Unit, + ) { + TestCase(codegenContext, rustCrate, matcherJson).renderTest(name) { + writable { + writeFn(scope) + } + } + } + + private fun successMatcher( + codegenContext: ClientCodegenContext, + rustCrate: RustCrate, + ) = testCase( + codegenContext, + rustCrate, + name = "success_matcher", + matcherJson = """{"success":true}""", + ) { scope -> + rustTemplate( + """ + let result = #{Ok}(#{Output}::builder().some_string("bar").build()); + assert!(#{matcher_fn}(result.as_ref())); + + let result = #{Err}(#{Error}::builder().message("asdf").build()); + assert!(!#{matcher_fn}(result.as_ref())); + """, + *scope, + ) + } + + private fun errorMatcher( + codegenContext: ClientCodegenContext, + rustCrate: RustCrate, + ) = testCase( + codegenContext, + rustCrate, + name = "error_matcher", + matcherJson = """{"errorType":"SomeError"}""", + ) { scope -> + rustTemplate( + """ + let result = #{Ok}(#{Output}::builder().some_string("bar").build()); + assert!(!#{matcher_fn}(result.as_ref())); + + let result = #{Err}( + #{Error}::builder() + .message("asdf") + .meta(#{ErrorMetadata}::builder().code("SomeOtherError").build()) + .build() + ); + assert!(!#{matcher_fn}(result.as_ref())); + + let result = #{Err}( + #{Error}::builder() + .message("asdf") + .meta(#{ErrorMetadata}::builder().code("SomeError").build()) + .build() + ); + assert!(#{matcher_fn}(result.as_ref())); + """, + *scope, + ) + } + + private fun outputPathMatcher( + codegenContext: ClientCodegenContext, + rustCrate: RustCrate, + ) { + fun test( + name: String, + matcherJson: String, + writeFn: RustWriter.(Scope) -> Unit, + ) = testCase(codegenContext, rustCrate, name, matcherJson, writeFn) + + fun matcherJson( + path: String, + expected: String, + comparator: String, + ) = """{"output":{"path":${path.dq()}, "expected":${expected.dq()}, "comparator": ${comparator.dq()}}}""" + + test( + "output_path_matcher_string_equals", + matcherJson( + path = "someString", + expected = "expected-value", + comparator = "stringEquals", + ), + ) { scope -> + rustTemplate( + """ + let result = #{Ok}(#{Output}::builder().some_string("bar").build()); + assert!(!#{matcher_fn}(result.as_ref())); + + let result = #{Ok}(#{Output}::builder().some_string("expected-value").build()); + assert!(#{matcher_fn}(result.as_ref())); + """, + *scope, + ) + } + + test( + "output_path_matcher_bool_equals", + matcherJson( + path = "someBool", + expected = "true", + comparator = "booleanEquals", + ), + ) { scope -> + rustTemplate( + """ + let result = #{Ok}(#{Output}::builder().some_bool(false).build()); + assert!(!#{matcher_fn}(result.as_ref())); + + let result = #{Ok}(#{Output}::builder().some_bool(true).build()); + assert!(#{matcher_fn}(result.as_ref())); + """, + *scope, + ) + } + + test( + "output_path_matcher_all_string_equals", + matcherJson( + path = "someList", + expected = "foo", + comparator = "allStringEquals", + ), + ) { scope -> + rustTemplate( + """ + let result = #{Ok}(#{Output}::builder() + .some_list("foo") + .some_list("bar") + .build()); + assert!(!#{matcher_fn}(result.as_ref())); + + let result = #{Ok}(#{Output}::builder() + .some_list("foo") + .some_list("foo") + .build()); + assert!(#{matcher_fn}(result.as_ref())); + """, + *scope, + ) + } + + test( + "output_path_matcher_any_string_equals", + matcherJson( + path = "someList", + expected = "foo", + comparator = "anyStringEquals", + ), + ) { scope -> + rustTemplate( + """ + let result = #{Ok}(#{Output}::builder() + .some_list("bar") + .build()); + assert!(!#{matcher_fn}(result.as_ref())); + + let result = #{Ok}(#{Output}::builder() + .some_list("bar") + .some_list("foo") + .build()); + assert!(#{matcher_fn}(result.as_ref())); + """, + *scope, + ) + } + + test( + "output_path_matcher_any_string_equals_enum", + matcherJson( + path = "someEnumList", + expected = "Foo", + comparator = "anyStringEquals", + ), + ) { scope -> + rustTemplate( + """ + let result = #{Ok}(#{Output}::builder() + .some_enum_list(#{SomeEnum}::Bar) + .build()); + assert!(!#{matcher_fn}(result.as_ref())); + + let result = #{Ok}(#{Output}::builder() + .some_enum_list(#{SomeEnum}::Bar) + .some_enum_list(#{SomeEnum}::Foo) + .build()); + assert!(#{matcher_fn}(result.as_ref())); + """, + *scope, + ) + } + } + + private fun inputOutputPathMatcher( + codegenContext: ClientCodegenContext, + rustCrate: RustCrate, + ) { + fun test( + name: String, + matcherJson: String, + writeFn: RustWriter.(Scope) -> Unit, + ) = testCase(codegenContext, rustCrate, name, matcherJson, writeFn) + + fun matcherJson( + path: String, + expected: String, + comparator: String, + ) = """{"inputOutput":{"path":${path.dq()}, "expected":${expected.dq()}, "comparator": ${comparator.dq()}}}""" + + test( + "input_output_path_matcher_boolean_equals", + matcherJson( + path = "input.foo == 'foo' && output.someString == 'bar'", + expected = "true", + comparator = "booleanEquals", + ), + ) { scope -> + rustTemplate( + """ + let input = #{Input}::builder().foo("foo").build().unwrap(); + let result = #{Ok}(#{Output}::builder().some_string("bar").build()); + assert!(#{matcher_fn}(&input, result.as_ref())); + + let input = #{Input}::builder().foo("asdf").build().unwrap(); + assert!(!#{matcher_fn}(&input, result.as_ref())); + """, + *scope, + ) + } + } + + private fun testModel() = + """ + ${'$'}version: "2" + namespace test + + @aws.protocols#awsJson1_0 + service TestService { + operations: [TestOperation], + } + + operation TestOperation { + input: GetEntityRequest, + output: GetEntityResponse, + errors: [SomeError], + } + + @error("server") + structure SomeError { + message: String, + } + + structure GetEntityRequest { + foo: String, + } + + structure GetEntityResponse { + someString: String, + someBool: Boolean, + someList: SomeList, + someEnumList: SomeEnumList, + } + + list SomeList { + member: String + } + + enum SomeEnum { + Foo, + Bar, + } + list SomeEnumList { + member: SomeEnum, + } + """.asSmithyModel() +} diff --git a/codegen-core/common-test-models/rest-json-extras.smithy b/codegen-core/common-test-models/rest-json-extras.smithy index ad49300167..73f45e7dfd 100644 --- a/codegen-core/common-test-models/rest-json-extras.smithy +++ b/codegen-core/common-test-models/rest-json-extras.smithy @@ -8,30 +8,6 @@ use smithy.test#httpRequestTests use smithy.test#httpResponseTests use smithy.framework#ValidationException -// TODO(https://github.com/smithy-lang/smithy/pull/2167): Remove this test once it's fixed in Smithy -apply AllQueryStringTypes @httpRequestTests([ - { - id: "RestJsonZeroAndFalseQueryValuesFixed" - documentation: "Query values of 0 and false are serialized" - protocol: restJson1 - method: "GET" - uri: "/AllQueryStringTypesInput" - body: "" - queryParams: [ - "Integer=0" - "Boolean=false" - ] - params: { - queryInteger: 0 - queryBoolean: false - queryParamsMapOfStringList: { - Integer: ["0"] - Boolean: ["false"] - } - } - } -]) - apply QueryPrecedence @httpRequestTests([ { id: "UrlParamsKeyEncoding", @@ -90,8 +66,6 @@ service RestJsonExtras { CaseInsensitiveErrorOperation, EmptyStructWithContentOnWireOp, QueryPrecedence, - // TODO(https://github.com/smithy-lang/smithy/pull/2167): Remove this test once it's fixed in Smithy - AllQueryStringTypes, ], errors: [ExtraError] } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/CargoDependency.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/CargoDependency.kt index 07a6a4c02a..444f65a09e 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/CargoDependency.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/CargoDependency.kt @@ -244,7 +244,7 @@ data class CargoDependency( companion object { // Forces AHash to be a later version that avoids // https://github.com/tkaitchuck/aHash/issues/200 - val AHash: CargoDependency = CargoDependency("ahash", CratesIo("0.8.11")) + val AHash: CargoDependency = CargoDependency("ahash", CratesIo("0.8.11"), defaultFeatures = false) val OnceCell: CargoDependency = CargoDependency("once_cell", CratesIo("1.16")) val Url: CargoDependency = CargoDependency("url", CratesIo("2.3.1")) val Bytes: CargoDependency = CargoDependency("bytes", CratesIo("1.0.0")) diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustType.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustType.kt index 8ac936d679..10c8def399 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustType.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustType.kt @@ -257,7 +257,7 @@ fun RustType.render(fullyQualified: Boolean = true): String { if (this.lifetime == "&") { "&${this.member.render(fullyQualified)}" } else { - "&${this.lifetime?.let { "'$it" } ?: ""} ${this.member.render(fullyQualified)}" + "&${this.lifetime?.let { "'$it " } ?: ""}${this.member.render(fullyQualified)}" } } is RustType.Application -> { @@ -375,6 +375,17 @@ fun RustType.isEq(): Boolean = else -> false } +/** Recursively replaces lifetimes with the new lifetime */ +fun RustType.replaceLifetimes(newLifetime: String?): RustType = + when (this) { + is RustType.Option -> copy(member = member.replaceLifetimes(newLifetime)) + is RustType.Vec -> copy(member = member.replaceLifetimes(newLifetime)) + is RustType.HashSet -> copy(member = member.replaceLifetimes(newLifetime)) + is RustType.HashMap -> copy(key = key.replaceLifetimes(newLifetime), member = member.replaceLifetimes(newLifetime)) + is RustType.Reference -> copy(lifetime = newLifetime) + else -> this + } + enum class Visibility { PRIVATE, PUBCRATE, @@ -531,6 +542,7 @@ class Attribute(val inner: Writable, val isDeriveHelper: Boolean = false) { val AllowClippyBoxedLocal = Attribute(allow("clippy::boxed_local")) val AllowClippyLetAndReturn = Attribute(allow("clippy::let_and_return")) val AllowClippyNeedlessBorrow = Attribute(allow("clippy::needless_borrow")) + val AllowClippyNeedlessLifetimes = Attribute(allow("clippy::needless_lifetimes")) val AllowClippyNewWithoutDefault = Attribute(allow("clippy::new_without_default")) val AllowClippyUnnecessaryWraps = Attribute(allow("clippy::unnecessary_wraps")) val AllowClippyUselessConversion = Attribute(allow("clippy::useless_conversion")) diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriter.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriter.kt index 7034ed1f12..c0922525b0 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriter.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/RustWriter.kt @@ -524,13 +524,22 @@ fun RustWriter.rawTemplate( */ fun docLink(docLink: String): String = docLink.replace("::r##", "::").replace("::r#", "::") +class SafeNamer { + private var n = 0 + + fun safeName(prefix: String = "var"): String { + n += 1 + return "${prefix}_$n" + } +} + class RustWriter private constructor( private val filename: String, val namespace: String, private val commentCharacter: String = "//", private val printWarning: Boolean = true, /** Insert comments indicating where code was generated */ - private val debugMode: Boolean = false, + val debugMode: Boolean = false, /** When true, automatically change all dependencies to be in the test scope */ val devDependenciesOnly: Boolean = false, ) : @@ -619,7 +628,7 @@ class RustWriter private constructor( private val preamble = mutableListOf() private val formatter = RustSymbolFormatter() - private var n = 0 + private val safeNamer = SafeNamer() init { expressionStart = '#' @@ -644,10 +653,7 @@ class RustWriter private constructor( null } - fun safeName(prefix: String = "var"): String { - n += 1 - return "${prefix}_$n" - } + fun safeName(prefix: String = "var"): String = safeNamer.safeName(prefix) fun first(preWriter: Writable) { preamble.add(preWriter) diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/Writable.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/Writable.kt index ad4b07c230..7b9ad23366 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/Writable.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/rustlang/Writable.kt @@ -37,12 +37,11 @@ fun Writable.some(): Writable { fun Writable.isNotEmpty(): Boolean = !this.isEmpty() -operator fun Writable.plus(other: Writable): Writable { - val first = this - return writable { - rustTemplate("#{First:W}#{Second:W}", "First" to first, "Second" to other) +operator fun Writable.plus(other: Writable): Writable = + writable { + this@plus(this) + other(this) } -} /** * Helper allowing a `Iterable` to be joined together using a `String` separator. diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/CoreRustSettings.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/CoreRustSettings.kt index 18c9fa5d7a..8b7f6bb72c 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/CoreRustSettings.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/CoreRustSettings.kt @@ -15,18 +15,18 @@ import software.amazon.smithy.model.shapes.ShapeId import software.amazon.smithy.rust.codegen.core.util.orNull import java.util.Optional import java.util.logging.Logger -import kotlin.streams.toList -const val SERVICE = "service" -const val MODULE_NAME = "module" -const val MODULE_DESCRIPTION = "moduleDescription" -const val MODULE_VERSION = "moduleVersion" -const val MODULE_AUTHORS = "moduleAuthors" -const val MODULE_REPOSITORY = "moduleRepository" -const val RUNTIME_CONFIG = "runtimeConfig" -const val LICENSE = "license" -const val EXAMPLES = "examples" -const val CUSTOMIZATION_CONFIG = "customizationConfig" +private const val SERVICE = "service" +private const val MODULE_NAME = "module" +private const val MODULE_DESCRIPTION = "moduleDescription" +private const val MODULE_VERSION = "moduleVersion" +private const val MODULE_AUTHORS = "moduleAuthors" +private const val MODULE_REPOSITORY = "moduleRepository" +private const val RUNTIME_CONFIG = "runtimeConfig" +private const val LICENSE = "license" +private const val EXAMPLES = "examples" +private const val MINIMUM_SUPPORTED_RUST_VERSION = "minimumSupportedRustVersion" +private const val CUSTOMIZATION_CONFIG = "customizationConfig" const val CODEGEN_SETTINGS = "codegen" /** @@ -88,6 +88,7 @@ open class CoreRustSettings( open val codegenConfig: CoreCodegenConfig, open val license: String?, open val examplesUri: String? = null, + open val minimumSupportedRustVersion: String? = null, open val customizationConfig: ObjectNode? = null, ) { /** @@ -177,6 +178,7 @@ open class CoreRustSettings( CODEGEN_SETTINGS, EXAMPLES, LICENSE, + MINIMUM_SUPPORTED_RUST_VERSION, CUSTOMIZATION_CONFIG, ), ) @@ -198,6 +200,7 @@ open class CoreRustSettings( codegenConfig = coreCodegenConfig, license = config.getStringMember(LICENSE).orNull()?.value, examplesUri = config.getStringMember(EXAMPLES).orNull()?.value, + minimumSupportedRustVersion = config.getStringMember(MINIMUM_SUPPORTED_RUST_VERSION).orNull()?.value, customizationConfig = config.getObjectMember(CUSTOMIZATION_CONFIG).orNull(), ) } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt index f0fc3e833e..26ff35a64f 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt @@ -253,6 +253,7 @@ data class RuntimeType(val path: String, val dependency: RustDependency? = null) val Debug = stdFmt.resolve("Debug") val Default = std.resolve("default::Default") val Display = stdFmt.resolve("Display") + val Duration = std.resolve("time::Duration") val Eq = stdCmp.resolve("Eq") val From = stdConvert.resolve("From") val Hash = std.resolve("hash::Hash") diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/SymbolVisitor.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/SymbolVisitor.kt index 89d5055448..d2c30f6091 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/SymbolVisitor.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/SymbolVisitor.kt @@ -103,7 +103,7 @@ fun SymbolProvider.toOptional( } /** - * Services can rename their contained shapes. See https://awslabs.github.io/smithy/1.0/spec/core/model.html#service + * Services can rename their contained shapes. See https://smithy.io/2.0/spec/service-types.html * specifically, `rename` */ fun Shape.contextName(serviceShape: ServiceShape?): String { diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/CargoTomlGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/CargoTomlGenerator.kt index f5112946d4..e5f4916348 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/CargoTomlGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/CargoTomlGenerator.kt @@ -49,6 +49,7 @@ class CargoTomlGenerator( private val moduleDescription: String?, private val moduleLicense: String?, private val moduleRepository: String?, + private val minimumSupportedRustVersion: String?, private val writer: RustWriter, private val manifestCustomizations: ManifestCustomizations = emptyMap(), private val dependencies: List = emptyList(), @@ -67,6 +68,7 @@ class CargoTomlGenerator( settings.moduleDescription, settings.license, settings.moduleRepository, + settings.minimumSupportedRustVersion, writer, manifestCustomizations, dependencies, @@ -90,6 +92,7 @@ class CargoTomlGenerator( "edition" to "2021", "license" to moduleLicense, "repository" to moduleRepository, + minimumSupportedRustVersion?.let { "rust-version" to it }, "metadata" to listOfNotNull( "smithy" to diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/LibRsGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/LibRsGenerator.kt index 85fc05ee98..24beaa51d8 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/LibRsGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/LibRsGenerator.kt @@ -51,6 +51,7 @@ class LibRsGenerator( fun render(writer: RustWriter) { writer.first { customizations.forEach { it.section(LibRsSection.Attributes)(this) } + rust("##![forbid(unsafe_code)]") if (requireDocs) { rust("##![warn(missing_docs)]") } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsJson.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsJson.kt index 1b54f4289f..486b443a6a 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsJson.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsJson.kt @@ -83,6 +83,9 @@ class AwsJsonHttpBindingResolver( "application/x-amz-json-${awsJsonVersion.value}" override fun responseContentType(operationShape: OperationShape): String = requestContentType(operationShape) + + override fun eventStreamMessageContentType(memberShape: MemberShape): String? = + ProtocolContentTypes.eventStreamMemberContentType(model, memberShape, "application/json") } /** diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsQueryCompatible.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsQueryCompatible.kt index 7b15e81051..4cc4a2fa14 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsQueryCompatible.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsQueryCompatible.kt @@ -5,6 +5,7 @@ package software.amazon.smithy.rust.codegen.core.smithy.protocols +import software.amazon.smithy.model.shapes.MemberShape import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.ToShapeId import software.amazon.smithy.model.traits.HttpTrait @@ -38,6 +39,9 @@ class AwsQueryCompatibleHttpBindingResolver( override fun responseContentType(operationShape: OperationShape): String = awsJsonHttpBindingResolver.requestContentType(operationShape) + + override fun eventStreamMessageContentType(memberShape: MemberShape): String? = + awsJsonHttpBindingResolver.eventStreamMessageContentType(memberShape) } class AwsQueryCompatible( diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/HttpBindingResolver.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/HttpBindingResolver.kt index 8eb693c41f..ad36e79190 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/HttpBindingResolver.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/HttpBindingResolver.kt @@ -8,8 +8,10 @@ package software.amazon.smithy.rust.codegen.core.smithy.protocols import software.amazon.smithy.model.Model import software.amazon.smithy.model.knowledge.HttpBinding import software.amazon.smithy.model.knowledge.HttpBindingIndex +import software.amazon.smithy.model.shapes.BlobShape import software.amazon.smithy.model.shapes.MemberShape import software.amazon.smithy.model.shapes.OperationShape +import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.model.shapes.ToShapeId import software.amazon.smithy.model.traits.HttpTrait import software.amazon.smithy.model.traits.TimestampFormatTrait @@ -98,6 +100,11 @@ interface HttpBindingResolver { * Determines the response content type for given [operationShape]. */ fun responseContentType(operationShape: OperationShape): String? + + /** + * Determines the value of the event stream `:content-type` header based on union member + */ + fun eventStreamMessageContentType(memberShape: MemberShape): String? } /** @@ -108,12 +115,30 @@ data class ProtocolContentTypes( val requestDocument: String? = null, /** Response content type override for when the shape is a Document */ val responseDocument: String? = null, - /** EventStream content type */ + /** EventStream content type initial request/response content-type */ val eventStreamContentType: String? = null, + /** EventStream content type for struct message shapes (for `:content-type`) */ + val eventStreamMessageContentType: String? = null, ) { companion object { /** Create an instance of [ProtocolContentTypes] where all content types are the same */ - fun consistent(type: String) = ProtocolContentTypes(type, type, type) + fun consistent(type: String) = ProtocolContentTypes(type, type, type, type) + + /** + * Returns the event stream message `:content-type` for the given event stream union member shape. + * + * The `protocolContentType` is the content-type to use for non-string/non-blob shapes. + */ + fun eventStreamMemberContentType( + model: Model, + memberShape: MemberShape, + protocolContentType: String?, + ): String? = + when (model.expectShape(memberShape.target)) { + is StringShape -> "text/plain" + is BlobShape -> "application/octet-stream" + else -> protocolContentType + } } } @@ -121,7 +146,7 @@ data class ProtocolContentTypes( * An [HttpBindingResolver] that relies on the HttpTrait data in the Smithy models. */ open class HttpTraitHttpBindingResolver( - model: Model, + private val model: Model, private val contentTypes: ProtocolContentTypes, ) : HttpBindingResolver { private val httpIndex: HttpBindingIndex = HttpBindingIndex.of(model) @@ -158,6 +183,9 @@ open class HttpTraitHttpBindingResolver( contentTypes.eventStreamContentType, ).orNull() + override fun eventStreamMessageContentType(memberShape: MemberShape): String? = + ProtocolContentTypes.eventStreamMemberContentType(model, memberShape, contentTypes.eventStreamMessageContentType) + // Sort the members after extracting them from the map to have a consistent order private fun mappedBindings(bindings: Map): List = bindings.values.map(::HttpBindingDescriptor).sortedBy { it.memberName } @@ -172,6 +200,7 @@ open class StaticHttpBindingResolver( private val httpTrait: HttpTrait, private val requestContentType: String, private val responseContentType: String, + private val eventStreamMessageContentType: String? = null, ) : HttpBindingResolver { private fun bindings(shape: ToShapeId?) = shape?.let { model.expectShape(it.toShapeId()) }?.members() @@ -192,4 +221,7 @@ open class StaticHttpBindingResolver( override fun requestContentType(operationShape: OperationShape): String = requestContentType override fun responseContentType(operationShape: OperationShape): String = responseContentType + + override fun eventStreamMessageContentType(memberShape: MemberShape): String? = + ProtocolContentTypes.eventStreamMemberContentType(model, memberShape, eventStreamMessageContentType) } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/HttpBoundProtocolPayloadGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/HttpBoundProtocolPayloadGenerator.kt index a8fa69a6c2..1c5c94d800 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/HttpBoundProtocolPayloadGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/HttpBoundProtocolPayloadGenerator.kt @@ -197,7 +197,6 @@ class HttpBoundProtocolPayloadGenerator( if (operationShape.isInputEventStream(model) && target == CodegenTarget.CLIENT) { val payloadMember = operationShape.inputShape(model).expectMember(payloadMemberName) writer.serializeViaEventStream( - operationShape, payloadMember, serializerGenerator, shapeName, @@ -206,7 +205,6 @@ class HttpBoundProtocolPayloadGenerator( } else if (operationShape.isOutputEventStream(model) && target == CodegenTarget.SERVER) { val payloadMember = operationShape.outputShape(model).expectMember(payloadMemberName) writer.serializeViaEventStream( - operationShape, payloadMember, serializerGenerator, "output", @@ -239,7 +237,6 @@ class HttpBoundProtocolPayloadGenerator( } private fun RustWriter.serializeViaEventStream( - operationShape: OperationShape, memberShape: MemberShape, serializerGenerator: StructuredDataSerializerGenerator, outerName: String, @@ -248,11 +245,10 @@ class HttpBoundProtocolPayloadGenerator( val memberName = symbolProvider.toMemberName(memberShape) val unionShape = model.expectShape(memberShape.target, UnionShape::class.java) - val contentType = - when (target) { - CodegenTarget.CLIENT -> httpBindingResolver.requestContentType(operationShape) - CodegenTarget.SERVER -> httpBindingResolver.responseContentType(operationShape) - } + val payloadContentType = + httpBindingResolver.eventStreamMessageContentType(memberShape) + ?: throw CodegenException("event streams must set a content type") + val errorMarshallerConstructorFn = EventStreamErrorMarshallerGenerator( model, @@ -261,7 +257,7 @@ class HttpBoundProtocolPayloadGenerator( symbolProvider, unionShape, serializerGenerator, - contentType ?: throw CodegenException("event streams must set a content type"), + payloadContentType, ).render() val marshallerConstructorFn = EventStreamMarshallerGenerator( @@ -271,7 +267,7 @@ class HttpBoundProtocolPayloadGenerator( symbolProvider, unionShape, serializerGenerator, - contentType, + payloadContentType, ).render() // TODO(EventStream): [RPC] RPC protocols need to send an initial message with the diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestJson.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestJson.kt index d839bac3c8..641548fc11 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestJson.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestJson.kt @@ -29,7 +29,7 @@ import software.amazon.smithy.rust.codegen.core.util.outputShape /** * This [HttpBindingResolver] implementation mostly delegates to the [HttpTraitHttpBindingResolver] class, since the * RestJson1 protocol can be almost entirely described by Smithy's HTTP binding traits - * (https://awslabs.github.io/smithy/1.0/spec/core/http-traits.html). + * (https://smithy.io/2.0/spec/http-bindings.html). * The only protocol-specific behavior that is truly custom is the response `Content-Type` header, which defaults to * `application/json` if not overridden. */ @@ -74,7 +74,15 @@ open class RestJson(val codegenContext: CodegenContext) : Protocol { ) override val httpBindingResolver: HttpBindingResolver = - RestJsonHttpBindingResolver(codegenContext.model, ProtocolContentTypes("application/json", "application/json", "application/vnd.amazon.eventstream")) + RestJsonHttpBindingResolver( + codegenContext.model, + ProtocolContentTypes( + requestDocument = "application/json", + responseDocument = "application/json", + eventStreamContentType = "application/vnd.amazon.eventstream", + eventStreamMessageContentType = "application/json", + ), + ) override val defaultTimestampFormat: TimestampFormatTrait.Format = TimestampFormatTrait.Format.EPOCH_SECONDS diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestXml.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestXml.kt index 700fe60775..e8dab762a1 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestXml.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestXml.kt @@ -36,7 +36,15 @@ open class RestXml(val codegenContext: CodegenContext) : Protocol { } override val httpBindingResolver: HttpBindingResolver = - HttpTraitHttpBindingResolver(codegenContext.model, ProtocolContentTypes("application/xml", "application/xml", "application/vnd.amazon.eventstream")) + HttpTraitHttpBindingResolver( + codegenContext.model, + ProtocolContentTypes( + requestDocument = "application/xml", + responseDocument = "application/xml", + eventStreamContentType = "application/vnd.amazon.eventstream", + eventStreamMessageContentType = "application/xml", + ), + ) override val defaultTimestampFormat: TimestampFormatTrait.Format = TimestampFormatTrait.Format.DATE_TIME diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/EventStreamUnmarshallerGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/EventStreamUnmarshallerGenerator.kt index b114911d92..fc2f98f339 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/EventStreamUnmarshallerGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/EventStreamUnmarshallerGenerator.kt @@ -41,6 +41,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.transformers.eventStreamE import software.amazon.smithy.rust.codegen.core.util.dq import software.amazon.smithy.rust.codegen.core.util.expectTrait import software.amazon.smithy.rust.codegen.core.util.hasTrait +import software.amazon.smithy.rust.codegen.core.util.isTargetUnit import software.amazon.smithy.rust.codegen.core.util.toPascalCase fun RustModule.Companion.eventStreamSerdeModule(): RustModule.LeafModule = private("event_stream_serde") @@ -189,12 +190,20 @@ class EventStreamUnmarshallerGenerator( // Don't attempt to parse the payload for an empty struct. The payload can be empty, or if the model was // updated since the code was generated, it can have content that would not be understood. empty -> { - rustTemplate( - "Ok(#{UnmarshalledMessage}::Event(#{Output}::$unionMemberName(#{UnionStruct}::builder().build())))", - "Output" to unionSymbol, - "UnionStruct" to symbolProvider.toSymbol(unionStruct), - *codegenScope, - ) + if (unionMember.isTargetUnit()) { + rustTemplate( + "Ok(#{UnmarshalledMessage}::Event(#{Output}::$unionMemberName))", + "Output" to unionSymbol, + *codegenScope, + ) + } else { + rustTemplate( + "Ok(#{UnmarshalledMessage}::Event(#{Output}::$unionMemberName(#{UnionStruct}::builder().build())))", + "Output" to unionSymbol, + "UnionStruct" to symbolProvider.toSymbol(unionStruct), + *codegenScope, + ) + } } payloadOnly -> { diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/EventStreamMarshallerGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/EventStreamMarshallerGenerator.kt index 84e31a6173..153e37c8fe 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/EventStreamMarshallerGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/serialize/EventStreamMarshallerGenerator.kt @@ -42,6 +42,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.protocols.parse.eventStre import software.amazon.smithy.rust.codegen.core.smithy.rustType import software.amazon.smithy.rust.codegen.core.util.dq import software.amazon.smithy.rust.codegen.core.util.hasTrait +import software.amazon.smithy.rust.codegen.core.util.isTargetUnit import software.amazon.smithy.rust.codegen.core.util.toPascalCase open class EventStreamMarshallerGenerator( @@ -107,7 +108,15 @@ open class EventStreamMarshallerGenerator( rustBlock("let payload = match input") { for (member in unionShape.members()) { val eventType = member.memberName // must be the original name, not the Rust-safe name - rustBlock("Self::Input::${symbolProvider.toMemberName(member)}(inner) => ") { + // Union members targeting the Smithy `Unit` type do not have associated data in the + // Rust enum generated for the type. + val mayHaveInner = + if (!member.isTargetUnit()) { + "(inner)" + } else { + "" + } + rustBlock("Self::Input::${symbolProvider.toMemberName(member)}$mayHaveInner => ") { addStringHeader(":event-type", "${eventType.dq()}.into()") val target = model.expectShape(member.target, StructureShape::class.java) renderMarshallEvent(member, target) @@ -147,7 +156,15 @@ open class EventStreamMarshallerGenerator( renderMarshallEventPayload("inner.$memberName", payloadMember, target, serializerFn) } else if (headerMembers.isEmpty()) { val serializerFn = serializerGenerator.payloadSerializer(unionMember) - renderMarshallEventPayload("inner", unionMember, eventStruct, serializerFn) + // Union members targeting the Smithy `Unit` type do not have associated data in the + // Rust enum generated for the type. For these, we need to pass the `crate::model::Unit` data type. + val inner = + if (unionMember.isTargetUnit()) { + "crate::model::Unit::builder().build()" + } else { + "inner" + } + renderMarshallEventPayload(inner, unionMember, eventStruct, serializerFn) } else { rust("Vec::new()") } @@ -180,7 +197,7 @@ open class EventStreamMarshallerGenerator( } } - // Event stream header types: https://awslabs.github.io/smithy/1.0/spec/core/stream-traits.html#eventheader-trait + // Event stream header types: https://smithy.io/2.0/spec/streaming.html#eventheader-trait // Note: there are no floating point header types for Event Stream. private fun headerValue( inputName: String, diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamMarshallTestCases.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamMarshallTestCases.kt index 65ae5019cb..ba37f3c421 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamMarshallTestCases.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamMarshallTestCases.kt @@ -111,7 +111,7 @@ object EventStreamMarshallTestCases { let headers = headers_to_map(message.headers()); assert_eq!(&str_header("event"), *headers.get(":message-type").unwrap()); assert_eq!(&str_header("MessageWithStruct"), *headers.get(":event-type").unwrap()); - assert_eq!(&str_header(${testCase.requestContentType.dq()}), *headers.get(":content-type").unwrap()); + assert_eq!(&str_header(${testCase.eventStreamMessageContentType.dq()}), *headers.get(":content-type").unwrap()); validate_body( message.payload(), @@ -146,7 +146,7 @@ object EventStreamMarshallTestCases { let headers = headers_to_map(message.headers()); assert_eq!(&str_header("event"), *headers.get(":message-type").unwrap()); assert_eq!(&str_header("MessageWithUnion"), *headers.get(":event-type").unwrap()); - assert_eq!(&str_header(${testCase.requestContentType.dq()}), *headers.get(":content-type").unwrap()); + assert_eq!(&str_header(${testCase.eventStreamMessageContentType.dq()}), *headers.get(":content-type").unwrap()); validate_body( message.payload(), @@ -236,7 +236,7 @@ object EventStreamMarshallTestCases { let headers = headers_to_map(message.headers()); assert_eq!(&str_header("event"), *headers.get(":message-type").unwrap()); assert_eq!(&str_header("MessageWithNoHeaderPayloadTraits"), *headers.get(":event-type").unwrap()); - assert_eq!(&str_header(${testCase.requestContentType.dq()}), *headers.get(":content-type").unwrap()); + assert_eq!(&str_header(${testCase.eventStreamMessageContentType.dq()}), *headers.get(":content-type").unwrap()); validate_body( message.payload(), diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestModels.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestModels.kt index c0f61e07db..dc37caf714 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestModels.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/EventStreamTestModels.kt @@ -109,6 +109,7 @@ object EventStreamTestModels { val mediaType: String, val requestContentType: String, val responseContentType: String, + val eventStreamMessageContentType: String, val validTestStruct: String, val validMessageWithNoHeaderPayloadTraits: String, val validTestUnion: String, @@ -130,6 +131,7 @@ object EventStreamTestModels { mediaType = "application/json", requestContentType = "application/vnd.amazon.eventstream", responseContentType = "application/json", + eventStreamMessageContentType = "application/json", validTestStruct = """{"someString":"hello","someInt":5}""", validMessageWithNoHeaderPayloadTraits = """{"someString":"hello","someInt":5}""", validTestUnion = """{"Foo":"hello"}""", @@ -145,6 +147,7 @@ object EventStreamTestModels { mediaType = "application/x-amz-json-1.1", requestContentType = "application/x-amz-json-1.1", responseContentType = "application/x-amz-json-1.1", + eventStreamMessageContentType = "application/json", validTestStruct = """{"someString":"hello","someInt":5}""", validMessageWithNoHeaderPayloadTraits = """{"someString":"hello","someInt":5}""", validTestUnion = """{"Foo":"hello"}""", @@ -160,6 +163,7 @@ object EventStreamTestModels { mediaType = "application/xml", requestContentType = "application/vnd.amazon.eventstream", responseContentType = "application/xml", + eventStreamMessageContentType = "application/xml", validTestStruct = """ diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/Rust.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/Rust.kt index 89ce563e2a..2f13c96455 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/Rust.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/testutil/Rust.kt @@ -118,7 +118,7 @@ object TestWorkspace { // help rust select the right version when we run cargo test // TODO(https://github.com/smithy-lang/smithy-rs/issues/2048): load this from the msrv property using a // method as we do for runtime crate versions - "[toolchain]\nchannel = \"1.74.1\"\n", + "[toolchain]\nchannel = \"1.75.0\"\n", ) // ensure there at least an empty lib.rs file to avoid broken crates newProject.resolve("src").mkdirs() @@ -466,6 +466,7 @@ private fun String.intoCrate( moduleDescription = null, moduleLicense = null, moduleRepository = null, + minimumSupportedRustVersion = null, writer = this, dependencies = deps, ).render() diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/EnumTraitValidationErrorMessage.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/EnumTraitValidationErrorMessage.kt new file mode 100644 index 0000000000..5144732064 --- /dev/null +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/EnumTraitValidationErrorMessage.kt @@ -0,0 +1,17 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.rust.codegen.server.smithy + +import software.amazon.smithy.model.shapes.Shape +import software.amazon.smithy.model.traits.EnumTrait + +fun EnumTrait.validationErrorMessage() = + "Value at '{}' failed to satisfy constraint: Member must satisfy enum value set: [${enumValueSet()}]" + +fun EnumTrait.shapeConstraintViolationDisplayMessage(shape: Shape) = + "Value provided for '${shape.id}' failed to satisfy constraint: Member must satisfy enum value set: [${enumValueSet()}]" + +fun EnumTrait.enumValueSet() = this.enumDefinitionValues.joinToString(", ") diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/LengthTraitValidationErrorMessage.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/LengthTraitValidationErrorMessage.kt index f31feae6ad..1e91156a9b 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/LengthTraitValidationErrorMessage.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/LengthTraitValidationErrorMessage.kt @@ -5,20 +5,21 @@ package software.amazon.smithy.rust.codegen.server.smithy +import software.amazon.smithy.model.shapes.Shape import software.amazon.smithy.model.traits.LengthTrait -fun LengthTrait.validationErrorMessage(): String { - val beginning = "Value with length {} at '{}' failed to satisfy constraint: Member must have length " - val ending = - if (this.min.isPresent && this.max.isPresent) { - "between ${this.min.get()} and ${this.max.get()}, inclusive" - } else if (this.min.isPresent) { - ( - "greater than or equal to ${this.min.get()}" - ) - } else { - check(this.max.isPresent) - "less than or equal to ${this.max.get()}" - } - return "$beginning$ending" -} +fun LengthTrait.validationErrorMessage() = + "Value with length {} at '{}' failed to satisfy constraint: Member must have length ${this.lengthDescription()}" + +fun LengthTrait.shapeConstraintViolationDisplayMessage(shape: Shape) = + "Value with length {} provided for '${shape.id}' failed to satisfy constraint: Member must have length ${this.lengthDescription()}" + +fun LengthTrait.lengthDescription() = + if (this.min.isPresent && this.max.isPresent) { + "between ${this.min.get()} and ${this.max.get()}, inclusive" + } else if (this.min.isPresent) { + "greater than or equal to ${this.min.get()}" + } else { + check(this.max.isPresent) + "less than or equal to ${this.max.get()}" + } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/PatternTraitValidationErrorMessage.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/PatternTraitValidationErrorMessage.kt new file mode 100644 index 0000000000..0a92c0942c --- /dev/null +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/PatternTraitValidationErrorMessage.kt @@ -0,0 +1,15 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.rust.codegen.server.smithy + +import software.amazon.smithy.model.shapes.Shape +import software.amazon.smithy.model.traits.PatternTrait + +fun PatternTrait.validationErrorMessage() = + "Value at '{}' failed to satisfy constraint: Member must satisfy regular expression pattern: {}" + +fun PatternTrait.shapeConstraintViolationDisplayMessage(shape: Shape) = + "Value provided for `${shape.id}` failed to satisfy the constraint: Member must match the regular expression pattern: {}" diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RangeTraitValidationErrorMessage.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RangeTraitValidationErrorMessage.kt index 560777debb..6eb44f9388 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RangeTraitValidationErrorMessage.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/RangeTraitValidationErrorMessage.kt @@ -5,20 +5,21 @@ package software.amazon.smithy.rust.codegen.server.smithy +import software.amazon.smithy.model.shapes.Shape import software.amazon.smithy.model.traits.RangeTrait -fun RangeTrait.validationErrorMessage(): String { - val beginning = "Value at '{}' failed to satisfy constraint: Member must be " - val ending = - if (this.min.isPresent && this.max.isPresent) { - "between ${this.min.get()} and ${this.max.get()}, inclusive" - } else if (this.min.isPresent) { - ( - "greater than or equal to ${this.min.get()}" - ) - } else { - check(this.max.isPresent) - "less than or equal to ${this.max.get()}" - } - return "$beginning$ending" -} +fun RangeTrait.validationErrorMessage() = + "Value at '{}' failed to satisfy constraint: Member must be ${this.rangeDescription()}" + +fun RangeTrait.shapeConstraintViolationDisplayMessage(shape: Shape) = + "Value for `${shape.id}`failed to satisfy constraint: Member must be ${this.rangeDescription()}" + +fun RangeTrait.rangeDescription() = + if (this.min.isPresent && this.max.isPresent) { + "between ${this.min.get()} and ${this.max.get()}, inclusive" + } else if (this.min.isPresent) { + "greater than or equal to ${this.min.get()}" + } else { + check(this.max.isPresent) + "less than or equal to ${this.max.get()}" + } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerRustSettings.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerRustSettings.kt index 6f6c25a450..1cfb11f5ae 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerRustSettings.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerRustSettings.kt @@ -38,6 +38,7 @@ data class ServerRustSettings( override val codegenConfig: ServerCodegenConfig, override val license: String?, override val examplesUri: String?, + override val minimumSupportedRustVersion: String? = null, override val customizationConfig: ObjectNode?, ) : CoreRustSettings( service, @@ -50,6 +51,7 @@ data class ServerRustSettings( codegenConfig, license, examplesUri, + minimumSupportedRustVersion, customizationConfig, ) { companion object { @@ -71,6 +73,7 @@ data class ServerRustSettings( codegenConfig = ServerCodegenConfig.fromCodegenConfigAndNode(coreCodegenConfig, codegenSettingsNode), license = coreRustSettings.license, examplesUri = coreRustSettings.examplesUri, + minimumSupportedRustVersion = coreRustSettings.minimumSupportedRustVersion, customizationConfig = coreRustSettings.customizationConfig, ) } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UniqueItemsTraitValidationErrorMessage.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UniqueItemsTraitValidationErrorMessage.kt index 938066e17c..3c491ead23 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UniqueItemsTraitValidationErrorMessage.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UniqueItemsTraitValidationErrorMessage.kt @@ -5,9 +5,16 @@ package software.amazon.smithy.rust.codegen.server.smithy +import software.amazon.smithy.model.shapes.Shape import software.amazon.smithy.model.traits.UniqueItemsTrait fun UniqueItemsTrait.validationErrorMessage() = // We're using the `Debug` representation of `Vec` here e.g. `[0, 2, 3]`, which is the exact format we need // to match the expected format of the error message in the protocol tests. "Value with repeated values at indices {:?} at '{}' failed to satisfy constraint: Member must have unique values" + +fun UniqueItemsTrait.shapeConstraintViolationDisplayMessage(shape: Shape) = + """ + Value with repeated values at indices {:?} provided for '${shape.id}' + failed to satisfy constraint: Member must have unique values + """.trimIndent().replace("\n", "") diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/SmithyValidationExceptionDecorator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/SmithyValidationExceptionDecorator.kt index 9e9438b641..255099601c 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/SmithyValidationExceptionDecorator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/SmithyValidationExceptionDecorator.kt @@ -161,8 +161,7 @@ class SmithyValidationExceptionConversionGenerator(private val codegenContext: S override fun enumShapeConstraintViolationImplBlock(enumTrait: EnumTrait) = writable { - val enumValueSet = enumTrait.enumDefinitionValues.joinToString(", ") - val message = "Value at '{}' failed to satisfy constraint: Member must satisfy enum value set: [$enumValueSet]" + val message = enumTrait.validationErrorMessage() rustTemplate( """ pub(crate) fn as_validation_exception_field(self, path: #{String}) -> crate::model::ValidationExceptionField { diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/CollectionConstraintViolationGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/CollectionConstraintViolationGenerator.kt index 77ebf832ee..8c5b3dea8a 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/CollectionConstraintViolationGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/CollectionConstraintViolationGenerator.kt @@ -9,6 +9,8 @@ import software.amazon.smithy.model.shapes.CollectionShape import software.amazon.smithy.rust.codegen.core.rustlang.Visibility import software.amazon.smithy.rust.codegen.core.rustlang.join import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate +import software.amazon.smithy.rust.codegen.core.rustlang.writable +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.makeRustBoxed import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.letIf @@ -80,8 +82,22 @@ class CollectionConstraintViolationGenerator( ${constraintViolationVisibility.toRustQualifier()} enum $constraintViolationName { #{ConstraintViolationVariants:W} } + + impl #{Display} for $constraintViolationName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let message = match self { + #{VariantDisplayMessages:W} + }; + write!(f, "{message}") + } + } + + impl #{Error} for $constraintViolationName {} """, "ConstraintViolationVariants" to constraintViolationVariants.join(",\n"), + "Error" to RuntimeType.StdError, + "Display" to RuntimeType.Display, + "VariantDisplayMessages" to generateDisplayMessageForEachVariant(shape.isReachableFromOperationInput() && isMemberConstrained), ) if (shape.isReachableFromOperationInput()) { @@ -96,4 +112,20 @@ class CollectionConstraintViolationGenerator( } } } + + private fun generateDisplayMessageForEachVariant(memberConstraintVariantPresent: Boolean) = + writable { + for (constraintsInfo in collectionConstraintsInfo) { + constraintsInfo.shapeConstraintViolationDisplayMessage(shape).invoke(this) + } + + if (memberConstraintVariantPresent) { + rustTemplate( + """ + Self::Member(index, failing_member) => format!("Value at index {index} failed to satisfy constraint. {}", + failing_member) + """, + ) + } + } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGenerator.kt index 9d90562908..2380a90f36 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedBlobGenerator.kt @@ -7,6 +7,7 @@ package software.amazon.smithy.rust.codegen.server.smithy.generators import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.shapes.BlobShape +import software.amazon.smithy.model.shapes.Shape import software.amazon.smithy.model.traits.LengthTrait import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.Visibility @@ -18,6 +19,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.render import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate +import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.expectRustMetadata import software.amazon.smithy.rust.codegen.core.smithy.makeMaybeConstrained @@ -26,6 +28,7 @@ import software.amazon.smithy.rust.codegen.core.util.orNull import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.PubCrateConstraintViolationSymbolProvider import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext +import software.amazon.smithy.rust.codegen.server.smithy.shapeConstraintViolationDisplayMessage import software.amazon.smithy.rust.codegen.server.smithy.traits.isReachableFromOperationInput import software.amazon.smithy.rust.codegen.server.smithy.validationErrorMessage @@ -128,8 +131,22 @@ class ConstrainedBlobGenerator( pub enum ${constraintViolation.name} { #{Variants:W} } + + impl #{Display} for ${constraintViolation.name} { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let message = match self { + #{VariantDisplayMessages:W} + }; + write!(f, "{message}") + } + } + + impl #{Error} for ${constraintViolation.name} {} """, "Variants" to constraintsInfo.map { it.constraintViolationVariant }.join(",\n"), + "Error" to RuntimeType.StdError, + "Display" to RuntimeType.Display, + "VariantDisplayMessages" to generateDisplayMessageForEachVariant(), ) if (shape.isReachableFromOperationInput()) { @@ -143,9 +160,22 @@ class ConstrainedBlobGenerator( ) } } + + private fun generateDisplayMessageForEachVariant() = + writable { + blobConstraintsInfo.forEach { + it.shapeConstraintViolationDisplayMessage(shape).invoke(this) + } + } } -data class BlobLength(val lengthTrait: LengthTrait) { +// Each type of constraint that can be put on a Blob must implement the BlobConstraintGenerator +// interface. This allows the +interface BlobConstraintGenerator { + fun shapeConstraintViolationDisplayMessage(shape: Shape): Writable +} + +data class BlobLength(val lengthTrait: LengthTrait) : BlobConstraintGenerator { fun toTraitInfo(): TraitInfo = TraitInfo( { rust("Self::check_length(&value)?;") }, @@ -159,7 +189,8 @@ data class BlobLength(val lengthTrait: LengthTrait) { Self::Length(length) => crate::model::ValidationExceptionField { message: format!("${lengthTrait.validationErrorMessage()}", length, &path), path, - },""", + }, + """, ) }, this::renderValidationFunction, @@ -188,4 +219,15 @@ data class BlobLength(val lengthTrait: LengthTrait) { """, ) } + + override fun shapeConstraintViolationDisplayMessage(shape: Shape) = + writable { + rustTemplate( + """ + Self::Length(length) => { + format!("${lengthTrait.shapeConstraintViolationDisplayMessage(shape).replace("#", "##")}", length) + }, + """, + ) + } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGenerator.kt index d2029bfd2e..9f7aeb637c 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGenerator.kt @@ -9,6 +9,7 @@ import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.codegen.core.SymbolProvider import software.amazon.smithy.model.shapes.CollectionShape import software.amazon.smithy.model.shapes.EnumShape +import software.amazon.smithy.model.shapes.Shape import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.model.shapes.UnionShape import software.amazon.smithy.model.traits.LengthTrait @@ -16,19 +17,23 @@ import software.amazon.smithy.model.traits.Trait import software.amazon.smithy.model.traits.UniqueItemsTrait import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.Visibility +import software.amazon.smithy.rust.codegen.core.rustlang.Writable import software.amazon.smithy.rust.codegen.core.rustlang.docs import software.amazon.smithy.rust.codegen.core.rustlang.documentShape import software.amazon.smithy.rust.codegen.core.rustlang.join import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate +import software.amazon.smithy.rust.codegen.core.rustlang.writable import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.expectRustMetadata import software.amazon.smithy.rust.codegen.core.util.PANIC +import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.orNull import software.amazon.smithy.rust.codegen.server.smithy.PubCrateConstraintViolationSymbolProvider import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.canReachConstrainedShape +import software.amazon.smithy.rust.codegen.server.smithy.shapeConstraintViolationDisplayMessage import software.amazon.smithy.rust.codegen.server.smithy.supportedCollectionConstraintTraits import software.amazon.smithy.rust.codegen.server.smithy.validationErrorMessage @@ -315,6 +320,16 @@ sealed class CollectionTraitInfo { } }, ) + + override fun shapeConstraintViolationDisplayMessage(shape: Shape) = + writable { + rustTemplate( + """ + Self::UniqueItems { duplicate_indices, .. } => + format!("${uniqueItemsTrait.shapeConstraintViolationDisplayMessage(shape).replace("#", "##")}", &duplicate_indices), + """, + ) + } } data class Length(val lengthTrait: LengthTrait) : CollectionTraitInfo() { @@ -354,6 +369,17 @@ sealed class CollectionTraitInfo { } }, ) + + override fun shapeConstraintViolationDisplayMessage(shape: Shape) = + writable { + rustTemplate( + """ + Self::Length(length) => { + format!("${lengthTrait.shapeConstraintViolationDisplayMessage(shape).replace("#", "##")}", length) + }, + """, + ) + } } companion object { @@ -386,4 +412,6 @@ sealed class CollectionTraitInfo { } abstract fun toTraitInfo(): TraitInfo + + abstract fun shapeConstraintViolationDisplayMessage(shape: Shape): Writable } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGenerator.kt index 2128cdaec8..cf84950a63 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGenerator.kt @@ -34,7 +34,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.typeNameContainsNonPubl * If [unconstrainedSymbol] is provided, the `MaybeConstrained` trait is implemented for the constrained type, using the * [unconstrainedSymbol]'s associated type as the associated type for the trait. * - * [`length` trait]: https://awslabs.github.io/smithy/1.0/spec/core/constraint-traits.html#length-trait + * [`length` trait]: https://smithy.io/2.0/spec/constraint-traits.html#length-trait */ class ConstrainedMapGenerator( val codegenContext: ServerCodegenContext, diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGenerator.kt index 248f9a5774..55072a3d47 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGenerator.kt @@ -31,6 +31,7 @@ import software.amazon.smithy.rust.codegen.core.util.redactIfNecessary import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.PubCrateConstraintViolationSymbolProvider import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext +import software.amazon.smithy.rust.codegen.server.smithy.shapeConstraintViolationDisplayMessage import software.amazon.smithy.rust.codegen.server.smithy.traits.isReachableFromOperationInput import software.amazon.smithy.rust.codegen.server.smithy.validationErrorMessage @@ -135,13 +136,23 @@ class ConstrainedNumberGenerator( writer.renderTryFrom(unconstrainedTypeName, name, constraintViolation, constraintsInfo) inlineModuleCreator(constraintViolation) { - rust( + rustTemplate( """ ##[derive(Debug, PartialEq)] pub enum ${constraintViolation.name} { Range($unconstrainedTypeName), } + + impl #{Display} for ${constraintViolation.name} { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "${rangeInfo.rangeTrait.shapeConstraintViolationDisplayMessage(shape).replace("#", "##")}") + } + } + + impl #{Error} for ${constraintViolation.name} {} """, + "Error" to RuntimeType.StdError, + "Display" to RuntimeType.Display, ) if (shape.isReachableFromOperationInput()) { diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedShapeGeneratorCommon.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedShapeGeneratorCommon.kt index e001eda981..5318e92a2d 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedShapeGeneratorCommon.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedShapeGeneratorCommon.kt @@ -14,7 +14,7 @@ fun rustDocsConstrainedTypeEpilogue(typeName: String) = This is a constrained type because its corresponding modeled Smithy shape has one or more [constraint traits]. Use [`$typeName::try_from`] to construct values of this type. - [constraint traits]: https://awslabs.github.io/smithy/1.0/spec/core/constraint-traits.html + [constraint traits]: https://smithy.io/2.0/spec/constraint-traits.html """ fun rustDocsTryFromMethod( diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGenerator.kt index 994dff469f..0bed2b9969 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGenerator.kt @@ -37,6 +37,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.PubCrateConstraintViolationSymbolProvider import software.amazon.smithy.rust.codegen.server.smithy.ServerCargoDependency import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext +import software.amazon.smithy.rust.codegen.server.smithy.shapeConstraintViolationDisplayMessage import software.amazon.smithy.rust.codegen.server.smithy.supportedStringConstraintTraits import software.amazon.smithy.rust.codegen.server.smithy.traits.isReachableFromOperationInput import software.amazon.smithy.rust.codegen.server.smithy.validationErrorMessage @@ -126,7 +127,6 @@ class ConstrainedStringGenerator( } } - impl #{From}<$name> for $inner { fn from(value: $name) -> Self { value.into_inner() @@ -158,8 +158,22 @@ class ConstrainedStringGenerator( pub enum ${constraintViolation.name} { #{Variants:W} } + + impl #{Display} for ${constraintViolation.name} { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let message = match self { + #{VariantDisplayMessages:W} + }; + write!(f, "{message}") + } + } + + impl #{Error} for ${constraintViolation.name} {} """, "Variants" to constraintsInfo.map { it.constraintViolationVariant }.join(",\n"), + "Error" to RuntimeType.StdError, + "Display" to RuntimeType.Display, + "VariantDisplayMessages" to generateDisplayMessageForEachVariant(), ) if (shape.isReachableFromOperationInput()) { @@ -174,6 +188,13 @@ class ConstrainedStringGenerator( } } + private fun generateDisplayMessageForEachVariant() = + writable { + stringConstraintsInfo.forEach { + it.shapeConstraintViolationDisplayMessage(shape).invoke(this) + } + } + private fun renderTests(shape: Shape) { val testCases = TraitInfo.testCases(constraintsInfo) @@ -239,6 +260,17 @@ data class Length(val lengthTrait: LengthTrait) : StringTraitInfo() { """, ) } + + override fun shapeConstraintViolationDisplayMessage(shape: Shape) = + writable { + rustTemplate( + """ + Self::Length(length) => { + format!("${lengthTrait.shapeConstraintViolationDisplayMessage(shape).replace("#", "##")}", length) + }, + """, + ) + } } data class Pattern(val symbol: Symbol, val patternTrait: PatternTrait, val isSensitive: Boolean) : StringTraitInfo() { @@ -278,12 +310,11 @@ data class Pattern(val symbol: Symbol, val patternTrait: PatternTrait, val isSen } fun errorMessage(): Writable { - val pattern = patternTrait.pattern - return writable { + val pattern = patternTrait.pattern.toString().replace("#", "##") rust( """ - format!("Value at '{}' failed to satisfy constraint: Member must satisfy regular expression pattern: {}", &path, r##"$pattern"##) + format!("${patternTrait.validationErrorMessage()}", &path, r##"$pattern"##) """, ) } @@ -297,7 +328,7 @@ data class Pattern(val symbol: Symbol, val patternTrait: PatternTrait, val isSen constraintViolation: Symbol, unconstrainedTypeName: String, ): Writable { - val pattern = patternTrait.pattern + val pattern = patternTrait.pattern.toString().replace("#", "##") val errorMessageForUnsupportedRegex = """The regular expression $pattern is not supported by the `regex` crate; feel free to file an issue under https://github.com/smithy-lang/smithy-rs/issues for support""" @@ -327,6 +358,19 @@ data class Pattern(val symbol: Symbol, val patternTrait: PatternTrait, val isSen ) } } + + override fun shapeConstraintViolationDisplayMessage(shape: Shape) = + writable { + val errorMessage = patternTrait.shapeConstraintViolationDisplayMessage(shape).replace("#", "##") + val pattern = patternTrait.pattern.toString().replace("#", "##") + rustTemplate( + """ + Self::Pattern(_) => { + format!(r##"$errorMessage"##, r##"$pattern"##) + }, + """, + ) + } } sealed class StringTraitInfo { @@ -349,4 +393,6 @@ sealed class StringTraitInfo { } abstract fun toTraitInfo(): TraitInfo + + abstract fun shapeConstraintViolationDisplayMessage(shape: Shape): Writable } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/MapConstraintViolationGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/MapConstraintViolationGenerator.kt index eb4fcc6687..cb25c2176f 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/MapConstraintViolationGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/MapConstraintViolationGenerator.kt @@ -10,12 +10,16 @@ import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.model.traits.LengthTrait import software.amazon.smithy.rust.codegen.core.rustlang.Visibility import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate +import software.amazon.smithy.rust.codegen.core.rustlang.writable +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.makeRustBoxed +import software.amazon.smithy.rust.codegen.core.util.getTrait import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.letIf import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator import software.amazon.smithy.rust.codegen.server.smithy.PubCrateConstraintViolationSymbolProvider import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext +import software.amazon.smithy.rust.codegen.server.smithy.shapeConstraintViolationDisplayMessage import software.amazon.smithy.rust.codegen.server.smithy.traits.ConstraintViolationRustBoxTrait import software.amazon.smithy.rust.codegen.server.smithy.traits.isReachableFromOperationInput @@ -84,8 +88,23 @@ class MapConstraintViolationGenerator( ${if (keyConstraintViolationExists) "##[doc(hidden)] Key(#{KeyConstraintViolationSymbol})," else ""} ${if (valueConstraintViolationExists) "##[doc(hidden)] Value(#{KeySymbol}, #{ValueConstraintViolationSymbol})," else ""} } + + impl #{Display} for $constraintViolationName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ${if (shape.hasTrait()) "#{LengthMatchingArm}" else ""} + ${if (keyConstraintViolationExists) """Self::Key(key_constraint_violation) => write!(f, "{}", key_constraint_violation),""" else ""} + ${if (valueConstraintViolationExists) """Self::Value(_, value_constraint_violation) => write!(f, "{}", value_constraint_violation),""" else ""} + } + } + } + + impl #{Error} for $constraintViolationName {} """, *constraintViolationCodegenScope, + "LengthMatchingArm" to lengthMatchingArm(), + "Error" to RuntimeType.StdError, + "Display" to RuntimeType.Display, ) if (shape.isReachableFromOperationInput()) { @@ -107,4 +126,17 @@ class MapConstraintViolationGenerator( } } } + + private fun lengthMatchingArm() = + writable { + shape.getTrait()?.let { + rustTemplate( + """ + Self::Length(length) => { + write!(f, "${it.shapeConstraintViolationDisplayMessage(shape).replace("#", "##")}", length) + }, + """, + ) + } + } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerEnumGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerEnumGenerator.kt index 354cbc0f66..5bc2218ad1 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerEnumGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerEnumGenerator.kt @@ -20,6 +20,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.module import software.amazon.smithy.rust.codegen.core.util.dq import software.amazon.smithy.rust.codegen.server.smithy.PubCrateConstraintViolationSymbolProvider import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext +import software.amazon.smithy.rust.codegen.server.smithy.shapeConstraintViolationDisplayMessage import software.amazon.smithy.rust.codegen.server.smithy.traits.isReachableFromOperationInput open class ConstrainedEnum( @@ -50,8 +51,18 @@ open class ConstrainedEnum( """ ##[derive(Debug, PartialEq)] pub struct $constraintViolationName(pub(crate) #{String}); + + impl #{Display} for $constraintViolationName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, r##"${context.enumTrait.shapeConstraintViolationDisplayMessage(shape).replace("#", "##")}"##) + } + } + + impl #{Error} for $constraintViolationName {} """, *codegenScope, + "Error" to RuntimeType.StdError, + "Display" to RuntimeType.Display, ) if (shape.isReachableFromOperationInput()) { diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt index b4a0976e6b..b1130ac6e5 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGenerator.kt @@ -25,6 +25,7 @@ import software.amazon.smithy.rust.codegen.core.smithy.makeMaybeConstrained import software.amazon.smithy.rust.codegen.core.smithy.makeRustBoxed import software.amazon.smithy.rust.codegen.core.smithy.traits.RustBoxTrait import software.amazon.smithy.rust.codegen.core.util.hasTrait +import software.amazon.smithy.rust.codegen.core.util.isTargetUnit import software.amazon.smithy.rust.codegen.core.util.letIf import software.amazon.smithy.rust.codegen.core.util.toPascalCase import software.amazon.smithy.rust.codegen.server.smithy.InlineModuleCreator @@ -86,10 +87,16 @@ class UnconstrainedUnionGenerator( """, ) { sortedMembers.forEach { member -> - rust( - "${unconstrainedShapeSymbolProvider.toMemberName(member)}(#T),", - unconstrainedShapeSymbolProvider.toSymbol(member), - ) + if (member.isTargetUnit()) { + rust( + "${unconstrainedShapeSymbolProvider.toMemberName(member)},", + ) + } else { + rust( + "${unconstrainedShapeSymbolProvider.toMemberName(member)}(#T),", + unconstrainedShapeSymbolProvider.toSymbol(member), + ) + } } } @@ -147,6 +154,23 @@ class UnconstrainedUnionGenerator( constraintViolations().forEach { renderConstraintViolation(this, it) } } + rustTemplate( + """ + impl #{Display} for $constraintViolationName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + #{ConstraintVariants:W} + } + } + } + + impl #{Error} for $constraintViolationName {} + """, + "Error" to RuntimeType.StdError, + "Display" to RuntimeType.Display, + "ConstraintVariants" to generateDisplayMessageForEachVariant(), + ) + if (shape.isReachableFromOperationInput()) { rustBlock("impl $constraintViolationName") { rustBlockTemplate( @@ -164,6 +188,17 @@ class UnconstrainedUnionGenerator( } } + private fun generateDisplayMessageForEachVariant() = + writable { + constraintViolations().forEach { + rustTemplate( + """ + Self::${it.name()}(inner) => write!(f, "{inner}"), + """, + ) + } + } + data class ConstraintViolation(val forMember: MemberShape) { fun name() = forMember.memberName.toPascalCase() } @@ -198,60 +233,24 @@ class UnconstrainedUnionGenerator( withBlock("match value {", "}") { sortedMembers.forEach { member -> val memberName = unconstrainedShapeSymbolProvider.toMemberName(member) - withBlockTemplate( - "#{UnconstrainedUnion}::$memberName(unconstrained) => Self::$memberName(", - "),", - "UnconstrainedUnion" to symbol, - ) { - if (!member.canReachConstrainedShape(model, symbolProvider)) { - rust("unconstrained") - } else { - val targetShape = model.expectShape(member.target) - val resolveToNonPublicConstrainedType = - targetShape !is StructureShape && targetShape !is UnionShape && !targetShape.hasTrait() && - (!publicConstrainedTypes || !targetShape.isDirectlyConstrained(symbolProvider)) - - val (unconstrainedVar, boxIt) = - if (member.hasTrait()) { - "(*unconstrained)" to ".map(Box::new)" - } else { - "unconstrained" to "" - } - val boxErr = - if (member.hasTrait()) { - ".map_err(Box::new)" - } else { - "" - } - - if (resolveToNonPublicConstrainedType) { - val constrainedSymbol = - if (!publicConstrainedTypes && targetShape.isDirectlyConstrained(symbolProvider)) { - codegenContext.constrainedShapeSymbolProvider.toSymbol(targetShape) - } else { - pubCrateConstrainedShapeSymbolProvider.toSymbol(targetShape) - } - rustTemplate( - """ - { - let constrained: #{ConstrainedSymbol} = $unconstrainedVar - .try_into()$boxIt$boxErr - .map_err(Self::Error::${ConstraintViolation(member).name()})?; - constrained.into() - } - """, - "ConstrainedSymbol" to constrainedSymbol, - ) + if (member.isTargetUnit()) { + // Unit type within Unions do not have associated data. + rustTemplate( + """ + #{UnconstrainedUnion}::$memberName => Self::$memberName, + """, + "UnconstrainedUnion" to symbol, + ) + } else { + withBlockTemplate( + "#{UnconstrainedUnion}::$memberName(unconstrained) => Self::$memberName(", + "),", + "UnconstrainedUnion" to symbol, + ) { + if (!member.canReachConstrainedShape(model, symbolProvider)) { + rust("unconstrained") } else { - rust( - """ - $unconstrainedVar - .try_into() - $boxIt - $boxErr - .map_err(Self::Error::${ConstraintViolation(member).name()})? - """, - ) + generateTryFromImplForReachableConstrainedShape(member).invoke(this) } } } @@ -259,4 +258,55 @@ class UnconstrainedUnionGenerator( } } } + + private fun generateTryFromImplForReachableConstrainedShape(member: MemberShape) = + writable { + val targetShape = model.expectShape(member.target) + val resolveToNonPublicConstrainedType = + targetShape !is StructureShape && targetShape !is UnionShape && !targetShape.hasTrait() && + (!publicConstrainedTypes || !targetShape.isDirectlyConstrained(symbolProvider)) + + val (unconstrainedVar, boxIt) = + if (member.hasTrait()) { + "(*unconstrained)" to ".map(Box::new)" + } else { + "unconstrained" to "" + } + val boxErr = + if (member.hasTrait()) { + ".map_err(Box::new)" + } else { + "" + } + + if (resolveToNonPublicConstrainedType) { + val constrainedSymbol = + if (!publicConstrainedTypes && targetShape.isDirectlyConstrained(symbolProvider)) { + codegenContext.constrainedShapeSymbolProvider.toSymbol(targetShape) + } else { + pubCrateConstrainedShapeSymbolProvider.toSymbol(targetShape) + } + rustTemplate( + """ + { + let constrained: #{ConstrainedSymbol} = $unconstrainedVar + .try_into()$boxIt$boxErr + .map_err(Self::Error::${ConstraintViolation(member).name()})?; + constrained.into() + } + """, + "ConstrainedSymbol" to constrainedSymbol, + ) + } else { + rust( + """ + $unconstrainedVar + .try_into() + $boxIt + $boxErr + .map_err(Self::Error::${ConstraintViolation(member).name()})? + """, + ) + } + } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt index b5678277c8..fc1b7e9b80 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt @@ -627,7 +627,7 @@ class ServerProtocolTestGenerator( if (testCase.body.isEmpty) return val httpMalformedResponseBodyDefinition = testCase.body.get() - // From https://awslabs.github.io/smithy/1.0/spec/http-protocol-compliance-tests.html?highlight=httpresponsetest#httpmalformedresponsebodyassertion + // From https://smithy.io/2.0/additional-specs/http-protocol-compliance-tests.html#httpmalformedresponsebodyassertion // // A union describing the assertion to run against the response body. As it is a union, exactly one // member must be set. @@ -813,10 +813,6 @@ class ServerProtocolTestGenerator( FailingTest(RestJson, "RestJsonEndpointTrait", TestType.Request), FailingTest(RestJson, "RestJsonEndpointTraitWithHostLabel", TestType.Request), FailingTest(RestJson, "RestJsonOmitsEmptyListQueryValues", TestType.Request), - // TODO(https://github.com/smithy-lang/smithy/pull/2167): BEGIN Remove this failing test once it's fixed in Smithy - FailingTest(RestJson, "RestJsonZeroAndFalseQueryValues", TestType.Request), - FailingTest(RestJsonExtras, "RestJsonZeroAndFalseQueryValues", TestType.Request), - // TODO(https://github.com/smithy-lang/smithy/pull/2167): END Remove this failing test once it's fixed in Smithy // Tests involving `@range` on floats. // Pending resolution from the Smithy team, see https://github.com/smithy-lang/smithy-rs/issues/2007. FailingTest(RestJsonValidation, "RestJsonMalformedRangeFloat_case0", TestType.MalformedRequest), @@ -915,6 +911,8 @@ class ServerProtocolTestGenerator( // RestXml S3 tests that fail to compile "S3EscapeObjectKeyInUriLabel", "S3EscapePathObjectKeyInUriLabel", + "S3PreservesLeadingDotSegmentInUriLabel", + "S3PreservesEmbeddedDotSegmentInUriLabel", ) // TODO(https://github.com/awslabs/smithy/issues/1506) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerAwsJson.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerAwsJson.kt index f967e9450d..459ebbcd56 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerAwsJson.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerAwsJson.kt @@ -86,10 +86,10 @@ class ServerAwsJsonError(private val awsJsonVersion: AwsJsonVersion) : JsonSeria val typeId = when (awsJsonVersion) { // AwsJson 1.0 wants the whole shape ID (namespace#Shape). - // https://awslabs.github.io/smithy/1.0/spec/aws/aws-json-1_0-protocol.html#operation-error-serialization + // https://smithy.io/2.0/aws/protocols/aws-json-1_0-protocol.html#operation-error-serialization AwsJsonVersion.Json10 -> section.structureShape.id.toString() // AwsJson 1.1 wants only the shape name (Shape). - // https://awslabs.github.io/smithy/1.0/spec/aws/aws-json-1_1-protocol.html#operation-error-serialization + // https://smithy.io/2.0/aws/protocols/aws-json-1_1-protocol.html#operation-error-serialization AwsJsonVersion.Json11 -> section.structureShape.id.name.toString() } rust("""${section.jsonObject}.key("__type").string("${escape(typeId)}");""") @@ -104,7 +104,7 @@ class ServerAwsJsonError(private val awsJsonVersion: AwsJsonVersion) : JsonSeria * AwsJson requires operation errors to be serialized in server response with an additional `__type` field. This class * customizes [JsonSerializerGenerator] to add this functionality. * - * https://awslabs.github.io/smithy/1.0/spec/aws/aws-json-1_0-protocol.html#operation-error-serialization + * https://smithy.io/2.0/aws/protocols/aws-json-1_0-protocol.html#operation-error-serialization */ class ServerAwsJsonSerializerGenerator( private val codegenContext: ServerCodegenContext, diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt index 071b109504..910acf4a70 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt @@ -214,7 +214,7 @@ class ServerHttpBoundProtocolTraitImplGenerator( /* * Generation of `from_request` and `into_response`. * For non-streaming request bodies, that is, models without streaming traits - * (https://awslabs.github.io/smithy/1.0/spec/core/stream-traits.html) + * (https://smithy.io/2.0/spec/streaming.html#streaming-trait) * we require the HTTP body to be fully read in memory before parsing or deserialization. * From a server perspective we need a way to parse an HTTP request from `Bytes` and serialize * an HTTP response to `Bytes`. diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt index 03643d80a8..a03dfbdd4e 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/testutil/ServerTestHelpers.kt @@ -81,6 +81,7 @@ fun serverTestRustSettings( codegenConfig: ServerCodegenConfig = ServerCodegenConfig(), license: String? = null, examplesUri: String? = null, + minimumSupportedRustVersion: String? = null, customizationConfig: ObjectNode? = null, ) = ServerRustSettings( service, @@ -93,6 +94,7 @@ fun serverTestRustSettings( codegenConfig, license, examplesUri, + minimumSupportedRustVersion, customizationConfig, ) diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnionWithUnitTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnionWithUnitTest.kt new file mode 100644 index 0000000000..3f48d86e1f --- /dev/null +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/UnionWithUnitTest.kt @@ -0,0 +1,77 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.rust.codegen.server.smithy + +import org.junit.jupiter.api.Test +import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel +import software.amazon.smithy.rust.codegen.server.smithy.testutil.serverIntegrationTest + +class UnionWithUnitTest { + @Test + fun `a constrained union that has a unit member should compile`() { + val model = + """ + ${'$'}version: "2" + namespace com.example + use aws.protocols#restJson1 + use smithy.framework#ValidationException + + @restJson1 @title("Test Service") + service TestService { + version: "0.1", + operations: [ + TestOperation + TestSimpleUnionWithUnit + ] + } + + @http(uri: "/testunit", method: "POST") + operation TestSimpleUnionWithUnit { + input := { + @required + request: SomeUnionWithUnit + } + output := { + result : SomeUnionWithUnit + } + errors: [ + ValidationException + ] + } + + @length(min: 13) + string StringRestricted + + union SomeUnionWithUnit { + Option1: Unit + Option2: StringRestricted + } + + @http(uri: "/test", method: "POST") + operation TestOperation { + input := { payload: String } + output := { + @httpPayload + events: TestEvent + }, + errors: [ValidationException] + } + + @streaming + union TestEvent { + KeepAlive: Unit, + Response: TestResponseEvent, + } + + structure TestResponseEvent { + data: String + } + """.asSmithyModel() + + // Ensure the generated SDK compiles. + serverIntegrationTest(model) { _, _ -> } + } +} diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt index 23158df233..ee8d5acde6 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedCollectionGeneratorTest.kt @@ -18,6 +18,7 @@ import software.amazon.smithy.model.node.ArrayNode import software.amazon.smithy.model.shapes.CollectionShape import software.amazon.smithy.model.shapes.ListShape import software.amazon.smithy.model.shapes.SetShape +import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.Writable import software.amazon.smithy.rust.codegen.core.rustlang.rust @@ -25,6 +26,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.rustlang.withBlock import software.amazon.smithy.rust.codegen.core.rustlang.writable +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest @@ -177,6 +179,10 @@ class ConstrainedCollectionGeneratorTest { val codegenContext = serverTestCodegenContext(testCase.model) val project = TestWorkspace.testProject(codegenContext.symbolProvider) + project.withModule(ServerRustModule.Model) { + TestUtility.generateIsDisplay().invoke(this) + TestUtility.generateIsError().invoke(this) + } for (shape in listOf(constrainedListShape, constrainedSetShape)) { val shapeName = @@ -256,7 +262,15 @@ class ConstrainedCollectionGeneratorTest { withBlock("let expected_err = ", ";") { rustTemplate("#{ExpectedError:W}", "ExpectedError" to expectedErrorWritable) } - rust("assert_eq!(err, expected_err);") + rust( + """ + assert_eq!(err, expected_err); + is_error(&err); + is_display(&err); + // Ensure that the `std::fmt::Display` implementation for `ConstraintViolation` error works. + assert_eq!(err.to_string(), expected_err.to_string()); + """.trimMargin(), + ) } ?: run { rust("constrained_res.unwrap_err();") } @@ -291,6 +305,110 @@ class ConstrainedCollectionGeneratorTest { writer.toString() shouldContain "pub struct ConstrainedList(pub(crate) ::std::vec::Vec<::std::string::String>);" } + @Test + fun `error trait implemented for ConstraintViolation should work for constrained member`() { + val model = + """ + ${'$'}version: "1.0" + + namespace test + + use aws.protocols#restJson1 + use smithy.framework#ValidationException + + // The `ConstraintViolation` code generated for a constrained map that is not reachable from an + // operation does not have the `Key`, or `Value` variants. Hence, we need to define a service + // and an operation that uses the constrained map. + @restJson1 + service MyService { + version: "2023-04-01", + operations: [ + MyOperation, + ] + } + + @http(method: "POST", uri: "/echo") + operation MyOperation { + input: MyOperationInput + errors : [ValidationException] + } + + @input + structure MyOperationInput { + member1: ConstrainedList, + member2: ConstrainedSet, + } + + @length(min: 2, max: 69) + list ConstrainedList { + member: ConstrainedString + } + + @length(min: 2, max: 69) + set ConstrainedSet { + member: ConstrainedString + } + + @pattern("#\\d+") + string ConstrainedString + """.asSmithyModel().let(ShapesReachableFromOperationInputTagger::transform) + + val codegenContext = serverTestCodegenContext(model) + val symbolProvider = codegenContext.symbolProvider + val project = TestWorkspace.testProject(symbolProvider) + + project.withModule(ServerRustModule.Model) { + TestUtility.generateIsDisplay().invoke(this) + TestUtility.generateIsError().invoke(this) + TestUtility.renderConstrainedString( + codegenContext, this, + model.lookup("test#ConstrainedString"), + ) + + rustTemplate( + """ + // Define `ValidationExceptionField` since it is required by the `ConstraintViolation` code for constrained maps, + // and the complete SDK generation process, which would generate it, is not invoked as part of the test. + pub struct ValidationExceptionField { + pub message: String, + pub path: String + } + """, + "Result" to RuntimeType.std.resolve("Result"), + ) + + val constrainedListShape = model.lookup("test#ConstrainedList") + val constrainedSetShape = model.lookup("test#ConstrainedSet") + render(codegenContext, this, constrainedListShape) + render(codegenContext, this, constrainedSetShape) + + unitTest( + name = "try_from_fail_invalid_constrained_list", + test = """ + let constrained_error = ConstrainedString::try_from("one".to_string()).unwrap_err(); + let error = crate::model::constrained_list::ConstraintViolation::Member(0, constrained_error); + is_error(&error); + is_display(&error); + assert_eq!("Value at index 0 failed to satisfy constraint. Value provided for `test#ConstrainedString` failed to satisfy the constraint: Member must match the regular expression pattern: #\\d+", + error.to_string()); + """, + ) + unitTest( + name = "try_from_fail_invalid_constrained_set", + test = """ + let constrained_error = ConstrainedString::try_from("one".to_string()).unwrap_err(); + let error = crate::model::constrained_set::ConstraintViolation::Member(0, constrained_error); + is_error(&error); + is_display(&error); + assert_eq!("Value at index 0 failed to satisfy constraint. Value provided for `test#ConstrainedString` failed to satisfy the constraint: Member must match the regular expression pattern: #\\d+", + error.to_string()); + """, + ) + } + + project.compileAndTest() + } + private fun render( codegenContext: ServerCodegenContext, writer: RustWriter, diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt index ae050460a4..b52d4a0397 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedMapGeneratorTest.kt @@ -15,13 +15,17 @@ import org.junit.jupiter.params.provider.ArgumentsSource import software.amazon.smithy.model.Model import software.amazon.smithy.model.node.ObjectNode import software.amazon.smithy.model.shapes.MapShape +import software.amazon.smithy.model.shapes.StringShape import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock +import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup +import software.amazon.smithy.rust.codegen.core.util.toSnakeCase import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.ServerRustModule import software.amazon.smithy.rust.codegen.server.smithy.createTestInlineModuleCreator @@ -79,6 +83,9 @@ class ConstrainedMapGeneratorTest { val project = TestWorkspace.testProject(symbolProvider) project.withModule(ServerRustModule.Model) { + TestUtility.generateIsDisplay().invoke(this) + TestUtility.generateIsError().invoke(this) + render(codegenContext, this, constrainedMapShape) val instantiator = ServerInstantiator(codegenContext) @@ -101,7 +108,10 @@ class ConstrainedMapGeneratorTest { test = """ let map = build_invalid_map(); let constrained_res: Result = map.try_into(); - constrained_res.unwrap_err(); + let error = constrained_res.unwrap_err(); + + is_display(&error); + is_error(&error); """, ) unitTest( @@ -150,6 +160,161 @@ class ConstrainedMapGeneratorTest { writer.toString() shouldContain "pub struct ConstrainedMap(pub(crate) ::std::collections::HashMap<::std::string::String, ::std::string::String>);" } + @Test + fun `error trait implemented for ConstraintViolation should work for constrained key and value`() { + val model = + """ + ${'$'}version: "2" + + namespace test + + use aws.protocols#restJson1 + use smithy.framework#ValidationException + + // The `ConstraintViolation` code generated for a constrained map that is not reachable from an + // operation does not have the `Key`, or `Value` variants. Hence, we need to define a service + // and an operation that uses the constrained map. + @restJson1 + service MyService { + version: "2023-04-01", + operations: [ + MyOperation, + ] + } + + @http(method: "POST", uri: "/echo") + operation MyOperation { + input:= { + member1: ConstrainedMapWithConstrainedKey, + member2: ConstrainedMapWithConstrainedKeyAndValue, + member3: ConstrainedMapWithConstrainedValue, + }, + output:= {}, + errors : [ValidationException] + } + + @length(min: 2, max: 69) + map ConstrainedMapWithConstrainedKey { + key: ConstrainedKey, + value: String + } + + @length(min: 2, max: 69) + map ConstrainedMapWithConstrainedValue { + key: String, + value: ConstrainedValue + } + + @length(min: 2, max: 69) + map ConstrainedMapWithConstrainedKeyAndValue { + key: ConstrainedKey, + value: ConstrainedValue, + } + + @pattern("#\\d+") + string ConstrainedKey + + @pattern("A-Z") + string ConstrainedValue + """.asSmithyModel().let(ShapesReachableFromOperationInputTagger::transform) + val constrainedKeyShape = model.lookup("test#ConstrainedKey") + val constrainedValueShape = model.lookup("test#ConstrainedValue") + + val codegenContext = serverTestCodegenContext(model) + val symbolProvider = codegenContext.symbolProvider + val project = TestWorkspace.testProject(symbolProvider) + + project.withModule(ServerRustModule.Model) { + TestUtility.generateIsDisplay().invoke(this) + TestUtility.generateIsError().invoke(this) + TestUtility.renderConstrainedString(codegenContext, this, constrainedKeyShape) + TestUtility.renderConstrainedString(codegenContext, this, constrainedValueShape) + + val mapsToVerify = + listOf( + model.lookup("test#ConstrainedMapWithConstrainedKey"), + model.lookup("test#ConstrainedMapWithConstrainedKeyAndValue"), + model.lookup("test#ConstrainedMapWithConstrainedValue"), + ) + + rustTemplate( + """ + fn build_invalid_constrained_map_with_constrained_key() -> #{HashMap} { + let mut m = ::std::collections::HashMap::new(); + m.insert(ConstrainedKey("1".to_string()), "Y".to_string()); + m + } + fn build_invalid_constrained_map_with_constrained_key_and_value() -> std::collections::HashMap { + let mut m = ::std::collections::HashMap::new(); + m.insert(ConstrainedKey("1".to_string()), ConstrainedValue("Y".to_string())); + m + } + fn build_invalid_constrained_map_with_constrained_value() -> std::collections::HashMap { + let mut m = ::std::collections::HashMap::new(); + m.insert("1".to_string(), ConstrainedValue("Y".to_string())); + m + } + + // Define `ValidationExceptionField` since it is required by the `ConstraintViolation` code for constrained maps, + // and the complete SDK generation process, which would generate it, is not invoked as part of the test. + pub struct ValidationExceptionField { + pub message: String, + pub path: String + } + """, + "HashMap" to RuntimeType.HashMap, + ) + + for (mapToVerify in mapsToVerify) { + val rustShapeName = mapToVerify.toShapeId().name + val rustShapeSnakeCaseName = rustShapeName.toSnakeCase() + + render(codegenContext, this, mapToVerify) + + unitTest( + name = "try_from_fail_$rustShapeSnakeCaseName", + test = """ + let map = build_invalid_$rustShapeSnakeCaseName(); + let constrained_res: Result<$rustShapeName, $rustShapeSnakeCaseName::ConstraintViolation> = map.try_into(); + let error = constrained_res.unwrap_err(); + is_error(&error); + is_display(&error); + assert_eq!("Value with length 1 provided for 'test#$rustShapeName' failed to satisfy constraint: Member must have length between 2 and 69, inclusive", error.to_string()); + """, + ) + } + + unitTest( + name = "try_constrained_key", + test = + """ + let error = constrained_map_with_constrained_key::ConstraintViolation::Key(constrained_key::ConstraintViolation::Pattern("some error".to_string())); + assert_eq!(error.to_string(), "Value provided for `test#ConstrainedKey` failed to satisfy the constraint: Member must match the regular expression pattern: #\\d+"); + """, + ) + unitTest( + name = "try_constrained_value", + test = + """ + let error = constrained_map_with_constrained_value::ConstraintViolation::Value("some_key".to_string(), constrained_value::ConstraintViolation::Pattern("some error".to_string())); + assert_eq!(error.to_string(), "Value provided for `test#ConstrainedValue` failed to satisfy the constraint: Member must match the regular expression pattern: A-Z"); + """, + ) + unitTest( + name = "try_constrained_key_and_value", + test = + """ + let error = constrained_map_with_constrained_key_and_value::ConstraintViolation::Key(constrained_key::ConstraintViolation::Pattern("some error".to_string())); + assert_eq!(error.to_string(), "Value provided for `test#ConstrainedKey` failed to satisfy the constraint: Member must match the regular expression pattern: #\\d+"); + let error = constrained_map_with_constrained_key_and_value::ConstraintViolation::Value(ConstrainedKey("1".to_string()), constrained_value::ConstraintViolation::Pattern("some error".to_string())); + assert_eq!(error.to_string(), "Value provided for `test#ConstrainedValue` failed to satisfy the constraint: Member must match the regular expression pattern: A-Z"); + """, + ) + } + + project.compileAndTest() + } + private fun render( codegenContext: ServerCodegenContext, writer: RustWriter, diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt index 9e19265e59..ca87b29abd 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt @@ -73,6 +73,9 @@ class ConstrainedNumberGeneratorTest { val project = TestWorkspace.testProject(symbolProvider) project.withModule(ServerRustModule.Model) { + TestUtility.generateIsDisplay().invoke(this) + TestUtility.generateIsError().invoke(this) + ConstrainedNumberGenerator( codegenContext, this.createTestInlineModuleCreator(), @@ -91,7 +94,9 @@ class ConstrainedNumberGeneratorTest { name = "try_from_fail", test = """ let constrained_res: Result<${testCase.shapeName}, _> = ${testCase.invalidValue}.try_into(); - constrained_res.unwrap_err(); + let error = constrained_res.unwrap_err(); + is_error(&error); + is_display(&error); """, ) unitTest( diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt index bdc89c0078..3333602b5a 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedStringGeneratorTest.kt @@ -53,9 +53,9 @@ class ConstrainedStringGeneratorTest { Triple( """ @length(min: 3, max: 10) - @pattern("^a string$") + @pattern("^a # string$") """, - "a string", "an invalid string", + "a # string", "an invalid string", ), Triple("@pattern(\"123\")", "some pattern 123 in the middle", "no pattern at all"), ).map { @@ -86,6 +86,9 @@ class ConstrainedStringGeneratorTest { val project = TestWorkspace.testProject(symbolProvider) project.withModule(ServerRustModule.Model) { + TestUtility.generateIsDisplay().invoke(this) + TestUtility.generateIsError().invoke(this) + ConstrainedStringGenerator( codegenContext, this.createTestInlineModuleCreator(), @@ -106,7 +109,9 @@ class ConstrainedStringGeneratorTest { test = """ let string = "${testCase.invalidString}".to_owned(); let constrained_res: Result = string.try_into(); - constrained_res.unwrap_err(); + let error = constrained_res.unwrap_err(); + is_error(&error); + is_display(&error); """, ) unitTest( diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/TestUtility.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/TestUtility.kt new file mode 100644 index 0000000000..d01218bbba --- /dev/null +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/TestUtility.kt @@ -0,0 +1,52 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.rust.codegen.server.smithy.generators + +import software.amazon.smithy.model.shapes.StringShape +import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter +import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate +import software.amazon.smithy.rust.codegen.core.rustlang.writable +import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType +import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext +import software.amazon.smithy.rust.codegen.server.smithy.createTestInlineModuleCreator +import software.amazon.smithy.rust.codegen.server.smithy.customizations.SmithyValidationExceptionConversionGenerator + +object TestUtility { + fun generateIsDisplay() = + writable { + rustTemplate( + """ + pub fn is_display(_t: &T) { } + """, + "Display" to RuntimeType.Display, + ) + } + + fun generateIsError() = + writable { + rustTemplate( + """ + pub fn is_error(_t: &T) { } + """, + "Error" to RuntimeType.StdError, + ) + } + + fun renderConstrainedString( + codegenContext: ServerCodegenContext, + writer: RustWriter, + constrainedStringShape: StringShape, + ) { + val validationExceptionConversionGenerator = SmithyValidationExceptionConversionGenerator(codegenContext) + ConstrainedStringGenerator( + codegenContext, + writer.createTestInlineModuleCreator(), + writer, + constrainedStringShape, + validationExceptionConversionGenerator, + ).render() + } +} diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt index 45f8b33fbc..ce6c693d4c 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedMapGeneratorTest.kt @@ -11,6 +11,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.smithy.CoreCodegenConfig import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace import software.amazon.smithy.rust.codegen.core.testutil.asSmithyModel +import software.amazon.smithy.rust.codegen.core.testutil.compileAndTest import software.amazon.smithy.rust.codegen.core.testutil.testModule import software.amazon.smithy.rust.codegen.core.testutil.unitTest import software.amazon.smithy.rust.codegen.core.util.lookup @@ -71,6 +72,9 @@ class UnconstrainedMapGeneratorTest { serverIntegrationTest(model) { _, rustCrate -> rustCrate.testModule { + TestUtility.generateIsDisplay().invoke(this) + TestUtility.generateIsError().invoke(this) + unitTest("map_a_unconstrained_fail_to_constrain_with_some_error") { rust( """ @@ -105,8 +109,17 @@ class UnconstrainedMapGeneratorTest { ); let actual_err = crate::constrained::map_a_constrained::MapAConstrained::try_from(map_a_unconstrained).unwrap_err(); - assert!(actual_err == missing_string_expected_err || actual_err == missing_int_expected_err); + + is_display(&actual_err); + is_error(&actual_err); + + let error_str = actual_err.to_string(); + assert!( + error_str == "`string` was not provided but it is required when building `StructureC`" + || error_str + == "`int` was not provided but it is required when building `StructureC`" + ); """, ) } @@ -162,5 +175,7 @@ class UnconstrainedMapGeneratorTest { } } } + + project.compileAndTest() } } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt index 613ee61876..3c23461ac0 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/UnconstrainedUnionGeneratorTest.kt @@ -59,6 +59,9 @@ class UnconstrainedUnionGeneratorTest { } project.withModule(ServerRustModule.UnconstrainedModule) unconstrainedModuleWriter@{ + TestUtility.generateIsDisplay().invoke(this) + TestUtility.generateIsError().invoke(this) + project.withModule(ServerRustModule.Model) modelsModuleWriter@{ UnconstrainedUnionGenerator(codegenContext, project.createInlineModuleCreator(), this@modelsModuleWriter, unionShape).render() @@ -71,11 +74,13 @@ class UnconstrainedUnionGeneratorTest { let expected_err = crate::model::union::ConstraintViolation::Structure( crate::model::structure::ConstraintViolation::MissingRequiredMember, ); - + let err = crate::model::Union::try_from(union_unconstrained).unwrap_err(); assert_eq!( - expected_err, - crate::model::Union::try_from(union_unconstrained).unwrap_err() + expected_err, err ); + is_display(&err); + is_error(&err); + assert_eq!(err.to_string(), "`required_member` was not provided but it is required when building `Structure`"); """, ) diff --git a/design/src/SUMMARY.md b/design/src/SUMMARY.md index 5022659593..665fafd9e8 100644 --- a/design/src/SUMMARY.md +++ b/design/src/SUMMARY.md @@ -3,16 +3,11 @@ - [Design Overview](./overview.md) - [Tenets](./tenets.md) - [Design FAQ](./faq.md) -- [Transport](transport/overview.md) - - [HTTP Operations](transport/operation.md) - - [HTTP Middleware](transport/middleware.md) - - [TLS Connector](transport/connector.md) - [Smithy](./smithy/overview.md) - [Simple Shapes](./smithy/simple_shapes.md) - [Recursive Shapes](./smithy/recursive_shapes.md) - [Aggregate Shapes](./smithy/aggregate_shapes.md) - - [Endpoint Resolution](smithy/endpoint.md) - [Backwards Compatibility](smithy/backwards-compat.md) - [Client](./client/overview.md) @@ -67,6 +62,9 @@ - [RFC-0038: User-configurable retry classification](./rfcs/rfc0038_retry_classifier_customization.md) - [RFC-0039: Forward Compatible Errors](./rfcs/rfc0039_forward_compatible_errors.md) - [RFC-0040: Behavior Versions](./rfcs/rfc0040_behavior_versions.md) - + - [RFC-0041: Improve client error ergonomics](./rfcs/rfc0041_improve_client_error_ergonomics.md) + - [RFC-0042: File-per-change changelog](./rfcs/rfc0042_file_per_change_changelog.md) + - [RFC-0043: Identity Cache Partitions](./rfcs/rfc0043_identity_cache_partitions.md) + - [RFC-0044: Environment-defined service configuration](./rfcs/rfc0044_env_defined_service_config.md) - [Contributing](./contributing/overview.md) - [Writing and debugging a low-level feature that relies on HTTP](./contributing/writing_and_debugging_a_low-level_feature_that_relies_on_HTTP.md) diff --git a/design/src/rfcs/overview.md b/design/src/rfcs/overview.md index 11d036d535..d44f6f591f 100644 --- a/design/src/rfcs/overview.md +++ b/design/src/rfcs/overview.md @@ -50,3 +50,8 @@ - [RFC-0038: Retry Classifier Customization](./rfc0038_retry_classifier_customization.md) - [RFC-0039: Forward Compatible Errors](./rfc0039_forward_compatible_errors.md) - [RFC-0040: Behavior Versions](./rfc0040_behavior_versions.md) +- [RFC-0041: Improve client error ergonomics](./rfc0041_improve_client_error_ergonomics.md) +- [RFC-0042: File-per-change changelog](./rfc0042_file_per_change_changelog.md) +- [RFC-0043: Identity Cache Partitions](./rfc0043_identity_cache_partitions.md) + +>>>>>>> 4a8757c23 (add RFC to fix identity cache partitioning and default cache behaviors) diff --git a/design/src/rfcs/rfc0041_improve_client_error_ergonomics.md b/design/src/rfcs/rfc0041_improve_client_error_ergonomics.md new file mode 100644 index 0000000000..94aefafd21 --- /dev/null +++ b/design/src/rfcs/rfc0041_improve_client_error_ergonomics.md @@ -0,0 +1,113 @@ +RFC: Improve Client Error Ergonomics +==================================== + +> Status: Implemented +> +> Applies to: clients + +This RFC proposes some changes to code generated errors to make them easier to use for customers. +With the SDK and code generated clients, customers have two primary use-cases that should be made +easy without compromising the compatibility rules established in [RFC-0022]: + +1. Checking the error type +2. Retrieving information specific to that error type + +Case Study: Handling an error in S3 +----------------------------------- + +The following is an example of handling errors with S3 with the latest generated (and unreleased) +SDK as of 2022-12-07: + +```rust,ignore +let result = client + .get_object() + .bucket(BUCKET_NAME) + .key("some-key") + .send() + .await; + match result { + Ok(_output) => { /* Do something with the output */ } + Err(err) => match err.into_service_error() { + GetObjectError { kind, .. } => match kind { + GetObjectErrorKind::InvalidObjectState(value) => println!("invalid object state: {:?}", value), + GetObjectErrorKind::NoSuchKey(_) => println!("object didn't exist"), + } + err @ GetObjectError { .. } if err.code() == Some("SomeUnmodeledError") => {} + err @ _ => return Err(err.into()), + }, + } +``` + +The refactor that implemented [RFC-0022] added the `into_service_error()` method on `SdkError` that +infallibly converts the `SdkError` into the concrete error type held by the `SdkError::ServiceError` variant. +This improvement lets customers discard transient failures and immediately handle modeled errors +returned by the service. + +Despite this, the code is still quite verbose. + +Proposal: Combine `Error` and `ErrorKind` +----------------------------------------- + +At time of writing, each operation has both an `Error` and `ErrorKind` type generated. +The `Error` type holds information that is common across all operation errors: message, +error code, "extra" key/value pairs, and the request ID. + +The `ErrorKind` is always nested inside the `Error`, which results in the verbose +nested matching shown in the case study above. + +To make error handling more ergonomic, the code generated `Error` and `ErrorKind` types +should be combined. Hypothetically, this would allow for the case study above to look as follows: + +```rust,ignore +let result = client + .get_object() + .bucket(BUCKET_NAME) + .key("some-key") + .send() + .await; +match result { + Ok(_output) => { /* Do something with the output */ } + Err(err) => match err.into_service_error() { + GetObjectError::InvalidObjectState(value) => { + println!("invalid object state: {:?}", value); + } + err if err.is_no_such_key() => { + println!("object didn't exist"); + } + err if err.code() == Some("SomeUnmodeledError") => {} + err @ _ => return Err(err.into()), + }, +} +``` + +If a customer only cares about checking one specific error type, they can also do: + +```rust,ignore +match result { + Ok(_output) => { /* Do something with the output */ } + Err(err) => { + let err = err.into_service_error(); + if err.is_no_such_key() { + println!("object didn't exist"); + } else { + return Err(err); + } + } +} +``` + +The downside of this is that combining the error types requires adding the general error +metadata to each generated error struct so that it's accessible by the enum error type. +However, this aligns with our tenet of making things easier for customers even if it +makes it harder for ourselves. + +Changes Checklist +----------------- + +- [x] Merge the `${operation}Error`/`${operation}ErrorKind` code generators to only generate an `${operation}Error` enum: + - Preserve the `is_${variant}` methods + - Preserve error metadata by adding it to each individual variant's context struct +- [x] Write upgrade guidance +- [x] Fix examples + +[RFC-0022]: ./rfc0022_error_context_and_compatibility.md diff --git a/design/src/rfcs/rfc0042_file_per_change_changelog.md b/design/src/rfcs/rfc0042_file_per_change_changelog.md new file mode 100644 index 0000000000..ace771a748 --- /dev/null +++ b/design/src/rfcs/rfc0042_file_per_change_changelog.md @@ -0,0 +1,133 @@ +RFC: File-per-change changelog +============================== + +> Status: RFC +> +> Applies to: client and server + +For a summarized list of proposed changes, see the [Changes Checklist] section. + +Historically, the smithy-rs and AWS SDK for Rust's changelogs and release notes have been +generated from the `changelogger` tool in `tools/ci-build/changelogger`. This is a tool built +specifically for development and release of smithy-rs, and it requires developers to add +changelog entries to a root `CHANGELOG.next.toml` file. Upon release, the `[[smithy-rs]]` entries +in this file go into the smithy-rs release notes, and the `[[aws-sdk-rust]]` entries are associated +with a smithy-rs release commit hash, and added to the `aws/SDK_CHANGELOG.next.json` for +incorporation into the AWS SDK's changelog when it releases. + +This system has gotten us far, but it has always made merging PRs into main more difficult +since the central `CHANGELOG.next.toml` file is almost always a merge conflict for two PRs +with changelog entries. + +This RFC proposes a new approach to change logging that will remedy the merge conflict issue, +and explains how this can be done without disrupting the current release process. + +The proposed developer experience +--------------------------------- + +There will be a `changelog/` directory in the smithy-rs root where +developers can add changelog entry Markdown files. Any file name can be picked +for these entries. Suggestions are the development branch name for the +change, or the PR number. + +The changelog entry format will change to make it easier to duplicate entries +across both smithy-rs and aws-sdk-rust, a common use-case. + +This new format will make use of Markdown front matter in the YAML format. +This change in format has a couple benefits: +- It's easier to write change entries in Markdown than in a TOML string. +- There's no way to escape special characters (such as quotes) in a TOML string, + so the text that can be a part of the message will be expanded. + +While it would be preferable to use TOML for the front matter (and there are libraries +that support that), it will use YAML so that GitHub's Markdown renderer will recognize it. + +A changelog entry file will look as follows: + +```markdown +--- +# Adding `aws-sdk-rust` here duplicates this entry into the SDK changelog. +applies_to: ["client", "server", "aws-sdk-rust"] +authors: ["author1", "author2"] +references: ["smithy-rs#1234", "aws-sdk-rust#1234"] +# The previous `meta` section is broken up into its constituents: +breaking: false +# This replaces "tada": +new_feature: false +bug_fix: false +--- + +Some message for the change. +``` + +Implementation +-------------- + +When a release is performed, the release script will generate the release notes, +update the `CHANGELOG.md` file, copy SDK changelog entries into the SDK, +and delete all the files in `changelog/`. + +### SDK Entries + +The SDK changelog entries currently end up in `aws/SDK_CHANGELOG.next.json`, and each entry +is given `age` and `since_commit` entries. The age is a number that starts at zero, and gets +incremented with every smithy-rs release. When it reaches a hardcoded threshold, that entry +is removed from `aws/SDK_CHANGELOG.next.json`. The SDK release process uses the `since_commit` +to determine which changelog entries go into the next SDK release's changelog. + +The SDK release process doesn't write back to smithy-rs, and history has shown that it +can't since this leads to all sorts of release issues as PRs get merged into smithy-rs +while the release is in progress. Thus, this `age`/`since_commit` dichotomy needs to +stay in place. + +The `aws/SDK_CHANGELOG.next.json` will stay in place in its current format without changes. +Its JSON format is capable of escaping characters in the message string, so it will be +compatible with the transition from TOML to Markdown with YAML front matter. + +The `SDK_CHANGELOG.next.json` file has had merge conflicts in the past, but this only +happened when the release process wasn't followed correctly. If we're consistent with +our release process, it should never have conflicts. + +### Safety requirements + +Implementation will be tricky since it needs to be done without disrupting the existing +release process. The biggest area of risk is the SDK sync job that generates individual +commits in the aws-sdk-rust repo for each commit in the smithy-rs release. Fortunately, +the `changelogger` is invoked a single time at the very end of that process, and only +the latest `changelogger` version that is included in the build image. Thus, we can safely +refactor the `changelogger` tool so long as the command-line interface for it remains +backwards compatible. (We _could_ change the CLI interface as well, but it will +require synchronizing the smithy-rs changes with changes to the SDK release scripts.) + +At a high level, these requirements must be observed to do this refactor safely: +- The CLI for the `changelogger render` subcommand _MUST_ stay the same, or have minimal + backwards compatible changes made to it. +- The `SDK_CHANGELOG.next.json` format can change, but _MUST_ remain a single JSON file. + If it is changed at all, the existing file _MUST_ be transitioned to the new format, + and a mechanism _MUST_ be in place for making sure it is the correct format after + merging with other PRs. It's probably better to leave this file alone though, or make + any changes to it backwards compatible. + +Future Improvements +------------------- + +After the initial migration, additional niceties could be added such as pulling authors +from git history rather than needing to explicitly state them (at least by default; there +should always be an option to override the author in case a maintainer adds a changelog +entry on behalf of a contributor). + +Changes checklist +----------------- + +- [ ] Refactor changelogger and smithy-rs-tool-common to separate the changelog + serialization format from the internal representation used for rendering and splitting. +- [ ] Implement deserialization for the new Markdown entry format +- [ ] Incorporate new format into the `changelogger render` subcommand +- [ ] Incorporate new format into the `changelogger split` subcommand +- [ ] Port existing `CHANGELOG.next.toml` to individual entries +- [ ] Update `sdk-lints` to fail if `CHANGELOG.next.toml` exists at all to avoid losing + changelog entries during merges. +- [ ] Dry-run test against the smithy-rs release process. +- [ ] Dry-run test against the SDK release process. + +[Changes Checklist]: #changes-checklist diff --git a/design/src/rfcs/rfc0043_identity_cache_partitions.md b/design/src/rfcs/rfc0043_identity_cache_partitions.md new file mode 100644 index 0000000000..f24193e181 --- /dev/null +++ b/design/src/rfcs/rfc0043_identity_cache_partitions.md @@ -0,0 +1,295 @@ +RFC: Identity Cache Partitions +=============================== + +> Status: Accepted +> +> Applies to: AWS SDK for Rust + +Motivation +----------- + +In the below example two clients are created from the same shared `SdkConfig` instance and each +invoke a fictitious operation. Assume the operations use the same auth scheme relying on the same identity resolver. + +```rust,ignore +#[tokio::main] +async fn main() -> Result<(), Box> { + + let config = aws_config::defaults(BehaviorVersion::latest()) + .load() + .await; + + let c1 = aws_sdk_foo::Client::new(&config); + c1.foo_operation().send().await; + + let c2 = aws_sdk_bar::Client::new(&config); + c2.bar_operation().send().await; + + Ok(()) +} +``` + +There are two problems with this currently. + + +1. The identity resolvers (e.g. `credentials_provider` for SigV4) are re-used but we end up with a different +[`IdentityCachePartition`](https://github.com/smithy-lang/smithy-rs/blob/release-2024-03-25/rust-runtime/aws-smithy-runtime-api/src/client/identity.rs#L41) +each time a client is created. + * More specifically this happens every time a `SharedIdentityResolver` is [created](https://github.com/smithy-lang/smithy-rs/blob/release-2024-03-25/rust-runtime/aws-smithy-runtime-api/src/client/identity.rs#L197). The conversion from [`From`](https://github.com/awslabs/aws-sdk-rust/blob/release-2024-04-01/sdk/sts/src/config.rs#L1207) + sets the credentials provider which [associates](https://github.com/awslabs/aws-sdk-rust/blob/release-2024-04-01/sdk/sts/src/config.rs#L960) it as + the identity resolver for the auth scheme. Internally this is [converted](https://github.com/awslabs/aws-sdk-rust/blob/release-2024-04-01/sdk/aws-smithy-runtime-api/src/client/runtime_components.rs#L663) to `SharedIdentityResolver` which creates the new partition (if it were already a `SharedIdentityResolver` this would be detected and a new instance would not be created which means it must be a `SharedCredentialsProvider` or `SharedTokenProvider` that is getting converted). The end result is the credentials + provider from shared config is re-used but the cache partition differs so a cache miss occurs the first time + any new client created from that shared config needs credentials. + +2. The `SdkConfig` does not create an identity cache by default. Even if the partitioning is fixed, any clients created from +a shared config instance will end up with their own identity cache which also results in having to resolve identity +again. Only if a user supplies an identity cache explicitly when creating shared config would it be re-used across +different clients. + +### Design intent + +Identity providers and identity caching are intentionally decoupled. This allows caching behavior to be more easily +customized and centrally configured while also removing the need for each identity provider to have to implement +caching. There is some fallout from sharing an identity cache though. This is fairly well documented on +`IdentityCachePartition` itself. + +```rust,ignore +/// ... +/// +/// Identities need cache partitioning because a single identity cache is used across +/// multiple identity providers across multiple auth schemes. In addition, a single auth scheme +/// may have many different identity providers due to operation-level config overrides. +/// +/// ... +pub struct IdentityCachePartition(...) +``` + +Cache partitioning allows for different identity types to be stored in the same cache instance as long as they +are assigned to a different partition. Partitioning also solves the issue of overriding configuration on a per operation +basis where it would not be the correct or desired behavior to re-use or overwrite the cache if a different resolver +is used. + +In other words cache partitioning is effectively tied to a particular instance of an identity resolver. Re-using the +same instance of a resolver _SHOULD_ be allowed to share a cache partition. The fact that this isn't the case +today is an oversight in how types are wrapped and threaded through the SDK. + + +The user experience if this RFC is implemented +---------------------------------------------- + +In the current version of the SDK, users are unable to share cached results of identity resolvers via shared `SdkConfig` +across clients. + +Once this RFC is implemented, users that create clients via `SdkConfig` with the latest behavior version will share +a default identity cache. Shared identity resolvers (e.g. `credentials_provider`, `token_provider`, etc) will provide +their own cache partition that is re-used instead of creating a new one each time a provider is converted into a +`SharedIdentityResolver`. + +### Default behavior + +```rust,ignore +let config = aws_config::defaults(BehaviorVersion::latest()) + .load() + .await; + +let c1 = aws_sdk_foo::Client::new(&config); +c1.foo_operation().send().await; + + +let c2 = aws_sdk_bar::Client::new(&config); +// will re-use credentials/identity resolved via c1 +c2.bar_operation().send().await; +``` + +Operations invoked on `c2` will see the results of cached identities resolved by client `c1` (for operations that use +the same identity resolvers). The creation of a default identity cache in `SdkConfig` if not provided will be added +behind a new behavior version. + +### Opting out + +Users can disable the shared identity cache by explicitly setting it to `None`. This will result in each client +creating their own identity cache. + +```rust,ignore +let config = aws_config::defaults(BehaviorVersion::latest()) + // new method similar to `no_credentials()` to disable default cache setup + .no_identity_cache() + .load() + .await; + +let c1 = aws_sdk_foo::Client::new(&config); +c1.foo_operation().send().await; + + +let c2 = aws_sdk_bar::Client::new(&config); +c2.bar_operation().send().await; +``` + +The same can be achieved by explicitly supplying a new identity cache to a client: + +```rust,ignore + +let config = aws_config::defaults(BehaviorVersion::latest()) + .load() + .await; + +let c1 = aws_sdk_foo::Client::new(&config); +c1.foo_operation().send().await; + +let modified_config = aws_sdk_bar::Config::from(&config) + .to_builder() + .identity_cache(IdentityCache::lazy().build()) + .build(); + +// uses it's own identity cache +let c2 = aws_sdk_bar::Client::from_conf(modified_config); +c2.bar_operation().send().await; +``` + +### Interaction with operation config override + +How per/operation configuration override behaves depends on what is provided for an identity resolver. + +```rust,ignore +let config = aws_config::defaults(BehaviorVersion::latest()) + .load() + .await; + +let c1 = aws_sdk_foo::Client::new(&config); + +let scoped_creds = my_custom_provider(); +let config_override = c1 + .config() + .to_builder() + .credentials_provider(scoped_creds); + +// override config for two specific operations + +c1.operation1() + .customize() + .config_override(config_override); + .send() + .await; + +c1.operation2() + .customize() + .config_override(config_override); + .send() + .await; +``` + +By default if an identity resolver does not provide it's own cache partition then `operation1` and `operation2` will +be wrapped in new `SharedIdentityResolver` instances and get distinct cache partitions. If `my_custom_provider()` +provides it's own cache partition then `operation2` will see the cached results. + +Users can control this by wrapping their provider into a `SharedCredentialsProvider` which will claim it's own +cache partition. + +```rust,ignore + +let scoped_creds = SharedCredentialsProvider::new(my_custom_provider()); +let config_override = c1 + .config() + .to_builder() + .set_credentials_provider(Some(scoped_creds)); +... +``` + + +How to actually implement this RFC +---------------------------------- + +In order to implement this RFC implementations of `ResolveIdentity` need to be allowed to provide their own cache +partition. + +```rust,ignore +pub trait ResolveIdentity: Send + Sync + Debug { + ... + + /// Returns the identity cache partition associated with this identity resolver. + /// + /// By default this returns `None` and cache partitioning is left up to `SharedIdentityResolver`. + /// If sharing instances of this type should use the same partition then you should override this + /// method and return a claimed partition. + fn cache_partition(&self) -> Option { + None + } + +} +``` + +Crucially cache partitions must remain globally unique so this method returns `IdentityCachePartition` which is +unique by construction. It doesn't matter if partitions are claimed early by an implementation of `ResolveIdentity` +or at the time they are wrapped in `SharedIdentityResolver`. + +This is because `SdkConfig` stores instances of `SharedCredentialsProvider` (or `SharedTokenProvider`) rather than +`SharedIdentityResolver` which is what currently knows about cache partitioning. By allowing implementations of `ResolveIdentity` +to provide their own partition then `SharedCredentialsProvider` can claim a partition at construction time +and return that which will re-use the same partition anywhere that the provider is shared. + + +```rust,ignore +#[derive(Clone, Debug)] +pub struct SharedCredentialsProvider(Arc, IdentityCachePartition); + +impl SharedCredentialsProvider { + pub fn new(provider: impl ProvideCredentials + 'static) -> Self { + Self(Arc::new(provider), IdentityCachePartition::new()) + } +} + +impl ResolveIdentity for SharedCredentialsProvider { + ... + + fn cache_partition(&self) -> Option { + Some(self.1) + } +} + +``` + +Additionally a new behavior version must be introduced that conditionally creates a default `IdentityCache` on `SdkConfig` +if not explicitly configured (similar to how credentials provider works internally). + +Alternatives Considered +----------------------- + +`SdkConfig` [internally](https://github.com/smithy-lang/smithy-rs/blob/release-2024-03-25/aws/rust-runtime/aws-types/src/sdk_config.rs#L58-L59) +stores `SharedCredentialsProvider`/`SharedTokenProvider`. Neither of these types knows anything about cache partitioning. +One alternative would be to create and store a `SharedIdentityResolver` for each identity resolver type. + +```rust,ignore +pub struct SdkConfig { + ... + credentials_provider: Option, + credentials_identity_provider: Option, + token_provider: Option, + token_identity_provider: Option, +} +``` + +Setting one of the identity resolver types like `credentials_provider` would also create and set the equivalent +`SharedIdentityResolver` which would claim a cache partition. When generating the `From` implementations +the identity resolver type would be favored. + +There are a few downsides to this approach: + +1. `SdkConfig` would have to expose accessor methods for the equivalents +(e.g. `credentials_identity_provider(&self) -> Option<&SharedIdentityResolver>`). This creates additional noise +and confusion as well as the chance for using the type wrong. +2. Every new identity type added to `SdkConfig` would have to be sure to use `SharedIdentityResolver`. + +The advantage of the proposed approach of letting `ResolveIdentity` implementations provide a cache partition means +`SdkConfig` does not need to change. It also gives customers more control over whether an identity resolver implementation +shares a cache partition or not. + +Changes checklist +----------------- + +- [ ] Add new `cache_partition()` method to `ResolveIdentity` +- [ ] Update `SharedIdentityResolver::new` to use the new `cache_partition()` method on the `resolver` to determine if a new cache partition should be created or not +- [ ] Claim a cache partition when `SharedCredentialsProvider` is created and override the new `ResolveIdentity` method +- [ ] Claim a cache partition when `SharedTokenProvider` is created and override the new `ResolveIdentity` method +- [ ] Introduce new behavior version +- [ ] Conditionally (gated on behavior version) create a new default `IdentityCache` on `SdkConfig` if not explicitly configured +- [ ] Add a new `no_identity_cache()` method to `ConfigLoader` that marks the identity cache as explicitly unset diff --git a/design/src/rfcs/rfc0044_env_defined_service_config.md b/design/src/rfcs/rfc0044_env_defined_service_config.md new file mode 100644 index 0000000000..df6bcb9123 --- /dev/null +++ b/design/src/rfcs/rfc0044_env_defined_service_config.md @@ -0,0 +1,365 @@ +# RFC: Environment-defined service configuration + +> Status: RFC +> +> Applies to: client + +For a summarized list of proposed changes, see the [Changes +Checklist](#changes-checklist) section. + +In the AWS SDK for Rust today, customers are limited to setting global +configuration variables in their environment; They cannot set service-specific +variables. Other SDKs and the AWS CLI do allow for setting service-specific +variables. + +This RFC proposes an implementation that would enable users to set +service-specific variables in their environment. + +## Terminology + +* **Global configuration**: configuration which will be used for requests to any + service. May be overridden by service-specific configuration. +* **Service-specific configuration**: configuration which will be used for + requests only to a specific service. +* **Configuration variable**: A key-value pair that defines configuration e.g. + `key = value`, `key: value`, `KEY=VALUE`, etc. + * Key and value as used in this RFC refer to each half of a configuration + variable. +* **Sub-properties**: When parsing config variables from a profile file, + sub-properties are a newline-delimited list of key-value pairs in an indented + block following a `=\n` line. _For an example, see the **Profile + File Configuration** section of this RFC where sub-properties are declared for + two different services._ + +## The user experience if this RFC is implemented + +While users can already set global configuration in their environment, this RFC +proposes two new ways to set service-specific configuration in their +environment. + +### Environment Variables + +When defining service-specific configuration with an environment variable, all +keys are formatted like so: + +```sh +"AWS" + "_" + "" + "_" + "" +``` + +As an example, setting an endpoint URL for different services would look like +this: + +```sh +export AWS_ENDPOINT_URL=http://localhost:4444 +export AWS_ENDPOINT_URL_ELASTICBEANSTALK=http://localhost:5555 +export AWS_ENDPOINT_URL_DYNAMODB=http://localhost:6666 +``` + +The first variable sets a global endpoint URL. The second variable overrides the +first variable, but only for the Elastic Beanstalk service. The third variable +overrides the first variable, but only for the DynamoDB service. + +### Profile File Configuration + +When defining service-specific configuration in a profile file, it looks like +this: + +```ignore +[profile dev] +services = testing-s3-and-eb +endpoint_url = http://localhost:9000 + +[services testing-s3-and-eb] +s3 = + endpoint_url = http://localhost:4567 +elasticbeanstalk = + endpoint_url = http://localhost:8000 +``` + +When `dev` is the active profile, all services will use the +`http://localhost:9000` endpoint URL except where it is overridden. Because the +`dev` profile references the `testing-s3-and-eb` services, and because two +service-specific endpoint URLs are set, those URLs will override the +`http://localhost:9000` endpoint URL when making requests to S3 +(`http://localhost:4567`) and Elastic Beanstalk (`http://localhost:8000`). + +### Configuration Precedence + +When configuration is set in multiple places, the value used is determined in +this order of precedence: + +*highest precedence* + +1. *EXISTING* Programmatic client configuration +2. *NEW* Service-specific environment variables +3. *EXISTING* Global environment variables +4. *NEW* Service-specific profile file variables in the active profile +5. *EXISTING* Global profile file variables in the active profile + +*lowest precedence* + +How to actually implement this RFC +---------------------------------- + +This RFC may be implemented in several steps which are detailed below. + +### Sourcing service-specific config from the environment and profile + +`aws_config::profile::parser::ProfileSet` is responsible for storing the active +profile and all profile configuration data. Currently, it only tracks +`sso_session` and `profile` sections, so it must be updated to store arbitrary +sections, their properties, and sub-properties. These sections will be publicly +accessible via a new method `ProfileSet::other_sections` which returns a ref to +a `Properties` struct. + +The `Properties` struct is defined as follows: + +```rust,ignore +type SectionKey = String; +type SectionName = String; +type PropertyName = String; +type SubPropertyName = String; +type PropertyValue = String; + +/// A key for to a property value. +/// +/// ```txt +/// # An example AWS profile config section with properties and sub-properties +/// [section-key section-name] +/// property-name = property-value +/// property-name = +/// sub-property-name = property-value +/// ``` +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct PropertiesKey { + section_key: SectionKey, + section_name: SectionName, + property_name: PropertyName, + sub_property_name: Option, +} + +impl PropertiesKey { + /// Create a new builder for a `PropertiesKey`. + pub fn builder() -> Builder { + Default::default() + } +} + +// The builder code is omitted from this RFC. It allows users to set each field +// individually and then build a PropertiesKey + +/// A map of [`PropertiesKey`]s to property values. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct Properties { + inner: HashMap, +} + +impl Properties { + /// Create a new empty [`Properties`]. + pub fn new() -> Self { + Default::default() + } + + #[cfg(test)] + pub(crate) fn new_from_slice(slice: &[(PropertiesKey, PropertyValue)]) -> Self { + let mut properties = Self::new(); + for (key, value) in slice { + properties.insert(key.clone(), value.clone()); + } + properties + } + + /// Insert a new key/value pair into this map. + pub fn insert(&mut self, properties_key: PropertiesKey, value: PropertyValue) { + let _ = self + .inner + // If we don't clone then we don't get to log a useful warning for a value getting overwritten. + .entry(properties_key.clone()) + .and_modify(|v| { + tracing::trace!("overwriting {properties_key}: was {v}, now {value}"); + *v = value.clone(); + }) + .or_insert(value); + } + + /// Given a [`PropertiesKey`], return the corresponding value, if any. + pub fn get(&self, properties_key: &PropertiesKey) -> Option<&PropertyValue> { + self.inner.get(properties_key) + } +} +``` + +The `aws_config::env` module remains unchanged. It already provides all the +necessary functionality. + +### Exposing valid service configuration during `::Config` construction + +Environment variables *(from `Env`)* and profile variables *(from +`EnvConfigSections`)* must be available during the conversion of `SdkConfig` to +`::Config`. To accomplish this, we'll define a new trait +`LoadServiceConfig` and implement it for `EnvServiceConfig` which will be +stored in the `SdkConfig` struct. + +```rust,ignore +/// A struct used with the [`LoadServiceConfig`] trait to extract service config from the user's environment. +// [profile active-profile] +// services = dev +// +// [services dev] +// service-id = +// config-key = config-value +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct ServiceConfigKey<'a> { + service_id: &'a str, + profile: &'a str, + env: &'a str, +} + +impl<'a> ServiceConfigKey<'a> { + /// Create a new [`ServiceConfigKey`] builder struct. + pub fn builder() -> builder::Builder<'a> { + Default::default() + } + /// Get the service ID. + pub fn service_id(&self) -> &'a str { + self.service_id + } + /// Get the profile key. + pub fn profile(&self) -> &'a str { + self.profile + } + /// Get the environment key. + pub fn env(&self) -> &'a str { + self.env + } +} + +/// Implementers of this trait can provide service config defined in a user's environment. +pub trait LoadServiceConfig: fmt::Debug + Send + Sync { + /// Given a [`ServiceConfigKey`], return the value associated with it. + fn load_config(&self, key: ServiceConfigKey<'_>) -> Option; +} + +#[derive(Debug)] +pub(crate) struct EnvServiceConfig { + pub(crate) env: Env, + pub(crate) env_config_sections: EnvConfigSections, +} + +impl LoadServiceConfig for EnvServiceConfig { + fn load_config(&self, key: ServiceConfigKey<'_>) -> Option { + let (value, _source) = EnvConfigValue::new() + .env(key.env()) + .profile(key.profile()) + .service_id(key.service_id()) + .load(&self.env, Some(&self.env_config_sections))?; + + Some(value.to_string()) + } +} +``` + +### Code generation + +We require two things to check for when constructing the service config: + +- The service's ID +- The service's supported configuration variables + +We **only** have this information once we get to the service level. Because of +that, we must use code generation to define: + +- What config to look for in the environment +- How to validate that config + +Codegen for configuration must be updated for all config variables that we want +to support. For an example, here's how we'd update the `RegionDecorator` to check +for service-specific regions: + +```java +class RegionDecorator : ClientCodegenDecorator { + // ... + override fun extraSections(codegenContext: ClientCodegenContext): List { + return usesRegion(codegenContext).thenSingletonListOf { + adhocCustomization { section -> + rust( + """ + ${section.serviceConfigBuilder}.set_region( + ${section.sdkConfig} + .service_config() + .and_then(|conf| { + conf.load_config(service_config_key($envKey, $profileKey)) + .map(Region::new) + }) + .or_else(|| ${section.sdkConfig}.region().cloned()), + ); + """, + ) + } + } + } + // ... +``` + +To construct the keys necessary to locate the service-specific configuration, we +generate a `service_config_key` function for each service crate: + +```java +class ServiceEnvConfigDecorator : ClientCodegenDecorator { + override val name: String = "ServiceEnvConfigDecorator" + override val order: Byte = 10 + + override fun extras( + codegenContext: ClientCodegenContext, + rustCrate: RustCrate, + ) { + val rc = codegenContext.runtimeConfig + val serviceId = codegenContext.serviceShape.sdkId().toSnakeCase().dq() + rustCrate.withModule(ClientRustModule.config) { + Attribute.AllowDeadCode.render(this) + rustTemplate( + """ + fn service_config_key<'a>( + env: &'a str, + profile: &'a str, + ) -> aws_types::service_config::ServiceConfigKey<'a> { + #{ServiceConfigKey}::builder() + .service_id($serviceId) + .env(env) + .profile(profile) + .build() + .expect("all field sets explicitly, can't fail") + } + """, + "ServiceConfigKey" to AwsRuntimeType.awsTypes(rc).resolve("service_config::ServiceConfigKey"), + ) + } + } +} +``` + +## Changes checklist + +- In `aws-types`: + - [x] Add new `service_config: Option>` field to `SdkConfig` and builder. + - [x] Add setters and getters for the new `service_config` field. + - [x] Add a new `service_config` module. + - [x] Add new `ServiceConfigKey` struct and builder. + - [x] Add new `LoadServiceConfig` trait. +- In `aws-config`: + - [x] Move profile parsing out of `aws-config` into `aws-runtime`. + - [x] Deprecate the `aws-config` reëxports and direct users to `aws-runtime`. + - [x] Add a new `EnvServiceConfig` struct and implement `LoadServiceConfig` for it. + - [x] Update `ConfigLoader` to set the `service_config` field in `SdkConfig`. + - [x] Update all default providers to use the new of the `EnvConfigValue::validate` method. +- In `aws-runtime`: + - [x] Rename all profile-related code moved from `aws-config` to `aws-runtime` so that it's easier to understand in light of the API changes we're making. + - [x] Add a new struct `PropertiesKey` and `Properties` to store profile data. +- [x] Add an integration test that ensures service-specific config has the expected precedence. +- [x] Update codegen to generate a method to easily construct `ServiceConfigKey`s. +- [x] Update codegen to generate code that loads service-specific config from the environment for a limited initial set of config variables: + - Region + - Endpoint URL + - Endpoint-related "built-ins" like `use_arn_region` and `disable_multi_region_access_points`. +- [x] Write a [guide](https://github.com/smithy-lang/smithy-rs/discussions/3537) for users. + - [x] Explain to users how they can determine a service's ID. diff --git a/design/src/smithy/endpoint.md b/design/src/smithy/endpoint.md deleted file mode 100644 index bef52bdfeb..0000000000 --- a/design/src/smithy/endpoint.md +++ /dev/null @@ -1,51 +0,0 @@ -# Endpoint Resolution - -## Requirements -The core codegen generates HTTP requests that do not contain an authority, scheme or post. These properties must be set later based on configuration. Existing AWS services have a number of requirements that increase the complexity: - -1. Endpoints must support manual configuration by end users: -```rust,ignore -let config = dynamodb::Config::builder() - .endpoint(StaticEndpoint::for_uri("http://localhost:8000")) -``` - -When a user specifies a custom endpoint URI, _typically_ they will want to avoid having this URI mutated by other endpoint discovery machinery. - -2. Endpoints must support being customized on a per-operation basis by the endpoint trait. This will prefix the base endpoint, potentially driven by fields of the operation. [Docs](https://awslabs.github.io/smithy/1.0/spec/core/endpoint-traits.html#endpoint-trait) - -3. Endpoints must support being customized by [endpoint discovery](https://awslabs.github.io/smithy/1.0/spec/aws/aws-core.html#client-endpoint-discovery). A request, customized by a predefined set of fields from the input operation is dispatched to a specific URI. That operation returns the endpoint that should be used. Endpoints must be cached by a cache key containing: -```markdown -(access_key_id, [all input fields], operation) -``` -Endpoints retrieved in this way specify a TTL. - -4. Endpoints must be able to customize the signing (and other phases of the operation). For example, requests sent to a global region will have a region set by the endpoint provider. - - -## Design - -Configuration objects for services _must_ contain an `Endpoint`. This endpoint may be set by a user or it will default to the `endpointPrefix` from the service definition. In the case of endpoint discovery, _this_ is the endpoint that we will start with. - -During operation construction (see [Operation Construction](../transport/operation.md#operation-construction)) an `EndpointPrefix` may be set on the property bag. The eventual endpoint middleware will search for this in the property bag and (depending on the URI mutability) utilize this prefix when setting the endpoint. - -In the case of endpoint discovery, we envision a different pattern: -```rust,ignore -// EndpointClient manages the endpoint cache -let (tx, rx) = dynamodb::EndpointClient::new(); -let client = aws_hyper::Client::new(); -// `endpoint_req` is an operation that can be dispatched to retrieve endpoints -// During operation construction, the endpoint resolver is configured to be `rx` instead static endpoint -// resolver provided by the service. -let (endpoint_req, req) = GetRecord::builder().endpoint_disco(rx).build_with_endpoint(); -// depending on the duration of endpoint expiration, this may be spawned into a separate task to continuously -// refresh endpoints. -if tx.needs(endpoint_req) { - let new_endpoint = client. - call(endpoint_req) - .await; - tx.send(new_endpoint) -} -let rsp = client.call(req).await?; -``` - -We believe that this design results in an SDK that both offers customers more control & reduces the likelihood of bugs from nested operation dispatch. Endpoint resolution is currently extremely rare in AWS services so this design may remain a prototype while we solidify other behaviors. diff --git a/design/src/smithy/overview.md b/design/src/smithy/overview.md index f894c7e9d0..85df2fd66b 100644 --- a/design/src/smithy/overview.md +++ b/design/src/smithy/overview.md @@ -1,7 +1,7 @@ # Smithy The Rust SDK uses Smithy models and code generation tooling to generate an SDK. Smithy is an open source IDL (interface design language) developed by Amazon. Although the Rust SDK uses Smithy models for AWS services, smithy-rs and Smithy models in general are not AWS specific. -Design documentation here covers both our implementation of Smithy Primitives (e.g. simple shape) as well as more complex Smithy traits like [Endpoint](./endpoint.md). +Design documentation here covers both our implementation of Smithy Primitives (e.g. simple shape) as well as more complex Smithy traits like `Endpoint`. ## Internals Smithy introduces a few concepts that are defined here: diff --git a/design/src/transport/connector.md b/design/src/transport/connector.md deleted file mode 100644 index edb50d4412..0000000000 --- a/design/src/transport/connector.md +++ /dev/null @@ -1,7 +0,0 @@ -The Smithy client provides a default TLS connector, but a custom one can be -plugged in. `rustls` is enabled with the feature flag `rustls`. - -The client had previously (prior to version 0.56.0) supported `native-tls`. You -can continue to use a client whose TLS implementation is backed by `native-tls` -by passing in a custom connector. Check out the `custom_connectors.rs` tests in -the `pokemon-service-tls` example crate. diff --git a/design/src/transport/middleware.md b/design/src/transport/middleware.md deleted file mode 100644 index bf7a1bc7e9..0000000000 --- a/design/src/transport/middleware.md +++ /dev/null @@ -1,7 +0,0 @@ -# HTTP middleware - -Signing, endpoint specification, and logging are all handled as middleware. The Rust SDK takes a minimalist approach to middleware: - -Middleware is defined as minimally as possible, then adapted into the middleware system used by the IO layer. Tower is the de facto standard for HTTP middleware in Rust—we will probably use it. But we also want to make our middleware usable for users who aren't using Tower (or if we decide to not use Tower in the long run). - -Because of this, rather than implementing all our middleware as "Tower Middleware", we implement it narrowly (e.g. as a function that operates on `operation::Request`), then define optional adapters to make our middleware tower compatible. diff --git a/design/src/transport/operation.md b/design/src/transport/operation.md deleted file mode 100644 index 9ca8a4dfc9..0000000000 --- a/design/src/transport/operation.md +++ /dev/null @@ -1,64 +0,0 @@ -# HTTP-based Operations -The Smithy code generator for Rust (and by extension), the AWS SDK use an `Operation` abstraction to provide a unified -interface for dispatching requests. `Operation`s contain: -* A base HTTP request (with a potentially streaming body) -* A typed property bag of configuration options -* A fully generic response handler - -In the typical case, these configuration options include things like a `CredentialsProvider`, however, they can also be -full middleware layers that will get added by the dispatch stack. - -## Operation Phases -This section details the flow of a request through the SDK until a response is returned to the user. - -### Input Construction - -A customer interacts with the SDK builders to construct an input. The `build()` method on an input returns -an `Operation`. This codifies the base HTTP request & all the configuration and middleware layers required to modify and dispatch the request. - -```rust,ignore -pub struct Operation { - request: Request, - response_handler: H, - _retry_policy: R, -} - -pub struct Request { - inner: http::Request, - properties: PropertyBag, -} -``` - -For most requests, `.build()` will NOT consume the input. A user can call `.build()` multiple times to produce multiple operations from the same input. - -By using a property bag, we can define the `Operation` in Smithy core. AWS specific configuration can be added later in the stack. - -### Operation Construction -In order to construct an operation, the generated code injects appropriate middleware & configuration via the configuration property bag. It does this by reading the configuration properties out of the service -config, copying them as necessary, and loading them into the `Request`: - -```rust,ignore -// This is approximately the generated code, I've cleaned a few things up for readability. -pub fn build(self, config: &dynamodb::config::Config) -> Operation { - let op = BatchExecuteStatement::new(BatchExecuteStatementInput { - statements: self.statements, - }); - let req = op.build_http_request().map(SdkBody::from); - - let mut req = operation::Request::new(req); - let mut props = req.properties_mut(); - props.insert_signing_config(config.signing_service()); - props.insert_endpoint_resolver(config.endpoint_resolver.clone()); - Operation::new(req) -} -``` - -### Operation Dispatch and Middleware - -The Rust SDK endeavors to behave as predictably as possible. This means that if at all possible we will not dispatch extra HTTP requests during the dispatch of normal operation. Making this work is covered in more detail in the design of credentials providers & endpoint resolution. - -The upshot is that we will always prefer a design where the user has explicit control of when credentials are loaded and endpoints are resolved. This doesn't mean that users can't use easy-to-use options (We will provide an automatically refreshing credentials provider), however, the credential provider won't load requests during the dispatch of an individual request. - -## Operation Parsing and Response Loading - -The fundamental trait for HTTP-based protocols is `ParseHttpResponse` diff --git a/design/src/transport/overview.md b/design/src/transport/overview.md deleted file mode 100644 index 42bf318814..0000000000 --- a/design/src/transport/overview.md +++ /dev/null @@ -1,11 +0,0 @@ -# Transport -The transport layer of smithy-rs and the Rust SDK. Our goal is support customers to bring their own HTTP stack and runtime. - -## Where we are today -`aws-hyper` assembles a middleware stack with `tower`. It provides a way to use an HTTP client other than Hyper, however, it currently has a hard dependency on Hyper & Tokio. `hyper::Body` is being used directly as the body implementation for responses. - -## Where we want to go -1. Extend `HttpService` to add a `sleep` method. This is required to enable runtimes other than Tokio to define how they should sleep. -2. Replace `hyper::Body` in responses with SDK Body. For now, SDKBody will probably privately wrap `hyper::Body`. -3. Merge `aws-hyper` into `aws-http`. Tokio becomes an optional feature—When the Tokio feature is opted out the "fast path" variants for the connection variants are `cfg`'d out. -4. By default, customers get a fully baked HTTP stack, but they can opt out of certain features and BYO implementation of `HttpService`. diff --git a/examples/README.md b/examples/README.md index 37ea375b7a..40b8ea2180 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,7 +1,8 @@ # Smithy Rust Server SDK examples -This folder contains some example services showcasing Smithy Rust Server SDK, -also known as the Rust service framework, capabilities and to run benchmarks. +This folder contains: +- example services showcasing Smithy Rust Server SDK, also known as the Rust service framework, +- benchmarking tooling Three server implementations are available: @@ -20,7 +21,7 @@ a suitable choice for implementing your web service. ## Pre-requisites -You will need install Java 11 to run the smithy-rs code generator and an +You will need install Java 17 to run the smithy-rs code generator and an installation of Rust, including `cargo`, to compile the generated code. (Optional) The [Cargo Lambda](https://cargo-lambda.info/) sub-command for diff --git a/gradle.properties b/gradle.properties index e198984afd..3a44cdddf5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ # # Rust MSRV (entered into the generated README) -rust.msrv=1.74.1 +rust.msrv=1.75.0 # To enable debug, swap out the two lines below. # When changing this value, be sure to run `./gradlew --stop` to kill the Gradle daemon. @@ -21,7 +21,7 @@ kotlin.code.style=official # codegen smithyGradlePluginVersion=0.9.0 -smithyVersion=1.45.0 +smithyVersion=1.47.0 allowLocalDeps=false # kotlin diff --git a/rust-runtime/aws-smithy-http-server-python/Cargo.toml b/rust-runtime/aws-smithy-http-server-python/Cargo.toml index 2f65440e33..4aff637200 100644 --- a/rust-runtime/aws-smithy-http-server-python/Cargo.toml +++ b/rust-runtime/aws-smithy-http-server-python/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aws-smithy-http-server-python" -version = "0.62.0" +version = "0.62.1" authors = ["Smithy Rust Server "] edition = "2021" license = "Apache-2.0" diff --git a/rust-runtime/aws-smithy-http-server-python/src/error.rs b/rust-runtime/aws-smithy-http-server-python/src/error.rs index 020bee15c1..a2523e8437 100644 --- a/rust-runtime/aws-smithy-http-server-python/src/error.rs +++ b/rust-runtime/aws-smithy-http-server-python/src/error.rs @@ -105,7 +105,7 @@ impl IntoResponse for PyMiddlewareException { http::Response::builder() .status(self.status_code) .header("Content-Type", "application/x-amz-json-1.0") - // See https://awslabs.github.io/smithy/1.0/spec/aws/aws-json-1_0-protocol.html#empty-body-serialization + // See https://smithy.io/2.0/aws/protocols/aws-json-1_0-protocol.html#empty-body-serialization .body(to_boxed(self.json_body())) .expect("invalid HTTP response for `MiddlewareException`; please file a bug report under https://github.com/smithy-lang/smithy-rs/issues") } @@ -116,7 +116,7 @@ impl IntoResponse for PyMiddlewareException { http::Response::builder() .status(self.status_code) .header("Content-Type", "application/x-amz-json-1.1") - // See https://awslabs.github.io/smithy/1.0/spec/aws/aws-json-1_1-protocol.html#empty-body-serialization + // See https://smithy.io/2.0/aws/protocols/aws-json-1_1-protocol.html#empty-body-serialization .body(to_boxed(self.json_body())) .expect("invalid HTTP response for `MiddlewareException`; please file a bug report under https://github.com/smithy-lang/smithy-rs/issues") } diff --git a/rust-runtime/aws-smithy-http-server/Cargo.toml b/rust-runtime/aws-smithy-http-server/Cargo.toml index 7d5957a75e..18b12aaa01 100644 --- a/rust-runtime/aws-smithy-http-server/Cargo.toml +++ b/rust-runtime/aws-smithy-http-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aws-smithy-http-server" -version = "0.61.1" +version = "0.61.2" authors = ["Smithy Rust Server "] edition = "2021" license = "Apache-2.0" diff --git a/rust-runtime/aws-smithy-http-server/src/instrumentation/mod.rs b/rust-runtime/aws-smithy-http-server/src/instrumentation/mod.rs index bad93a9ae1..087c4eda4d 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/mod.rs @@ -57,7 +57,7 @@ //! # } //! ``` //! -//! [sensitive trait]: https://awslabs.github.io/smithy/1.0/spec/core/documentation-traits.html?highlight=sensitive%20trait#sensitive-trait +//! [sensitive trait]: https://smithy.io/2.0/spec/documentation-traits.html#sensitive-trait mod plugin; pub mod sensitivity; diff --git a/rust-runtime/aws-smithy-http-server/src/instrumentation/plugin.rs b/rust-runtime/aws-smithy-http-server/src/instrumentation/plugin.rs index 4e8c0a66ca..7aa9b1d85d 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/plugin.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/plugin.rs @@ -34,7 +34,7 @@ pub trait InstrumentExt { /// Applies an [`InstrumentOperation`] to every operation, respecting the [@sensitive] trait given on the input and /// output models. See [`InstrumentOperation`] for more information. /// - /// [@sensitive]: https://awslabs.github.io/smithy/2.0/spec/documentation-traits.html#sensitive-trait + /// [@sensitive]: https://smithy.io/2.0/spec/documentation-traits.html#sensitive-trait fn instrument(self) -> HttpPlugins>; } diff --git a/rust-runtime/aws-smithy-http-server/src/instrumentation/sensitivity/headers.rs b/rust-runtime/aws-smithy-http-server/src/instrumentation/sensitivity/headers.rs index 479820b564..a522d15b94 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/sensitivity/headers.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/sensitivity/headers.rs @@ -44,8 +44,8 @@ pub struct HeaderMarker { /// println!("{headers:?}"); /// ``` /// -/// [httpPrefixHeaders trait]: https://awslabs.github.io/smithy/1.0/spec/core/http-traits.html#httpprefixheaders-trait -/// [httpHeader trait]: https://awslabs.github.io/smithy/1.0/spec/core/http-traits.html#httpheader-trait +/// [httpPrefixHeaders trait]: https://smithy.io/2.0/spec/http-bindings.html#httpprefixheaders-trait +/// [httpHeader trait]: https://smithy.io/2.0/spec/http-bindings.html#httpheader-trait pub struct SensitiveHeaders<'a, F> { headers: &'a HeaderMap, marker: F, diff --git a/rust-runtime/aws-smithy-http-server/src/instrumentation/sensitivity/mod.rs b/rust-runtime/aws-smithy-http-server/src/instrumentation/sensitivity/mod.rs index e18652618a..85d0093df2 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/sensitivity/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/sensitivity/mod.rs @@ -6,8 +6,8 @@ //! The combination of [HTTP binding traits] and the [sensitive trait] require us to redact //! portions of the HTTP requests/responses during logging. //! -//! [HTTP binding traits]: https://awslabs.github.io/smithy/1.0/spec/core/http-traits.html -//! [sensitive trait]: https://awslabs.github.io/smithy/1.0/spec/core/documentation-traits.html?highlight=sensitive#sensitive-trait +//! [HTTP binding traits]: https://smithy.io/2.0/spec/http-bindings.html +//! [sensitive trait]: https://smithy.io/2.0/spec/documentation-traits.html#sensitive-trait pub mod headers; mod request; diff --git a/rust-runtime/aws-smithy-http-server/src/instrumentation/sensitivity/uri/label.rs b/rust-runtime/aws-smithy-http-server/src/instrumentation/sensitivity/uri/label.rs index 54bfd969f2..1cc758e32a 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/sensitivity/uri/label.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/sensitivity/uri/label.rs @@ -26,7 +26,7 @@ use crate::instrumentation::{sensitivity::Sensitive, MakeFmt}; /// println!("{uri}"); /// ``` /// -/// [httpLabel trait]: https://awslabs.github.io/smithy/1.0/spec/core/http-traits.html#httplabel-trait +/// [httpLabel trait]: https://smithy.io/2.0/spec/http-bindings.html#httplabel-trait #[allow(missing_debug_implementations)] #[derive(Clone)] pub struct Label<'a, F> { diff --git a/rust-runtime/aws-smithy-http-server/src/instrumentation/sensitivity/uri/query.rs b/rust-runtime/aws-smithy-http-server/src/instrumentation/sensitivity/uri/query.rs index d3645366cd..8bb9566a53 100644 --- a/rust-runtime/aws-smithy-http-server/src/instrumentation/sensitivity/uri/query.rs +++ b/rust-runtime/aws-smithy-http-server/src/instrumentation/sensitivity/uri/query.rs @@ -34,8 +34,8 @@ pub struct QueryMarker { /// println!("{uri}"); /// ``` /// -/// [httpQuery trait]: https://awslabs.github.io/smithy/1.0/spec/core/http-traits.html#httpquery-trait -/// [httpQueryParams trait]: https://awslabs.github.io/smithy/1.0/spec/core/http-traits.html#httpqueryparams-trait +/// [httpQuery trait]: https://smithy.io/2.0/spec/http-bindings.html#httpquery-trait +/// [httpQueryParams trait]: https://smithy.io/2.0/spec/http-bindings.html#httpqueryparams-trait #[allow(missing_debug_implementations)] pub struct Query<'a, F> { query: &'a str, diff --git a/rust-runtime/aws-smithy-http-server/src/operation/mod.rs b/rust-runtime/aws-smithy-http-server/src/operation/mod.rs index 8450da8366..8fdbf1cd8d 100644 --- a/rust-runtime/aws-smithy-http-server/src/operation/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/operation/mod.rs @@ -158,7 +158,7 @@ //! The [`UpgradePlugin`], being a [`Plugin`](crate::plugin::Plugin), is parameterized by a protocol. This allows for //! upgrading to `Service` to be protocol dependent. //! -//! [Smithy operation]: https://awslabs.github.io/smithy/2.0/spec/service-types.html#operation +//! [Smithy operation]: https://smithy.io/2.0/spec/service-types.html#operation mod handler; mod operation_service; diff --git a/rust-runtime/aws-smithy-http-server/src/operation/shape.rs b/rust-runtime/aws-smithy-http-server/src/operation/shape.rs index 6d3d774868..aec4693807 100644 --- a/rust-runtime/aws-smithy-http-server/src/operation/shape.rs +++ b/rust-runtime/aws-smithy-http-server/src/operation/shape.rs @@ -10,7 +10,7 @@ use crate::shape_id::ShapeId; /// Models the [Smithy Operation shape]. /// -/// [Smithy Operation shape]: https://awslabs.github.io/smithy/1.0/spec/core/model.html#operation +/// [Smithy Operation shape]: https://smithy.io/2.0/spec/service-types.html#operation pub trait OperationShape { /// The ID of the operation. const ID: ShapeId; diff --git a/rust-runtime/aws-smithy-http-server/src/protocol/aws_json/router.rs b/rust-runtime/aws-smithy-http-server/src/protocol/aws_json/router.rs index cf9308124d..295c670b27 100644 --- a/rust-runtime/aws-smithy-http-server/src/protocol/aws_json/router.rs +++ b/rust-runtime/aws-smithy-http-server/src/protocol/aws_json/router.rs @@ -43,8 +43,8 @@ const ROUTE_CUTOFF: usize = 15; /// A [`Router`] supporting [`AWS JSON 1.0`] and [`AWS JSON 1.1`] protocols. /// -/// [AWS JSON 1.0]: https://awslabs.github.io/smithy/2.0/aws/protocols/aws-json-1_0-protocol.html -/// [AWS JSON 1.1]: https://awslabs.github.io/smithy/2.0/aws/protocols/aws-json-1_1-protocol.html +/// [AWS JSON 1.0]: https://smithy.io/2.0/aws/protocols/aws-json-1_0-protocol.html +/// [AWS JSON 1.1]: https://smithy.io/2.0/aws/protocols/aws-json-1_1-protocol.html #[derive(Debug, Clone)] pub struct AwsJsonRouter { routes: TinyMap, diff --git a/rust-runtime/aws-smithy-http-server/src/protocol/aws_json_10/mod.rs b/rust-runtime/aws-smithy-http-server/src/protocol/aws_json_10/mod.rs index 43cb03409e..8dfd48e466 100644 --- a/rust-runtime/aws-smithy-http-server/src/protocol/aws_json_10/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/protocol/aws_json_10/mod.rs @@ -5,5 +5,5 @@ pub mod router; -/// [AWS JSON 1.0 Protocol](https://awslabs.github.io/smithy/2.0/aws/protocols/aws-json-1_0-protocol.html). +/// [AWS JSON 1.0 Protocol](https://smithy.io/2.0/aws/protocols/aws-json-1_0-protocol.html). pub struct AwsJson1_0; diff --git a/rust-runtime/aws-smithy-http-server/src/protocol/aws_json_11/mod.rs b/rust-runtime/aws-smithy-http-server/src/protocol/aws_json_11/mod.rs index 2e1a0acce5..6fb09920a0 100644 --- a/rust-runtime/aws-smithy-http-server/src/protocol/aws_json_11/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/protocol/aws_json_11/mod.rs @@ -5,5 +5,5 @@ pub mod router; -/// [AWS JSON 1.1 Protocol](https://awslabs.github.io/smithy/2.0/aws/protocols/aws-json-1_1-protocol.html). +/// [AWS JSON 1.1 Protocol](https://smithy.io/2.0/aws/protocols/aws-json-1_1-protocol.html). pub struct AwsJson1_1; diff --git a/rust-runtime/aws-smithy-http-server/src/protocol/rest_json_1/mod.rs b/rust-runtime/aws-smithy-http-server/src/protocol/rest_json_1/mod.rs index 567a26f5bd..f8384578d2 100644 --- a/rust-runtime/aws-smithy-http-server/src/protocol/rest_json_1/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/protocol/rest_json_1/mod.rs @@ -7,5 +7,5 @@ pub mod rejection; pub mod router; pub mod runtime_error; -/// [AWS REST JSON 1.0 Protocol](https://awslabs.github.io/smithy/2.0/aws/protocols/aws-restjson1-protocol.html). +/// [AWS REST JSON 1.0 Protocol](https://smithy.io/2.0/aws/protocols/aws-restjson1-protocol.html). pub struct RestJson1; diff --git a/rust-runtime/aws-smithy-http-server/src/protocol/rest_xml/mod.rs b/rust-runtime/aws-smithy-http-server/src/protocol/rest_xml/mod.rs index 1924afbbbb..0b16df11e3 100644 --- a/rust-runtime/aws-smithy-http-server/src/protocol/rest_xml/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/protocol/rest_xml/mod.rs @@ -7,5 +7,5 @@ pub mod rejection; pub mod router; pub mod runtime_error; -/// [AWS REST XML Protocol](https://awslabs.github.io/smithy/2.0/aws/protocols/aws-restxml-protocol.html). +/// [AWS REST XML Protocol](https://smithy.io/2.0/aws/protocols/aws-restxml-protocol.html). pub struct RestXml; diff --git a/rust-runtime/aws-smithy-http-server/src/routing/mod.rs b/rust-runtime/aws-smithy-http-server/src/routing/mod.rs index 4f0cb8c0fa..14f124f687 100644 --- a/rust-runtime/aws-smithy-http-server/src/routing/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/routing/mod.rs @@ -5,7 +5,7 @@ //! HTTP routing that adheres to the [Smithy specification]. //! -//! [Smithy specification]: https://awslabs.github.io/smithy/1.0/spec/core/http-traits.html +//! [Smithy specification]: https://smithy.io/2.0/spec/http-bindings.html mod into_make_service; mod into_make_service_with_connect_info; diff --git a/rust-runtime/aws-smithy-http/Cargo.toml b/rust-runtime/aws-smithy-http/Cargo.toml index fa177027df..d240b16595 100644 --- a/rust-runtime/aws-smithy-http/Cargo.toml +++ b/rust-runtime/aws-smithy-http/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aws-smithy-http" -version = "0.60.7" +version = "0.60.8" authors = [ "AWS Rust SDK Team ", "Russell Cohen ", diff --git a/rust-runtime/aws-smithy-http/src/label.rs b/rust-runtime/aws-smithy-http/src/label.rs index e2f083a383..82ff9a501c 100644 --- a/rust-runtime/aws-smithy-http/src/label.rs +++ b/rust-runtime/aws-smithy-http/src/label.rs @@ -4,7 +4,7 @@ */ //! Formatting values as Smithy -//! [httpLabel](https://awslabs.github.io/smithy/1.0/spec/core/http-traits.html#httplabel-trait) +//! [httpLabel](https://smithy.io/2.0/spec/http-bindings.html#httplabel-trait) use crate::urlencode::BASE_SET; use aws_smithy_types::date_time::{DateTimeFormatError, Format}; diff --git a/rust-runtime/aws-smithy-http/src/query.rs b/rust-runtime/aws-smithy-http/src/query.rs index 81ac8b344a..213a895503 100644 --- a/rust-runtime/aws-smithy-http/src/query.rs +++ b/rust-runtime/aws-smithy-http/src/query.rs @@ -6,7 +6,7 @@ //! Utilities for writing Smithy values into a query string. //! //! Formatting values into the query string as specified in -//! [httpQuery](https://awslabs.github.io/smithy/1.0/spec/core/http-traits.html#httpquery-trait) +//! [httpQuery](https://smithy.io/2.0/spec/http-bindings.html#httpquery-trait) use crate::urlencode::BASE_SET; use aws_smithy_types::date_time::{DateTimeFormatError, Format}; diff --git a/rust-runtime/aws-smithy-runtime-api/Cargo.toml b/rust-runtime/aws-smithy-runtime-api/Cargo.toml index ea9b6e970e..f6687beb11 100644 --- a/rust-runtime/aws-smithy-runtime-api/Cargo.toml +++ b/rust-runtime/aws-smithy-runtime-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aws-smithy-runtime-api" -version = "1.3.0" +version = "1.5.0" authors = ["AWS Rust SDK Team ", "Zelda Hessler "] description = "Smithy runtime types." edition = "2021" diff --git a/rust-runtime/aws-smithy-runtime-api/src/client.rs b/rust-runtime/aws-smithy-runtime-api/src/client.rs index cb5a439522..d133a82cb8 100644 --- a/rust-runtime/aws-smithy-runtime-api/src/client.rs +++ b/rust-runtime/aws-smithy-runtime-api/src/client.rs @@ -121,3 +121,6 @@ pub mod behavior_version; pub mod ser_de; pub mod stalled_stream_protection; + +/// Smithy support-code for code generated waiters. +pub mod waiters; diff --git a/rust-runtime/aws-smithy-runtime-api/src/client/identity.rs b/rust-runtime/aws-smithy-runtime-api/src/client/identity.rs index 2671a883a0..8177b059ba 100644 --- a/rust-runtime/aws-smithy-runtime-api/src/client/identity.rs +++ b/rust-runtime/aws-smithy-runtime-api/src/client/identity.rs @@ -168,6 +168,13 @@ pub trait ResolveIdentity: Send + Sync + Debug { fn cache_location(&self) -> IdentityCacheLocation { IdentityCacheLocation::RuntimeComponents } + + /// Returns the identity cache partition associated with this identity resolver. + /// + /// By default this returns `None` and cache partitioning is left up to `SharedIdentityResolver`. + fn cache_partition(&self) -> Option { + None + } } /// Cache location for identity caching. @@ -195,9 +202,16 @@ pub struct SharedIdentityResolver { impl SharedIdentityResolver { /// Creates a new [`SharedIdentityResolver`] from the given resolver. pub fn new(resolver: impl ResolveIdentity + 'static) -> Self { + // NOTE: `IdentityCachePartition` is globally unique by construction so even + // custom implementations of `ResolveIdentity::cache_partition()` are unique. + let partition = match resolver.cache_partition() { + Some(p) => p, + None => IdentityCachePartition::new(), + }; + Self { inner: Arc::new(resolver), - cache_partition: IdentityCachePartition::new(), + cache_partition: partition, } } @@ -222,6 +236,10 @@ impl ResolveIdentity for SharedIdentityResolver { fn cache_location(&self) -> IdentityCacheLocation { self.inner.cache_location() } + + fn cache_partition(&self) -> Option { + Some(self.cache_partition()) + } } impl_shared_conversions!(convert SharedIdentityResolver from ResolveIdentity using SharedIdentityResolver::new); diff --git a/rust-runtime/aws-smithy-runtime-api/src/client/interceptors/context.rs b/rust-runtime/aws-smithy-runtime-api/src/client/interceptors/context.rs index 5d406bf846..6b564ab76b 100644 --- a/rust-runtime/aws-smithy-runtime-api/src/client/interceptors/context.rs +++ b/rust-runtime/aws-smithy-runtime-api/src/client/interceptors/context.rs @@ -239,6 +239,13 @@ impl InterceptorContext { self.output_or_error.as_mut() } + /// Grants ownership of the deserialized output/error. + /// + /// Note: This method is intended for internal use only. + pub fn take_output_or_error(&mut self) -> Option>> { + self.output_or_error.take() + } + /// Return `true` if this context's `output_or_error` is an error. Otherwise, return `false`. /// /// Note: This method is intended for internal use only. @@ -409,16 +416,23 @@ where /// Convert this context into the final operation result that is returned in client's the public API. /// /// Note: This method is intended for internal use only. - pub fn finalize(self) -> Result> { - let Self { - output_or_error, - response, - phase, - .. - } = self; - output_or_error - .expect("output_or_error must always be set before finalize is called.") - .map_err(|error| OrchestratorError::into_sdk_error(error, &phase, response)) + pub fn finalize(mut self) -> Result> { + let output_or_error = self + .output_or_error + .take() + .expect("output_or_error must always be set before finalize is called."); + self.finalize_result(output_or_error) + } + + /// Convert the given output/error into a final operation result that is returned in the client's public API. + /// + /// Note: This method is intended for internal use only. + pub fn finalize_result( + &mut self, + result: Result>, + ) -> Result> { + let response = self.response.take(); + result.map_err(|error| OrchestratorError::into_sdk_error(error, &self.phase, response)) } /// Mark this context as failed due to errors during the operation. Any errors already contained diff --git a/rust-runtime/aws-smithy-runtime-api/src/client/result.rs b/rust-runtime/aws-smithy-runtime-api/src/client/result.rs index 84dde1e3c3..b97f0ef6c8 100644 --- a/rust-runtime/aws-smithy-runtime-api/src/client/result.rs +++ b/rust-runtime/aws-smithy-runtime-api/src/client/result.rs @@ -170,7 +170,7 @@ pub mod builders { /// Error context for [`SdkError::ConstructionFailure`] #[derive(Debug)] pub struct ConstructionFailure { - source: BoxError, + pub(crate) source: BoxError, } impl ConstructionFailure { diff --git a/rust-runtime/aws-smithy-runtime-api/src/client/runtime_components.rs b/rust-runtime/aws-smithy-runtime-api/src/client/runtime_components.rs index 7a936aef10..6ec7b540e0 100644 --- a/rust-runtime/aws-smithy-runtime-api/src/client/runtime_components.rs +++ b/rust-runtime/aws-smithy-runtime-api/src/client/runtime_components.rs @@ -891,12 +891,39 @@ impl RuntimeComponentsBuilder { Ok(()) } + /// Converts this builder into [`TimeComponents`]. + pub fn into_time_components(mut self) -> TimeComponents { + TimeComponents { + sleep_impl: self.sleep_impl.take().map(|s| s.value), + time_source: self.time_source.take().map(|s| s.value), + } + } + /// Wraps `v` in tracking associated with this builder fn tracked(&self, v: Option) -> Option> { v.map(|v| Tracked::new(self.builder_name, v)) } } +/// Time-related subset of components that can be extracted directly from [`RuntimeComponentsBuilder`] prior to validation. +#[derive(Debug)] +pub struct TimeComponents { + sleep_impl: Option, + time_source: Option, +} + +impl TimeComponents { + /// Returns the async sleep implementation if one is available. + pub fn sleep_impl(&self) -> Option { + self.sleep_impl.clone() + } + + /// Returns the time source if one is available. + pub fn time_source(&self) -> Option { + self.time_source.clone() + } +} + #[derive(Clone, Debug)] #[cfg_attr(test, derive(Eq, PartialEq))] pub(crate) struct Tracked { diff --git a/rust-runtime/aws-smithy-runtime-api/src/client/stalled_stream_protection.rs b/rust-runtime/aws-smithy-runtime-api/src/client/stalled_stream_protection.rs index 25c9c5c67d..f90f886592 100644 --- a/rust-runtime/aws-smithy-runtime-api/src/client/stalled_stream_protection.rs +++ b/rust-runtime/aws-smithy-runtime-api/src/client/stalled_stream_protection.rs @@ -20,15 +20,17 @@ const DEFAULT_GRACE_PERIOD: Duration = Duration::from_secs(5); /// When enabled, download streams that stall out will be cancelled. #[derive(Clone, Debug)] pub struct StalledStreamProtectionConfig { - is_enabled: bool, + upload_enabled: bool, + download_enabled: bool, grace_period: Duration, } impl StalledStreamProtectionConfig { - /// Create a new config that enables stalled stream protection. + /// Create a new config that enables stalled stream protection for both uploads and downloads. pub fn enabled() -> Builder { Builder { - is_enabled: Some(true), + upload_enabled: Some(true), + download_enabled: Some(true), grace_period: None, } } @@ -36,14 +38,25 @@ impl StalledStreamProtectionConfig { /// Create a new config that disables stalled stream protection. pub fn disabled() -> Self { Self { - is_enabled: false, + upload_enabled: false, + download_enabled: false, grace_period: DEFAULT_GRACE_PERIOD, } } - /// Return whether stalled stream protection is enabled. + /// Return whether stalled stream protection is enabled for either uploads or downloads. pub fn is_enabled(&self) -> bool { - self.is_enabled + self.upload_enabled || self.download_enabled + } + + /// True if stalled stream protection is enabled for upload streams. + pub fn upload_enabled(&self) -> bool { + self.upload_enabled + } + + /// True if stalled stream protection is enabled for download streams. + pub fn download_enabled(&self) -> bool { + self.download_enabled } /// Return the grace period for stalled stream protection. @@ -57,7 +70,8 @@ impl StalledStreamProtectionConfig { #[derive(Clone, Debug)] pub struct Builder { - is_enabled: Option, + upload_enabled: Option, + download_enabled: Option, grace_period: Option, } @@ -74,22 +88,48 @@ impl Builder { self } - /// Set whether stalled stream protection is enabled. - pub fn is_enabled(mut self, is_enabled: bool) -> Self { - self.is_enabled = Some(is_enabled); + /// Set whether stalled stream protection is enabled for both uploads and downloads. + pub fn is_enabled(mut self, enabled: bool) -> Self { + self.set_is_enabled(Some(enabled)); + self + } + + /// Set whether stalled stream protection is enabled for both uploads and downloads. + pub fn set_is_enabled(&mut self, enabled: Option) -> &mut Self { + self.set_upload_enabled(enabled); + self.set_download_enabled(enabled); + self + } + + /// Set whether stalled stream protection is enabled for upload streams. + pub fn upload_enabled(mut self, enabled: bool) -> Self { + self.set_upload_enabled(Some(enabled)); + self + } + + /// Set whether stalled stream protection is enabled for upload streams. + pub fn set_upload_enabled(&mut self, enabled: Option) -> &mut Self { + self.upload_enabled = enabled; + self + } + + /// Set whether stalled stream protection is enabled for download streams. + pub fn download_enabled(mut self, enabled: bool) -> Self { + self.set_download_enabled(Some(enabled)); self } - /// Set whether stalled stream protection is enabled. - pub fn set_is_enabled(&mut self, is_enabled: Option) -> &mut Self { - self.is_enabled = is_enabled; + /// Set whether stalled stream protection is enabled for download streams. + pub fn set_download_enabled(&mut self, enabled: Option) -> &mut Self { + self.download_enabled = enabled; self } /// Build the config. pub fn build(self) -> StalledStreamProtectionConfig { StalledStreamProtectionConfig { - is_enabled: self.is_enabled.unwrap_or_default(), + upload_enabled: self.upload_enabled.unwrap_or_default(), + download_enabled: self.download_enabled.unwrap_or_default(), grace_period: self.grace_period.unwrap_or(DEFAULT_GRACE_PERIOD), } } @@ -98,7 +138,8 @@ impl Builder { impl From for Builder { fn from(config: StalledStreamProtectionConfig) -> Self { Builder { - is_enabled: Some(config.is_enabled), + upload_enabled: Some(config.upload_enabled), + download_enabled: Some(config.download_enabled), grace_period: Some(config.grace_period), } } diff --git a/rust-runtime/aws-smithy-runtime-api/src/client/waiters.rs b/rust-runtime/aws-smithy-runtime-api/src/client/waiters.rs new file mode 100644 index 0000000000..dcb14ee48d --- /dev/null +++ b/rust-runtime/aws-smithy-runtime-api/src/client/waiters.rs @@ -0,0 +1,232 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +/// Error types for waiters. +pub mod error { + use crate::client::{ + orchestrator::HttpResponse, + result::{ConstructionFailure, SdkError}, + }; + use crate::{box_error::BoxError, client::waiters::FinalPoll}; + use aws_smithy_types::error::{ + metadata::{ProvideErrorMetadata, EMPTY_ERROR_METADATA}, + ErrorMetadata, + }; + use std::{fmt, time::Duration}; + + /// An error occurred while waiting. + /// + /// This error type is useful for distinguishing between the max wait + /// time being exceeded, or some other failure occurring. + #[derive(Debug)] + #[non_exhaustive] + pub enum WaiterError { + /// An error occurred during waiter initialization. + /// + /// This can happen if the input/config is invalid. + ConstructionFailure(ConstructionFailure), + + /// The maximum wait time was exceeded without completion. + ExceededMaxWait(ExceededMaxWait), + + /// Waiting ended in a failure state. + /// + /// A failed waiter state can occur on a successful response from the server + /// if, for example, that response indicates that the thing being waited for + /// won't succeed/finish. + /// + /// A failure state error will only occur for successful or modeled error responses. + /// Unmodeled error responses will never make it into this error case. + FailureState(FailureState), + + /// A polling operation failed while waiting. + /// + /// This error will only occur for unmodeled errors. Modeled errors can potentially + /// be handled by the waiter logic, and will therefore end up in [`WaiterError::FailureState`]. + /// + /// Note: If retry is configured, this means that the operation failed + /// after retrying the configured number of attempts. + OperationFailed(OperationFailed), + } + + impl WaiterError { + /// Construct a waiter construction failure with the given error source. + pub fn construction_failure(source: impl Into) -> Self { + Self::ConstructionFailure(ConstructionFailure::builder().source(source).build()) + } + } + + impl std::error::Error for WaiterError + where + O: fmt::Debug, + E: std::error::Error + fmt::Debug + 'static, + { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::ConstructionFailure(inner) => Some(&*inner.source), + Self::ExceededMaxWait(_) => None, + Self::FailureState(inner) => match &inner.final_poll.result { + Ok(_) => None, + Err(err) => Some(err), + }, + Self::OperationFailed(inner) => Some(&inner.source), + } + } + } + + impl fmt::Display for WaiterError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::ConstructionFailure(_) => f.write_str("failed to construct waiter"), + Self::ExceededMaxWait(ctx) => { + write!(f, "exceeded max wait time ({:?})", ctx.max_wait) + } + Self::FailureState(_) => f.write_str("waiting failed"), + Self::OperationFailed(_) => f.write_str("operation failed while waiting"), + } + } + } + + // Implement `ProvideErrorMetadata` so that request IDs can be discovered from waiter failures. + impl ProvideErrorMetadata for WaiterError + where + E: ProvideErrorMetadata, + { + fn meta(&self) -> &ErrorMetadata { + match self { + WaiterError::ConstructionFailure(_) | WaiterError::ExceededMaxWait(_) => { + &EMPTY_ERROR_METADATA + } + WaiterError::FailureState(inner) => inner + .final_poll() + .as_result() + .err() + .map(ProvideErrorMetadata::meta) + .unwrap_or(&EMPTY_ERROR_METADATA), + WaiterError::OperationFailed(inner) => inner.error().meta(), + } + } + } + + /// Error context for [`WaiterError::ExceededMaxWait`]. + #[derive(Debug)] + pub struct ExceededMaxWait { + max_wait: Duration, + elapsed: Duration, + poll_count: u32, + } + + impl ExceededMaxWait { + /// Creates new error context. + pub fn new(max_wait: Duration, elapsed: Duration, poll_count: u32) -> Self { + Self { + max_wait, + elapsed, + poll_count, + } + } + + /// Returns the configured max wait time that was exceeded. + pub fn max_wait(&self) -> Duration { + self.max_wait + } + + /// How much time actually elapsed before max wait was triggered. + pub fn elapsed(&self) -> Duration { + self.elapsed + } + + /// Returns the number of polling operations that were made before exceeding the max wait time. + pub fn poll_count(&self) -> u32 { + self.poll_count + } + } + + /// Error context for [`WaiterError::FailureState`]. + #[derive(Debug)] + #[non_exhaustive] + pub struct FailureState { + final_poll: FinalPoll, + } + + impl FailureState { + /// Creates new error context given a final poll result. + pub fn new(final_poll: FinalPoll) -> Self { + Self { final_poll } + } + + /// Returns the result of the final polling attempt. + pub fn final_poll(&self) -> &FinalPoll { + &self.final_poll + } + + /// Grants ownership of the result of the final polling attempt. + pub fn into_final_poll(self) -> FinalPoll { + self.final_poll + } + } + + /// Error context for [`WaiterError::OperationFailed`]. + #[derive(Debug)] + #[non_exhaustive] + pub struct OperationFailed { + source: SdkError, + } + + impl OperationFailed { + /// Creates new error context given a source [`SdkError`]. + pub fn new(source: SdkError) -> Self { + Self { source } + } + + /// Returns the underlying source [`SdkError`]. + pub fn error(&self) -> &SdkError { + &self.source + } + + /// Grants ownership of the underlying source [`SdkError`]. + pub fn into_error(self) -> SdkError { + self.source + } + } +} + +/// Result of the final polling attempt made by a waiter. +/// +/// Waiters make several requests ("polls") to the remote service, and this +/// struct holds the result of the final poll attempt that was made by the +/// waiter so that it can be inspected. +#[non_exhaustive] +#[derive(Debug)] +pub struct FinalPoll { + result: Result, +} + +impl FinalPoll { + /// Creates a new `FinalPoll` from a result. + pub fn new(result: Result) -> Self { + Self { result } + } + + /// Grants ownership of the underlying result. + pub fn into_result(self) -> Result { + self.result + } + + /// Returns the underlying result. + pub fn as_result(&self) -> Result<&O, &E> { + self.result.as_ref() + } + + /// Maps the operation type with a function. + pub fn map O2>(self, mapper: F) -> FinalPoll { + FinalPoll::new(self.result.map(mapper)) + } + + /// Maps the error type with a function. + pub fn map_err E2>(self, mapper: F) -> FinalPoll { + FinalPoll::new(self.result.map_err(mapper)) + } +} diff --git a/rust-runtime/aws-smithy-runtime/Cargo.toml b/rust-runtime/aws-smithy-runtime/Cargo.toml index 276add22ef..7327df20e0 100644 --- a/rust-runtime/aws-smithy-runtime/Cargo.toml +++ b/rust-runtime/aws-smithy-runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aws-smithy-runtime" -version = "1.2.1" +version = "1.4.0" authors = ["AWS Rust SDK Team ", "Zelda Hessler "] description = "The new smithy runtime crate" edition = "2021" @@ -27,6 +27,8 @@ aws-smithy-protocol-test = { path = "../aws-smithy-protocol-test", optional = tr aws-smithy-runtime-api = { path = "../aws-smithy-runtime-api" } aws-smithy-types = { path = "../aws-smithy-types", features = ["http-body-0-4-x"] } bytes = "1" +# Make sure to update `fastrand` in [dev-dependencies] if we bump the major version +# We probably need to update unit tests using the `fastrand` crate when that happens fastrand = "2.0.0" h2 = { version = "0.3", default-features = false, optional = true } http = { version = "0.2.8" } @@ -43,13 +45,16 @@ serde_json = { version = "1", features = ["preserve_order"], optional = true } indexmap = { version = "2", optional = true, features = ["serde"] } tokio = { version = "1.25", features = [] } tracing = "0.1.37" -tracing-subscriber = { version = "0.3.16", optional = true, features = ["fmt", "json"] } +tracing-subscriber = { version = "0.3.16", optional = true, features = ["env-filter", "fmt", "json"] } [dev-dependencies] approx = "0.5.1" aws-smithy-async = { path = "../aws-smithy-async", features = ["rt-tokio", "test-util"] } aws-smithy-runtime-api = { path = "../aws-smithy-runtime-api", features = ["test-util"] } aws-smithy-types = { path = "../aws-smithy-types", features = ["test-util"] } +# Allow only patch-level bumps since major-level or minor-level bumps can cause seed-value-breaking changes +# https://github.com/smol-rs/fastrand/issues/20 +fastrand = "~2.0.0" futures-util = "0.3.29" pretty_assertions = "1.4.0" tokio = { version = "1.25", features = ["macros", "rt", "rt-multi-thread", "test-util", "full"] } diff --git a/rust-runtime/aws-smithy-runtime/src/client.rs b/rust-runtime/aws-smithy-runtime/src/client.rs index bb3a85ad3d..db146e9959 100644 --- a/rust-runtime/aws-smithy-runtime/src/client.rs +++ b/rust-runtime/aws-smithy-runtime/src/client.rs @@ -46,3 +46,6 @@ pub mod interceptors; /// Stalled stream protection for clients pub mod stalled_stream_protection; + +/// Smithy support-code for code generated waiters. +pub mod waiters; diff --git a/rust-runtime/aws-smithy-runtime/src/client/defaults.rs b/rust-runtime/aws-smithy-runtime/src/client/defaults.rs index 5a23e3f3db..99f549e542 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/defaults.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/defaults.rs @@ -171,7 +171,16 @@ pub fn default_identity_cache_plugin() -> Option { /// /// By default, when throughput falls below 1/Bs for more than 5 seconds, the /// stream is cancelled. +#[deprecated( + since = "1.2.0", + note = "This function wasn't intended to be public, and didn't take the behavior major version as an argument, so it couldn't be evolved over time." +)] pub fn default_stalled_stream_protection_config_plugin() -> Option { + default_stalled_stream_protection_config_plugin_v2(BehaviorVersion::v2023_11_09()) +} +fn default_stalled_stream_protection_config_plugin_v2( + _behavior_version: BehaviorVersion, +) -> Option { Some( default_plugin( "default_stalled_stream_protection_config_plugin", @@ -184,6 +193,8 @@ pub fn default_stalled_stream_protection_config_plugin() -> Option impl IntoIterator { + let behavior_version = params + .behavior_version + .unwrap_or_else(BehaviorVersion::latest); + [ default_http_client_plugin(), default_identity_cache_plugin(), @@ -272,7 +287,7 @@ pub fn default_plugins( default_timeout_config_plugin(), // TODO(https://github.com/smithy-lang/smithy-rs/issues/3523): Reenable this /* enforce_content_length_runtime_plugin(), */ - default_stalled_stream_protection_config_plugin(), + default_stalled_stream_protection_config_plugin_v2(behavior_version), ] .into_iter() .flatten() diff --git a/rust-runtime/aws-smithy-runtime/src/client/http/body/minimum_throughput.rs b/rust-runtime/aws-smithy-runtime/src/client/http/body/minimum_throughput.rs index c576a34afa..59c8a3c64c 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/http/body/minimum_throughput.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/http/body/minimum_throughput.rs @@ -15,25 +15,46 @@ pub mod options; pub use throughput::Throughput; mod throughput; +use crate::client::http::body::minimum_throughput::throughput::ThroughputReport; use aws_smithy_async::rt::sleep::Sleep; use aws_smithy_async::rt::sleep::{AsyncSleep, SharedAsyncSleep}; use aws_smithy_async::time::{SharedTimeSource, TimeSource}; -use aws_smithy_runtime_api::box_error::BoxError; -use aws_smithy_runtime_api::shared::IntoShared; +use aws_smithy_runtime_api::{ + box_error::BoxError, + client::{ + http::HttpConnectorFuture, result::ConnectorError, runtime_components::RuntimeComponents, + stalled_stream_protection::StalledStreamProtectionConfig, + }, +}; +use aws_smithy_runtime_api::{client::orchestrator::HttpResponse, shared::IntoShared}; +use aws_smithy_types::config_bag::{ConfigBag, Storable, StoreReplace}; use options::MinimumThroughputBodyOptions; -use std::fmt; -use std::time::SystemTime; +use std::{ + fmt, + sync::{Arc, Mutex}, + task::Poll, +}; +use std::{future::Future, pin::Pin}; +use std::{ + task::Context, + time::{Duration, SystemTime}, +}; use throughput::ThroughputLogs; +/// Use [`MinimumThroughputDownloadBody`] instead. +#[deprecated(note = "Renamed to MinimumThroughputDownloadBody since it doesn't work for uploads")] +pub type MinimumThroughputBody = MinimumThroughputDownloadBody; + pin_project_lite::pin_project! { /// A body-wrapping type that ensures data is being streamed faster than some lower limit. /// /// If data is being streamed too slowly, this body type will emit an error next time it's polled. - pub struct MinimumThroughputBody { + pub struct MinimumThroughputDownloadBody { async_sleep: SharedAsyncSleep, time_source: SharedTimeSource, options: MinimumThroughputBodyOptions, throughput_logs: ThroughputLogs, + resolution: Duration, #[pin] sleep_fut: Option, #[pin] @@ -43,10 +64,7 @@ pin_project_lite::pin_project! { } } -const SIZE_OF_ONE_LOG: usize = std::mem::size_of::<(SystemTime, u64)>(); // 24 bytes per log -const NUMBER_OF_LOGS_IN_ONE_KB: f64 = 1024.0 / SIZE_OF_ONE_LOG as f64; - -impl MinimumThroughputBody { +impl MinimumThroughputDownloadBody { /// Create a new minimum throughput body. pub fn new( time_source: impl TimeSource + 'static, @@ -54,14 +72,15 @@ impl MinimumThroughputBody { body: B, options: MinimumThroughputBodyOptions, ) -> Self { + let time_source: SharedTimeSource = time_source.into_shared(); + let now = time_source.now(); + let throughput_logs = ThroughputLogs::new(options.check_window(), now); + let resolution = throughput_logs.resolution(); Self { - throughput_logs: ThroughputLogs::new( - // Never keep more than 10KB of logs in memory. This currently - // equates to 426 logs. - (NUMBER_OF_LOGS_IN_ONE_KB * 10.0) as usize, - ), + throughput_logs, + resolution, async_sleep: async_sleep.into_shared(), - time_source: time_source.into_shared(), + time_source, inner: body, sleep_fut: None, grace_period_fut: None, @@ -93,4 +112,286 @@ impl fmt::Display for Error { impl std::error::Error for Error {} -// Tests are implemented per HTTP body type. +/// Used to store the upload throughput in the interceptor context. +#[derive(Clone, Debug)] +pub(crate) struct UploadThroughput { + logs: Arc>, +} + +impl UploadThroughput { + pub(crate) fn new(time_window: Duration, now: SystemTime) -> Self { + Self { + logs: Arc::new(Mutex::new(ThroughputLogs::new(time_window, now))), + } + } + + pub(crate) fn resolution(&self) -> Duration { + self.logs.lock().unwrap().resolution() + } + + pub(crate) fn push_pending(&self, now: SystemTime) { + self.logs.lock().unwrap().push_pending(now); + } + pub(crate) fn push_bytes_transferred(&self, now: SystemTime, bytes: u64) { + self.logs.lock().unwrap().push_bytes_transferred(now, bytes); + } + + pub(crate) fn report(&self, now: SystemTime) -> ThroughputReport { + self.logs.lock().unwrap().report(now) + } +} + +impl Storable for UploadThroughput { + type Storer = StoreReplace; +} + +pin_project_lite::pin_project! { + pub(crate) struct ThroughputReadingBody { + time_source: SharedTimeSource, + throughput: UploadThroughput, + #[pin] + inner: B, + } +} + +impl ThroughputReadingBody { + pub(crate) fn new( + time_source: SharedTimeSource, + throughput: UploadThroughput, + body: B, + ) -> Self { + Self { + time_source, + throughput, + inner: body, + } + } +} + +const ZERO_THROUGHPUT: Throughput = Throughput::new_bytes_per_second(0); + +// Helper trait for interpretting the throughput report. +trait UploadReport { + fn minimum_throughput_violated(self, minimum_throughput: Throughput) -> (bool, Throughput); +} +impl UploadReport for ThroughputReport { + fn minimum_throughput_violated(self, minimum_throughput: Throughput) -> (bool, Throughput) { + let throughput = match self { + // If the report is incomplete, then we don't have enough data yet to + // decide if minimum throughput was violated. + ThroughputReport::Incomplete => { + tracing::trace!( + "not enough data to decide if minimum throughput has been violated" + ); + return (false, ZERO_THROUGHPUT); + } + // If most of the datapoints are Poll::Pending, then the user has stalled. + // In this case, we don't want to say minimum throughput was violated. + ThroughputReport::Pending => { + tracing::debug!( + "the user has stalled; this will not become a minimum throughput violation" + ); + return (false, ZERO_THROUGHPUT); + } + // If there has been no polling, then the server has stalled. Alternatively, + // if we're transferring data, but it's too slow, then we also want to say + // that the minimum throughput has been violated. + ThroughputReport::NoPolling => ZERO_THROUGHPUT, + ThroughputReport::Transferred(tp) => tp, + }; + if throughput < minimum_throughput { + tracing::debug!( + "current throughput: {throughput} is below minimum: {minimum_throughput}" + ); + (true, throughput) + } else { + (false, throughput) + } + } +} + +pin_project_lite::pin_project! { + /// Future that pairs with [`UploadThroughput`] to add a minimum throughput + /// requirement to a request upload stream. + struct UploadThroughputCheckFuture { + #[pin] + response: HttpConnectorFuture, + #[pin] + check_interval: Option, + #[pin] + grace_period: Option, + + time_source: SharedTimeSource, + sleep_impl: SharedAsyncSleep, + upload_throughput: UploadThroughput, + resolution: Duration, + options: MinimumThroughputBodyOptions, + + failing_throughput: Option, + } +} + +impl UploadThroughputCheckFuture { + fn new( + response: HttpConnectorFuture, + time_source: SharedTimeSource, + sleep_impl: SharedAsyncSleep, + upload_throughput: UploadThroughput, + options: MinimumThroughputBodyOptions, + ) -> Self { + let resolution = upload_throughput.resolution(); + Self { + response, + check_interval: Some(sleep_impl.sleep(resolution)), + grace_period: None, + time_source, + sleep_impl, + upload_throughput, + resolution, + options, + failing_throughput: None, + } + } +} + +impl Future for UploadThroughputCheckFuture { + type Output = Result; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mut this = self.project(); + + if let Poll::Ready(output) = this.response.poll(cx) { + return Poll::Ready(output); + } else { + let mut below_minimum_throughput = false; + let check_interval_expired = this + .check_interval + .as_mut() + .as_pin_mut() + .expect("always set") + .poll(cx) + .is_ready(); + if check_interval_expired { + // Set up the next check interval + *this.check_interval = Some(this.sleep_impl.sleep(*this.resolution)); + + // Wake so that the check interval future gets polled + // next time this poll method is called. If it never gets polled, + // then this task won't be woken to check again. + cx.waker().wake_by_ref(); + } + + let should_check = check_interval_expired || this.grace_period.is_some(); + if should_check { + let now = this.time_source.now(); + let report = this.upload_throughput.report(now); + let (violated, current_throughput) = + report.minimum_throughput_violated(this.options.minimum_throughput()); + below_minimum_throughput = violated; + if below_minimum_throughput && !this.failing_throughput.is_some() { + *this.failing_throughput = Some(current_throughput); + } else if !below_minimum_throughput { + *this.failing_throughput = None; + } + } + + // If we kicked off a grace period and are now satisfied, clear out the grace period + if !below_minimum_throughput && this.grace_period.is_some() { + tracing::debug!("upload minimum throughput recovered during grace period"); + *this.grace_period = None; + } + if below_minimum_throughput { + // Start a grace period if below minimum throughput + if this.grace_period.is_none() { + tracing::debug!( + grace_period=?this.options.grace_period(), + "upload minimum throughput below configured minimum; starting grace period" + ); + *this.grace_period = Some(this.sleep_impl.sleep(this.options.grace_period())); + } + // Check the grace period if one is already set and we're not satisfied + if let Some(grace_period) = this.grace_period.as_pin_mut() { + if grace_period.poll(cx).is_ready() { + tracing::debug!("grace period ended; timing out request"); + return Poll::Ready(Err(ConnectorError::timeout( + Error::ThroughputBelowMinimum { + expected: this.options.minimum_throughput(), + actual: this + .failing_throughput + .expect("always set if there's a grace period"), + } + .into(), + ))); + } + } + } + } + Poll::Pending + } +} + +pin_project_lite::pin_project! { + #[project = EnumProj] + pub(crate) enum MaybeUploadThroughputCheckFuture { + Direct { #[pin] future: HttpConnectorFuture }, + Checked { #[pin] future: UploadThroughputCheckFuture }, + } +} + +impl MaybeUploadThroughputCheckFuture { + pub(crate) fn new( + cfg: &mut ConfigBag, + components: &RuntimeComponents, + connector_future: HttpConnectorFuture, + ) -> Self { + if let Some(sspcfg) = cfg.load::().cloned() { + if sspcfg.is_enabled() { + let options = MinimumThroughputBodyOptions::from(sspcfg); + return Self::new_inner( + connector_future, + components.time_source(), + components.sleep_impl(), + cfg.interceptor_state().load::().cloned(), + Some(options), + ); + } + } + tracing::debug!("no minimum upload throughput checks"); + Self::new_inner(connector_future, None, None, None, None) + } + + fn new_inner( + response: HttpConnectorFuture, + time_source: Option, + sleep_impl: Option, + upload_throughput: Option, + options: Option, + ) -> Self { + match (time_source, sleep_impl, upload_throughput, options) { + (Some(time_source), Some(sleep_impl), Some(upload_throughput), Some(options)) => { + tracing::debug!(options=?options, "applying minimum upload throughput check future"); + Self::Checked { + future: UploadThroughputCheckFuture::new( + response, + time_source, + sleep_impl, + upload_throughput, + options, + ), + } + } + _ => Self::Direct { future: response }, + } + } +} + +impl Future for MaybeUploadThroughputCheckFuture { + type Output = Result; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + match self.project() { + EnumProj::Direct { future } => future.poll(cx), + EnumProj::Checked { future } => future.poll(cx), + } + } +} diff --git a/rust-runtime/aws-smithy-runtime/src/client/http/body/minimum_throughput/http_body_0_4_x.rs b/rust-runtime/aws-smithy-runtime/src/client/http/body/minimum_throughput/http_body_0_4_x.rs index 075ef39d63..a8f2fe9c4b 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/http/body/minimum_throughput/http_body_0_4_x.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/http/body/minimum_throughput/http_body_0_4_x.rs @@ -3,14 +3,58 @@ * SPDX-License-Identifier: Apache-2.0 */ -use super::{BoxError, Error, MinimumThroughputBody}; +use super::{BoxError, Error, MinimumThroughputDownloadBody}; +use crate::client::http::body::minimum_throughput::{ + throughput::ThroughputReport, Throughput, ThroughputReadingBody, +}; use aws_smithy_async::rt::sleep::AsyncSleep; use http_body_0_4::Body; use std::future::Future; use std::pin::{pin, Pin}; use std::task::{Context, Poll}; -impl Body for MinimumThroughputBody +const ZERO_THROUGHPUT: Throughput = Throughput::new_bytes_per_second(0); + +// Helper trait for interpretting the throughput report. +trait DownloadReport { + fn minimum_throughput_violated(self, minimum_throughput: Throughput) -> (bool, Throughput); +} +impl DownloadReport for ThroughputReport { + fn minimum_throughput_violated(self, minimum_throughput: Throughput) -> (bool, Throughput) { + let throughput = match self { + // If the report is incomplete, then we don't have enough data yet to + // decide if minimum throughput was violated. + ThroughputReport::Incomplete => { + tracing::trace!( + "not enough data to decide if minimum throughput has been violated" + ); + return (false, ZERO_THROUGHPUT); + } + // If no polling is taking place, then the user has stalled. + // In this case, we don't want to say minimum throughput was violated. + ThroughputReport::NoPolling => { + tracing::debug!( + "the user has stalled; this will not become a minimum throughput violation" + ); + return (false, ZERO_THROUGHPUT); + } + // If we're stuck in Poll::Pending, then the server has stalled. Alternatively, + // if we're transferring data, but it's too slow, then we also want to say + // that the minimum throughput has been violated. + ThroughputReport::Pending => ZERO_THROUGHPUT, + ThroughputReport::Transferred(tp) => tp, + }; + let violated = throughput < minimum_throughput; + if violated { + tracing::debug!( + "current throughput: {throughput} is below minimum: {minimum_throughput}" + ); + } + (violated, throughput) + } +} + +impl Body for MinimumThroughputDownloadBody where B: Body, { @@ -30,12 +74,13 @@ where let poll_res = match this.inner.poll_data(cx) { Poll::Ready(Some(Ok(bytes))) => { tracing::trace!("received data: {}", bytes.len()); - this.throughput_logs.push((now, bytes.len() as u64)); + this.throughput_logs + .push_bytes_transferred(now, bytes.len() as u64); Poll::Ready(Some(Ok(bytes))) } Poll::Pending => { tracing::trace!("received poll pending"); - this.throughput_logs.push((now, 0)); + this.throughput_logs.push_pending(now); Poll::Pending } // If we've read all the data or an error occurred, then return that result. @@ -46,44 +91,27 @@ where let mut sleep_fut = this .sleep_fut .take() - .unwrap_or_else(|| this.async_sleep.sleep(this.options.check_interval())); + .unwrap_or_else(|| this.async_sleep.sleep(*this.resolution)); if let Poll::Ready(()) = pin!(&mut sleep_fut).poll(cx) { tracing::trace!("sleep future triggered—triggering a wakeup"); // Whenever the sleep future expires, we replace it. - sleep_fut = this.async_sleep.sleep(this.options.check_interval()); + sleep_fut = this.async_sleep.sleep(*this.resolution); // We also schedule a wake up for current task to ensure that // it gets polled at least one more time. cx.waker().wake_by_ref(); }; this.sleep_fut.replace(sleep_fut); - let calculated_tpt = match this - .throughput_logs - .calculate_throughput(now, this.options.check_window()) - { - Some(tpt) => tpt, - None => { - tracing::trace!("calculated throughput is None!"); - return poll_res; - } - }; - tracing::trace!( - "calculated throughput {:?} (window: {:?})", - calculated_tpt, - this.options.check_window() - ); // Calculate the current throughput and emit an error if it's too low and // the grace period has elapsed. - let is_below_minimum_throughput = calculated_tpt <= this.options.minimum_throughput(); - if is_below_minimum_throughput { - // Check the grace period future to see if it needs creating. - tracing::trace!( - in_grace_period = this.grace_period_fut.is_some(), - observed_throughput = ?calculated_tpt, - minimum_throughput = ?this.options.minimum_throughput(), - "below minimum throughput" - ); + let report = this.throughput_logs.report(now); + let (violated, current_throughput) = + report.minimum_throughput_violated(this.options.minimum_throughput()); + if violated { + if this.grace_period_fut.is_none() { + tracing::debug!("entering minimum throughput grace period"); + } let mut grace_period_fut = this .grace_period_fut .take() @@ -92,13 +120,16 @@ where // The grace period has ended! return Poll::Ready(Some(Err(Box::new(Error::ThroughputBelowMinimum { expected: self.options.minimum_throughput(), - actual: calculated_tpt, + actual: current_throughput, })))); }; this.grace_period_fut.replace(grace_period_fut); } else { // Ensure we don't have an active grace period future if we're not // currently below the minimum throughput. + if this.grace_period_fut.is_some() { + tracing::debug!("throughput recovered; exiting grace period"); + } let _ = this.grace_period_fut.take(); } @@ -112,290 +143,63 @@ where let this = self.as_mut().project(); this.inner.poll_trailers(cx) } -} - -// These tests use `hyper::body::Body::wrap_stream` -#[cfg(all(test, feature = "connector-hyper-0-14-x", feature = "test-util"))] -mod test { - use super::{super::Throughput, Error, MinimumThroughputBody}; - use crate::client::http::body::minimum_throughput::options::MinimumThroughputBodyOptions; - use crate::test_util::capture_test_logs::capture_test_logs; - use aws_smithy_async::rt::sleep::AsyncSleep; - use aws_smithy_async::test_util::{instant_time_and_sleep, InstantSleep, ManualTimeSource}; - use aws_smithy_types::body::SdkBody; - use aws_smithy_types::byte_stream::{AggregatedBytes, ByteStream}; - use aws_smithy_types::error::display::DisplayErrorContext; - use bytes::{BufMut, Bytes, BytesMut}; - use http::HeaderMap; - use http_body_0_4::Body; - use once_cell::sync::Lazy; - use pretty_assertions::assert_eq; - use std::convert::Infallible; - use std::error::Error as StdError; - use std::future::{poll_fn, Future}; - use std::pin::{pin, Pin}; - use std::task::{Context, Poll}; - use std::time::{Duration, UNIX_EPOCH}; - - struct NeverBody; - - impl Body for NeverBody { - type Data = Bytes; - type Error = Box<(dyn StdError + Send + Sync + 'static)>; - - fn poll_data( - self: Pin<&mut Self>, - _cx: &mut Context<'_>, - ) -> Poll>> { - Poll::Pending - } - - fn poll_trailers( - self: Pin<&mut Self>, - _cx: &mut Context<'_>, - ) -> Poll, Self::Error>> { - unreachable!("body can't be read, so this won't be called") - } - } - - #[tokio::test()] - async fn test_self_waking() { - let (time_source, async_sleep) = instant_time_and_sleep(UNIX_EPOCH); - let mut body = MinimumThroughputBody::new( - time_source.clone(), - async_sleep.clone(), - NeverBody, - Default::default(), - ); - time_source.advance(Duration::from_secs(1)); - let actual_err = body.data().await.expect("next chunk exists").unwrap_err(); - let expected_err = Error::ThroughputBelowMinimum { - expected: (1, Duration::from_secs(1)).into(), - actual: (0, Duration::from_secs(1)).into(), - }; - assert_eq!(expected_err.to_string(), actual_err.to_string()); + fn size_hint(&self) -> http_body_0_4::SizeHint { + self.inner.size_hint() } - fn create_test_stream( - async_sleep: impl AsyncSleep + Clone, - ) -> impl futures_util::Stream> { - futures_util::stream::unfold(1, move |state| { - let async_sleep = async_sleep.clone(); - async move { - if state > 255 { - None - } else { - async_sleep.sleep(Duration::from_secs(1)).await; - Some(( - Result::<_, Infallible>::Ok(Bytes::from_static(b"00000000")), - state + 1, - )) - } - } - }) + fn is_end_stream(&self) -> bool { + self.inner.is_end_stream() } +} - static EXPECTED_BYTES: Lazy> = - Lazy::new(|| (1..=255).flat_map(|_| b"00000000").copied().collect()); - - fn eight_byte_per_second_stream_with_minimum_throughput_timeout( - minimum_throughput: Throughput, - ) -> ( - impl Future>, - ManualTimeSource, - InstantSleep, - ) { - let (time_source, async_sleep) = instant_time_and_sleep(UNIX_EPOCH); - let time_clone = time_source.clone(); - - // Will send ~8 bytes per second. - let stream = create_test_stream(async_sleep.clone()); - let body = ByteStream::new(SdkBody::from_body_0_4(hyper_0_14::body::Body::wrap_stream( - stream, - ))); - let body = body.map(move |body| { - let time_source = time_clone.clone(); - // We don't want to log these sleeps because it would duplicate - // the `sleep` calls being logged by the MTB - let async_sleep = InstantSleep::unlogged(); - SdkBody::from_body_0_4(MinimumThroughputBody::new( - time_source, - async_sleep, - body, - MinimumThroughputBodyOptions::builder() - .minimum_throughput(minimum_throughput) - .build(), - )) - }); - - (body.collect(), time_source, async_sleep) - } +impl Body for ThroughputReadingBody +where + B: Body, +{ + type Data = bytes::Bytes; + type Error = BoxError; - async fn expect_error(minimum_throughput: Throughput) { - let (res, ..) = - eight_byte_per_second_stream_with_minimum_throughput_timeout(minimum_throughput); - let expected_err = Error::ThroughputBelowMinimum { - expected: minimum_throughput, - actual: Throughput::new(8, Duration::from_secs(1)), - }; - match res.await { - Ok(_) => { - panic!( - "response succeeded instead of returning the expected error '{expected_err}'" - ) - } - Err(actual_err) => { - assert_eq!( - expected_err.to_string(), - // We need to source this so that we don't get the streaming error it's wrapped in. - actual_err.source().unwrap().to_string() - ); + fn poll_data( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll>> { + // this code is called quite frequently in production—one every millisecond or so when downloading + // a stream. However, SystemTime::now is on the order of nanoseconds + let now = self.time_source.now(); + // Attempt to read the data from the inner body, then update the + // throughput logs. + let this = self.as_mut().project(); + match this.inner.poll_data(cx) { + Poll::Ready(Some(Ok(bytes))) => { + tracing::trace!("received data: {}", bytes.len()); + this.throughput + .push_bytes_transferred(now, bytes.len() as u64); + Poll::Ready(Some(Ok(bytes))) } - } - } - - #[tokio::test] - async fn test_throughput_timeout_less_than() { - let minimum_throughput = Throughput::new_bytes_per_second(9); - expect_error(minimum_throughput).await; - } - - async fn expect_success(minimum_throughput: Throughput) { - let (res, time_source, async_sleep) = - eight_byte_per_second_stream_with_minimum_throughput_timeout(minimum_throughput); - match res.await { - Ok(res) => { - assert_eq!(255.0, time_source.seconds_since_unix_epoch()); - assert_eq!(Duration::from_secs(255), async_sleep.total_duration()); - assert_eq!(*EXPECTED_BYTES, res.to_vec()); + Poll::Pending => { + tracing::trace!("received poll pending"); + this.throughput.push_pending(now); + Poll::Pending } - Err(err) => panic!("{}", DisplayErrorContext(err.source().unwrap())), + // If we've read all the data or an error occurred, then return that result. + res => res, } } - #[tokio::test] - async fn test_throughput_timeout_equal_to() { - let (_guard, _) = capture_test_logs(); - // a tiny bit less. To capture 0-throughput properly, we need to allow 0 to be 0 - let minimum_throughput = Throughput::new(31, Duration::from_secs(4)); - expect_success(minimum_throughput).await; - } - - #[tokio::test] - async fn test_throughput_timeout_greater_than() { - let minimum_throughput = Throughput::new(20, Duration::from_secs(3)); - expect_success(minimum_throughput).await; - } - - // A multiplier for the sine wave amplitude; Chosen arbitrarily. - const BYTE_COUNT_UPPER_LIMIT: u64 = 1000; - - /// emits 1000B/S for 5 seconds then suddenly stops - fn sudden_stop( - async_sleep: impl AsyncSleep + Clone, - ) -> impl futures_util::Stream> { - let sleep_dur = Duration::from_millis(50); - fastrand::seed(0); - futures_util::stream::unfold(1, move |i| { - let async_sleep = async_sleep.clone(); - async move { - let number_seconds = (i * sleep_dur).as_secs_f64(); - async_sleep.sleep(sleep_dur).await; - if number_seconds > 5.0 { - Some((Result::::Ok(Bytes::new()), i + 1)) - } else { - let mut bytes = BytesMut::new(); - let bytes_per_segment = - (BYTE_COUNT_UPPER_LIMIT as f64) * sleep_dur.as_secs_f64(); - for _ in 0..bytes_per_segment as usize { - bytes.put_u8(0) - } - - Some((Result::::Ok(bytes.into()), i + 1)) - } - } - }) - } - - #[tokio::test] - async fn test_stalled_stream_detection() { - test_suddenly_stopping_stream(0, Duration::from_secs(6)).await - } - - #[tokio::test] - async fn test_slow_stream_detection() { - test_suddenly_stopping_stream(BYTE_COUNT_UPPER_LIMIT / 2, Duration::from_secs_f64(5.50)) - .await + fn poll_trailers( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll, Self::Error>> { + let this = self.as_mut().project(); + this.inner.poll_trailers(cx) } - #[tokio::test] - async fn test_check_interval() { - let (_guard, _) = capture_test_logs(); - let (ts, sleep) = instant_time_and_sleep(UNIX_EPOCH); - let mut body = MinimumThroughputBody::new( - ts, - sleep.clone(), - NeverBody, - MinimumThroughputBodyOptions::builder() - .check_interval(Duration::from_millis(1234)) - .grace_period(Duration::from_millis(456)) - .build(), - ); - let mut body = pin!(body); - let _ = poll_fn(|cx| body.as_mut().poll_data(cx)).await; - assert_eq!( - sleep.logs(), - vec![ - // sleep, by second sleep we know we have no data, then the grace period - Duration::from_millis(1234), - Duration::from_millis(1234), - Duration::from_millis(456) - ] - ); + fn size_hint(&self) -> http_body_0_4::SizeHint { + self.inner.size_hint() } - async fn test_suddenly_stopping_stream(throughput_limit: u64, time_until_timeout: Duration) { - let (_guard, _) = capture_test_logs(); - let options = MinimumThroughputBodyOptions::builder() - // Minimum throughput per second will be approx. half of the BYTE_COUNT_UPPER_LIMIT. - .minimum_throughput(Throughput::new_bytes_per_second(throughput_limit)) - .build(); - let (time_source, async_sleep) = instant_time_and_sleep(UNIX_EPOCH); - let time_clone = time_source.clone(); - - let stream = sudden_stop(async_sleep.clone()); - let body = ByteStream::new(SdkBody::from_body_0_4(hyper_0_14::body::Body::wrap_stream( - stream, - ))); - let res = body - .map(move |body| { - let time_source = time_clone.clone(); - // We don't want to log these sleeps because it would duplicate - // the `sleep` calls being logged by the MTB - let async_sleep = InstantSleep::unlogged(); - SdkBody::from_body_0_4(MinimumThroughputBody::new( - time_source, - async_sleep, - body, - options.clone(), - )) - }) - .collect(); - - match res.await { - Ok(_res) => { - panic!("stream should have timed out"); - } - Err(err) => { - dbg!(err); - assert_eq!( - async_sleep.total_duration(), - time_until_timeout, - "With throughput limit {:?} expected timeout after {:?} (stream starts sending 0's at 5 seconds.", - throughput_limit, time_until_timeout - ); - } - } + fn is_end_stream(&self) -> bool { + self.inner.is_end_stream() } } diff --git a/rust-runtime/aws-smithy-runtime/src/client/http/body/minimum_throughput/options.rs b/rust-runtime/aws-smithy-runtime/src/client/http/body/minimum_throughput/options.rs index 4c8fc1177b..113461a31e 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/http/body/minimum_throughput/options.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/http/body/minimum_throughput/options.rs @@ -12,6 +12,7 @@ use std::time::Duration; pub struct MinimumThroughputBodyOptions { /// The minimum throughput that is acceptable. minimum_throughput: Throughput, + /// The 'grace period' after which the minimum throughput will be enforced. /// /// If this is set to 0, the minimum throughput will be enforced immediately. @@ -24,9 +25,6 @@ pub struct MinimumThroughputBodyOptions { /// stream-startup. grace_period: Duration, - /// The interval at which the throughput is checked. - check_interval: Duration, - /// The period of time to consider when computing the throughput /// /// This SHOULD be longer than the check interval, or stuck-streams may evade detection. @@ -44,7 +42,6 @@ impl MinimumThroughputBodyOptions { MinimumThroughputBodyOptionsBuilder::new() .minimum_throughput(self.minimum_throughput) .grace_period(self.grace_period) - .check_interval(self.check_interval) } /// The throughput check grace period. @@ -65,12 +62,10 @@ impl MinimumThroughputBodyOptions { self.check_window } - /// The rate at which the throughput is checked. - /// - /// The actual rate throughput is checked may be higher than this value, - /// but it will never be lower. + /// Not used. Always returns `Duration::from_millis(500)`. + #[deprecated(note = "No longer used. Always returns Duration::from_millis(500)")] pub fn check_interval(&self) -> Duration { - self.check_interval + Duration::from_millis(500) } } @@ -79,7 +74,6 @@ impl Default for MinimumThroughputBodyOptions { Self { minimum_throughput: DEFAULT_MINIMUM_THROUGHPUT, grace_period: DEFAULT_GRACE_PERIOD, - check_interval: DEFAULT_CHECK_INTERVAL, check_window: DEFAULT_CHECK_WINDOW, } } @@ -89,11 +83,10 @@ impl Default for MinimumThroughputBodyOptions { #[derive(Debug, Default, Clone)] pub struct MinimumThroughputBodyOptionsBuilder { minimum_throughput: Option, - check_interval: Option, + check_window: Option, grace_period: Option, } -const DEFAULT_CHECK_INTERVAL: Duration = Duration::from_millis(500); const DEFAULT_GRACE_PERIOD: Duration = Duration::from_secs(0); const DEFAULT_MINIMUM_THROUGHPUT: Throughput = Throughput { bytes_read: 1, @@ -136,19 +129,30 @@ impl MinimumThroughputBodyOptionsBuilder { self } - /// Set the rate at which throughput is checked. - /// - /// Defaults to 1 second. - pub fn check_interval(mut self, check_interval: Duration) -> Self { - self.set_check_interval(Some(check_interval)); + /// No longer used. The check interval is now based on the check window (not currently configurable). + #[deprecated( + note = "No longer used. The check interval is now based on the check window (not currently configurable). Open an issue if you need to configure the check window." + )] + pub fn check_interval(self, _check_interval: Duration) -> Self { self } - /// Set the rate at which throughput is checked. - /// - /// Defaults to 1 second. - pub fn set_check_interval(&mut self, check_interval: Option) -> &mut Self { - self.check_interval = check_interval; + /// No longer used. The check interval is now based on the check window (not currently configurable). + #[deprecated( + note = "No longer used. The check interval is now based on the check window (not currently configurable). Open an issue if you need to configure the check window." + )] + pub fn set_check_interval(&mut self, _check_interval: Option) -> &mut Self { + self + } + + #[allow(unused)] + pub(crate) fn check_window(mut self, check_window: Duration) -> Self { + self.set_check_window(Some(check_window)); + self + } + #[allow(unused)] + pub(crate) fn set_check_window(&mut self, check_window: Option) -> &mut Self { + self.check_window = check_window; self } @@ -161,8 +165,7 @@ impl MinimumThroughputBodyOptionsBuilder { minimum_throughput: self .minimum_throughput .unwrap_or(DEFAULT_MINIMUM_THROUGHPUT), - check_interval: self.check_interval.unwrap_or(DEFAULT_CHECK_INTERVAL), - check_window: DEFAULT_CHECK_WINDOW, + check_window: self.check_window.unwrap_or(DEFAULT_CHECK_WINDOW), } } } @@ -172,7 +175,6 @@ impl From for MinimumThroughputBodyOptions { MinimumThroughputBodyOptions { grace_period: value.grace_period(), minimum_throughput: DEFAULT_MINIMUM_THROUGHPUT, - check_interval: DEFAULT_CHECK_INTERVAL, check_window: DEFAULT_CHECK_WINDOW, } } diff --git a/rust-runtime/aws-smithy-runtime/src/client/http/body/minimum_throughput/throughput.rs b/rust-runtime/aws-smithy-runtime/src/client/http/body/minimum_throughput/throughput.rs index e2a9b294e6..57ea3318e7 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/http/body/minimum_throughput/throughput.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/http/body/minimum_throughput/throughput.rs @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -use std::collections::VecDeque; use std::fmt; use std::time::{Duration, SystemTime}; /// Throughput representation for use when configuring [`super::MinimumThroughputBody`] #[derive(Debug, Clone, Copy)] +#[cfg_attr(test, derive(Eq))] pub struct Throughput { pub(super) bytes_read: u64, pub(super) per_time_elapsed: Duration, @@ -29,7 +29,7 @@ impl Throughput { } /// Create a new throughput in bytes per second. - pub fn new_bytes_per_second(bytes: u64) -> Self { + pub const fn new_bytes_per_second(bytes: u64) -> Self { Self { bytes_read: bytes, per_time_elapsed: Duration::from_secs(1), @@ -37,7 +37,7 @@ impl Throughput { } /// Create a new throughput in kilobytes per second. - pub fn new_kilobytes_per_second(kilobytes: u64) -> Self { + pub const fn new_kilobytes_per_second(kilobytes: u64) -> Self { Self { bytes_read: kilobytes * 1000, per_time_elapsed: Duration::from_secs(1), @@ -45,7 +45,7 @@ impl Throughput { } /// Create a new throughput in megabytes per second. - pub fn new_megabytes_per_second(megabytes: u64) -> Self { + pub const fn new_megabytes_per_second(megabytes: u64) -> Self { Self { bytes_read: megabytes * 1000 * 1000, per_time_elapsed: Duration::from_secs(1), @@ -97,90 +97,288 @@ impl From<(u64, Duration)> for Throughput { } } -#[derive(Clone)] +/// Overall label for a given bin. +#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)] +enum BinLabel { + // IMPORTANT: The order of these enums matters since it represents their priority: + // Pending > TransferredBytes > NoPolling > Empty + // + /// There is no data in this bin. + Empty, + + /// No polling took place during this bin. + NoPolling, + + /// This many bytes were transferred during this bin. + TransferredBytes, + + /// The user/remote was not providing/consuming data fast enough during this bin. + /// + /// The number is the number of bytes transferred, if this replaced TransferredBytes. + Pending, +} + +/// Represents a bin (or a cell) in a linear grid that represents a small chunk of time. +#[derive(Copy, Clone, Debug)] +struct Bin { + label: BinLabel, + bytes: u64, +} + +impl Bin { + const fn new(label: BinLabel, bytes: u64) -> Self { + Self { label, bytes } + } + const fn empty() -> Self { + Self::new(BinLabel::Empty, 0) + } + + fn is_empty(&self) -> bool { + matches!(self.label, BinLabel::Empty) + } + + fn merge(&mut self, other: Bin) -> &mut Self { + // Assign values based on this priority order (highest priority higher up): + // 1. Pending + // 2. TransferredBytes + // 3. NoPolling + // 4. Empty + self.label = if other.label > self.label { + other.label + } else { + self.label + }; + self.bytes += other.bytes; + self + } + + /// Number of bytes transferred during this bin + fn bytes(&self) -> u64 { + self.bytes + } +} + +#[derive(Copy, Clone, Debug, Default)] +struct BinCounts { + /// Number of bins with no data. + empty: usize, + /// Number of "no polling" bins. + no_polling: usize, + /// Number of "bytes transferred" bins. + transferred: usize, + /// Number of "pending" bins. + pending: usize, +} + +/// Underlying stack-allocated linear grid buffer for tracking +/// throughput events for [`ThroughputLogs`]. +#[derive(Copy, Clone, Debug)] +struct LogBuffer { + entries: [Bin; N], + // The length only needs to exist so that the `fill_gaps` function + // can differentiate between `Empty` due to there not having been enough + // time to establish a full buffer worth of data vs. `Empty` due to a + // polling gap. Once the length reaches N, it will never change again. + length: usize, +} +impl LogBuffer { + fn new() -> Self { + Self { + entries: [Bin::empty(); N], + length: 0, + } + } + + /// Mutably returns the tail of the buffer. + /// + /// ## Panics + /// + /// The buffer MUST have at least one bin in it before this is called. + fn tail_mut(&mut self) -> &mut Bin { + debug_assert!(self.length > 0); + &mut self.entries[self.length - 1] + } + + /// Pushes a bin into the buffer. If the buffer is already full, + /// then this will rotate the entire buffer to the left. + fn push(&mut self, bin: Bin) { + if self.filled() { + self.entries.rotate_left(1); + self.entries[N - 1] = bin; + } else { + self.entries[self.length] = bin; + self.length += 1; + } + } + + /// Returns the total number of bytes transferred within the time window. + fn bytes_transferred(&self) -> u64 { + self.entries.iter().take(self.length).map(Bin::bytes).sum() + } + + #[inline] + fn filled(&self) -> bool { + self.length == N + } + + /// Fills in missing NoData entries. + /// + /// We want NoData entries to represent when a future hasn't been polled. + /// Since the future is in charge of logging in the first place, the only + /// way we can know about these is by examining gaps in time. + fn fill_gaps(&mut self) { + for entry in self.entries.iter_mut().take(self.length) { + if entry.is_empty() { + *entry = Bin::new(BinLabel::NoPolling, 0); + } + } + } + + /// Returns the counts of each bin type in the buffer. + fn counts(&self) -> BinCounts { + let mut counts = BinCounts::default(); + for entry in &self.entries { + match entry.label { + BinLabel::Empty => counts.empty += 1, + BinLabel::NoPolling => counts.no_polling += 1, + BinLabel::TransferredBytes => counts.transferred += 1, + BinLabel::Pending => counts.pending += 1, + } + } + counts + } +} + +/// Report/summary of all the events in a time window. +#[cfg_attr(test, derive(Debug, Eq, PartialEq))] +pub(crate) enum ThroughputReport { + /// Not enough data to draw any conclusions. This happens early in a request/response. + Incomplete, + /// The stream hasn't been polled for most of this time window. + NoPolling, + /// The stream has been waiting for most of the time window. + Pending, + /// The stream transferred this amount of throughput during the time window. + Transferred(Throughput), +} + +const BIN_COUNT: usize = 10; + +/// Log of throughput in a request or response stream. +/// +/// Used to determine if a configured minimum throughput is being met or not +/// so that a request or response stream can be timed out in the event of a +/// stall. +/// +/// Request/response streams push data transfer or pending events to this log +/// based on what's going on in their poll functions. The log tracks three kinds +/// of events despite only receiving two: the third is "no polling". The poll +/// functions cannot know when they're not being polled, so the log examines gaps +/// in the event history to know when no polling took place. +/// +/// The event logging is simplified down to a linear grid consisting of 10 "bins", +/// with each bin representing 1/10th the total time window. When an event is pushed, +/// it is either merged into the current tail bin, or all the bins are rotated +/// left to create a new empty tail bin, and then it is merged into that one. +#[derive(Clone, Debug)] pub(super) struct ThroughputLogs { - max_length: usize, - inner: VecDeque<(SystemTime, u64)>, - bytes_processed: u64, + resolution: Duration, + current_tail: SystemTime, + buffer: LogBuffer, } impl ThroughputLogs { - pub(super) fn new(max_length: usize) -> Self { + /// Creates a new log starting at `now` with the given `time_window`. + /// + /// Note: the `time_window` gets divided by 10 to create smaller sub-windows + /// to track throughput. The time window should be configured to be large enough + /// so that these sub-windows aren't too small for network-based events. + /// A time window of 10ms probably won't work, but 500ms might. The default + /// is one second. + pub(super) fn new(time_window: Duration, now: SystemTime) -> Self { + assert!(!time_window.is_zero()); + let resolution = time_window.div_f64(BIN_COUNT as f64); Self { - inner: VecDeque::with_capacity(max_length), - max_length, - bytes_processed: 0, + resolution, + current_tail: now, + buffer: LogBuffer::new(), } } - pub(super) fn push(&mut self, throughput: (SystemTime, u64)) { - // When the number of logs exceeds the max length, toss the oldest log. - if self.inner.len() == self.max_length { - self.bytes_processed -= self.inner.pop_front().map(|(_, sz)| sz).unwrap_or_default(); - } + /// Returns the resolution at which events are logged at. + /// + /// The resolution is the number of bins in the time window. + pub(super) fn resolution(&self) -> Duration { + self.resolution + } + + /// Pushes a "pending" event. + /// + /// Pending indicates the streaming future is waiting for something. + /// In an upload, it is waiting for data from the user, and in a download, + /// it is waiting for data from the server. + pub(super) fn push_pending(&mut self, time: SystemTime) { + self.push(time, Bin::new(BinLabel::Pending, 0)); + } - debug_assert!(self.inner.capacity() > self.inner.len()); - self.bytes_processed += throughput.1; - self.inner.push_back(throughput); - } - - fn buffer_full(&self) -> bool { - self.inner.len() == self.max_length - } - - pub(super) fn calculate_throughput( - &self, - now: SystemTime, - time_window: Duration, - ) -> Option { - // There are a lot of pathological cases that are 0 throughput. These cases largely shouldn't - // happen, because the check interval MUST be less than the check window - let total_length = self - .inner - .iter() - .last()? - .0 - .duration_since(self.inner.front()?.0) - .ok()?; - // during a "healthy" request we'll only have a few milliseconds of logs (shorter than the check window) - if total_length < time_window { - // if we haven't hit our requested time window & the buffer still isn't full, then - // return `None` — this is the "startup grace period" - return if !self.buffer_full() { - None - } else { - // Otherwise, if the entire buffer fits in the timewindow, we can the shortcut to - // avoid recomputing all the data - Some(Throughput { - bytes_read: self.bytes_processed, - per_time_elapsed: total_length, - }) - }; + /// Pushes a data transferred event. + /// + /// Indicates that this number of bytes were transferred at this time. + pub(super) fn push_bytes_transferred(&mut self, time: SystemTime, bytes: u64) { + self.push(time, Bin::new(BinLabel::TransferredBytes, bytes)); + } + + fn push(&mut self, now: SystemTime, value: Bin) { + self.catch_up(now); + self.buffer.tail_mut().merge(value); + self.buffer.fill_gaps(); + } + + /// Pushes empty bins until `current_tail` is caught up to `now`. + fn catch_up(&mut self, now: SystemTime) { + while now >= self.current_tail { + self.current_tail += self.resolution; + self.buffer.push(Bin::empty()); } - let minimum_ts = now - time_window; - let first_item = self.inner.iter().find(|(ts, _)| *ts >= minimum_ts)?.0; + assert!(self.current_tail >= now); + } - let time_elapsed = now.duration_since(first_item).unwrap_or_default(); + /// Generates an overall report of the time window. + pub(super) fn report(&mut self, now: SystemTime) -> ThroughputReport { + self.catch_up(now); + self.buffer.fill_gaps(); + + let BinCounts { + empty, + no_polling, + transferred, + pending, + } = self.buffer.counts(); + + // If there are any empty cells at all, then we haven't been tracking + // long enough to make any judgements about the stream's progress. + if empty > 0 { + return ThroughputReport::Incomplete; + } - let total_bytes_logged = self - .inner - .iter() - .rev() - .take_while(|(ts, _)| *ts > minimum_ts) - .map(|t| t.1) - .sum::(); + let bytes = self.buffer.bytes_transferred(); + let time = self.resolution * (BIN_COUNT - empty) as u32; + let throughput = Throughput::new(bytes, time); - Some(Throughput { - bytes_read: total_bytes_logged, - per_time_elapsed: time_elapsed, - }) + let half = BIN_COUNT / 2; + match (transferred > 0, no_polling >= half, pending >= half) { + (true, _, _) => ThroughputReport::Transferred(throughput), + (_, true, _) => ThroughputReport::NoPolling, + (_, _, true) => ThroughputReport::Pending, + _ => ThroughputReport::Incomplete, + } } } #[cfg(test)] mod test { - use super::{Throughput, ThroughputLogs}; - use std::time::{Duration, SystemTime, UNIX_EPOCH}; + use super::*; + use std::time::Duration; #[test] fn test_throughput_eq() { @@ -192,92 +390,146 @@ mod test { assert_eq!(t2, t3); } - fn build_throughput_log( - length: u32, - tick_duration: Duration, - rate: u64, - ) -> (ThroughputLogs, SystemTime) { - let mut throughput_logs = ThroughputLogs::new(length as usize); - for i in 1..=length { - throughput_logs.push((UNIX_EPOCH + (tick_duration * i), rate)); - } + #[test] + fn incomplete_no_entries() { + let start = SystemTime::UNIX_EPOCH; + let mut logs = ThroughputLogs::new(Duration::from_secs(1), start); + let report = logs.report(start); + assert_eq!(ThroughputReport::Incomplete, report); + } + + #[test] + fn incomplete_with_entries() { + let start = SystemTime::UNIX_EPOCH; + let mut logs = ThroughputLogs::new(Duration::from_secs(1), start); + logs.push_pending(start); - assert_eq!(length as usize, throughput_logs.inner.len()); - (throughput_logs, UNIX_EPOCH + (tick_duration * length)) + let report = logs.report(start + Duration::from_millis(300)); + assert_eq!(ThroughputReport::Incomplete, report); } - const EPSILON: f64 = 0.001; - macro_rules! assert_delta { - ($x:expr, $y:expr, $d:expr) => { - if !(($x as f64) - $y < $d || $y - ($x as f64) < $d) { - panic!(); - } - }; + #[test] + fn incomplete_with_transferred() { + let start = SystemTime::UNIX_EPOCH; + let mut logs = ThroughputLogs::new(Duration::from_secs(1), start); + logs.push_pending(start); + logs.push_bytes_transferred(start + Duration::from_millis(100), 10); + + let report = logs.report(start + Duration::from_millis(300)); + assert_eq!(ThroughputReport::Incomplete, report); } #[test] - fn test_throughput_log_calculate_throughput_1() { - let (throughput_logs, now) = build_throughput_log(1000, Duration::from_secs(1), 1); - - for dur in [10, 100, 100] { - let throughput = throughput_logs - .calculate_throughput(now, Duration::from_secs(dur)) - .unwrap(); - assert_eq!(1.0, throughput.bytes_per_second()); + fn push_pending_at_the_beginning_of_each_tick() { + let start = SystemTime::UNIX_EPOCH; + let mut logs = ThroughputLogs::new(Duration::from_secs(1), start); + + let mut now = start; + for i in 1..=BIN_COUNT { + logs.push_pending(now); + now += logs.resolution(); + + assert_eq!(i, logs.buffer.counts().pending); } - let throughput = throughput_logs - .calculate_throughput(now, Duration::from_secs_f64(101.5)) - .unwrap(); - assert_delta!(1, throughput.bytes_per_second(), EPSILON); + + let report = dbg!(&mut logs).report(now); + assert_eq!(ThroughputReport::Pending, report); } #[test] - fn test_throughput_log_calculate_throughput_2() { - let (throughput_logs, now) = build_throughput_log(1000, Duration::from_secs(5), 5); + fn push_pending_at_the_end_of_each_tick() { + let start = SystemTime::UNIX_EPOCH; + let mut logs = ThroughputLogs::new(Duration::from_secs(1), start); + + let mut now = start; + for i in 1..BIN_COUNT { + now += logs.resolution(); + logs.push_pending(now); + + assert_eq!(i, dbg!(&logs).buffer.counts().pending); + assert_eq!(0, logs.buffer.counts().transferred); + assert_eq!(1, logs.buffer.counts().no_polling); + } + // This should replace the initial "no polling" bin + now += logs.resolution(); + logs.push_pending(now); + assert_eq!(0, logs.buffer.counts().no_polling); - let throughput = throughput_logs - .calculate_throughput(now, Duration::from_secs(1000)) - .unwrap(); - assert_eq!(1.0, throughput.bytes_per_second()); + let report = dbg!(&mut logs).report(now); + assert_eq!(ThroughputReport::Pending, report); } #[test] - fn test_throughput_log_calculate_throughput_3() { - let (throughput_logs, now) = build_throughput_log(1000, Duration::from_millis(200), 1024); + fn push_transferred_at_the_beginning_of_each_tick() { + let start = SystemTime::UNIX_EPOCH; + let mut logs = ThroughputLogs::new(Duration::from_secs(1), start); + + let mut now = start; + for i in 1..=BIN_COUNT { + logs.push_bytes_transferred(now, 10); + if i != BIN_COUNT { + now += logs.resolution(); + } - let throughput = throughput_logs - .calculate_throughput(now, Duration::from_secs(5)) - .unwrap(); - let expected_throughput = 1024.0 * 5.0; - assert_eq!(expected_throughput, throughput.bytes_per_second()); + assert_eq!(i, logs.buffer.counts().transferred); + assert_eq!(0, logs.buffer.counts().pending); + assert_eq!(0, logs.buffer.counts().no_polling); + } + + let report = dbg!(&mut logs).report(now); + assert_eq!( + ThroughputReport::Transferred(Throughput::new(100, Duration::from_secs(1))), + report + ); } #[test] - fn test_throughput_log_calculate_throughput_4() { - let (throughput_logs, now) = build_throughput_log(1000, Duration::from_millis(100), 12); - - let throughput = throughput_logs - .calculate_throughput(now, Duration::from_secs(1)) - .unwrap(); - let expected_throughput = 12.0 * 10.0; + fn no_polling() { + let start = SystemTime::UNIX_EPOCH; + let mut logs = ThroughputLogs::new(Duration::from_secs(1), start); + let report = logs.report(start + Duration::from_secs(2)); + assert_eq!(ThroughputReport::NoPolling, report); + } - assert_eq!(expected_throughput, throughput.bytes_per_second()); + // Transferred bytes MUST take priority over pending + #[test] + fn mixed_bag_mostly_pending() { + let start = SystemTime::UNIX_EPOCH; + let mut logs = ThroughputLogs::new(Duration::from_secs(1), start); + + logs.push_bytes_transferred(start + Duration::from_millis(50), 10); + logs.push_pending(start + Duration::from_millis(150)); + logs.push_pending(start + Duration::from_millis(250)); + logs.push_bytes_transferred(start + Duration::from_millis(350), 10); + logs.push_pending(start + Duration::from_millis(450)); + // skip 550 + logs.push_pending(start + Duration::from_millis(650)); + logs.push_pending(start + Duration::from_millis(750)); + logs.push_pending(start + Duration::from_millis(850)); + + let report = logs.report(start + Duration::from_millis(999)); + assert_eq!( + ThroughputReport::Transferred(Throughput::new_bytes_per_second(20)), + report + ); } #[test] - fn test_throughput_followed_by_0() { - let tick = Duration::from_millis(100); - let (mut throughput_logs, now) = build_throughput_log(1000, tick, 12); - let throughput = throughput_logs - .calculate_throughput(now, Duration::from_secs(1)) - .unwrap(); - let expected_throughput = 12.0 * 10.0; - - assert_eq!(expected_throughput, throughput.bytes_per_second()); - throughput_logs.push((now + tick, 0)); - let throughput = throughput_logs - .calculate_throughput(now + tick, Duration::from_secs(1)) - .unwrap(); - assert_eq!(108.0, throughput.bytes_per_second()); + fn mixed_bag_mostly_pending_no_transferred() { + let start = SystemTime::UNIX_EPOCH; + let mut logs = ThroughputLogs::new(Duration::from_secs(1), start); + + logs.push_pending(start + Duration::from_millis(50)); + logs.push_pending(start + Duration::from_millis(150)); + logs.push_pending(start + Duration::from_millis(250)); + // skip 350 + logs.push_pending(start + Duration::from_millis(450)); + // skip 550 + logs.push_pending(start + Duration::from_millis(650)); + logs.push_pending(start + Duration::from_millis(750)); + logs.push_pending(start + Duration::from_millis(850)); + + let report = logs.report(start + Duration::from_millis(999)); + assert_eq!(ThroughputReport::Pending, report); } } diff --git a/rust-runtime/aws-smithy-runtime/src/client/identity/cache/lazy.rs b/rust-runtime/aws-smithy-runtime/src/client/identity/cache/lazy.rs index e90ca2e37a..02cbcae40b 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/identity/cache/lazy.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/identity/cache/lazy.rs @@ -354,7 +354,7 @@ impl ResolveCachedIdentity for LazyCache { // `cache.get_or_load`, logging inside `cache.get_or_load` ensures that it is emitted // only once for the first thread that succeeds in populating a cache value. let printable = DateTime::from(expiration); - tracing::info!( + tracing::debug!( new_expiration=%printable, valid_for=?expiration.duration_since(time_source.now()).unwrap_or_default(), partition=?partition, diff --git a/rust-runtime/aws-smithy-runtime/src/client/orchestrator.rs b/rust-runtime/aws-smithy-runtime/src/client/orchestrator.rs index f8bbc2c05c..112fbe85ba 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/orchestrator.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/orchestrator.rs @@ -5,9 +5,12 @@ use self::auth::orchestrate_auth; use crate::client::interceptors::Interceptors; -use crate::client::orchestrator::endpoints::orchestrate_endpoint; use crate::client::orchestrator::http::{log_response_body, read_body}; use crate::client::timeout::{MaybeTimeout, MaybeTimeoutConfig, TimeoutKind}; +use crate::client::{ + http::body::minimum_throughput::MaybeUploadThroughputCheckFuture, + orchestrator::endpoints::orchestrate_endpoint, +}; use aws_smithy_async::rt::sleep::AsyncSleep; use aws_smithy_runtime_api::box_error::BoxError; use aws_smithy_runtime_api::client::http::{HttpClient, HttpConnector, HttpConnectorSettings}; @@ -385,7 +388,12 @@ async fn try_attempt( builder.build() }; let connector = http_client.http_connector(&settings, runtime_components); - connector.call(request).await.map_err(OrchestratorError::connector) + let response_future = MaybeUploadThroughputCheckFuture::new( + cfg, + runtime_components, + connector.call(request), + ); + response_future.await.map_err(OrchestratorError::connector) }); trace!(response = ?response, "received response from service"); ctx.set_response(response); diff --git a/rust-runtime/aws-smithy-runtime/src/client/orchestrator/operation.rs b/rust-runtime/aws-smithy-runtime/src/client/orchestrator/operation.rs index bd875c72e6..e761cf601f 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/orchestrator/operation.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/orchestrator/operation.rs @@ -12,7 +12,6 @@ use crate::client::orchestrator::endpoints::StaticUriEndpointResolver; use crate::client::retries::strategy::{NeverRetryStrategy, StandardRetryStrategy}; use aws_smithy_async::rt::sleep::AsyncSleep; use aws_smithy_async::time::TimeSource; -use aws_smithy_runtime_api::box_error::BoxError; use aws_smithy_runtime_api::client::auth::static_resolver::StaticAuthSchemeOptionResolver; use aws_smithy_runtime_api::client::auth::{ AuthSchemeOptionResolverParams, SharedAuthScheme, SharedAuthSchemeOptionResolver, @@ -35,6 +34,9 @@ use aws_smithy_runtime_api::client::ser_de::{ DeserializeResponse, SerializeRequest, SharedRequestSerializer, SharedResponseDeserializer, }; use aws_smithy_runtime_api::shared::IntoShared; +use aws_smithy_runtime_api::{ + box_error::BoxError, client::stalled_stream_protection::StalledStreamProtectionConfig, +}; use aws_smithy_types::config_bag::{ConfigBag, Layer}; use aws_smithy_types::retry::RetryConfig; use aws_smithy_types::timeout::TimeoutConfig; @@ -293,6 +295,15 @@ impl OperationBuilder { self } + /// Configures stalled stream protection with the given config. + pub fn stalled_stream_protection( + mut self, + stalled_stream_protection: StalledStreamProtectionConfig, + ) -> Self { + self.config.store_put(stalled_stream_protection); + self + } + /// Configures the serializer for the builder. pub fn serializer( mut self, @@ -339,6 +350,28 @@ impl OperationBuilder { } } + /// Configures the a deserializer implementation for the builder. + pub fn deserializer_impl( + mut self, + deserializer: impl DeserializeResponse + Send + Sync + 'static, + ) -> OperationBuilder + where + O2: fmt::Debug + Send + Sync + 'static, + E2: std::error::Error + fmt::Debug + Send + Sync + 'static, + { + let deserializer: SharedResponseDeserializer = deserializer.into_shared(); + self.config.store_put(deserializer); + + OperationBuilder { + service_name: self.service_name, + operation_name: self.operation_name, + config: self.config, + runtime_components: self.runtime_components, + runtime_plugins: self.runtime_plugins, + _phantom: Default::default(), + } + } + /// Creates an `Operation` from the builder. pub fn build(self) -> Operation { let service_name = self.service_name.expect("service_name required"); diff --git a/rust-runtime/aws-smithy-runtime/src/client/stalled_stream_protection.rs b/rust-runtime/aws-smithy-runtime/src/client/stalled_stream_protection.rs index 3e07b3f0b8..83cfb64752 100644 --- a/rust-runtime/aws-smithy-runtime/src/client/stalled_stream_protection.rs +++ b/rust-runtime/aws-smithy-runtime/src/client/stalled_stream_protection.rs @@ -3,7 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -use crate::client::http::body::minimum_throughput::MinimumThroughputBody; +use crate::client::http::body::minimum_throughput::{ + options::MinimumThroughputBodyOptions, MinimumThroughputDownloadBody, ThroughputReadingBody, + UploadThroughput, +}; use aws_smithy_async::rt::sleep::SharedAsyncSleep; use aws_smithy_async::time::SharedTimeSource; use aws_smithy_runtime_api::box_error::BoxError; @@ -18,14 +21,16 @@ use aws_smithy_types::config_bag::ConfigBag; use std::mem; /// Adds stalled stream protection when sending requests and/or receiving responses. -#[derive(Debug)] -pub struct StalledStreamProtectionInterceptor { - enable_for_request_body: bool, - enable_for_response_body: bool, -} +#[derive(Debug, Default)] +#[non_exhaustive] +pub struct StalledStreamProtectionInterceptor; /// Stalled stream protection can be enable for request bodies, response bodies, /// or both. +#[deprecated( + since = "1.2.0", + note = "This kind enum is no longer used. Configuration is stored in StalledStreamProtectionConfig in the config bag." +)] pub enum StalledStreamProtectionInterceptorKind { /// Enable stalled stream protection for request bodies. RequestBody, @@ -37,18 +42,13 @@ pub enum StalledStreamProtectionInterceptorKind { impl StalledStreamProtectionInterceptor { /// Create a new stalled stream protection interceptor. - pub fn new(kind: StalledStreamProtectionInterceptorKind) -> Self { - use StalledStreamProtectionInterceptorKind::*; - let (enable_for_request_body, enable_for_response_body) = match kind { - RequestBody => (true, false), - ResponseBody => (false, true), - RequestAndResponseBody => (true, true), - }; - - Self { - enable_for_request_body, - enable_for_response_body, - } + #[deprecated( + since = "1.2.0", + note = "The kind enum is no longer used. Configuration is stored in StalledStreamProtectionConfig in the config bag. Construct the interceptor using Default." + )] + #[allow(deprecated)] + pub fn new(_kind: StalledStreamProtectionInterceptorKind) -> Self { + Default::default() } } @@ -63,19 +63,26 @@ impl Intercept for StalledStreamProtectionInterceptor { runtime_components: &RuntimeComponents, cfg: &mut ConfigBag, ) -> Result<(), BoxError> { - if self.enable_for_request_body { - if let Some(cfg) = cfg.load::() { - if cfg.is_enabled() { - let (async_sleep, time_source) = - get_runtime_component_deps(runtime_components)?; - tracing::trace!("adding stalled stream protection to request body"); - add_stalled_stream_protection_to_body( - context.request_mut().body_mut(), - cfg, - async_sleep, + if let Some(sspcfg) = cfg.load::().cloned() { + if sspcfg.upload_enabled() { + let (_async_sleep, time_source) = get_runtime_component_deps(runtime_components)?; + let now = time_source.now(); + + let options: MinimumThroughputBodyOptions = sspcfg.into(); + let throughput = UploadThroughput::new(options.check_window(), now); + cfg.interceptor_state().store_put(throughput.clone()); + + tracing::trace!("adding stalled stream protection to request body"); + let it = mem::replace(context.request_mut().body_mut(), SdkBody::taken()); + let it = it.map_preserve_contents(move |body| { + let time_source = time_source.clone(); + SdkBody::from_body_0_4(ThroughputReadingBody::new( time_source, - ); - } + throughput.clone(), + body, + )) + }); + let _ = mem::replace(context.request_mut().body_mut(), it); } } @@ -88,19 +95,25 @@ impl Intercept for StalledStreamProtectionInterceptor { runtime_components: &RuntimeComponents, cfg: &mut ConfigBag, ) -> Result<(), BoxError> { - if self.enable_for_response_body { - if let Some(cfg) = cfg.load::() { - if cfg.is_enabled() { - let (async_sleep, time_source) = - get_runtime_component_deps(runtime_components)?; - tracing::trace!("adding stalled stream protection to response body"); - add_stalled_stream_protection_to_body( - context.response_mut().body_mut(), - cfg, - async_sleep, + if let Some(sspcfg) = cfg.load::() { + if sspcfg.download_enabled() { + let (async_sleep, time_source) = get_runtime_component_deps(runtime_components)?; + tracing::trace!("adding stalled stream protection to response body"); + let sspcfg = sspcfg.clone(); + let it = mem::replace(context.response_mut().body_mut(), SdkBody::taken()); + let it = it.map_preserve_contents(move |body| { + let sspcfg = sspcfg.clone(); + let async_sleep = async_sleep.clone(); + let time_source = time_source.clone(); + let mtb = MinimumThroughputDownloadBody::new( time_source, + async_sleep, + body, + sspcfg.into(), ); - } + SdkBody::from_body_0_4(mtb) + }); + let _ = mem::replace(context.response_mut().body_mut(), it); } } Ok(()) @@ -118,21 +131,3 @@ fn get_runtime_component_deps( .ok_or("A time source is required when stalled stream protection is enabled")?; Ok((async_sleep, time_source)) } - -fn add_stalled_stream_protection_to_body( - body: &mut SdkBody, - cfg: &StalledStreamProtectionConfig, - async_sleep: SharedAsyncSleep, - time_source: SharedTimeSource, -) { - let cfg = cfg.clone(); - let it = mem::replace(body, SdkBody::taken()); - let it = it.map_preserve_contents(move |body| { - let cfg = cfg.clone(); - let async_sleep = async_sleep.clone(); - let time_source = time_source.clone(); - let mtb = MinimumThroughputBody::new(time_source, async_sleep, body, cfg.into()); - SdkBody::from_body_0_4(mtb) - }); - let _ = mem::replace(body, it); -} diff --git a/rust-runtime/aws-smithy-runtime/src/client/waiters.rs b/rust-runtime/aws-smithy-runtime/src/client/waiters.rs new file mode 100644 index 0000000000..e9330b2fa4 --- /dev/null +++ b/rust-runtime/aws-smithy-runtime/src/client/waiters.rs @@ -0,0 +1,529 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use crate::client::waiters::backoff::{Backoff, RandomImpl}; +use aws_smithy_async::{ + rt::sleep::{AsyncSleep, SharedAsyncSleep}, + time::SharedTimeSource, +}; +use aws_smithy_runtime_api::client::waiters::FinalPoll; +use aws_smithy_runtime_api::client::{orchestrator::HttpResponse, result::SdkError}; +use aws_smithy_runtime_api::client::{ + result::CreateUnhandledError, + waiters::error::{ExceededMaxWait, FailureState, OperationFailed, WaiterError}, +}; +use std::future::Future; +use std::time::Duration; + +mod backoff; + +/// Waiter acceptor state +/// +/// This enum (vaguely) matches the [acceptor state] from the Smithy spec. +/// It has an additional `NoAcceptorsMatched` variant to indicate the case where +/// none of the modeled waiters matched the response, which the spec mentions but +/// doesn't consider an official part of the acceptor state enum. An `Option` +/// could have been used instead, but this seemed cleaner. +/// +/// [acceptor state]: https://smithy.io/2.0/additional-specs/waiters.html#acceptorstate-enum +#[non_exhaustive] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum AcceptorState { + /// None of the modeled acceptors matched the response. + NoAcceptorsMatched, + /// A `success` acceptor matched the response. + Success, + /// A `failure` acceptor matched the response. + Failure, + /// A `retry` acceptor matched the response. + Retry, +} + +/// Orchestrates waiting via polling with jittered exponential backoff. +/// +/// This is meant to be used internally by the generated code to provide +/// waiter functionality. +pub struct WaiterOrchestrator { + backoff: Backoff, + time_source: SharedTimeSource, + sleep_impl: SharedAsyncSleep, + acceptor_fn: AcceptorFn, + operation_fn: OperationFn, +} + +impl WaiterOrchestrator<(), ()> { + /// Returns a builder for the waiter orchestrator. + pub fn builder() -> WaiterOrchestratorBuilder<(), ()> { + WaiterOrchestratorBuilder::default() + } +} + +impl WaiterOrchestrator { + fn new( + backoff: Backoff, + time_source: SharedTimeSource, + sleep_impl: SharedAsyncSleep, + acceptor_fn: AcceptorFn, + operation_fn: OperationFn, + ) -> Self { + WaiterOrchestrator { + backoff, + time_source, + sleep_impl, + acceptor_fn, + operation_fn, + } + } +} + +impl WaiterOrchestrator +where + AcceptorFn: Fn(Result<&O, &E>) -> AcceptorState, + OperationFn: Fn() -> Fut, + Fut: Future>>, + E: CreateUnhandledError + std::error::Error + Send + Sync + 'static, +{ + /// Orchestrates waiting via polling with jittered exponential backoff. + pub async fn orchestrate( + self, + ) -> Result>, WaiterError> { + let start_time = self.time_source.now(); + let mut attempt = 0; + let mut done_retrying = false; + loop { + tracing::debug!("executing waiter poll attempt #{}", attempt + 1); + let result = (self.operation_fn)().await; + let error = result.is_err(); + + // "acceptable result" in this context means "an acceptor's matcher can match this result type" + let acceptable_result = result.as_ref().map_err(|err| err.as_service_error()); + let acceptor_state = match acceptable_result { + Ok(output) => (self.acceptor_fn)(Ok(output)), + Err(Some(err)) => (self.acceptor_fn)(Err(err)), + _ => { + // If we got an unmatchable failure (basically anything unmodeled), then just immediately exit + return Err(WaiterError::OperationFailed(OperationFailed::new( + result.err().expect("can only be an err in this branch"), + ))); + } + }; + + tracing::debug!("waiter acceptor state: {acceptor_state:?}"); + match acceptor_state { + AcceptorState::Success => return Ok(FinalPoll::new(result)), + AcceptorState::Failure => { + return Err(WaiterError::FailureState(FailureState::new( + FinalPoll::new(result.map_err(|err| err.into_service_error())), + ))) + } + // This occurs when there was a modeled error response, but none of the acceptors matched it + AcceptorState::NoAcceptorsMatched if error => { + return Err(WaiterError::OperationFailed(OperationFailed::new( + result.err().expect("checked above"), + ))) + } + AcceptorState::Retry | AcceptorState::NoAcceptorsMatched => { + attempt += 1; + + let now = self.time_source.now(); + let elapsed = now.duration_since(start_time).unwrap_or_default(); + if !done_retrying && elapsed <= self.backoff.max_wait() { + let delay = self.backoff.delay(attempt, elapsed); + + // The backoff function returns a zero delay when it is min_delay time away + // from max_time. If we didn't detect this and stop polling, then we could + // slam the server at the very end of the wait period for servers that are + // really fast (for example, a few milliseconds total round-trip latency). + if delay.is_zero() { + tracing::debug!( + "delay calculated for attempt #{attempt}; elapsed ({elapsed:?}); waiter is close to max time; will immediately poll one last time" + ); + done_retrying = true; + } else { + tracing::debug!( + "delay calculated for attempt #{attempt}; elapsed ({elapsed:?}); waiter will poll again in {delay:?}" + ); + self.sleep_impl.sleep(delay).await; + } + } else { + tracing::debug!( + "waiter exceeded max wait time of {:?}", + self.backoff.max_wait() + ); + return Err(WaiterError::ExceededMaxWait(ExceededMaxWait::new( + self.backoff.max_wait(), + elapsed, + attempt, + ))); + } + } + } + } + } +} + +/// Builder for [`WaiterOrchestrator`]. +#[derive(Default)] +pub struct WaiterOrchestratorBuilder { + min_delay: Option, + max_delay: Option, + max_wait: Option, + time_source: Option, + sleep_impl: Option, + random_fn: RandomImpl, + acceptor_fn: Option, + operation_fn: Option, +} + +impl WaiterOrchestratorBuilder { + /// Set the minimum delay time for the waiter. + pub fn min_delay(mut self, min_delay: Duration) -> Self { + self.min_delay = Some(min_delay); + self + } + + /// Set the maximum delay time for the waiter. + pub fn max_delay(mut self, max_delay: Duration) -> Self { + self.max_delay = Some(max_delay); + self + } + + /// Set the maximum total wait time for the waiter. + pub fn max_wait(mut self, max_wait: Duration) -> Self { + self.max_wait = Some(max_wait); + self + } + + #[cfg(all(test, feature = "test-util"))] + fn random(mut self, random_fn: impl Fn(u64, u64) -> u64 + Send + Sync + 'static) -> Self { + self.random_fn = RandomImpl::Override(Box::new(random_fn)); + self + } + + /// Set the time source the waiter will use. + pub fn time_source(mut self, time_source: SharedTimeSource) -> Self { + self.time_source = Some(time_source); + self + } + + /// Set the async sleep implementation the waiter will use to delay. + pub fn sleep_impl(mut self, sleep_impl: SharedAsyncSleep) -> Self { + self.sleep_impl = Some(sleep_impl); + self + } + + /// Build a waiter orchestrator. + pub fn build(self) -> WaiterOrchestrator { + WaiterOrchestrator::new( + Backoff::new( + self.min_delay.expect("min delay is required"), + self.max_delay.expect("max delay is required"), + self.max_wait.expect("max wait is required"), + self.random_fn, + ), + self.time_source.expect("time source required"), + self.sleep_impl.expect("sleep impl required"), + self.acceptor_fn.expect("acceptor fn required"), + self.operation_fn.expect("operation fn required"), + ) + } +} + +impl WaiterOrchestratorBuilder<(), OperationFn> { + /// Set the acceptor function for the waiter. + pub fn acceptor( + self, + acceptor: AcceptorFn, + ) -> WaiterOrchestratorBuilder { + WaiterOrchestratorBuilder { + min_delay: self.min_delay, + max_delay: self.max_delay, + max_wait: self.max_wait, + time_source: self.time_source, + sleep_impl: self.sleep_impl, + random_fn: self.random_fn, + acceptor_fn: Some(acceptor), + operation_fn: self.operation_fn, + } + } +} + +impl WaiterOrchestratorBuilder { + /// Set the operation function for the waiter. + pub fn operation( + self, + operation: OperationFn, + ) -> WaiterOrchestratorBuilder { + WaiterOrchestratorBuilder { + min_delay: self.min_delay, + max_delay: self.max_delay, + max_wait: self.max_wait, + time_source: self.time_source, + sleep_impl: self.sleep_impl, + random_fn: self.random_fn, + acceptor_fn: self.acceptor_fn, + operation_fn: Some(operation), + } + } +} + +/// Attaches a tracing span with a semi-unique waiter ID number so that all the operations +/// made by the waiter can be correlated together in logs. +pub fn attach_waiter_tracing_span( + future: impl Future>, WaiterError>>, +) -> impl Future>, WaiterError>> { + use tracing::Instrument; + + // Create a random seven-digit ID for the waiter so that it can be correlated in the logs. + let span = tracing::debug_span!("waiter", waiter_id = fastrand::u32(1_000_000..10_000_000)); + future.instrument(span) +} + +#[cfg(all(test, feature = "test-util"))] +mod tests { + use super::*; + use crate::test_util::capture_test_logs::show_test_logs; + use aws_smithy_async::{ + test_util::tick_advance_sleep::tick_advance_time_and_sleep, time::TimeSource, + }; + use aws_smithy_runtime_api::{http::StatusCode, shared::IntoShared}; + use aws_smithy_types::body::SdkBody; + use std::{ + fmt, + sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, Mutex, + }, + time::SystemTime, + }; + + #[derive(Debug)] + struct TestError; + impl std::error::Error for TestError {} + impl fmt::Display for TestError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("TestError") + } + } + impl CreateUnhandledError for TestError { + fn create_unhandled_error( + _source: Box, + _meta: Option, + ) -> Self { + unreachable!("If this is called, there is a bug in the orchestrator implementation. Unmodeled errors should never make it into FailureState.") + } + } + + fn test_orchestrator( + sleep_impl: impl IntoShared, + time_source: impl IntoShared, + ) -> WaiterOrchestratorBuilder<(), ()> { + let test_random = |min: u64, max: u64| (min + max) / 2; + WaiterOrchestrator::builder() + .min_delay(Duration::from_secs(2)) + .max_delay(Duration::from_secs(120)) + .max_wait(Duration::from_secs(300)) + .random(test_random) + .sleep_impl(sleep_impl.into_shared()) + .time_source(time_source.into_shared()) + } + + #[tokio::test] + async fn immediate_success() { + let _logs = show_test_logs(); + let (time_source, sleep_impl) = tick_advance_time_and_sleep(); + let orchestrator = test_orchestrator(sleep_impl, time_source) + .acceptor(|_result: Result<&usize, &TestError>| AcceptorState::Success) + .operation(|| async { Result::<_, SdkError>::Ok(5usize) }) + .build(); + + let result = orchestrator.orchestrate().await; + assert!(result.is_ok()); + assert_eq!(5, *result.unwrap().as_result().unwrap()); + } + + #[tokio::test] + async fn immediate_failure() { + let _logs = show_test_logs(); + let (time_source, sleep_impl) = tick_advance_time_and_sleep(); + let orchestrator = test_orchestrator(sleep_impl, time_source) + .acceptor(|_result: Result<&usize, &TestError>| AcceptorState::Failure) + .operation(|| async { Result::<_, SdkError>::Ok(5usize) }) + .build(); + + let result = orchestrator.orchestrate().await; + assert!( + matches!(result, Err(WaiterError::FailureState(_))), + "expected failure state, got: {result:?}" + ); + } + + #[tokio::test] + async fn five_polls_then_success() { + let _logs = show_test_logs(); + + let (time_source, sleep_impl) = tick_advance_time_and_sleep(); + + let acceptor = |result: Result<&usize, &TestError>| match result { + Err(_) => unreachable!(), + Ok(5) => AcceptorState::Success, + _ => AcceptorState::Retry, + }; + + let times = Arc::new(Mutex::new(Vec::new())); + let attempt = Arc::new(AtomicUsize::new(1)); + let operation = { + let sleep_impl = sleep_impl.clone(); + let time_source = time_source.clone(); + let times = times.clone(); + move || { + let attempt = attempt.clone(); + let sleep_impl = sleep_impl.clone(); + let time_source = time_source.clone(); + let times = times.clone(); + async move { + // simulate time passing for the network hop/service processing time + sleep_impl.sleep(Duration::from_secs(1)).await; + times.lock().unwrap().push( + time_source + .now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .as_secs(), + ); + Result::<_, SdkError>::Ok( + attempt.fetch_add(1, Ordering::SeqCst), + ) + } + } + }; + + let orchestrator = test_orchestrator(sleep_impl.clone(), time_source.clone()) + .acceptor(acceptor) + .operation(operation) + .build(); + + let task = tokio::spawn(orchestrator.orchestrate()); + tokio::task::yield_now().await; + time_source.tick(Duration::from_secs(500)).await; + let result = task.await.unwrap(); + + assert!(result.is_ok()); + assert_eq!(5, *result.unwrap().as_result().unwrap()); + assert_eq!(vec![1, 4, 8, 14, 24], *times.lock().unwrap()); + } + + #[tokio::test] + async fn exceed_max_wait_time() { + let _logs = show_test_logs(); + let (time_source, sleep_impl) = tick_advance_time_and_sleep(); + + let orchestrator = test_orchestrator(sleep_impl.clone(), time_source.clone()) + .acceptor(|_result: Result<&usize, &TestError>| AcceptorState::Retry) + .operation(|| async { Result::<_, SdkError>::Ok(1) }) + .build(); + + let task = tokio::spawn(orchestrator.orchestrate()); + tokio::task::yield_now().await; + time_source.tick(Duration::from_secs(500)).await; + let result = task.await.unwrap(); + + match result { + Err(WaiterError::ExceededMaxWait(context)) => { + assert_eq!(Duration::from_secs(300), context.max_wait()); + assert_eq!(300, context.elapsed().as_secs()); + assert_eq!(12, context.poll_count()); + } + _ => panic!("expected ExceededMaxWait, got {result:?}"), + } + } + + #[tokio::test] + async fn operation_timed_out() { + let _logs = show_test_logs(); + let (time_source, sleep_impl) = tick_advance_time_and_sleep(); + let orchestrator = test_orchestrator(sleep_impl, time_source) + .acceptor(|_result: Result<&usize, &TestError>| unreachable!()) + .operation(|| async { + Result::>::Err(SdkError::timeout_error( + "test", + )) + }) + .build(); + + match orchestrator.orchestrate().await { + Err(WaiterError::OperationFailed(err)) => match err.error() { + SdkError::TimeoutError(_) => { /* good */ } + result => panic!("unexpected final poll: {result:?}"), + }, + result => panic!("unexpected result: {result:?}"), + } + } + + #[tokio::test] + async fn modeled_service_error_no_acceptors_matched() { + let _logs = show_test_logs(); + let (time_source, sleep_impl) = tick_advance_time_and_sleep(); + let orchestrator = test_orchestrator(sleep_impl, time_source) + .acceptor(|_result: Result<&usize, &TestError>| AcceptorState::NoAcceptorsMatched) + .operation(|| async { + Result::>::Err(SdkError::service_error( + TestError, + HttpResponse::new(StatusCode::try_from(400).unwrap(), SdkBody::empty()), + )) + }) + .build(); + + match dbg!(orchestrator.orchestrate().await) { + Err(WaiterError::OperationFailed(err)) => match err.error() { + SdkError::ServiceError(_) => { /* good */ } + result => panic!("unexpected result: {result:?}"), + }, + result => panic!("unexpected result: {result:?}"), + } + } + + #[tokio::test] + async fn modeled_error_matched_as_failure() { + let _logs = show_test_logs(); + let (time_source, sleep_impl) = tick_advance_time_and_sleep(); + let orchestrator = test_orchestrator(sleep_impl, time_source) + .acceptor(|_result: Result<&usize, &TestError>| AcceptorState::Failure) + .operation(|| async { + Result::>::Err(SdkError::service_error( + TestError, + HttpResponse::new(StatusCode::try_from(400).unwrap(), SdkBody::empty()), + )) + }) + .build(); + + match orchestrator.orchestrate().await { + Err(WaiterError::FailureState(err)) => match err.final_poll().as_result() { + Err(TestError) => { /* good */ } + result => panic!("unexpected final poll: {result:?}"), + }, + result => panic!("unexpected result: {result:?}"), + } + } + + #[tokio::test] + async fn modeled_error_matched_as_success() { + let _logs = show_test_logs(); + let (time_source, sleep_impl) = tick_advance_time_and_sleep(); + let orchestrator = test_orchestrator(sleep_impl, time_source) + .acceptor(|_result: Result<&usize, &TestError>| AcceptorState::Success) + .operation(|| async { + Result::>::Err(SdkError::service_error( + TestError, + HttpResponse::new(StatusCode::try_from(400).unwrap(), SdkBody::empty()), + )) + }) + .build(); + + let result = orchestrator.orchestrate().await; + assert!(result.is_ok()); + assert!(result.unwrap().as_result().is_err()); + } +} diff --git a/rust-runtime/aws-smithy-runtime/src/client/waiters/backoff.rs b/rust-runtime/aws-smithy-runtime/src/client/waiters/backoff.rs new file mode 100644 index 0000000000..9cf885d2a6 --- /dev/null +++ b/rust-runtime/aws-smithy-runtime/src/client/waiters/backoff.rs @@ -0,0 +1,173 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use std::{fmt, time::Duration}; + +#[derive(Debug)] +pub(super) struct Backoff { + min_delay: Duration, + max_delay: Duration, + max_wait: Duration, + attempt_ceiling: u32, + random: RandomImpl, +} + +impl Backoff { + pub(super) fn new( + min_delay: Duration, + max_delay: Duration, + max_wait: Duration, + random: RandomImpl, + ) -> Self { + Self { + min_delay, + max_delay, + max_wait, + // Attempt ceiling calculation taken from the Smithy spec: https://smithy.io/2.0/additional-specs/waiters.html#waiter-retries + attempt_ceiling: (((max_delay.as_secs_f64() / min_delay.as_secs_f64()).ln() + / 2f64.ln()) + + 1.0) as u32, + random, + } + } + + // Calculates backoff delay time according to the Smithy spec: https://smithy.io/2.0/additional-specs/waiters.html#waiter-retries + pub(super) fn delay(&self, attempt: u32, elapsed: Duration) -> Duration { + let delay = if attempt > self.attempt_ceiling { + self.max_delay.as_secs() + } else { + self.min_delay.as_secs() * 2u64.pow(attempt - 1) + }; + let mut delay = Duration::from_secs(self.random.random(self.min_delay.as_secs(), delay)); + + let remaining_time = self.max_wait.saturating_sub(elapsed); + if remaining_time.saturating_sub(delay) <= self.min_delay { + // Note: deviating from the spec here. Subtracting `min_delay` doesn't fulfill the original intent. + delay = remaining_time; + } + delay + } + + #[inline] + pub(super) fn max_wait(&self) -> Duration { + self.max_wait + } +} + +#[derive(Default)] +pub(super) enum RandomImpl { + #[default] + Default, + #[cfg(test)] + Override(Box u64 + Send + Sync>), +} + +impl fmt::Debug for RandomImpl { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Default => write!(f, "Default"), + #[cfg(test)] + Self::Override(_) => f.debug_tuple("Override").field(&"** function **").finish(), + } + } +} + +impl RandomImpl { + fn random(&self, min_inclusive: u64, max_inclusive: u64) -> u64 { + match self { + Self::Default => fastrand::u64(min_inclusive..=max_inclusive), + #[cfg(test)] + Self::Override(overrid) => (overrid)(min_inclusive, max_inclusive), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::sync::{Arc, Mutex}; + + fn test_backoff( + min_delay: u64, + max_delay: u64, + test_random: impl Fn(u64, u64) -> u64 + Send + Sync + 'static, + attempt_delays: &[(u64, u64)], + ) { + let backoff = dbg!(Backoff::new( + Duration::from_secs(min_delay), + Duration::from_secs(max_delay), + Duration::from_secs(300), + RandomImpl::Override(Box::new(test_random)), + )); + + for (index, (delay, time)) in attempt_delays.iter().enumerate() { + let attempt = index + 1; + println!("attempt: {attempt}, delay: {delay}, time: {time}"); + assert_eq!( + Duration::from_secs(*delay), + backoff.delay(attempt as _, Duration::from_secs(*time)) + ); + } + } + + #[test] + fn backoff_jitter_as_average() { + let test_random = |min: u64, max: u64| (min + max) / 2; + let attempt_delays = &[ + // delay, time + (2, 2), + (3, 4), + (5, 7), + (9, 12), + (17, 21), + (33, 38), + (61, 71), + (61, 132), + (61, 193), + (46, 254), + (0, 300), + ]; + test_backoff(2, 120, test_random, attempt_delays); + } + + #[test] + fn backoff_with_seeded_jitter() { + let random = Arc::new(Mutex::new(fastrand::Rng::with_seed(1))); + let test_random = move |min: u64, max: u64| random.lock().unwrap().u64(min..=max); + let attempt_delays = &[ + // delay, time + (2, 2), + (3, 4), + (5, 7), + (2, 12), + (2, 14), + (57, 16), + (91, 73), + (6, 164), + (57, 170), + (29, 227), + (27, 256), + (17, 283), + (0, 300), + ]; + test_backoff(2, 120, test_random, attempt_delays); + } + + #[test] + fn backoff_with_large_min_delay() { + let test_random = |min: u64, max: u64| (min + max) / 2; + let attempt_delays = &[ + // delay, time + (15, 1), + (22, 16), + (37, 38), + (67, 75), + (67, 142), + (24, 276), + (0, 300), + ]; + test_backoff(15, 120, test_random, attempt_delays); + } +} diff --git a/rust-runtime/aws-smithy-runtime/src/test_util/capture_test_logs.rs b/rust-runtime/aws-smithy-runtime/src/test_util/capture_test_logs.rs index 92b450c115..d5447c98ab 100644 --- a/rust-runtime/aws-smithy-runtime/src/test_util/capture_test_logs.rs +++ b/rust-runtime/aws-smithy-runtime/src/test_util/capture_test_logs.rs @@ -14,6 +14,29 @@ use tracing_subscriber::fmt::TestWriter; #[derive(Debug)] pub struct LogCaptureGuard(#[allow(dead_code)] DefaultGuard); +/// Enables output of test logs to stdout at trace level by default. +/// +/// The env filter can be changed with the `RUST_LOG` environment variable. +#[must_use] +pub fn show_test_logs() -> LogCaptureGuard { + let (mut writer, _rx) = Tee::stdout(); + writer.loud(); + + let env_var = env::var("RUST_LOG").ok(); + let env_filter = env_var.as_deref().unwrap_or("trace"); + eprintln!( + "Enabled verbose test logging with env filter {env_filter:?}. \ + You can change the env filter with the RUST_LOG environment variable." + ); + + let subscriber = tracing_subscriber::fmt() + .with_env_filter(env_filter) + .with_writer(Mutex::new(writer)) + .finish(); + let guard = tracing::subscriber::set_default(subscriber); + LogCaptureGuard(guard) +} + /// Capture logs from this test. /// /// The logs will be captured until the `DefaultGuard` is dropped. diff --git a/rust-runtime/aws-smithy-runtime/tests/stalled_stream_common.rs b/rust-runtime/aws-smithy-runtime/tests/stalled_stream_common.rs new file mode 100644 index 0000000000..01d0248327 --- /dev/null +++ b/rust-runtime/aws-smithy-runtime/tests/stalled_stream_common.rs @@ -0,0 +1,115 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#![cfg(all(feature = "client", feature = "test-util"))] +// Extra imports are used by stalled_stream_download and stalled_stream_upload as conveniences +#![allow(unused_imports)] + +pub use aws_smithy_async::{ + test_util::tick_advance_sleep::{ + tick_advance_time_and_sleep, TickAdvanceSleep, TickAdvanceTime, + }, + time::TimeSource, +}; +pub use aws_smithy_runtime::{ + assert_str_contains, + client::{ + orchestrator::operation::Operation, + stalled_stream_protection::StalledStreamProtectionInterceptor, + }, + test_util::capture_test_logs::show_test_logs, +}; +pub use aws_smithy_runtime_api::{ + box_error::BoxError, + client::{ + http::{ + HttpClient, HttpConnector, HttpConnectorFuture, HttpConnectorSettings, + SharedHttpConnector, + }, + interceptors::context::{Error, Output}, + orchestrator::{HttpRequest, HttpResponse, OrchestratorError}, + result::SdkError, + runtime_components::RuntimeComponents, + ser_de::DeserializeResponse, + stalled_stream_protection::StalledStreamProtectionConfig, + }, + http::{Response, StatusCode}, + shared::IntoShared, +}; +pub use aws_smithy_types::{ + body::SdkBody, error::display::DisplayErrorContext, timeout::TimeoutConfig, +}; +pub use bytes::Bytes; +pub use http_body_0_4::Body; +pub use pin_utils::pin_mut; +pub use std::{ + collections::VecDeque, + convert::Infallible, + future::poll_fn, + mem, + pin::Pin, + sync::{Arc, Mutex}, + task::{Context, Poll}, + time::Duration, +}; +pub use tracing::{info, Instrument as _}; + +/// No really, it's 42 bytes long... super neat +pub const NEAT_DATA: Bytes = Bytes::from_static(b"some really neat data"); + +/// Ticks time forward by the given duration, and logs the current time for debugging. +#[macro_export] +macro_rules! tick { + ($ticker:ident, $duration:expr) => { + $ticker.tick($duration).await; + let now = $ticker + .now() + .duration_since(std::time::SystemTime::UNIX_EPOCH) + .unwrap(); + tracing::info!("ticked {:?}, now at {:?}", $duration, now); + }; +} + +#[derive(Debug)] +pub struct FakeServer(pub SharedHttpConnector); +impl HttpClient for FakeServer { + fn http_connector( + &self, + _settings: &HttpConnectorSettings, + _components: &RuntimeComponents, + ) -> SharedHttpConnector { + self.0.clone() + } +} + +struct ChannelBody { + receiver: tokio::sync::mpsc::Receiver, +} +impl http_body_0_4::Body for ChannelBody { + type Data = Bytes; + type Error = Infallible; + + fn poll_data( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll>> { + match self.receiver.poll_recv(cx) { + Poll::Ready(value) => Poll::Ready(value.map(|v| Ok(v))), + Poll::Pending => Poll::Pending, + } + } + + fn poll_trailers( + self: Pin<&mut Self>, + _cx: &mut Context<'_>, + ) -> Poll, Self::Error>> { + unreachable!() + } +} + +pub fn channel_body() -> (SdkBody, tokio::sync::mpsc::Sender) { + let (sender, receiver) = tokio::sync::mpsc::channel(1000); + (SdkBody::from_body_0_4(ChannelBody { receiver }), sender) +} diff --git a/rust-runtime/aws-smithy-runtime/tests/stalled_stream_download.rs b/rust-runtime/aws-smithy-runtime/tests/stalled_stream_download.rs new file mode 100644 index 0000000000..54e953322c --- /dev/null +++ b/rust-runtime/aws-smithy-runtime/tests/stalled_stream_download.rs @@ -0,0 +1,297 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#![cfg(all(feature = "client", feature = "test-util"))] + +use std::time::Duration; + +#[macro_use] +mod stalled_stream_common; +use stalled_stream_common::*; + +/// Scenario: Successfully download at a rate above the minimum throughput. +/// Expected: MUST NOT timeout. +#[tokio::test] +async fn download_success() { + let _logs = show_test_logs(); + + let (time, sleep) = tick_advance_time_and_sleep(); + let (server, response_sender) = channel_server(); + let op = operation(server, time.clone(), sleep); + + let server = tokio::spawn(async move { + for _ in 1..100 { + response_sender.send(NEAT_DATA).await.unwrap(); + tick!(time, Duration::from_secs(1)); + } + drop(response_sender); + tick!(time, Duration::from_secs(1)); + }); + + let response_body = op.invoke(()).await.expect("initial success"); + let result = eagerly_consume(response_body).await; + server.await.unwrap(); + + result.ok().expect("response MUST NOT timeout"); +} + +/// Scenario: Download takes a some time to start, but then goes normally. +/// Expected: MUT NOT timeout. +#[tokio::test] +async fn download_slow_start() { + let _logs = show_test_logs(); + + let (time, sleep) = tick_advance_time_and_sleep(); + let (server, response_sender) = channel_server(); + let op = operation(server, time.clone(), sleep); + + let server = tokio::spawn(async move { + // Delay almost to the end of the grace period before sending anything + tick!(time, Duration::from_secs(4)); + for _ in 1..100 { + response_sender.send(NEAT_DATA).await.unwrap(); + tick!(time, Duration::from_secs(1)); + } + drop(response_sender); + tick!(time, Duration::from_secs(1)); + }); + + let response_body = op.invoke(()).await.expect("initial success"); + let result = eagerly_consume(response_body).await; + server.await.unwrap(); + + result.ok().expect("response MUST NOT timeout"); +} + +/// Scenario: Download starts fine, and then slowly falls below minimum throughput. +/// Expected: MUST timeout. +#[tokio::test] +async fn download_too_slow() { + let _logs = show_test_logs(); + + let (time, sleep) = tick_advance_time_and_sleep(); + let (server, response_sender) = channel_server(); + let op = operation(server, time.clone(), sleep); + + let server = tokio::spawn(async move { + // Get slower with every poll + for delay in 1..100 { + let _ = response_sender.send(NEAT_DATA).await; + tick!(time, Duration::from_secs(delay)); + } + drop(response_sender); + tick!(time, Duration::from_secs(1)); + }); + + let response_body = op.invoke(()).await.expect("initial success"); + let result = eagerly_consume(response_body).await; + server.await.unwrap(); + + let err = result.expect_err("should have timed out"); + assert_str_contains!( + DisplayErrorContext(err.as_ref()).to_string(), + "minimum throughput was specified at 1 B/s, but throughput of 0 B/s was observed" + ); +} + +/// Scenario: Download starts fine, and then the server stalls and stops sending data. +/// Expected: MUST timeout. +#[tokio::test] +async fn download_stalls() { + let _logs = show_test_logs(); + + let (time, sleep) = tick_advance_time_and_sleep(); + let (server, response_sender) = channel_server(); + let op = operation(server, time.clone(), sleep); + + let server = tokio::spawn(async move { + for _ in 1..10 { + response_sender.send(NEAT_DATA).await.unwrap(); + tick!(time, Duration::from_secs(1)); + } + tick!(time, Duration::from_secs(10)); + }); + + let response_body = op.invoke(()).await.expect("initial success"); + let result = tokio::spawn(eagerly_consume(response_body)); + server.await.unwrap(); + + let err = result + .await + .expect("no panics") + .expect_err("should have timed out"); + assert_str_contains!( + DisplayErrorContext(err.as_ref()).to_string(), + "minimum throughput was specified at 1 B/s, but throughput of 0 B/s was observed" + ); +} + +/// Scenario: Download starts fine, but then the server stalls for a time within the +/// grace period. Following that, it starts sending data again. +/// Expected: MUST NOT timeout. +#[tokio::test] +async fn download_stall_recovery_in_grace_period() { + let _logs = show_test_logs(); + + let (time, sleep) = tick_advance_time_and_sleep(); + let (server, response_sender) = channel_server(); + let op = operation(server, time.clone(), sleep); + + let server = tokio::spawn(async move { + for _ in 1..10 { + response_sender.send(NEAT_DATA).await.unwrap(); + tick!(time, Duration::from_secs(1)); + } + // Delay almost to the end of the grace period + tick!(time, Duration::from_secs(4)); + // And now recover + for _ in 1..10 { + response_sender.send(NEAT_DATA).await.unwrap(); + tick!(time, Duration::from_secs(1)); + } + drop(response_sender); + tick!(time, Duration::from_secs(1)); + }); + + let response_body = op.invoke(()).await.expect("initial success"); + let result = eagerly_consume(response_body).await; + server.await.unwrap(); + + result.ok().expect("response MUST NOT timeout"); +} + +/// Scenario: The server sends data fast enough, but the customer doesn't consume the +/// data fast enough. +/// Expected: MUST NOT timeout. +#[tokio::test] +async fn user_downloads_data_too_slowly() { + let _logs = show_test_logs(); + + let (time, sleep) = tick_advance_time_and_sleep(); + let (server, response_sender) = channel_server(); + let op = operation(server, time.clone(), sleep); + + let server = tokio::spawn(async move { + for _ in 1..100 { + response_sender.send(NEAT_DATA).await.unwrap(); + } + drop(response_sender); + }); + + let response_body = op.invoke(()).await.expect("initial success"); + let result = slowly_consume(time, response_body).await; + server.await.unwrap(); + + result.ok().expect("response MUST NOT timeout"); +} + +use download_test_tools::*; +mod download_test_tools { + use crate::stalled_stream_common::*; + + fn response(body: SdkBody) -> HttpResponse { + HttpResponse::try_from(http::Response::builder().status(200).body(body).unwrap()).unwrap() + } + + pub fn operation( + http_connector: impl HttpConnector + 'static, + time: TickAdvanceTime, + sleep: TickAdvanceSleep, + ) -> Operation<(), SdkBody, Infallible> { + #[derive(Debug)] + struct Deserializer; + impl DeserializeResponse for Deserializer { + fn deserialize_streaming( + &self, + response: &mut HttpResponse, + ) -> Option>> { + let mut body = SdkBody::taken(); + mem::swap(response.body_mut(), &mut body); + Some(Ok(Output::erase(body))) + } + + fn deserialize_nonstreaming( + &self, + _: &HttpResponse, + ) -> Result> { + unreachable!() + } + } + + let operation = Operation::builder() + .service_name("test") + .operation_name("test") + .http_client(FakeServer(http_connector.into_shared())) + .endpoint_url("http://localhost:1234/doesntmatter") + .no_auth() + .no_retry() + .timeout_config(TimeoutConfig::disabled()) + .serializer(|_body: ()| Ok(HttpRequest::new(SdkBody::empty()))) + .deserializer_impl(Deserializer) + .stalled_stream_protection( + StalledStreamProtectionConfig::enabled() + .grace_period(Duration::from_secs(5)) + .build(), + ) + .interceptor(StalledStreamProtectionInterceptor::default()) + .sleep_impl(sleep) + .time_source(time) + .build(); + operation + } + + /// Fake server/connector that responds with a channel body. + pub fn channel_server() -> (SharedHttpConnector, tokio::sync::mpsc::Sender) { + #[derive(Debug)] + struct FakeServerConnector { + body: Arc>>, + } + impl HttpConnector for FakeServerConnector { + fn call(&self, _request: HttpRequest) -> HttpConnectorFuture { + let body = self.body.lock().unwrap().take().unwrap(); + HttpConnectorFuture::new(async move { Ok(response(body)) }) + } + } + + let (body, body_sender) = channel_body(); + ( + FakeServerConnector { + body: Arc::new(Mutex::new(Some(body))), + } + .into_shared(), + body_sender, + ) + } + + /// Simulate a client eagerly consuming all the data sent to it from the server. + pub async fn eagerly_consume(body: SdkBody) -> Result<(), BoxError> { + pin_mut!(body); + while let Some(result) = poll_fn(|cx| body.as_mut().poll_data(cx)).await { + if let Err(err) = result { + return Err(err); + } else { + tracing::info!("consumed bytes from the response body"); + } + } + Ok(()) + } + + /// Simulate a client very slowly consuming data with an eager server. + /// + /// This implementation will take longer than the grace period to consume + /// the next piece of data. + pub async fn slowly_consume(time: TickAdvanceTime, body: SdkBody) -> Result<(), BoxError> { + pin_mut!(body); + while let Some(result) = poll_fn(|cx| body.as_mut().poll_data(cx)).await { + if let Err(err) = result { + return Err(err); + } else { + tracing::info!("consumed bytes from the response body"); + tick!(time, Duration::from_secs(10)); + } + } + Ok(()) + } +} diff --git a/rust-runtime/aws-smithy-runtime/tests/stalled_stream_performance.rs b/rust-runtime/aws-smithy-runtime/tests/stalled_stream_performance.rs index 70211cfe52..f1ed0f779a 100644 --- a/rust-runtime/aws-smithy-runtime/tests/stalled_stream_performance.rs +++ b/rust-runtime/aws-smithy-runtime/tests/stalled_stream_performance.rs @@ -7,7 +7,7 @@ use aws_smithy_async::rt::sleep::TokioSleep; use aws_smithy_async::time::{SystemTimeSource, TimeSource}; -use aws_smithy_runtime::client::http::body::minimum_throughput::MinimumThroughputBody; +use aws_smithy_runtime::client::http::body::minimum_throughput::MinimumThroughputDownloadBody; use aws_smithy_runtime_api::client::stalled_stream_protection::StalledStreamProtectionConfig; use aws_smithy_types::body::SdkBody; use aws_smithy_types::byte_stream::ByteStream; @@ -92,7 +92,7 @@ async fn make_request(address: &str, wrap_body: bool) -> Duration { let time_source = SystemTimeSource::new(); let sleep = TokioSleep::new(); let opts = StalledStreamProtectionConfig::enabled().build(); - let mtb = MinimumThroughputBody::new(time_source, sleep, body, opts.into()); + let mtb = MinimumThroughputDownloadBody::new(time_source, sleep, body, opts.into()); SdkBody::from_body_0_4(mtb) }); } diff --git a/rust-runtime/aws-smithy-runtime/tests/stalled_stream_upload.rs b/rust-runtime/aws-smithy-runtime/tests/stalled_stream_upload.rs new file mode 100644 index 0000000000..f64fa321b2 --- /dev/null +++ b/rust-runtime/aws-smithy-runtime/tests/stalled_stream_upload.rs @@ -0,0 +1,342 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#![cfg(all(feature = "client", feature = "test-util"))] + +#[macro_use] +mod stalled_stream_common; +use stalled_stream_common::*; + +/// Scenario: Successful upload at a rate above the minimum throughput. +/// Expected: MUST NOT timeout. +#[tokio::test] +async fn upload_success() { + let _logs = show_test_logs(); + + let (server, time, sleep) = eager_server(true); + let op = operation(server, time, sleep); + + let (body, body_sender) = channel_body(); + let result = tokio::spawn(async move { op.invoke(body).await }); + + for _ in 0..100 { + body_sender.send(NEAT_DATA).await.unwrap(); + } + drop(body_sender); + + assert_eq!(200, result.await.unwrap().expect("success").as_u16()); +} + +/// Scenario: Upload takes some time to start, but then goes normally. +/// Expected: MUST NOT timeout. +#[tokio::test] +async fn upload_slow_start() { + let _logs = show_test_logs(); + + let (server, time, sleep) = eager_server(false); + let op = operation(server, time.clone(), sleep); + + let (body, body_sender) = channel_body(); + let result = tokio::spawn(async move { op.invoke(body).await }); + + let _streamer = tokio::spawn(async move { + // Advance longer than the grace period. This shouldn't fail since + // it is the customer's side that hasn't produced data yet, not a server issue. + time.tick(Duration::from_secs(10)).await; + + for _ in 0..100 { + body_sender.send(NEAT_DATA).await.unwrap(); + time.tick(Duration::from_secs(1)).await; + } + drop(body_sender); + time.tick(Duration::from_secs(1)).await; + }); + + assert_eq!(200, result.await.unwrap().expect("success").as_u16()); +} + +/// Scenario: The upload is going fine, but falls below the minimum throughput. +/// Expected: MUST timeout. +#[tokio::test] +async fn upload_too_slow() { + let _logs = show_test_logs(); + + // Server that starts off fast enough, but gets slower over time until it should timeout. + let (server, time, sleep) = time_sequence_server([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + let op = operation(server, time, sleep); + + let (body, body_sender) = channel_body(); + let result = tokio::spawn(async move { op.invoke(body).await }); + + let _streamer = tokio::spawn(async move { + for send in 0..100 { + info!("send {send}"); + body_sender.send(NEAT_DATA).await.unwrap(); + } + drop(body_sender); + }); + + expect_timeout(result.await.expect("no panics")); +} + +/// Scenario: The server stops asking for data, the client maxes out its send buffer, +/// and the request stream stops being polled. +/// Expected: MUST timeout after the grace period completes. +#[tokio::test] +async fn upload_stalls() { + let _logs = show_test_logs(); + + let (server, time, sleep) = stalling_server(); + let op = operation(server, time.clone(), sleep); + + let (body, body_sender) = channel_body(); + let result = tokio::spawn(async move { op.invoke(body).await }); + + let _streamer = tokio::spawn(async move { + for send in 1..=100 { + info!("send {send}"); + body_sender.send(NEAT_DATA).await.unwrap(); + tick!(time, Duration::from_secs(1)); + } + drop(body_sender); + time.tick(Duration::from_secs(1)).await; + }); + + expect_timeout(result.await.expect("no panics")); +} + +/// Scenario: All the request data is either uploaded to the server or buffered in the +/// HTTP client, but the response doesn't start coming through within the grace period. +/// Expected: MUST timeout after the grace period completes. +#[tokio::test] +async fn complete_upload_no_response() { + let _logs = show_test_logs(); + + let (server, time, sleep) = stalling_server(); + let op = operation(server, time.clone(), sleep); + + let (body, body_sender) = channel_body(); + let result = tokio::spawn(async move { op.invoke(body).await }); + + let _streamer = tokio::spawn(async move { + body_sender.send(NEAT_DATA).await.unwrap(); + tick!(time, Duration::from_secs(1)); + drop(body_sender); + time.tick(Duration::from_secs(6)).await; + }); + + expect_timeout(result.await.expect("no panics")); +} + +// Scenario: The server stops asking for data, the client maxes out its send buffer, +// and the request stream stops being polled. However, before the grace period +// is over, the server recovers and starts asking for data again. +// Expected: MUST NOT timeout. +#[tokio::test] +async fn upload_stall_recovery_in_grace_period() { + let _logs = show_test_logs(); + + // Server starts off fast enough, but then slows down almost up to + // the grace period, and then recovers. + let (server, time, sleep) = time_sequence_server([1, 4, 1]); + let op = operation(server, time, sleep); + + let (body, body_sender) = channel_body(); + let result = tokio::spawn(async move { op.invoke(body).await }); + + let _streamer = tokio::spawn(async move { + for send in 0..100 { + info!("send {send}"); + body_sender.send(NEAT_DATA).await.unwrap(); + } + drop(body_sender); + }); + + assert_eq!(200, result.await.unwrap().expect("success").as_u16()); +} + +// Scenario: The customer isn't providing data on the stream fast enough to satisfy +// the minimum throughput. This shouldn't be considered a stall since the +// server is asking for more data and could handle it if it were available. +// Expected: MUST NOT timeout. +#[tokio::test] +async fn user_provides_data_too_slowly() { + let _logs = show_test_logs(); + + let (server, time, sleep) = eager_server(false); + let op = operation(server, time.clone(), sleep.clone()); + + let (body, body_sender) = channel_body(); + let result = tokio::spawn(async move { op.invoke(body).await }); + + let _streamer = tokio::spawn(async move { + body_sender.send(NEAT_DATA).await.unwrap(); + tick!(time, Duration::from_secs(1)); + body_sender.send(NEAT_DATA).await.unwrap(); + + // Now advance 10 seconds before sending more data, simulating a + // customer taking time to produce more data to stream. + tick!(time, Duration::from_secs(10)); + body_sender.send(NEAT_DATA).await.unwrap(); + drop(body_sender); + tick!(time, Duration::from_secs(1)); + }); + + assert_eq!(200, result.await.unwrap().expect("success").as_u16()); +} + +use upload_test_tools::*; +mod upload_test_tools { + use crate::stalled_stream_common::*; + + pub fn successful_response() -> HttpResponse { + HttpResponse::try_from( + http::Response::builder() + .status(200) + .body(SdkBody::empty()) + .unwrap(), + ) + .unwrap() + } + + pub fn operation( + http_connector: impl HttpConnector + 'static, + time: TickAdvanceTime, + sleep: TickAdvanceSleep, + ) -> Operation { + let operation = Operation::builder() + .service_name("test") + .operation_name("test") + .http_client(FakeServer(http_connector.into_shared())) + .endpoint_url("http://localhost:1234/doesntmatter") + .no_auth() + .no_retry() + .timeout_config(TimeoutConfig::disabled()) + .serializer(|body: SdkBody| Ok(HttpRequest::new(body))) + .deserializer::<_, Infallible>(|response| Ok(response.status())) + .stalled_stream_protection( + StalledStreamProtectionConfig::enabled() + .grace_period(Duration::from_secs(5)) + .build(), + ) + .interceptor(StalledStreamProtectionInterceptor::default()) + .sleep_impl(sleep) + .time_source(time) + .build(); + operation + } + + /// Creates a fake HttpConnector implementation that calls the given async $body_fn + /// to get the response body. This $body_fn is given a request body, time, and sleep. + macro_rules! fake_server { + ($name:ident, $body_fn:expr) => { + fake_server!($name, $body_fn, (), ()) + }; + ($name:ident, $body_fn:expr, $params_ty:ty, $params:expr) => {{ + #[derive(Debug)] + struct $name(TickAdvanceTime, TickAdvanceSleep, $params_ty); + impl HttpConnector for $name { + fn call(&self, mut request: HttpRequest) -> HttpConnectorFuture { + let time = self.0.clone(); + let sleep = self.1.clone(); + let params = self.2.clone(); + let span = tracing::span!(tracing::Level::INFO, "FAKE SERVER"); + HttpConnectorFuture::new( + async move { + let mut body = SdkBody::taken(); + mem::swap(request.body_mut(), &mut body); + pin_mut!(body); + + Ok($body_fn(body, time, sleep, params).await) + } + .instrument(span), + ) + } + } + let (time, sleep) = tick_advance_time_and_sleep(); + ( + $name(time.clone(), sleep.clone(), $params).into_shared(), + time, + sleep, + ) + }}; + } + + /// Fake server/connector that immediately reads all incoming data with an + /// optional 1 second gap in between polls. + pub fn eager_server( + advance_time: bool, + ) -> (SharedHttpConnector, TickAdvanceTime, TickAdvanceSleep) { + async fn fake_server( + mut body: Pin<&mut SdkBody>, + time: TickAdvanceTime, + _: TickAdvanceSleep, + advance_time: bool, + ) -> HttpResponse { + while poll_fn(|cx| body.as_mut().poll_data(cx)).await.is_some() { + if advance_time { + tick!(time, Duration::from_secs(1)); + } + } + successful_response() + } + fake_server!(FakeServerConnector, fake_server, bool, advance_time) + } + + /// Fake server/connector that reads some data, and then stalls. + pub fn stalling_server() -> (SharedHttpConnector, TickAdvanceTime, TickAdvanceSleep) { + async fn fake_server( + mut body: Pin<&mut SdkBody>, + _time: TickAdvanceTime, + _sleep: TickAdvanceSleep, + _: (), + ) -> HttpResponse { + let mut times = 5; + while times > 0 && poll_fn(|cx| body.as_mut().poll_data(cx)).await.is_some() { + times -= 1; + } + // never awake after this + tracing::info!("stalling indefinitely"); + std::future::pending::<()>().await; + unreachable!() + } + fake_server!(FakeServerConnector, fake_server) + } + + /// Fake server/connector that polls data after each period of time in the given + /// sequence. Once the sequence completes, it will delay 1 second after each poll. + pub fn time_sequence_server( + time_sequence: impl IntoIterator, + ) -> (SharedHttpConnector, TickAdvanceTime, TickAdvanceSleep) { + async fn fake_server( + mut body: Pin<&mut SdkBody>, + time: TickAdvanceTime, + _sleep: TickAdvanceSleep, + time_sequence: Vec, + ) -> HttpResponse { + let mut time_sequence: VecDeque = + time_sequence.into_iter().map(Duration::from_secs).collect(); + while poll_fn(|cx| body.as_mut().poll_data(cx)).await.is_some() { + let next_time = time_sequence.pop_front().unwrap_or(Duration::from_secs(1)); + tick!(time, next_time); + } + successful_response() + } + fake_server!( + FakeServerConnector, + fake_server, + Vec, + time_sequence.into_iter().collect() + ) + } + + pub fn expect_timeout(result: Result>>) { + let err = result.expect_err("should have timed out"); + assert_str_contains!( + DisplayErrorContext(&err).to_string(), + "minimum throughput was specified at 1 B/s, but throughput of 0 B/s was observed" + ); + } +} diff --git a/rust-runtime/aws-smithy-types/Cargo.toml b/rust-runtime/aws-smithy-types/Cargo.toml index 0b30a2e428..c16bf6615a 100644 --- a/rust-runtime/aws-smithy-types/Cargo.toml +++ b/rust-runtime/aws-smithy-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aws-smithy-types" -version = "1.1.8" +version = "1.1.9" authors = [ "AWS Rust SDK Team ", "Russell Cohen ", diff --git a/rust-runtime/aws-smithy-types/src/date_time/mod.rs b/rust-runtime/aws-smithy-types/src/date_time/mod.rs index bfcbfb22e3..d8b5f7637d 100644 --- a/rust-runtime/aws-smithy-types/src/date_time/mod.rs +++ b/rust-runtime/aws-smithy-types/src/date_time/mod.rs @@ -55,7 +55,7 @@ const NANOS_PER_SECOND_U32: u32 = 1_000_000_000; /// The [`aws-smithy-types-convert`](https://crates.io/crates/aws-smithy-types-convert) crate /// can be used for conversions to/from other libraries, such as /// [`time`](https://crates.io/crates/time) or [`chrono`](https://crates.io/crates/chrono). -#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] +#[derive(PartialEq, Eq, Hash, Clone, Copy)] pub struct DateTime { pub(crate) seconds: i64, /// Subsecond nanos always advances the wallclock time, even for times where seconds is negative @@ -336,6 +336,12 @@ impl Display for DateTime { write!(f, "{}", date) } } + +impl fmt::Debug for DateTime { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} /// Failure to convert a `DateTime` to or from another type. #[derive(Debug)] #[non_exhaustive] @@ -394,6 +400,21 @@ mod test { assert_eq!(format!("{}", date_time), "1970-07-16T16:52:03Z"); } + #[test] + fn test_debug_date_time() { + let date_time = DateTime::from_secs(1576540098); + assert_eq!(format!("{:?}", date_time), "2019-12-16T23:48:18Z"); + + let date_time = DateTime::from_fractional_secs(1576540098, 0.52); + assert_eq!(format!("{:?}", date_time), "2019-12-16T23:48:18.52Z"); + + let date_time = DateTime::from_secs(1699942527); + assert_eq!(format!("{:?}", date_time), "2023-11-14T06:15:27Z"); + + let date_time = DateTime::from_secs(16995123); + assert_eq!(format!("{:?}", date_time), "1970-07-16T16:52:03Z"); + } + #[test] fn test_fmt() { let date_time = DateTime::from_secs(1576540098); diff --git a/rust-runtime/aws-smithy-xml/Cargo.toml b/rust-runtime/aws-smithy-xml/Cargo.toml index eb0c4fe1ec..a658c54ec2 100644 --- a/rust-runtime/aws-smithy-xml/Cargo.toml +++ b/rust-runtime/aws-smithy-xml/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aws-smithy-xml" -version = "0.60.7" +version = "0.60.8" authors = ["AWS Rust SDK Team ", "Russell Cohen "] description = "XML parsing logic for Smithy protocols." edition = "2021" diff --git a/rust-runtime/aws-smithy-xml/src/lib.rs b/rust-runtime/aws-smithy-xml/src/lib.rs index 48952cfced..fad590f46a 100644 --- a/rust-runtime/aws-smithy-xml/src/lib.rs +++ b/rust-runtime/aws-smithy-xml/src/lib.rs @@ -15,7 +15,7 @@ )] //! Abstractions for Smithy -//! [XML Binding Traits](https://awslabs.github.io/smithy/1.0/spec/core/xml-traits.html) +//! [XML Binding Traits](https://smithy.io/2.0/spec/protocol-traits.html#xml-bindings) pub mod decode; pub mod encode; diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 27ae62c5bc..7897a24d1a 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "1.74.1" +channel = "1.75.0" diff --git a/tools/ci-build/Dockerfile b/tools/ci-build/Dockerfile index 8abe689cd8..a383c06576 100644 --- a/tools/ci-build/Dockerfile +++ b/tools/ci-build/Dockerfile @@ -6,7 +6,7 @@ # This is the base Docker build image used by CI ARG base_image=public.ecr.aws/amazonlinux/amazonlinux:2023 -ARG rust_stable_version=1.74.1 +ARG rust_stable_version=1.75.0 ARG rust_nightly_version=nightly-2024-02-07 FROM ${base_image} AS bare_base_image @@ -14,10 +14,10 @@ RUN yum -y updateinfo FROM bare_base_image as musl_toolchain RUN yum -y install --allowerasing tar gzip gcc make -RUN curl https://musl.libc.org/releases/musl-1.2.3.tar.gz -o musl-1.2.3.tar.gz \ +RUN curl https://musl.libc.org/releases/musl-1.2.5.tar.gz -o musl-1.2.5.tar.gz \ && ls \ - && tar xvzf musl-1.2.3.tar.gz \ - && (cd musl-1.2.3 && ./configure && make install) + && tar xvzf musl-1.2.5.tar.gz \ + && (cd musl-1.2.5 && ./configure && make install) # # Rust & Tools Installation Stage @@ -92,16 +92,16 @@ RUN set -eux; \ chmod g+rw -R /opt/cargo/registry FROM install_rust AS cargo_deny -ARG cargo_deny_version=0.13.5 +ARG cargo_deny_version=0.14.20 RUN cargo install cargo-deny --locked --version ${cargo_deny_version} FROM install_rust AS cargo_udeps -ARG cargo_udeps_version=0.1.46 +ARG cargo_udeps_version=0.1.47 ARG rust_nightly_version RUN cargo +${rust_nightly_version} install cargo-udeps --locked --version ${cargo_udeps_version} FROM install_rust AS cargo_hack -ARG cargo_hack_version=0.5.23 +ARG cargo_hack_version=0.6.27 RUN cargo install cargo-hack --locked --version ${cargo_hack_version} FROM install_rust AS cargo_minimal_versions @@ -113,20 +113,20 @@ ARG cargo_check_external_types_version=0.1.11 RUN cargo install cargo-check-external-types --locked --version ${cargo_check_external_types_version} FROM install_rust AS maturin -ARG maturin_version=0.14.1 +ARG maturin_version=1.5.1 RUN cargo install maturin --locked --version ${maturin_version} FROM install_rust AS wasm_pack -ARG wasm_pack_version=0.11.0 +ARG wasm_pack_version=0.12.1 RUN cargo install wasm-pack --locked --version ${wasm_pack_version} FROM install_rust AS wasmtime -ARG cargo_wasmtime_version=18.0.1 +ARG cargo_wasmtime_version=19.0.1 ARG rust_nightly_version RUN cargo install wasmtime-cli --features="component-model" --locked --version ${cargo_wasmtime_version} FROM install_rust AS cargo_component -ARG cargo_component_version=0.7.1 +ARG cargo_component_version=0.10.1 ARG rust_nightly_version RUN cargo +${rust_nightly_version} install cargo-component --locked --version ${cargo_component_version} @@ -135,11 +135,11 @@ ARG cargo_semver_checks_version=0.24.1 RUN cargo install cargo-semver-checks --locked --version ${cargo_semver_checks_version} FROM install_rust AS cargo_mdbook -ARG cargo_mdbook_version=0.4.30 +ARG cargo_mdbook_version=0.4.37 RUN cargo install mdbook --locked --version ${cargo_mdbook_version} FROM install_rust AS cargo_mdbook_mermaid -ARG cargo_mdbook_mermaid_version=0.12.6 +ARG cargo_mdbook_mermaid_version=0.13.0 RUN cargo install mdbook-mermaid --locked --version ${cargo_mdbook_mermaid_version} # @@ -158,7 +158,7 @@ RUN set -eux; \ git \ glibc-langpack-en \ go \ - java-11-amazon-corretto-headless \ + java-17-amazon-corretto-headless \ make \ openssl-devel \ pkgconfig \ @@ -167,12 +167,14 @@ RUN set -eux; \ python3-pip \ shadow-utils \ cmake \ - tar; \ + tar \ + unzip; \ yum clean all; \ rm -rf /var/cache/yum; \ groupadd build; \ useradd -m -g build build; \ chmod 775 /home/build; +RUN set -eux; cd /tmp; curl 'https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip' -o awscliv2.zip && unzip awscliv2.zip && ./aws/install COPY --chown=build:build --from=local_tools /opt/cargo /opt/cargo COPY --chown=build:build --from=cargo_deny /opt/cargo/bin/cargo-deny /opt/cargo/bin/cargo-deny COPY --chown=build:build --from=cargo_udeps /opt/cargo/bin/cargo-udeps /opt/cargo/bin/cargo-udeps @@ -192,7 +194,7 @@ ENV PATH=$PATH:/usr/local/musl/bin/ ENV PATH=/opt/cargo/bin:$PATH \ CARGO_HOME=/opt/cargo \ RUSTUP_HOME=/opt/rustup \ - JAVA_HOME=/usr/lib/jvm/java-11-amazon-corretto.x86_64 \ + JAVA_HOME=/usr/lib/jvm/java-17-amazon-corretto.x86_64 \ GRADLE_USER_HOME=/home/build/.gradle \ RUST_STABLE_VERSION=${rust_stable_version} \ RUST_NIGHTLY_VERSION=${rust_nightly_version} \ diff --git a/tools/ci-build/changelogger/Cargo.lock b/tools/ci-build/changelogger/Cargo.lock index c7de5cafaa..400851481d 100644 --- a/tools/ci-build/changelogger/Cargo.lock +++ b/tools/ci-build/changelogger/Cargo.lock @@ -19,28 +19,28 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", ] [[package]] @@ -56,15 +56,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -77,9 +77,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "bitflags" @@ -89,31 +89,38 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] -name = "cc" -version = "1.0.83" +name = "cargo_toml" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "a98356df42a2eb1bd8f1793ae4ee4de48e384dd974ce5eac8eee802edb7492be" dependencies = [ - "libc", + "serde", + "toml 0.8.12", ] +[[package]] +name = "cc" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" + [[package]] name = "cfg-if" version = "1.0.0" @@ -134,7 +141,7 @@ dependencies = [ "smithy-rs-tool-common", "tempfile", "time", - "toml", + "toml 0.5.11", ] [[package]] @@ -192,11 +199,31 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +[[package]] +name = "crates-index" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879bde76e7fb6166c3d36dd2b1e376d012e8b110b52cbec72bf59c40d20ec9fe" +dependencies = [ + "hex", + "home", + "http", + "memchr", + "rustc-hash", + "semver", + "serde", + "serde_derive", + "serde_json", + "smol_str", + "thiserror", + "toml 0.8.12", +] + [[package]] name = "deranged" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", ] @@ -209,9 +236,9 @@ checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -234,9 +261,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "fnv" @@ -270,41 +297,50 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-core", + "futures-io", "futures-task", + "memchr", "pin-project-lite", "pin-utils", + "slab", ] [[package]] @@ -315,9 +351,9 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "h2" -version = "0.3.22" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -325,7 +361,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.1.0", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -359,11 +395,29 @@ dependencies = [ "libc", ] +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -372,9 +426,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -395,9 +449,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -410,7 +464,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2", "tokio", "tower-service", "tracing", @@ -452,9 +506,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -468,15 +522,15 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -489,27 +543,27 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "mime" @@ -519,18 +573,18 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", @@ -555,39 +609,44 @@ dependencies = [ "tempfile", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] [[package]] name = "num_threads" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" dependencies = [ "libc", ] [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -600,11 +659,11 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl" -version = "0.10.61" +version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b8419dc8cc6d866deb801274bba2e6f8f6108c1bb7fcc10ee5ab864931dbb45" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.5.0", "cfg-if", "foreign-types", "libc", @@ -621,7 +680,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", ] [[package]] @@ -632,9 +691,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.97" +version = "0.9.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3eaad34cdd97d81de97964fc7f29e2d104f483840d906ef56daa1912338460b" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" dependencies = [ "cc", "libc", @@ -665,9 +724,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -677,9 +736,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "powerfmt" @@ -723,36 +782,27 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "regex" -version = "1.10.2" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", @@ -762,9 +812,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -773,15 +823,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reqwest" -version = "0.11.22" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64", "bytes", @@ -801,9 +851,11 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", "tokio-native-tls", @@ -821,39 +873,54 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustix" -version = "0.38.26" +version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9470c4bf8246c8daf25f9598dca807fb6510347b1e1cfa55749113850c79d88a" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", "windows-sys 0.52.0", ] +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64", +] + [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "security-framework" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -864,9 +931,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" dependencies = [ "core-foundation-sys", "libc", @@ -874,41 +941,50 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "itoa", "ryu", "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -936,6 +1012,8 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", + "cargo_toml", + "crates-index", "lazy_static", "regex", "reqwest", @@ -943,28 +1021,27 @@ dependencies = [ "serde", "serde_json", "thiserror", - "toml", + "toml 0.5.11", "tracing", ] [[package]] -name = "socket2" -version = "0.4.10" +name = "smol_str" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +checksum = "e6845563ada680337a52d43bb0b29f396f2d911616f6573012645b9e3d048a49" dependencies = [ - "libc", - "winapi", + "serde", ] [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -986,15 +1063,21 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "system-configuration" version = "0.5.1" @@ -1018,60 +1101,60 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.1" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "termcolor" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "textwrap" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", ] [[package]] name = "time" -version = "0.3.30" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "libc", + "num-conv", "num_threads", "powerfmt", "serde", @@ -1101,16 +1184,16 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.34.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", "libc", "mio", "pin-project-lite", - "socket2 0.5.5", + "socket2", "windows-sys 0.48.0", ] @@ -1148,6 +1231,40 @@ dependencies = [ "serde", ] +[[package]] +name = "toml" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" +dependencies = [ + "indexmap 2.2.6", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tower-service" version = "0.3.2" @@ -1173,7 +1290,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", ] [[package]] @@ -1193,9 +1310,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -1205,9 +1322,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -1252,9 +1369,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1262,24 +1379,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -1289,9 +1406,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1299,28 +1416,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -1372,7 +1489,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.4", ] [[package]] @@ -1392,17 +1509,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] @@ -1413,9 +1530,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" @@ -1425,9 +1542,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" @@ -1437,9 +1554,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" @@ -1449,9 +1566,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" @@ -1461,9 +1578,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" @@ -1473,9 +1590,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" @@ -1485,9 +1602,18 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + +[[package]] +name = "winnow" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" +dependencies = [ + "memchr", +] [[package]] name = "winreg" diff --git a/tools/ci-build/changelogger/README.md b/tools/ci-build/changelogger/README.md new file mode 100644 index 0000000000..3d08f653d8 --- /dev/null +++ b/tools/ci-build/changelogger/README.md @@ -0,0 +1,14 @@ +# ChangeLogger + +The Changelogger tool generates public facing `.md` changelogs from the structured `CHANGELOG.next.toml` formats that developers modify. The changelogger runs during smithy-rs releases to generate the smithy-rs specific changelog as well as during SDK releases to generate the SDK changelog. The smithy-rs changelog generation moves the AWS changelog entries into a separate file so that they can later be consumed. + +[smithy-rs-maintainers.txt](./smithy-rs-maintainers.txt) controls the set of users that is **not** acknowledged for their contributions in changelogs. + +## Commands +### Split +Splits changelog entries into two `json` files, splitting up `aws-sdk-rust` entries from `smithy-rs` entries. This is a prestep to full changelog generation. The end result is `aws/SDK_CHANGELOG.next.json`. + +This command is invoked as part of `smithy-rs-release`. + +### Render +Render a `.md` format changelog from a structured changelog. diff --git a/tools/ci-build/changelogger/smithy-rs-maintainers.txt b/tools/ci-build/changelogger/smithy-rs-maintainers.txt index 0c3bb18924..7143fc996f 100644 --- a/tools/ci-build/changelogger/smithy-rs-maintainers.txt +++ b/tools/ci-build/changelogger/smithy-rs-maintainers.txt @@ -8,3 +8,4 @@ ysaito1001 drganjoo rschmitt rhernandez35 +aajtodd diff --git a/tools/ci-build/crate-hasher/Cargo.lock b/tools/ci-build/crate-hasher/Cargo.lock index 83cef64575..c88c603fc4 100644 --- a/tools/ci-build/crate-hasher/Cargo.lock +++ b/tools/ci-build/crate-hasher/Cargo.lock @@ -19,28 +19,28 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.58", ] [[package]] @@ -56,15 +56,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -83,9 +83,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "block-buffer" @@ -98,9 +98,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.8.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" dependencies = [ "memchr", "serde", @@ -108,18 +108,15 @@ dependencies = [ [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cc" -version = "1.0.83" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" [[package]] name = "cfg-if" @@ -168,9 +165,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -191,21 +188,18 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crypto-common" @@ -240,14 +234,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "filetime" @@ -258,7 +252,7 @@ dependencies = [ "cfg-if", "libc", "redox_syscall", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -363,42 +357,42 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -417,9 +411,9 @@ checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pretty_assertions" @@ -457,18 +451,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -484,9 +478,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", @@ -496,9 +490,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -507,9 +501,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "rustc-demangle" @@ -519,15 +513,15 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.26" +version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9470c4bf8246c8daf25f9598dca807fb6510347b1e1cfa55749113850c79d88a" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -541,22 +535,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.58", ] [[package]] @@ -572,9 +566,9 @@ dependencies = [ [[package]] name = "sha256" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7895c8ae88588ccead14ff438b939b0c569cd619116f14b4d13fdff7b8333386" +checksum = "18278f6a914fa3070aa316493f7d2ddfb9ac86ebc06fa3b83bffda487e9065b0" dependencies = [ "async-trait", "bytes", @@ -602,9 +596,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" dependencies = [ "proc-macro2", "quote", @@ -624,22 +618,21 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.1" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", "rustix", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] name = "termcolor" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -652,9 +645,9 @@ checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d" [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -662,9 +655,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.34.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -691,9 +684,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -730,145 +723,81 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "xattr" -version = "1.0.1" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985" +checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" dependencies = [ "libc", + "linux-raw-sys", + "rustix", ] [[package]] diff --git a/tools/ci-build/crate-hasher/README.md b/tools/ci-build/crate-hasher/README.md new file mode 100644 index 0000000000..8723180dcb --- /dev/null +++ b/tools/ci-build/crate-hasher/README.md @@ -0,0 +1,11 @@ +# crate-hasher +The Crate Hasher generates deterministic hashes of crates. This is used as a dependency of `publisher generate-version-manifests` to generate the `source_hash` field: + +```toml +[crates.aws-config] +category = 'AwsRuntime' +version = '0.12.0' +source_hash = '12d172094a2576e6f4d00a8ba58276c0d4abc4e241bb75f0d3de8ac3412e8e47' +``` + +Note: (@rcoh, 4/24/2024): As far as I can tell, no tooling currently relies on the `source_hash`. It seems like this could potentially be used in `runtime-versioner audit` in the future. diff --git a/tools/ci-build/difftags/Cargo.lock b/tools/ci-build/difftags/Cargo.lock index 29773e435a..f0e68cc6d4 100644 --- a/tools/ci-build/difftags/Cargo.lock +++ b/tools/ci-build/difftags/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -24,9 +24,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "bitflags" @@ -130,15 +130,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "once_cell" @@ -178,27 +178,27 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] [[package]] name = "regex" -version = "1.10.2" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", @@ -208,9 +208,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -219,9 +219,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "strsim" @@ -242,18 +242,18 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "textwrap" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "unicode-ident" diff --git a/tools/ci-build/difftags/README.md b/tools/ci-build/difftags/README.md index 2b74c36ebf..4927287c78 100644 --- a/tools/ci-build/difftags/README.md +++ b/tools/ci-build/difftags/README.md @@ -2,3 +2,6 @@ difftags ======== Simple CLI tool to convert a unified diff file into human readable/browsable paginated HTML files. + + +This is used by the [GitHub PR Bot](../../../.github/) diff --git a/tools/ci-build/publisher/Cargo.lock b/tools/ci-build/publisher/Cargo.lock index 6aacb8502a..6a12b7e0f4 100644 --- a/tools/ci-build/publisher/Cargo.lock +++ b/tools/ci-build/publisher/Cargo.lock @@ -28,9 +28,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "async-recursion" @@ -45,13 +45,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.78" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -67,15 +67,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -115,15 +115,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cargo_toml" @@ -135,11 +135,21 @@ dependencies = [ "toml 0.8.12", ] +[[package]] +name = "cargo_toml" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a98356df42a2eb1bd8f1793ae4ee4de48e384dd974ce5eac8eee802edb7492be" +dependencies = [ + "serde", + "toml 0.8.12", +] + [[package]] name = "cc" -version = "1.0.90" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" [[package]] name = "cfg-if" @@ -228,9 +238,9 @@ dependencies = [ [[package]] name = "crates-index" -version = "2.5.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9efa03a974d583ad530bbfe00e3d0021de7f26217120437b128dc4c331aa4f" +checksum = "879bde76e7fb6166c3d36dd2b1e376d012e8b110b52cbec72bf59c40d20ec9fe" dependencies = [ "hex", "home", @@ -292,9 +302,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -317,9 +327,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "fnv" @@ -426,9 +436,9 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "h2" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -436,7 +446,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.2.5", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -601,9 +611,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.5" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -617,9 +627,9 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" @@ -675,9 +685,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "mime" @@ -781,7 +791,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -792,9 +802,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.101" +version = "0.9.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" dependencies = [ "cc", "libc", @@ -845,9 +855,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.8" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f8023d0fb78c8e03784ea1c7f3fa36e68a723138990b8d5a47d916b651e7a8" +checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95" dependencies = [ "memchr", "thiserror", @@ -856,9 +866,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.8" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0d24f72393fd16ab6ac5738bc33cdb6a9aa73f8b902e8fe29cf4e67d7dd1026" +checksum = "f73541b156d32197eecda1a4014d7f868fd2bcb3c550d5386087cfba442bf69c" dependencies = [ "pest", "pest_generator", @@ -866,22 +876,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.8" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc17e2a6c7d0a492f0158d7a4bd66cc17280308bbaff78d5bef566dca35ab80" +checksum = "c35eeed0a3fab112f75165fdc026b3913f4183133f19b49be773ac9ea966e8bd" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] name = "pest_meta" -version = "2.7.8" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "934cd7631c050f4674352a6e835d5f6711ffbfb9345c2fc0107155ac495ae293" +checksum = "2adbf29bb9776f28caece835398781ab24435585fe0d4dc1374a61db5accedca" dependencies = [ "once_cell", "pest", @@ -890,9 +900,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -956,14 +966,14 @@ dependencies = [ "anyhow", "async-recursion", "async-trait", - "cargo_toml", + "cargo_toml 0.16.3", "clap", "dialoguer", "fs-err", "handlebars", "once_cell", "pretty_assertions", - "regex", + "regex-lite", "semver", "serde", "serde_json", @@ -979,9 +989,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -997,14 +1007,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.3" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", "regex-automata 0.4.6", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -1024,9 +1034,15 @@ checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] +[[package]] +name = "regex-lite" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b661b2f27137bdbc16f00eda72866a92bb28af1753ffbd56744fb6e2e9cd8e" + [[package]] name = "regex-syntax" version = "0.6.29" @@ -1035,9 +1051,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reqwest" @@ -1136,9 +1152,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "security-framework" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -1149,9 +1165,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" dependencies = [ "core-foundation-sys", "libc", @@ -1180,14 +1196,14 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "itoa", "ryu", @@ -1278,6 +1294,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", + "cargo_toml 0.19.2", "crates-index", "lazy_static", "regex", @@ -1329,9 +1346,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.53" +version = "2.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" dependencies = [ "proc-macro2", "quote", @@ -1419,7 +1436,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -1449,9 +1466,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.36.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -1474,7 +1491,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -1538,7 +1555,7 @@ version = "0.22.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", @@ -1570,7 +1587,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -1722,7 +1739,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", "wasm-bindgen-shared", ] @@ -1756,7 +1773,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1942,9 +1959,9 @@ checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" dependencies = [ "memchr", ] diff --git a/tools/ci-build/publisher/Cargo.toml b/tools/ci-build/publisher/Cargo.toml index af964ca03b..0e7dec69a4 100644 --- a/tools/ci-build/publisher/Cargo.toml +++ b/tools/ci-build/publisher/Cargo.toml @@ -23,7 +23,7 @@ dialoguer = "0.8" fs-err = "2" handlebars = "4.2" once_cell = "1.16.0" -regex = "1.5.4" +regex-lite = "0.1.5" semver = "1.0" serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/tools/ci-build/publisher/src/cargo/get_owners.rs b/tools/ci-build/publisher/src/cargo/get_owners.rs index b549738a1d..8c69f5f1fc 100644 --- a/tools/ci-build/publisher/src/cargo/get_owners.rs +++ b/tools/ci-build/publisher/src/cargo/get_owners.rs @@ -4,10 +4,14 @@ */ use anyhow::Result; -use regex::Regex; +use once_cell::sync::Lazy; +use regex_lite::Regex; use smithy_rs_tool_common::shell::{handle_failure, output_text, ShellOperation}; use std::process::Command; +static LINE_REGEX: Lazy = + Lazy::new(|| Regex::new(r"^([\w\d\-_:]+)\s+\([\w\d\s\-_]+\)$").unwrap()); + pub struct GetOwners { program: &'static str, package_name: String, @@ -33,9 +37,8 @@ impl ShellOperation for GetOwners { let mut result = Vec::new(); let (stdout, _) = output_text(&output); - let line_re = Regex::new(r"^([\w\d\-_:]+)\s+\([\w\d\s\-_]+\)$").unwrap(); for line in stdout.lines() { - if let Some(captures) = line_re.captures(line) { + if let Some(captures) = LINE_REGEX.captures(line) { let user_id = captures.get(1).unwrap().as_str(); result.push(user_id.to_string()); } else { diff --git a/tools/ci-build/publisher/src/cargo/publish.rs b/tools/ci-build/publisher/src/cargo/publish.rs index 71e79e3814..3f0f2a50d0 100644 --- a/tools/ci-build/publisher/src/cargo/publish.rs +++ b/tools/ci-build/publisher/src/cargo/publish.rs @@ -3,9 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -use crate::package::PackageHandle; use anyhow::Result; -use smithy_rs_tool_common::shell::{capture_error, output_text, ShellOperation}; +use smithy_rs_tool_common::{ + package::PackageHandle, + shell::{capture_error, output_text, ShellOperation}, +}; use std::path::PathBuf; use std::process::Command; use tracing::info; @@ -18,6 +20,10 @@ pub struct Publish { impl Publish { pub fn new(package_handle: PackageHandle, package_path: impl Into) -> Publish { + assert!( + package_handle.version.is_some(), + "crate version number required; given {package_handle}" + ); Publish { program: "cargo", package_handle, @@ -42,12 +48,12 @@ impl ShellOperation for Publish { let (stdout, stderr) = output_text(&output); let already_uploaded_msg = format!( "error: crate version `{}` is already uploaded", - self.package_handle.version + self.package_handle.expect_version() ); if stdout.contains(&already_uploaded_msg) || stderr.contains(&already_uploaded_msg) { info!( - "{}-{} has already been published to crates.io.", - self.package_handle.name, self.package_handle.version + "{} has already been published to crates.io.", + self.package_handle ); } else { return Err(capture_error("cargo publish", &output)); @@ -69,7 +75,7 @@ mod tests { program: "./fake_cargo/cargo_success", package_handle: PackageHandle::new( "aws-sdk-dynamodb", - Version::parse("0.0.22-alpha").unwrap(), + Version::parse("0.0.22-alpha").ok(), ), package_path: env::current_dir().unwrap(), } @@ -82,10 +88,7 @@ mod tests { async fn publish_fails() { let result = Publish { program: "./fake_cargo/cargo_fails", - package_handle: PackageHandle::new( - "something", - Version::parse("0.0.22-alpha").unwrap(), - ), + package_handle: PackageHandle::new("something", Version::parse("0.0.22-alpha").ok()), package_path: env::current_dir().unwrap(), } .spawn() @@ -106,7 +109,7 @@ mod tests { program: "./fake_cargo/cargo_publish_already_published", package_handle: PackageHandle::new( "aws-sdk-dynamodb", - Version::parse("0.0.22-alpha").unwrap(), + Version::parse("0.0.22-alpha").ok(), ), package_path: env::current_dir().unwrap(), } diff --git a/tools/ci-build/publisher/src/main.rs b/tools/ci-build/publisher/src/main.rs index 176f04a9ce..273601a3c6 100644 --- a/tools/ci-build/publisher/src/main.rs +++ b/tools/ci-build/publisher/src/main.rs @@ -16,8 +16,6 @@ use publisher::subcommand::publish::subcommand_publish; use publisher::subcommand::publish::PublishArgs; use publisher::subcommand::tag_versions_manifest::subcommand_tag_versions_manifest; use publisher::subcommand::tag_versions_manifest::TagVersionsManifestArgs; -use publisher::subcommand::upgrade_runtime_crates_version::subcommand_upgrade_runtime_crates_version; -use publisher::subcommand::upgrade_runtime_crates_version::UpgradeRuntimeCratesVersionArgs; use publisher::subcommand::yank_release::{subcommand_yank_release, YankReleaseArgs}; use tracing_subscriber::fmt::format::FmtSpan; @@ -26,11 +24,6 @@ use tracing_subscriber::fmt::format::FmtSpan; enum Args { /// Fixes path dependencies in manifests to also have version numbers FixManifests(FixManifestsArgs), - /// Upgrade the version of the runtime crates used by the code generator (via `gradle.properties`). - /// - /// The command will fail if you try to perform a downgrade - e.g. change the version from - /// `0.53.1` to `0.52.0` or `0.53.0`. - UpgradeRuntimeCratesVersion(UpgradeRuntimeCratesVersionArgs), /// Publishes crates to crates.io Publish(PublishArgs), /// Publishes an empty library crate to crates.io when a new runtime crate is introduced. @@ -59,9 +52,6 @@ async fn main() -> Result<()> { match Args::parse() { Args::ClaimCrateNames(args) => subcommand_claim_crate_names(&args).await?, - Args::UpgradeRuntimeCratesVersion(args) => { - subcommand_upgrade_runtime_crates_version(&args).await? - } Args::Publish(args) => subcommand_publish(&args).await?, Args::FixManifests(args) => subcommand_fix_manifests(&args).await?, Args::YankRelease(args) => subcommand_yank_release(&args).await?, diff --git a/tools/ci-build/publisher/src/package.rs b/tools/ci-build/publisher/src/package.rs index 4fb572a687..7f2f823df2 100644 --- a/tools/ci-build/publisher/src/package.rs +++ b/tools/ci-build/publisher/src/package.rs @@ -7,101 +7,15 @@ use crate::fs::Fs; use crate::sort::dependency_order; -use crate::RUST_SDK_CI_OWNER; -use anyhow::{Context, Result}; -use cargo_toml::{Dependency, DepsSet, Manifest}; +use anyhow::Result; use semver::Version; -use smithy_rs_tool_common::package::PackageCategory; -use std::collections::{BTreeMap, BTreeSet, HashSet}; +use smithy_rs_tool_common::package::{Package, PackageCategory, PackageHandle, Publish}; use std::error::Error as StdError; -use std::fmt; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; +use std::{collections::BTreeMap, path::Path}; use tokio::fs; use tracing::warn; -/// Information required to identify a package (crate). -#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] -pub struct PackageHandle { - pub name: String, - pub version: Version, -} - -impl PackageHandle { - pub fn new(name: impl Into, version: Version) -> Self { - Self { - name: name.into(), - version, - } - } -} - -impl fmt::Display for PackageHandle { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}-{}", self.name, self.version) - } -} - -#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)] -pub enum Publish { - Allowed, - NotAllowed, -} - -/// Represents a crate (called Package since crate is a reserved word). -#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)] -pub struct Package { - /// Package name and version information - pub handle: PackageHandle, - /// Package category (Generated, SmithyRuntime, AwsRuntime, etc.) - pub category: PackageCategory, - /// Location to the crate on the current file system - pub crate_path: PathBuf, - /// Location to the crate manifest on the current file system - pub manifest_path: PathBuf, - /// Dependencies used by this package - pub local_dependencies: BTreeSet, - /// Whether or not the package should be published - pub publish: Publish, -} - -impl Package { - pub fn new( - handle: PackageHandle, - manifest_path: impl Into, - local_dependencies: BTreeSet, - publish: Publish, - ) -> Self { - let manifest_path = manifest_path.into(); - let category = PackageCategory::from_package_name(&handle.name); - Self { - handle, - category, - crate_path: manifest_path.parent().unwrap().into(), - manifest_path, - local_dependencies, - publish, - } - } - - /// Returns `true` if this package depends on `other` - pub fn locally_depends_on(&self, other: &PackageHandle) -> bool { - self.local_dependencies.contains(other) - } - - /// Returns the expected owners of the crate. - pub fn expected_owners(&self) -> HashSet { - expected_package_owners(&self.category, &self.handle.name) - } -} - -/// Returns the expected owners of the crate. -pub fn expected_package_owners( - _category: &PackageCategory, - _package_name: &str, -) -> HashSet { - [RUST_SDK_CI_OWNER.to_string()].into_iter().collect() -} - /// Batch of packages. pub type PackageBatch = Vec; @@ -145,7 +59,7 @@ pub async fn discover_and_validate_package_batches( fs: Fs, path: impl AsRef, ) -> Result<(Vec, PackageStats)> { - let packages = discover_packages(fs, path.as_ref().into()) + let packages = discover_packages(fs, path.as_ref()) .await? .into_iter() .filter(|package| package.publish == Publish::Allowed) @@ -175,9 +89,9 @@ pub enum Error { /// Discovers all Cargo.toml files under the given path recursively #[async_recursion::async_recursion] -pub async fn discover_manifests(path: PathBuf) -> Result> { +pub async fn discover_manifests(path: &Path) -> Result> { let mut manifests = Vec::new(); - let mut read_dir = fs::read_dir(&path).await?; + let mut read_dir = fs::read_dir(path).await?; while let Some(entry) = read_dir.next_entry().await? { let package_path = entry.path(); if package_path.is_dir() { @@ -185,91 +99,35 @@ pub async fn discover_manifests(path: PathBuf) -> Result> { if manifest_path.exists() { manifests.push(manifest_path); } - manifests.extend(discover_manifests(package_path).await?.into_iter()); + manifests.extend(discover_manifests(&package_path).await?.into_iter()); } } Ok(manifests) } /// Discovers and parses all Cargo.toml files that are packages (as opposed to being exclusively workspaces) -pub async fn discover_packages(fs: Fs, path: PathBuf) -> Result> { +pub async fn discover_packages(fs: Fs, path: &Path) -> Result> { let manifest_paths = discover_manifests(path).await?; read_packages(fs, manifest_paths).await } -/// Parses a semver version number and adds additional error context when parsing fails. -pub fn parse_version(manifest_path: &Path, version: &str) -> Result { - Version::parse(version) - .map_err(|err| Error::InvalidCrateVersion(manifest_path.into(), version.into(), err.into())) -} - -fn read_dependencies(path: &Path, dependencies: &DepsSet) -> Result> { - let mut result = Vec::new(); - for (name, metadata) in dependencies { - match metadata { - Dependency::Simple(_) => {} - Dependency::Detailed(detailed) => { - if detailed.path.is_some() { - let version = detailed - .version - .as_ref() - .map(|version| parse_version(path, version)) - .ok_or_else(|| Error::MissingVersion(path.into(), name.into()))??; - result.push(PackageHandle::new(name, version)); - } - } - Dependency::Inherited(_) => panic!("workspace deps are unsupported"), - } - } - Ok(result) -} - -/// Returns `Ok(None)` when the Cargo.toml is a workspace rather than a package -fn read_package(path: &Path, manifest_bytes: &[u8]) -> Result> { - let mut manifest = Manifest::from_slice(manifest_bytes) - .with_context(|| format!("failed to load package manifest for {:?}", path))?; - manifest.complete_from_path(path)?; - if let Some(package) = manifest.package { - let name = package.name; - let version = parse_version(path, &package.version.unwrap())?; - let handle = PackageHandle { name, version }; - let publish = match package.publish.unwrap() { - cargo_toml::Publish::Flag(true) => Publish::Allowed, - _ => Publish::NotAllowed, - }; - - let mut local_dependencies = BTreeSet::new(); - local_dependencies.extend(read_dependencies(path, &manifest.dependencies)?); - local_dependencies.extend(read_dependencies(path, &manifest.dev_dependencies)?); - local_dependencies.extend(read_dependencies(path, &manifest.build_dependencies)?); - Ok(Some(Package::new( - handle, - path, - local_dependencies, - publish, - ))) - } else { - Ok(None) - } -} - /// Validates that all of the publishable crates use consistent version numbers /// across all of their local dependencies. fn validate_packages(packages: &[Package]) -> Result<()> { let mut versions: BTreeMap = BTreeMap::new(); let track_version = &mut |handle: &PackageHandle| -> Result<(), Error> { if let Some(version) = versions.get(&handle.name) { - if *version != handle.version { + if version != handle.expect_version() { Err(Error::MultipleVersions( (&handle.name).into(), versions[&handle.name].clone(), - handle.version.clone(), + handle.expect_version().clone(), )) } else { Ok(()) } } else { - versions.insert(handle.name.clone(), handle.version.clone()); + versions.insert(handle.name.clone(), handle.expect_version().clone()); Ok(()) } }; @@ -287,7 +145,7 @@ pub async fn read_packages(fs: Fs, manifest_paths: Vec) -> Result = fs.read_file(path).await?; - if let Some(package) = read_package(path, &contents)? { + if let Some(package) = Package::try_load_manifest(path, &contents)? { result.push(package); } } @@ -337,79 +195,14 @@ fn batch_packages(packages: Vec) -> Result> { mod tests { use super::*; use semver::Version; - use std::path::PathBuf; - - fn version(version: &str) -> Version { - Version::parse(version).unwrap() - } - - #[test] - fn read_package_success() { - let manifest = br#" - [package] - name = "test" - version = "1.2.0-preview" - - [build-dependencies] - build_something = "1.3" - local_build_something = { version = "0.2.0", path = "../local_build_something" } - - [dev-dependencies] - dev_something = "1.1" - local_dev_something = { version = "0.1.0", path = "../local_dev_something" } - - [dependencies] - something = "1.0" - local_something = { version = "1.1.3", path = "../local_something" } - "#; - let path: PathBuf = "test/Cargo.toml".into(); - - let package = read_package(&path, manifest) - .expect("parse success") - .expect("is a package"); - assert_eq!("test", package.handle.name); - assert_eq!(version("1.2.0-preview"), package.handle.version); - - let mut expected = BTreeSet::new(); - expected.insert(PackageHandle::new( - "local_build_something", - version("0.2.0"), - )); - expected.insert(PackageHandle::new("local_dev_something", version("0.1.0"))); - expected.insert(PackageHandle::new("local_something", version("1.1.3"))); - assert_eq!(expected, package.local_dependencies); - } - - #[test] - fn read_package_version_requirement_invalid() { - let manifest = br#" - [package] - name = "test" - version = "1.2.0-preview" - - [dependencies] - local_something = { version = "1.0", path = "../local_something" } - "#; - let path: PathBuf = "test/Cargo.toml".into(); - - let error = format!( - "{}", - read_package(&path, manifest).expect_err("should fail") - ); - assert!( - error.contains("Invalid crate version"), - "'{}' should contain 'Invalid crate version'", - error - ); - } fn package(name: &str, dependencies: &[&str]) -> Package { Package::new( - PackageHandle::new(name, Version::parse("1.0.0").unwrap()), + PackageHandle::new(name, Version::parse("1.0.0").ok()), format!("{}/Cargo.toml", name), dependencies .iter() - .map(|d| PackageHandle::new(*d, Version::parse("1.0.0").unwrap())) + .map(|d| PackageHandle::new(*d, Version::parse("1.0.0").ok())) .collect(), Publish::Allowed, ) @@ -487,11 +280,11 @@ mod tests { fn pkg_ver(name: &str, version: &str, dependencies: &[(&str, &str)]) -> Package { Package::new( - PackageHandle::new(name, Version::parse(version).unwrap()), + PackageHandle::new(name, Some(Version::parse(version).unwrap())), format!("{}/Cargo.toml", name), dependencies .iter() - .map(|p| PackageHandle::new(p.0, Version::parse(p.1).unwrap())) + .map(|p| PackageHandle::new(p.0, Some(Version::parse(p.1).unwrap()))) .collect(), Publish::Allowed, ) @@ -540,33 +333,21 @@ mod tests { package("aws-smithy-http-server-typescript", &[]), ]; for pkg in server_packages { - assert_eq!( - [String::from("aws-sdk-rust-ci")] - .into_iter() - .collect::>(), - pkg.expected_owners() - ); + assert_eq!(&["aws-sdk-rust-ci"], pkg.expected_owners()); } } #[test] fn test_expected_package_owners_sdk_crate() { let sdk_package = package("aws-types", &[]); - assert_eq!( - [String::from("aws-sdk-rust-ci")] - .into_iter() - .collect::>(), - sdk_package.expected_owners() - ); + assert_eq!(&["aws-sdk-rust-ci"], sdk_package.expected_owners()); } #[test] fn test_expected_package_owners_smithy_runtime_crate() { let smithy_runtime_package = package("aws-smithy-types", &[]); assert_eq!( - [String::from("aws-sdk-rust-ci")] - .into_iter() - .collect::>(), + &["aws-sdk-rust-ci"], smithy_runtime_package.expected_owners() ); } diff --git a/tools/ci-build/publisher/src/publish.rs b/tools/ci-build/publisher/src/publish.rs index 3c8a1fb96f..6fc8ad1239 100644 --- a/tools/ci-build/publisher/src/publish.rs +++ b/tools/ci-build/publisher/src/publish.rs @@ -4,13 +4,12 @@ */ use crate::cargo; -use crate::package::PackageHandle; use anyhow::Result; -use smithy_rs_tool_common::shell::ShellOperation; use smithy_rs_tool_common::{ index::CratesIndex, retry::{run_with_retry, BoxError, ErrorClass}, }; +use smithy_rs_tool_common::{package::PackageHandle, shell::ShellOperation}; use std::time::Duration; use std::{path::Path, sync::Arc}; use tracing::info; diff --git a/tools/ci-build/publisher/src/sort.rs b/tools/ci-build/publisher/src/sort.rs index 6362e9c43d..3b0e2d5704 100644 --- a/tools/ci-build/publisher/src/sort.rs +++ b/tools/ci-build/publisher/src/sort.rs @@ -5,8 +5,8 @@ //! Logic for topological sorting packages by dependencies. -use crate::package::{Package, PackageHandle}; use anyhow::{anyhow, bail, Result}; +use smithy_rs_tool_common::package::{Package, PackageHandle}; use std::collections::{BTreeMap, BTreeSet}; /// Determines the dependency order of the given packages. @@ -72,16 +72,16 @@ fn dependency_order_visit( #[cfg(test)] mod tests { use super::*; - use crate::package::Publish; use semver::Version; + use smithy_rs_tool_common::package::Publish; fn package(name: &str, dependencies: &[&str]) -> Package { Package::new( - PackageHandle::new(name, Version::parse("1.0.0").unwrap()), + PackageHandle::new(name, Version::parse("1.0.0").ok()), format!("{}/Cargo.toml", name), dependencies .iter() - .map(|d| PackageHandle::new(*d, Version::parse("1.0.0").unwrap())) + .map(|d| PackageHandle::new(*d, Version::parse("1.0.0").ok())) .collect(), Publish::Allowed, ) diff --git a/tools/ci-build/publisher/src/subcommand/claim_crate_names.rs b/tools/ci-build/publisher/src/subcommand/claim_crate_names.rs index 11303f3685..caef6abb22 100644 --- a/tools/ci-build/publisher/src/subcommand/claim_crate_names.rs +++ b/tools/ci-build/publisher/src/subcommand/claim_crate_names.rs @@ -2,17 +2,17 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0 */ +use crate::publish::is_published; use crate::publish::publish; use crate::subcommand::publish::correct_owner; use crate::{cargo, SDK_REPO_NAME}; use crate::{fs::Fs, package::discover_manifests}; -use crate::{package::PackageHandle, publish::is_published}; use anyhow::{Context, Result}; use cargo_toml::Manifest; use clap::Parser; use dialoguer::Confirm; use semver::Version; -use smithy_rs_tool_common::package::PackageCategory; +use smithy_rs_tool_common::package::PackageHandle; use smithy_rs_tool_common::{git, index::CratesIndex}; use std::time::Duration; use std::{collections::HashSet, fs}; @@ -66,20 +66,19 @@ async fn claim_crate_name(name: &str) -> Result<()> { let crate_dir_path = temporary_directory.path(); create_dummy_lib_crate(Fs::Real, name, crate_dir_path.to_path_buf()).await?; - let category = PackageCategory::from_package_name(name); - let package_handle = PackageHandle::new(name, Version::new(0, 0, 1)); + let package_handle = PackageHandle::new(name, Some(Version::new(0, 0, 1))); publish(&package_handle, crate_dir_path).await?; // Keep things slow to avoid getting throttled by crates.io tokio::time::sleep(Duration::from_secs(2)).await; - correct_owner(&package_handle, &category).await?; + correct_owner(&package_handle).await?; info!("Successfully published `{}`", package_handle); Ok(()) } async fn load_publishable_crate_names(path: &Path) -> Result> { - let manifest_paths = discover_manifests(path.into()).await?; + let manifest_paths = discover_manifests(path).await?; let mut result = HashSet::new(); for manifest_path in &manifest_paths { let content = diff --git a/tools/ci-build/publisher/src/subcommand/fix_manifests.rs b/tools/ci-build/publisher/src/subcommand/fix_manifests.rs index 78814cdad5..cb42abc308 100644 --- a/tools/ci-build/publisher/src/subcommand/fix_manifests.rs +++ b/tools/ci-build/publisher/src/subcommand/fix_manifests.rs @@ -10,12 +10,12 @@ //! version numbers in addition to the dependency path. use crate::fs::Fs; -use crate::package::{discover_manifests, parse_version}; +use crate::package::discover_manifests; use crate::SDK_REPO_NAME; use anyhow::{bail, Context, Result}; use clap::Parser; use semver::Version; -use smithy_rs_tool_common::ci::running_in_ci; +use smithy_rs_tool_common::{ci::running_in_ci, package::parse_version}; use std::collections::BTreeMap; use std::ffi::OsStr; use std::path::{Path, PathBuf}; @@ -54,7 +54,7 @@ pub async fn subcommand_fix_manifests( true => Mode::Check, false => Mode::Execute, }; - let manifest_paths = discover_manifests(location.into()).await?; + let manifest_paths = discover_manifests(location).await?; let mut manifests = read_manifests(Fs::Real, manifest_paths).await?; let versions = package_versions(&manifests)?; diff --git a/tools/ci-build/publisher/src/subcommand/generate_version_manifest.rs b/tools/ci-build/publisher/src/subcommand/generate_version_manifest.rs index 6b9ac35397..9a5a53273e 100644 --- a/tools/ci-build/publisher/src/subcommand/generate_version_manifest.rs +++ b/tools/ci-build/publisher/src/subcommand/generate_version_manifest.rs @@ -70,7 +70,7 @@ pub async fn subcommand_generate_version_manifest( (None, Some(output_location)) => output_location, _ => bail!("Only one of `--location` or `--output-location` should be provided"), }; - let packages = discover_packages(Fs::Real, input_location.into()) + let packages = discover_packages(Fs::Real, input_location) .await .context("read packages")?; @@ -94,11 +94,12 @@ pub async fn subcommand_generate_version_manifest( matches!(package.category, PackageCategory::AwsSdk) == model_hash.is_some(), "all generated SDK crates should have a model hash" ); + let version = package.handle.expect_version().to_string(); crates.insert( package.handle.name, CrateVersion { category: package.category, - version: package.handle.version.to_string(), + version, source_hash: hash_crate(&package.crate_path).context("hash crate")?, model_hash, }, diff --git a/tools/ci-build/publisher/src/subcommand/mod.rs b/tools/ci-build/publisher/src/subcommand/mod.rs index 256993e7b0..9462cf58ca 100644 --- a/tools/ci-build/publisher/src/subcommand/mod.rs +++ b/tools/ci-build/publisher/src/subcommand/mod.rs @@ -9,5 +9,4 @@ pub mod generate_version_manifest; pub mod hydrate_readme; pub mod publish; pub mod tag_versions_manifest; -pub mod upgrade_runtime_crates_version; pub mod yank_release; diff --git a/tools/ci-build/publisher/src/subcommand/publish.rs b/tools/ci-build/publisher/src/subcommand/publish.rs index d724557f9b..2c568b3f65 100644 --- a/tools/ci-build/publisher/src/subcommand/publish.rs +++ b/tools/ci-build/publisher/src/subcommand/publish.rs @@ -4,16 +4,13 @@ */ use crate::fs::Fs; -use crate::package::{ - discover_and_validate_package_batches, expected_package_owners, Package, PackageBatch, - PackageHandle, PackageStats, -}; +use crate::package::{discover_and_validate_package_batches, PackageBatch, PackageStats}; use crate::publish::publish; use crate::{cargo, SDK_REPO_CRATE_PATH, SDK_REPO_NAME}; use anyhow::{bail, Context, Result}; use clap::Parser; use dialoguer::Confirm; -use smithy_rs_tool_common::package::PackageCategory; +use smithy_rs_tool_common::package::{Package, PackageHandle}; use smithy_rs_tool_common::retry::{run_with_retry, BoxError, ErrorClass}; use smithy_rs_tool_common::shell::ShellOperation; use smithy_rs_tool_common::{git, index::CratesIndex}; @@ -90,7 +87,7 @@ pub async fn subcommand_publish( for batch in &batches { for package in batch { - correct_owner(&package.handle, &package.category).await?; + correct_owner(&package.handle).await?; } } @@ -110,7 +107,7 @@ pub fn resolve_publish_location(location: &Path) -> PathBuf { async fn is_published(index: Arc, handle: &PackageHandle) -> Result { let name = handle.name.clone(); - let version = handle.version.clone(); + let version = handle.expect_version().clone(); tokio::task::spawn_blocking(move || { smithy_rs_tool_common::index::is_published(index.as_ref(), &name, &version) }) @@ -137,7 +134,7 @@ async fn wait_for_eventual_consistency(index: Arc, package: &Packag } /// Corrects the crate ownership. -pub async fn correct_owner(handle: &PackageHandle, category: &PackageCategory) -> Result<()> { +pub async fn correct_owner(handle: &PackageHandle) -> Result<()> { // https://github.com/orgs/awslabs/teams/smithy-rs-server const SMITHY_RS_SERVER_OWNER: &str = "github:awslabs:smithy-rs-server"; // https://github.com/orgs/awslabs/teams/rust-sdk-owners @@ -149,7 +146,7 @@ pub async fn correct_owner(handle: &PackageHandle, category: &PackageCategory) - Duration::from_secs(5), || async { let actual_owners: HashSet = cargo::GetOwners::new(&handle.name).spawn().await?.into_iter().collect(); - let expected_owners = expected_package_owners(category, &handle.name); + let expected_owners = handle.expected_owners().iter().map(|s| s.to_string()).collect::>(); let owners_to_be_added = expected_owners.difference(&actual_owners); let owners_to_be_removed = actual_owners.difference(&expected_owners); @@ -203,7 +200,8 @@ fn confirm_plan( for package in batch { full_plan.push(format!( "Publish version `{}` of `{}`", - package.handle.version, package.handle.name + package.handle.expect_version(), + package.handle.name )); } full_plan.push("-- wait --".into()); diff --git a/tools/ci-build/publisher/src/subcommand/upgrade_runtime_crates_version.rs b/tools/ci-build/publisher/src/subcommand/upgrade_runtime_crates_version.rs deleted file mode 100644 index f9df685bfb..0000000000 --- a/tools/ci-build/publisher/src/subcommand/upgrade_runtime_crates_version.rs +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -use crate::fs::Fs; -use anyhow::{anyhow, bail, Context}; -use clap::Parser; -use once_cell::sync::Lazy; -use regex::Regex; -use smithy_rs_tool_common::package::PackageStability; -use std::borrow::Cow; -use std::path::{Path, PathBuf}; - -static STABLE_VERSION_REGEX: Lazy = Lazy::new(|| { - Regex::new( - r"(?Psmithy\.rs\.runtime\.crate\.stable\.version=)(?P\d+\.\d+\.\d+.*)", - ) - .unwrap() -}); -static UNSTABLE_VERSION_REGEX: Lazy = Lazy::new(|| { - Regex::new( - r"(?Psmithy\.rs\.runtime\.crate\.unstable\.version=)(?P\d+\.\d+\.\d+.*)", - ) - .unwrap() -}); - -#[derive(Parser, Debug)] -pub struct UpgradeRuntimeCratesVersionArgs { - /// The version of stable runtime crates you want the code generator to use (e.g. `1.0.2`). - #[clap(long)] - stable_version: Option, - /// The version of unstable runtime crates you want the code generator to use (e.g. `0.52.0`). - #[clap(long)] - version: String, - /// The path to the `gradle.properties` file. It will default to `gradle.properties` if - /// left unspecified. - #[clap(long, default_value = "gradle.properties")] - gradle_properties_path: PathBuf, -} - -pub async fn subcommand_upgrade_runtime_crates_version( - args: &UpgradeRuntimeCratesVersionArgs, -) -> Result<(), anyhow::Error> { - check_crate_ver_against_stability(&args.version, PackageStability::Unstable)?; - let upgraded_unstable_version = semver::Version::parse(args.version.as_str()) - .with_context(|| format!("{} is not a valid semver version", &args.version))?; - let fs = Fs::Real; - let gradle_properties = read_gradle_properties(fs, &args.gradle_properties_path).await?; - let updated_gradle_properties = update_gradle_properties( - &gradle_properties, - &upgraded_unstable_version, - PackageStability::Unstable, - ) - .with_context(|| { - format!( - "Failed to extract the expected runtime crates version from `{:?}`", - &args.gradle_properties_path - ) - })?; - let updated_gradle_properties = if let Some(stable_version) = &args.stable_version { - check_crate_ver_against_stability(stable_version, PackageStability::Stable)?; - let upgraded_stable_version = semver::Version::parse(stable_version.as_str()) - .with_context(|| format!("{} is not a valid semver version", &stable_version))?; - update_gradle_properties( - &updated_gradle_properties, - &upgraded_stable_version, - PackageStability::Stable, - ) - .with_context(|| { - format!( - "Failed to extract the expected runtime crates version from `{:?}`", - &args.gradle_properties_path - ) - })? - } else { - updated_gradle_properties - }; - update_gradle_properties_file( - fs, - &args.gradle_properties_path, - updated_gradle_properties.as_ref(), - ) - .await?; - Ok(()) -} - -fn update_gradle_properties<'a>( - gradle_properties: &'a str, - upgraded_version: &semver::Version, - package_stability: PackageStability, -) -> Result, anyhow::Error> { - let version_regex = match package_stability { - PackageStability::Stable => &STABLE_VERSION_REGEX, - PackageStability::Unstable => &UNSTABLE_VERSION_REGEX, - }; - let current_version = version_regex - .captures(gradle_properties) - .ok_or_else(|| anyhow!("Failed to extract the expected runtime crates version"))?; - let current_version = current_version.name("version").unwrap(); - let current_version = semver::Version::parse(current_version.as_str()) - .with_context(|| format!("{} is not a valid semver version", current_version.as_str()))?; - if ¤t_version > upgraded_version - // Special version tag used on the `main` branch - && current_version != semver::Version::parse("0.0.0-smithy-rs-head").unwrap() - { - bail!("Moving from {current_version} to {upgraded_version} would be a *downgrade*. This command doesn't allow it!"); - } - Ok(version_regex.replace(gradle_properties, format!("${{field}}{}", upgraded_version))) -} - -async fn read_gradle_properties(fs: Fs, path: &Path) -> Result { - let bytes = fs.read_file(path).await?; - let contents = String::from_utf8(bytes) - .with_context(|| format!("`{:?}` contained non-UTF8 data", path))?; - Ok(contents) -} - -async fn update_gradle_properties_file( - fs: Fs, - path: &Path, - contents: &str, -) -> Result<(), anyhow::Error> { - fs.write_file(path, contents.as_bytes()).await?; - Ok(()) -} - -fn check_crate_ver_against_stability( - crate_ver: &str, - package_stability: PackageStability, -) -> Result<(), anyhow::Error> { - match package_stability { - PackageStability::Stable if crate_ver.starts_with("0.") => Err(anyhow::Error::msg( - format!("{} is an invalid stable crate version", &crate_ver), - )), - PackageStability::Unstable if !crate_ver.starts_with("0.") => Err(anyhow::Error::msg( - format!("{} is an invalid unstable crate version", &crate_ver), - )), - _ => Ok(()), - } -} - -#[cfg(test)] -mod tests { - use crate::subcommand::upgrade_runtime_crates_version::{ - check_crate_ver_against_stability, update_gradle_properties, - }; - use smithy_rs_tool_common::package::PackageStability; - - #[test] - fn upgrading_works_with_actual_unstable_version() { - let gradle_properties = "smithy.rs.runtime.crate.unstable.version=0.54.2"; - let version = semver::Version::new(0, 54, 3); - let updated = - update_gradle_properties(gradle_properties, &version, PackageStability::Unstable) - .unwrap(); - assert_eq!("smithy.rs.runtime.crate.unstable.version=0.54.3", updated); - } - - #[test] - fn upgrading_works_with_dummy_unstable_version() { - let gradle_properties = "smithy.rs.runtime.crate.unstable.version=0.0.0-smithy-rs-head"; - let version = semver::Version::new(0, 54, 3); - let updated = - update_gradle_properties(gradle_properties, &version, PackageStability::Unstable) - .unwrap(); - assert_eq!("smithy.rs.runtime.crate.unstable.version=0.54.3", updated); - } - - #[test] - fn upgrading_works_with_actual_stable_version() { - let gradle_properties = "smithy.rs.runtime.crate.stable.version=1.0.2"; - let version = semver::Version::new(1, 0, 3); - let updated = - update_gradle_properties(gradle_properties, &version, PackageStability::Stable) - .unwrap(); - assert_eq!("smithy.rs.runtime.crate.stable.version=1.0.3", updated); - } - - #[test] - fn upgrading_works_with_dummy_stable_version() { - let gradle_properties = "smithy.rs.runtime.crate.stable.version=0.0.0-smithy-rs-head"; - let version = semver::Version::new(1, 0, 3); - let updated = - update_gradle_properties(gradle_properties, &version, PackageStability::Stable) - .unwrap(); - assert_eq!("smithy.rs.runtime.crate.stable.version=1.0.3", updated); - } - - #[test] - fn downgrading_stable_crate_should_be_caught_as_err() { - let gradle_properties = "smithy.rs.runtime.crate.stable.version=1.0.2"; - let version = semver::Version::new(1, 0, 1); - let result = - update_gradle_properties(gradle_properties, &version, PackageStability::Stable); - assert!(result.is_err()); - assert!(format!("{:?}", result).contains("downgrade")); - } - - #[test] - fn downgrading_unstable_crate_should_be_caught_as_err() { - let gradle_properties = "smithy.rs.runtime.crate.unstable.version=0.57.1"; - let version = semver::Version::new(0, 57, 0); - let result = - update_gradle_properties(gradle_properties, &version, PackageStability::Unstable); - assert!(result.is_err()); - assert!(format!("{:?}", result).contains("downgrade")); - } - - #[test] - fn test_check_crate_ver_against_stability() { - assert!(check_crate_ver_against_stability("0.60.0", PackageStability::Stable).is_err()); - assert!(check_crate_ver_against_stability("1.0.0", PackageStability::Stable).is_ok()); - assert!(check_crate_ver_against_stability("2.0.0", PackageStability::Stable).is_ok()); - - assert!(check_crate_ver_against_stability("0.60.0", PackageStability::Unstable).is_ok()); - assert!(check_crate_ver_against_stability("1.0.0", PackageStability::Unstable).is_err()); - assert!(check_crate_ver_against_stability("2.0.0", PackageStability::Unstable).is_err()); - } -} diff --git a/tools/ci-build/runtime-versioner/Cargo.lock b/tools/ci-build/runtime-versioner/Cargo.lock index 025690ed20..85f0268451 100644 --- a/tools/ci-build/runtime-versioner/Cargo.lock +++ b/tools/ci-build/runtime-versioner/Cargo.lock @@ -76,15 +76,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "async-trait" -version = "0.1.78" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", @@ -93,15 +93,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -132,15 +132,15 @@ checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "camino" @@ -160,9 +160,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.90" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" [[package]] name = "cfg-if" @@ -172,9 +172,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.3" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", "clap_derive", @@ -194,9 +194,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.3" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ "heck", "proc-macro2", @@ -247,9 +247,9 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "crates-index" -version = "2.5.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9efa03a974d583ad530bbfe00e3d0021de7f26217120437b128dc4c331aa4f" +checksum = "879bde76e7fb6166c3d36dd2b1e376d012e8b110b52cbec72bf59c40d20ec9fe" dependencies = [ "hex", "home", @@ -273,9 +273,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -298,9 +298,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "fnv" @@ -388,9 +388,9 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "h2" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -398,7 +398,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.2.5", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -534,9 +534,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.5" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -572,9 +572,9 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" @@ -620,9 +620,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "mime" @@ -733,9 +733,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.101" +version = "0.9.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" dependencies = [ "cc", "libc", @@ -757,9 +757,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -790,23 +790,23 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] [[package]] name = "regex" -version = "1.10.3" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", "regex-automata 0.4.6", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -826,7 +826,7 @@ checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -837,9 +837,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reqwest" @@ -952,9 +952,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -965,9 +965,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" dependencies = [ "core-foundation-sys", "libc", @@ -1001,9 +1001,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "itoa", "ryu", @@ -1051,9 +1051,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smithy-rs-tool-common" @@ -1061,6 +1061,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", + "cargo_toml", "crates-index", "lazy_static", "regex", @@ -1094,15 +1095,15 @@ dependencies = [ [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.53" +version = "2.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" dependencies = [ "proc-macro2", "quote", @@ -1210,9 +1211,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.36.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -1284,7 +1285,7 @@ version = "0.22.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", @@ -1667,9 +1668,9 @@ checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" dependencies = [ "memchr", ] diff --git a/tools/ci-build/runtime-versioner/README.md b/tools/ci-build/runtime-versioner/README.md new file mode 100644 index 0000000000..76bd442c0a --- /dev/null +++ b/tools/ci-build/runtime-versioner/README.md @@ -0,0 +1,4 @@ +# runtime-versioner +Runtime versioner serves two purposes: +1. `audit` the runtime crates to ensure that if their contents have changed, the version number in the crate has been updated. This is run as part of pre-commit. +2. `patch-runtime`: Used by `check-semver-hazards` (and manually) to test a specific set of runtime crates against the generated AWS SDK. This works by utilizing [Cargo's source patching](https://doc.rust-lang.org/cargo/reference/overriding-dependencies.html). diff --git a/tools/ci-build/runtime-versioner/src/command/audit.rs b/tools/ci-build/runtime-versioner/src/command/audit.rs index b27d648208..997a8d6cb2 100644 --- a/tools/ci-build/runtime-versioner/src/command/audit.rs +++ b/tools/ci-build/runtime-versioner/src/command/audit.rs @@ -12,7 +12,8 @@ use crate::{ use anyhow::{anyhow, bail, Context, Result}; use camino::{Utf8Path, Utf8PathBuf}; use smithy_rs_tool_common::{ - command::sync::CommandExt, index::CratesIndex, release_tag::ReleaseTag, + command::sync::CommandExt, index::CratesIndex, package::PackageCategory, + release_tag::ReleaseTag, }; use std::{ collections::{BTreeMap, BTreeSet}, @@ -57,9 +58,22 @@ pub fn audit(args: Audit) -> Result<()> { fn audit_crate(repo: &Repo, release_tag: &ReleaseTag, rt_crate: RuntimeCrate) -> Result<()> { if rt_crate.changed_since_release(repo, release_tag)? { + // There is an edge case with the aws/rust-runtime crates due to the decoupled smithy-rs/SDK releases. + // After a smithy-rs release and before a SDK release, there is a period of time where the smithy-rs + // runtime crates are published to crates.io, but the SDK runtime crates are not. + // + // The way this manifests is that the crate's previous release version is now the same as the version + // number at HEAD, and the crate is not published. + let is_sdk_runtime_edge_case = PackageCategory::from_package_name(&rt_crate.name).is_sdk() + && rt_crate.previous_release_version.as_ref() == Some(&rt_crate.next_release_version) + && !rt_crate.next_version_is_published(); + if is_sdk_runtime_edge_case { + tracing::info!("For '{}', detected that a new version of smithy-rs has been released, but that the SDK release hasn't caught up yet.", rt_crate.name); + } + // If this version has never been published before, then we're good. // (This tool doesn't check semver compatibility.) - if !rt_crate.next_version_is_published() { + if !rt_crate.next_version_is_published() && !is_sdk_runtime_edge_case { if let Some(previous_version) = rt_crate.previous_release_version { tracing::info!( "'{}' changed and was version bumped from {previous_version} to {}", diff --git a/tools/ci-build/runtime-versioner/src/command/patch.rs b/tools/ci-build/runtime-versioner/src/command/patch.rs index 2984fbc17c..bf701ccdb9 100644 --- a/tools/ci-build/runtime-versioner/src/command/patch.rs +++ b/tools/ci-build/runtime-versioner/src/command/patch.rs @@ -9,12 +9,12 @@ use crate::{ PatchRuntime, PatchRuntimeWith, }; use anyhow::{bail, Context, Result}; -use camino::Utf8Path; +use camino::Utf8PathBuf; use cargo_toml::Manifest; use indicatif::{ProgressBar, ProgressStyle}; -use smithy_rs_tool_common::command::sync::CommandExt; +use smithy_rs_tool_common::{command::sync::CommandExt, package::Package}; use std::{fs, time::Duration}; -use toml_edit::DocumentMut; +use toml_edit::{DocumentMut, Item}; pub fn patch(args: PatchRuntime) -> Result<()> { let smithy_rs = step("Resolving smithy-rs", || { @@ -29,22 +29,14 @@ pub fn patch(args: PatchRuntime) -> Result<()> { bail!("aws-sdk-rust has a dirty working tree. Aborting."); } - // Use aws:sdk:assemble to generate both the smithy-rs runtime and AWS SDK - // runtime crates with the correct version numbers. - step("Generating an AWS SDK", || { - smithy_rs - .cmd( - "./gradlew", - // limit services down to minimum required to reduce generation time - ["-Paws.services=+sts,+sso,+ssooidc", "aws:sdk:assemble"], - ) - .expect_success_output("assemble SDK") - })?; - patch_with(PatchRuntimeWith { sdk_path: args.sdk_path, - runtime_crate_path: smithy_rs.root.join("aws/sdk/build/aws-sdk/sdk"), + runtime_crate_path: vec![ + smithy_rs.root.join("rust-runtime"), + smithy_rs.root.join("aws/rust-runtime"), + ], previous_release_tag: args.previous_release_tag, + no_checkout_sdk_release: args.no_checkout_sdk_release, })?; Ok(()) @@ -56,22 +48,24 @@ pub fn patch_with(args: PatchRuntimeWith) -> Result<()> { bail!("aws-sdk-rust has a dirty working tree. Aborting."); } - // Make sure the aws-sdk-rust repo is on the correct release tag - let release_tags = step("Resolving aws-sdk-rust release tags", || { - release_tags(&aws_sdk_rust) - })?; - let previous_release_tag = step("Resolving release tag", || { - previous_release_tag( - &aws_sdk_rust, - &release_tags, - args.previous_release_tag.as_deref(), - ) - })?; - step("Checking out release tag", || { - aws_sdk_rust - .git(["checkout", previous_release_tag.as_str()]) - .expect_success_output("check out release tag in aws-sdk-rust") - })?; + if !args.no_checkout_sdk_release { + // Make sure the aws-sdk-rust repo is on the correct release tag + let release_tags = step("Resolving aws-sdk-rust release tags", || { + release_tags(&aws_sdk_rust) + })?; + let previous_release_tag = step("Resolving release tag", || { + previous_release_tag( + &aws_sdk_rust, + &release_tags, + args.previous_release_tag.as_deref(), + ) + })?; + step("Checking out release tag", || { + aws_sdk_rust + .git(["checkout", previous_release_tag.as_str()]) + .expect_success_output("check out release tag in aws-sdk-rust") + })?; + } // Patch the new runtime crates into the old SDK step("Applying version-only dependencies", || { @@ -80,7 +74,7 @@ pub fn patch_with(args: PatchRuntimeWith) -> Result<()> { step("Patching aws-sdk-rust root Cargo.toml", || { let crates_to_patch = remove_unchanged_dependencies(&aws_sdk_rust, &args.runtime_crate_path)?; - patch_workspace_cargo_toml(&aws_sdk_rust, &args.runtime_crate_path, crates_to_patch) + patch_workspace_cargo_toml(&aws_sdk_rust, crates_to_patch) })?; step("Running cargo update", || { aws_sdk_rust @@ -107,19 +101,18 @@ fn apply_version_only_dependencies(aws_sdk_rust: &Repo) -> Result<()> { } /// Determine if a given crate has a new version vs. the release we're comparing -fn crate_version_has_changed( - crate_name: &str, - aws_sdk_rust: &Repo, - runtime_crate_path: &Utf8Path, -) -> Result { +fn crate_version_has_changed(runtime_crate: &Package, aws_sdk_rust: &Repo) -> Result { let sdk_cargo_toml = aws_sdk_rust .root .join("sdk") - .join(crate_name) + .join(&runtime_crate.handle.name) .join("Cargo.toml"); - let to_patch_cargo_toml = runtime_crate_path.join(crate_name).join("Cargo.toml"); + let to_patch_cargo_toml = &runtime_crate.manifest_path; if !sdk_cargo_toml.exists() { - tracing::trace!("`{crate_name}` is a new crate, so there is nothing to patch."); + tracing::trace!( + "`{}` is a new crate, so there is nothing to patch.", + runtime_crate.handle + ); // This is a new runtime crate, so there is nothing to patch. return Ok(false); } @@ -128,25 +121,25 @@ fn crate_version_has_changed( "{:?} did not exist!", to_patch_cargo_toml ); - let sdk_cargo_toml = Manifest::from_path(sdk_cargo_toml).context("could not parse")?; - let to_patch_toml = Manifest::from_path(to_patch_cargo_toml).context("could not parse")?; + let sdk_cargo_toml = Manifest::from_path(&sdk_cargo_toml) + .context("could not parse SDK Cargo.toml") + .context(sdk_cargo_toml)?; + let to_patch_toml = Manifest::from_path(to_patch_cargo_toml) + .context("could not parse Cargo.toml to patch") + .with_context(|| to_patch_cargo_toml.display().to_string())?; Ok(sdk_cargo_toml.package().version() != to_patch_toml.package().version()) } + fn patch_workspace_cargo_toml( aws_sdk_rust: &Repo, - runtime_crate_path: &Utf8Path, - crates_to_patch: impl Iterator, + crates_to_patch: impl Iterator, ) -> Result<()> { let patch_sections = crates_to_patch - .map(|crate_name| { - let path = runtime_crate_path.join(&crate_name); - assert!( - path.exists(), - "tried to reference a crate that did not exist!" - ); + .map(|runtime_crate| { format!( - "{crate_name} = {{ path = '{}' }}", - path.canonicalize_utf8().unwrap() + "{} = {{ path = '{}' }}", + runtime_crate.handle.name, + runtime_crate.crate_path.canonicalize().unwrap().display() ) }) .collect::>() @@ -166,46 +159,54 @@ fn patch_workspace_cargo_toml( /// Removes Path dependencies referring to unchanged crates & returns a list of crates to patch fn remove_unchanged_dependencies( aws_sdk_rust: &Repo, - runtime_crate_path: &Utf8Path, -) -> Result> { - let all_crates = fs::read_dir(runtime_crate_path) - .context(format!( - "could list crates in directory {:?}", - runtime_crate_path - ))? - .map(|dir| dir.unwrap().file_name()) - .map(|osstr| osstr.into_string().expect("invalid utf-8 directory")) - .collect::>(); + runtime_crate_paths: &[Utf8PathBuf], +) -> Result> { + let mut all_crates = Vec::new(); + for runtime_crate_path in runtime_crate_paths { + let read_dir = fs::read_dir(runtime_crate_path).context(format!( + "could list crates in directory {runtime_crate_path:?}" + ))?; + for directory in read_dir { + let path = directory?.path(); + if let Some(runtime_crate) = Package::try_load_path(path)? { + let name = &runtime_crate.handle.name; + if name.starts_with("aws-") && name != "aws-config" { + all_crates.push(runtime_crate); + } + } + } + } let (crates_to_patch, unchanged_crates): (Vec<_>, Vec<_>) = - all_crates.clone().into_iter().partition(|crate_dir| { - crate_version_has_changed(crate_dir, aws_sdk_rust, runtime_crate_path) + all_crates.clone().into_iter().partition(|runtime_crate| { + crate_version_has_changed(runtime_crate, aws_sdk_rust) .expect("failed to determine change-status") }); for patched_crate in &all_crates { - tracing::trace!("removing unchanged path dependencies for {patched_crate}"); - remove_unchanged_path_dependencies(runtime_crate_path, &unchanged_crates, patched_crate)?; + tracing::trace!( + "removing unchanged path dependencies for {}", + patched_crate.handle + ); + remove_unchanged_path_dependencies(&unchanged_crates, patched_crate)?; } - Ok(crates_to_patch - .into_iter() - .filter(|crte| crte.starts_with("aws-"))) + Ok(crates_to_patch.into_iter()) } -/// Remove `path = ...` from the dependency section for unchanged crates +/// Remove `path = ...` from the dependency section for unchanged crates, +/// and add version numbers for those where necessary. /// /// If we leave these path dependencies in, we'll get an error when we try to patch because the /// version numbers are the same. fn remove_unchanged_path_dependencies( - runtime_crate_path: &Utf8Path, - unchanged_crates: &[String], - patched_crate: &String, + unchanged_crates: &[Package], + patched_crate: &Package, ) -> Result<()> { - let path = runtime_crate_path.join(patched_crate).join("Cargo.toml"); - let manifest = Manifest::from_path(&path)?; - let mut mutable_manifest = fs::read_to_string(&path) + let manifest_path = &patched_crate.manifest_path; + let manifest = Manifest::from_path(manifest_path)?; + let mut mutable_manifest = fs::read_to_string(manifest_path) .context("failed to read file") - .context(path.clone())? + .with_context(|| manifest_path.display().to_string())? .parse::() .context("invalid toml in manifest!")?; let mut updates = false; @@ -215,25 +216,37 @@ fn remove_unchanged_path_dependencies( ]; for (deps_set, key) in sections { for (dependency_name, dependency_metadata) in deps_set.iter() { - if unchanged_crates.iter().any(|crate_name| { - crate_name.as_str() + let runtime_crate = unchanged_crates.iter().find(|rt_crate| { + rt_crate.handle.name.as_str() == dependency_metadata .package() .unwrap_or(dependency_name.as_str()) - }) { + }); + if let Some(runtime_crate) = runtime_crate { let it = &mut mutable_manifest[key][dependency_name]; match it.as_table_like_mut() { - Some(table_like) => table_like.remove("path"), - None => { - panic!("crate `{patched_crate}` depends on crate `{dependency_name}` crate by version instead of by path. Please update it to use path dependencies for all runtime crates."); + Some(table_like) => { + table_like.remove("path"); + if !table_like.contains_key("version") { + table_like.insert( + "version", + Item::Value(runtime_crate.handle.expect_version().to_string().into()), + ); + } } + None => panic!( + "crate `{}` depends on crate `{dependency_name}` crate by version instead \ + of by path. Please update it to use path dependencies for all runtime crates.", + patched_crate.handle + ) }; updates = true } } } if updates { - fs::write(&path, mutable_manifest.to_string()).context("failed to write back manifest")? + fs::write(manifest_path, mutable_manifest.to_string()) + .context("failed to write back manifest")? } Ok(()) } diff --git a/tools/ci-build/runtime-versioner/src/main.rs b/tools/ci-build/runtime-versioner/src/main.rs index 853395cb31..e8602cfece 100644 --- a/tools/ci-build/runtime-versioner/src/main.rs +++ b/tools/ci-build/runtime-versioner/src/main.rs @@ -58,6 +58,13 @@ pub struct PatchRuntime { /// Explicitly state the previous release's tag. Discovers it if not provided. #[arg(long)] previous_release_tag: Option, + /// Disable checking out the release tag in the SDK repo. + /// + /// This is useful if you need to test changes in runtime crates against + /// local changes in the SDK. + #[arg(long)] + no_checkout_sdk_release: bool, + /// Version number for stable crates. /// /// Deprecated: this argument is ignored @@ -75,15 +82,24 @@ pub struct PatchRuntimeWith { /// Path to aws-sdk-rust. #[arg(long)] sdk_path: Utf8PathBuf, - /// Path to runtime crates to patch in. + /// Path(s) to runtime crates to patch in. + /// + /// Multiple paths can be passed in, for example, if patching SDK and Smithy + /// runtime crates that are in different directories. /// /// Note: this doesn't need to be a complete set of runtime crates. It will /// only patch the crates included in the provided path. #[arg(long)] - runtime_crate_path: Utf8PathBuf, + runtime_crate_path: Vec, /// Explicitly state the previous release's tag. Discovers it if not provided. #[arg(long)] previous_release_tag: Option, + /// Disable checking out the release tag in the SDK repo. + /// + /// This is useful if you need to test changes in runtime crates against + /// local changes in the SDK. + #[arg(long)] + no_checkout_sdk_release: bool, } #[derive(clap::Parser, Clone)] diff --git a/tools/ci-build/sdk-lints/Cargo.lock b/tools/ci-build/sdk-lints/Cargo.lock index 17071c9c47..d4ed8832b7 100644 --- a/tools/ci-build/sdk-lints/Cargo.lock +++ b/tools/ci-build/sdk-lints/Cargo.lock @@ -19,28 +19,28 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", ] [[package]] @@ -49,22 +49,22 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi 0.1.19", + "hermit-abi", "libc", "winapi", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -89,21 +89,21 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cargo_toml" @@ -112,18 +112,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "802b755090e39835a4b0440fb0bbee0df7495a8b337f63db21e616f7821c7e8c" dependencies = [ "serde", - "toml 0.8.8", + "toml 0.8.12", ] [[package]] -name = "cc" -version = "1.0.83" +name = "cargo_toml" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "a98356df42a2eb1bd8f1793ae4ee4de48e384dd974ce5eac8eee802edb7492be" dependencies = [ - "libc", + "serde", + "toml 0.8.12", ] +[[package]] +name = "cc" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" + [[package]] name = "cfg-if" version = "1.0.0" @@ -187,9 +194,9 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "crates-index" -version = "2.5.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9efa03a974d583ad530bbfe00e3d0021de7f26217120437b128dc4c331aa4f" +checksum = "879bde76e7fb6166c3d36dd2b1e376d012e8b110b52cbec72bf59c40d20ec9fe" dependencies = [ "hex", "home", @@ -202,14 +209,14 @@ dependencies = [ "serde_json", "smol_str", "thiserror", - "toml 0.8.8", + "toml 0.8.12", ] [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -232,9 +239,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "fnv" @@ -322,9 +329,9 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "h2" -version = "0.3.23" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b553656127a00601c8ae5590fcfdc118e4083a7924b6cf4ffc1ea4b99dc429d7" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -332,7 +339,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.1.0", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -366,12 +373,6 @@ dependencies = [ "libc", ] -[[package]] -name = "hermit-abi" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "379dada1584ad501b383485dd706b8afb7a70fcbc7f4da7d780638a5a6124a60" - [[package]] name = "hex" version = "0.4.3" @@ -392,9 +393,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -483,9 +484,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -499,15 +500,15 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -520,27 +521,27 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.152" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "mime" @@ -550,18 +551,18 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", @@ -586,16 +587,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.8", - "libc", -] - [[package]] name = "object" version = "0.32.2" @@ -613,11 +604,11 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl" -version = "0.10.62" +version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cde4d2d9200ad5909f8dac647e29482e07c3a35de8a13fce7c9c7747ad9f671" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.5.0", "cfg-if", "foreign-types", "libc", @@ -634,7 +625,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", ] [[package]] @@ -645,9 +636,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.98" +version = "0.9.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1665caf8ab2dc9aef43d1c0023bd904633a6a05cb30b0ad59bec2ae986e57a7" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" dependencies = [ "cc", "libc", @@ -669,9 +660,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -681,9 +672,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "proc-macro-error" @@ -711,36 +702,27 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "regex" -version = "1.10.2" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", @@ -750,9 +732,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -761,15 +743,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reqwest" -version = "0.11.23" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64", "bytes", @@ -789,9 +771,11 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", "tokio-native-tls", @@ -817,22 +801,31 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", "windows-sys 0.52.0", ] +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64", +] + [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "schannel" @@ -848,7 +841,7 @@ name = "sdk-lints" version = "0.1.0" dependencies = [ "anyhow", - "cargo_toml", + "cargo_toml 0.18.0", "clap", "lazy_static", "serde", @@ -858,9 +851,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -871,9 +864,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" dependencies = [ "core-foundation-sys", "libc", @@ -881,35 +874,35 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.195" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", ] [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "itoa", "ryu", @@ -952,6 +945,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", + "cargo_toml 0.19.2", "crates-index", "lazy_static", "regex", @@ -975,12 +969,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1002,15 +996,21 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "system-configuration" version = "0.5.1" @@ -1034,13 +1034,12 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.9.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", "rustix", "windows-sys 0.52.0", ] @@ -1062,22 +1061,22 @@ checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d" [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", ] [[package]] @@ -1097,15 +1096,14 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.1" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "pin-project-lite", "socket2", "windows-sys 0.48.0", @@ -1147,9 +1145,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.8" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" dependencies = [ "serde", "serde_spanned", @@ -1168,11 +1166,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.21.0" +version = "0.22.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", @@ -1204,7 +1202,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", ] [[package]] @@ -1224,9 +1222,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -1236,9 +1234,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -1283,9 +1281,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1293,24 +1291,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -1320,9 +1318,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1330,28 +1328,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -1403,7 +1401,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.4", ] [[package]] @@ -1423,17 +1421,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] @@ -1444,9 +1442,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" @@ -1456,9 +1454,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" @@ -1468,9 +1466,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" @@ -1480,9 +1478,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" @@ -1492,9 +1490,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" @@ -1504,9 +1502,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" @@ -1516,15 +1514,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winnow" -version = "0.5.34" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16" +checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" dependencies = [ "memchr", ] diff --git a/tools/ci-build/sdk-lints/README.md b/tools/ci-build/sdk-lints/README.md new file mode 100644 index 0000000000..c6f2a0037f --- /dev/null +++ b/tools/ci-build/sdk-lints/README.md @@ -0,0 +1,2 @@ +# sdk-lints +Custom lints and fixes for sdk crates. These are run as part of `pre-commit` and during CI. diff --git a/tools/ci-build/sdk-versioner/Cargo.lock b/tools/ci-build/sdk-versioner/Cargo.lock index 709b9ae162..45d72fb58b 100644 --- a/tools/ci-build/sdk-versioner/Cargo.lock +++ b/tools/ci-build/sdk-versioner/Cargo.lock @@ -28,19 +28,19 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "async-trait" -version = "0.1.78" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -56,15 +56,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -95,21 +95,31 @@ checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "cargo_toml" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "a98356df42a2eb1bd8f1793ae4ee4de48e384dd974ce5eac8eee802edb7492be" +dependencies = [ + "serde", + "toml 0.8.12", +] [[package]] name = "cc" -version = "1.0.90" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" [[package]] name = "cfg-if" @@ -174,9 +184,9 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "crates-index" -version = "2.5.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9efa03a974d583ad530bbfe00e3d0021de7f26217120437b128dc4c331aa4f" +checksum = "879bde76e7fb6166c3d36dd2b1e376d012e8b110b52cbec72bf59c40d20ec9fe" dependencies = [ "hex", "home", @@ -200,9 +210,9 @@ checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -225,9 +235,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "fnv" @@ -315,9 +325,9 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "h2" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -325,7 +335,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.2.5", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -470,9 +480,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.5" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -486,9 +496,9 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" @@ -525,9 +535,9 @@ checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "mime" @@ -611,7 +621,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -622,9 +632,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.101" +version = "0.9.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" dependencies = [ "cc", "libc", @@ -652,9 +662,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -713,18 +723,18 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] [[package]] name = "regex" -version = "1.10.3" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", @@ -745,9 +755,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reqwest" @@ -853,9 +863,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -866,9 +876,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" dependencies = [ "core-foundation-sys", "libc", @@ -897,14 +907,14 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "itoa", "ryu", @@ -947,6 +957,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", + "cargo_toml", "crates-index", "lazy_static", "regex", @@ -997,9 +1008,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.53" +version = "2.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" dependencies = [ "proc-macro2", "quote", @@ -1077,7 +1088,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -1097,9 +1108,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.36.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -1171,7 +1182,7 @@ version = "0.22.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", @@ -1203,7 +1214,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", ] [[package]] @@ -1301,7 +1312,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", "wasm-bindgen-shared", ] @@ -1335,7 +1346,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.58", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1521,9 +1532,9 @@ checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" dependencies = [ "memchr", ] diff --git a/tools/ci-build/sdk-versioner/README.md b/tools/ci-build/sdk-versioner/README.md index 45247fd4c5..987d5de690 100644 --- a/tools/ci-build/sdk-versioner/README.md +++ b/tools/ci-build/sdk-versioner/README.md @@ -7,17 +7,4 @@ within that directory, and modifies dependency lines that point to the AWS Rust or its supporting crates. These dependencies can be updated to be based on file-system path, crates.io version, or both. -Example updating SDK examples to use SDK version 0.5.0 with Smithy version 0.35.0: -```bash -$ sdk-versioner \ - --sdk-version 0.5.0 \ - --smithy-version 0.35.0 \ - path/to/aws-doc-sdk-examples/rustv1 -``` - -Example updating SDK examples to refer to local generated code: -```bash -$ sdk-versioner \ - --sdk-path path/to/smithy-rs/aws/sdk/build/aws-sdk/sdk \ - path/to/aws-doc-sdk-examples/rustv1 -``` +This tool is currently used to update all the dependencies of all examples to refer to the latest SDK version. See [aws/sdk/build.gradle.kts](../../../aws/sdk/build.gradle.kts) for more context. diff --git a/tools/ci-build/smithy-rs-tool-common/Cargo.toml b/tools/ci-build/smithy-rs-tool-common/Cargo.toml index a9cbfa762c..d9fd0093e7 100644 --- a/tools/ci-build/smithy-rs-tool-common/Cargo.toml +++ b/tools/ci-build/smithy-rs-tool-common/Cargo.toml @@ -18,6 +18,7 @@ opt-level = 0 [dependencies] anyhow = "1" async-trait = "0.1.74" +cargo_toml = "0.19.2" crates-index = { version = "2.5.1", features = ["sparse"] } lazy_static = "1" regex = "1.6.0" diff --git a/tools/ci-build/smithy-rs-tool-common/README.md b/tools/ci-build/smithy-rs-tool-common/README.md new file mode 100644 index 0000000000..d69142e571 --- /dev/null +++ b/tools/ci-build/smithy-rs-tool-common/README.md @@ -0,0 +1,2 @@ +# smithy-rs-tool-common +Common shared libraries for runtime tooling diff --git a/tools/ci-build/smithy-rs-tool-common/src/lib.rs b/tools/ci-build/smithy-rs-tool-common/src/lib.rs index 567617de26..27e174d72b 100644 --- a/tools/ci-build/smithy-rs-tool-common/src/lib.rs +++ b/tools/ci-build/smithy-rs-tool-common/src/lib.rs @@ -15,3 +15,6 @@ pub mod release_tag; pub mod retry; pub mod shell; pub mod versions_manifest; + +// https://github.com/aws-sdk-rust-ci +pub const RUST_SDK_CI_OWNER: &str = "aws-sdk-rust-ci"; diff --git a/tools/ci-build/smithy-rs-tool-common/src/package.rs b/tools/ci-build/smithy-rs-tool-common/src/package.rs index 4197099b9b..e6f6a8d239 100644 --- a/tools/ci-build/smithy-rs-tool-common/src/package.rs +++ b/tools/ci-build/smithy-rs-tool-common/src/package.rs @@ -3,7 +3,16 @@ * SPDX-License-Identifier: Apache-2.0 */ +use crate::RUST_SDK_CI_OWNER; +use anyhow::{Context, Result}; +use cargo_toml::{Dependency, DepsSet, Manifest}; +use semver::Version; use serde::{Deserialize, Serialize}; +use std::{ + collections::BTreeSet, + fmt, fs, + path::{Path, PathBuf}, +}; pub const SMITHY_PREFIX: &str = "aws-smithy-"; pub const SDK_PREFIX: &str = "aws-sdk-"; @@ -46,3 +55,291 @@ pub enum PackageStability { Stable, Unstable, } + +/// Information required to identify a package (crate). +#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] +pub struct PackageHandle { + pub name: String, + pub version: Option, +} + +impl PackageHandle { + pub fn new(name: impl Into, version: Option) -> Self { + Self { + name: name.into(), + version, + } + } + + /// Returns the expected owners of the crate. + pub fn expected_owners(&self) -> &[&str] { + expected_owners() + } + + /// Returns the version number or panics + pub fn expect_version(&self) -> &Version { + if let Some(version) = &self.version { + version + } else { + panic!("Crate version number required for {}", self.name) + } + } +} + +impl fmt::Display for PackageHandle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match &self.version { + Some(version) => write!(f, "{}-{version}", self.name), + _ => f.write_str(&self.name), + } + } +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +pub enum Publish { + Allowed, + NotAllowed, +} + +/// Represents a crate (called Package since crate is a reserved word). +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +pub struct Package { + /// Package name and version information + pub handle: PackageHandle, + /// Package category (Generated, SmithyRuntime, AwsRuntime, etc.) + pub category: PackageCategory, + /// Location to the crate on the current file system + pub crate_path: PathBuf, + /// Location to the crate manifest on the current file system + pub manifest_path: PathBuf, + /// Dependencies used by this package + pub local_dependencies: BTreeSet, + /// Whether or not the package should be published + pub publish: Publish, +} + +impl Package { + pub fn new( + handle: PackageHandle, + manifest_path: impl Into, + local_dependencies: BTreeSet, + publish: Publish, + ) -> Self { + let manifest_path = manifest_path.into(); + let category = PackageCategory::from_package_name(&handle.name); + Self { + handle, + category, + crate_path: manifest_path.parent().unwrap().into(), + manifest_path, + local_dependencies, + publish, + } + } + + /// Try to load a package from the given path. + pub fn try_load_path(path: impl AsRef) -> Result> { + let path = path.as_ref(); + let manifest_path = path.join("Cargo.toml"); + if path.is_dir() && manifest_path.exists() { + let manifest = fs::read(&manifest_path) + .context("failed to read manifest") + .with_context(|| format!("{manifest_path:?}"))?; + Self::try_load_manifest(manifest_path, &manifest) + } else { + Ok(None) + } + } + + /// Returns `Ok(None)` when the Cargo.toml is a workspace rather than a package + pub fn try_load_manifest( + manifest_path: impl AsRef, + manifest: &[u8], + ) -> Result> { + let manifest_path = manifest_path.as_ref(); + let mut manifest = Manifest::from_slice(manifest) + .with_context(|| format!("failed to load package manifest for {:?}", manifest_path))?; + manifest.complete_from_path(manifest_path)?; + if let Some(package) = manifest.package { + let name = package.name; + let version = parse_version(manifest_path, &package.version.unwrap())?; + let handle = PackageHandle { + name, + version: Some(version), + }; + let publish = match package.publish.unwrap() { + cargo_toml::Publish::Flag(true) => Publish::Allowed, + _ => Publish::NotAllowed, + }; + + let mut local_dependencies = BTreeSet::new(); + local_dependencies.extend(read_dependencies(manifest_path, &manifest.dependencies)?); + local_dependencies.extend(read_dependencies( + manifest_path, + &manifest.dev_dependencies, + )?); + local_dependencies.extend(read_dependencies( + manifest_path, + &manifest.build_dependencies, + )?); + Ok(Some(Package::new( + handle, + manifest_path, + local_dependencies, + publish, + ))) + } else { + Ok(None) + } + } + + /// Returns `true` if this package depends on `other` + pub fn locally_depends_on(&self, other: &PackageHandle) -> bool { + self.local_dependencies.contains(other) + } + + /// Returns the expected owners of the crate. + pub fn expected_owners(&self) -> &[&str] { + expected_owners() + } +} + +fn expected_owners() -> &'static [&'static str] { + &[RUST_SDK_CI_OWNER] +} + +/// Parses a semver version number and adds additional error context when parsing fails. +pub fn parse_version(manifest_path: &Path, version: &str) -> Result { + Version::parse(version) + .with_context(|| format!("Invalid crate version {version} in {manifest_path:?}.")) +} + +fn read_dependencies(path: &Path, dependencies: &DepsSet) -> Result> { + let mut result = Vec::new(); + for (name, metadata) in dependencies { + match metadata { + Dependency::Simple(_) => {} + Dependency::Detailed(detailed) => { + if detailed.path.is_some() { + let version = detailed + .version + .as_ref() + .map(|version| parse_version(path, version)) + .transpose()?; + result.push(PackageHandle::new(name, version)); + } + } + Dependency::Inherited(_) => panic!("workspace deps are unsupported"), + } + } + Ok(result) +} + +#[cfg(test)] +mod tests { + use super::*; + use semver::Version; + + fn version(version: &str) -> Option { + Some(Version::parse(version).unwrap()) + } + + #[test] + fn try_load_manifest_success() { + let manifest = br#" + [package] + name = "test" + version = "1.2.0-preview" + + [build-dependencies] + build_something = "1.3" + local_build_something = { version = "0.2.0", path = "../local_build_something" } + + [dev-dependencies] + dev_something = "1.1" + local_dev_something = { version = "0.1.0", path = "../local_dev_something" } + + [dependencies] + something = "1.0" + local_something = { version = "1.1.3", path = "../local_something" } + "#; + let path: PathBuf = "test/Cargo.toml".into(); + + let package = Package::try_load_manifest(&path, manifest) + .expect("parse success") + .expect("is a package"); + assert_eq!("test", package.handle.name); + assert_eq!(version("1.2.0-preview"), package.handle.version); + + let mut expected = BTreeSet::new(); + expected.insert(PackageHandle::new( + "local_build_something", + version("0.2.0"), + )); + expected.insert(PackageHandle::new("local_dev_something", version("0.1.0"))); + expected.insert(PackageHandle::new("local_something", version("1.1.3"))); + assert_eq!(expected, package.local_dependencies); + } + + #[test] + fn try_load_manifest_version_requirement_invalid() { + let manifest = br#" + [package] + name = "test" + version = "1.2.0-preview" + + [dependencies] + local_something = { version = "1.0", path = "../local_something" } + "#; + let path: PathBuf = "test/Cargo.toml".into(); + + let error = format!( + "{}", + Package::try_load_manifest(&path, manifest).expect_err("should fail") + ); + assert!( + error.contains("Invalid crate version"), + "'{}' should contain 'Invalid crate version'", + error + ); + } + + fn package(name: &str, dependencies: &[&str]) -> Package { + Package::new( + PackageHandle::new(name, version("1.0.0")), + format!("{}/Cargo.toml", name), + dependencies + .iter() + .map(|d| PackageHandle::new(*d, version("1.0.0"))) + .collect(), + Publish::Allowed, + ) + } + + #[test] + fn test_expected_package_owners_server_crate() { + let server_packages = vec![ + package("aws-smithy-http-server", &[]), + package("aws-smithy-http-server-python", &[]), + package("aws-smithy-http-server-typescript", &[]), + ]; + for pkg in server_packages { + assert_eq!(&["aws-sdk-rust-ci"], pkg.expected_owners()); + } + } + + #[test] + fn test_expected_package_owners_sdk_crate() { + let sdk_package = package("aws-types", &[]); + assert_eq!(&["aws-sdk-rust-ci"], sdk_package.expected_owners()); + } + + #[test] + fn test_expected_package_owners_smithy_runtime_crate() { + let smithy_runtime_package = package("aws-smithy-types", &[]); + assert_eq!( + &["aws-sdk-rust-ci"], + smithy_runtime_package.expected_owners() + ); + } +} diff --git a/tools/ci-cdk/canary-runner/Cargo.lock b/tools/ci-cdk/canary-runner/Cargo.lock index 043ed5ae84..5132e7f6dc 100644 --- a/tools/ci-cdk/canary-runner/Cargo.lock +++ b/tools/ci-cdk/canary-runner/Cargo.lock @@ -17,15 +17,34 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "android-tzdata" version = "0.1.1" @@ -43,30 +62,30 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "async-recursion" -version = "1.0.5" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" +checksum = "30c5ef0ede93efbf733c1a727f3b6b5a1060bbedd5600183e66f6e4be4af0ec5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", ] [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", ] [[package]] @@ -82,18 +101,17 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "aws-config" -version = "1.0.3" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "004dc45f6b869e6a70725df448004a720b7f52f6607d55d8815cbd5448f86def" +checksum = "48730d0b4c3d91c43d0d37168831d9fd0e065ad4a889a2ee9faf8d34c3d2804d" dependencies = [ "aws-credential-types", - "aws-http", "aws-runtime", "aws-sdk-sso", "aws-sdk-ssooidc", @@ -108,20 +126,21 @@ dependencies = [ "bytes", "fastrand", "hex", - "http", + "http 0.2.12", "hyper", - "ring 0.17.7", + "ring 0.17.8", "time", "tokio", "tracing", + "url", "zeroize", ] [[package]] name = "aws-credential-types" -version = "1.0.3" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfa51c87f10211f37cd78e6d01d6f18b3f96a086906ed361d11e04ac53e29508" +checksum = "fa8587ae17c8e967e4b05a62d495be2fb7701bec52a97f7acfe8a29f938384c8" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", @@ -129,30 +148,13 @@ dependencies = [ "zeroize", ] -[[package]] -name = "aws-http" -version = "0.60.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "361c4310fdce94328cc2d1ca0c8a48c13f43009c61d3367585685a50ca8c66b6" -dependencies = [ - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "http", - "http-body", - "pin-project-lite", - "tracing", -] - [[package]] name = "aws-runtime" -version = "1.0.3" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce0953f7fc1c4428511345e28ea3e98c8b59c9e91eafae30bf76d71d70642693" +checksum = "c4ee6903f9d0197510eb6b44c4d86b493011d08b4992938f7b9be0333b6685aa" dependencies = [ "aws-credential-types", - "aws-http", "aws-sigv4", "aws-smithy-async", "aws-smithy-eventstream", @@ -160,21 +162,23 @@ dependencies = [ "aws-smithy-runtime-api", "aws-smithy-types", "aws-types", + "bytes", "fastrand", - "http", + "http 0.2.12", + "http-body 0.4.6", "percent-encoding", + "pin-project-lite", "tracing", "uuid", ] [[package]] name = "aws-sdk-cloudwatch" -version = "1.4.0" +version = "1.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7b55285ad9dde6bcb462e444cc98bd1918a566e035c35b8269d4e6b976f9994" +checksum = "ef91bf8677b736ef33c00ff4c548ce053989c15b38f53a1fa40cf69bd59a8144" dependencies = [ "aws-credential-types", - "aws-http", "aws-runtime", "aws-smithy-async", "aws-smithy-http", @@ -185,21 +189,22 @@ dependencies = [ "aws-smithy-types", "aws-smithy-xml", "aws-types", - "http", - "regex", + "http 0.2.12", + "once_cell", + "regex-lite", "tracing", ] [[package]] name = "aws-sdk-lambda" -version = "1.4.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66f1a1b5fdd170f38b740c88e955d7e1bb18b6a2f09487da0fbae0b5918d017b" +checksum = "36c82b5020292136599390eb0a481f4164ed3214f0d44cb222f626b01a00ce69" dependencies = [ "aws-credential-types", - "aws-http", "aws-runtime", "aws-smithy-async", + "aws-smithy-eventstream", "aws-smithy-http", "aws-smithy-json", "aws-smithy-runtime", @@ -207,19 +212,20 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", - "http", - "regex", + "http 0.2.12", + "once_cell", + "regex-lite", "tracing", ] [[package]] name = "aws-sdk-s3" -version = "1.5.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "959a7325827d882819a2ac77e27e26626b9713b9cfec44686785e0db6e73388f" +checksum = "644c5939c1b78097d37f3341708978d68490070d4b0f8fa91f0878678c06a7ef" dependencies = [ + "ahash", "aws-credential-types", - "aws-http", "aws-runtime", "aws-sigv4", "aws-smithy-async", @@ -233,23 +239,27 @@ dependencies = [ "aws-smithy-xml", "aws-types", "bytes", - "http", - "http-body", + "fastrand", + "hex", + "hmac", + "http 0.2.12", + "http-body 0.4.6", + "lru", "once_cell", "percent-encoding", - "regex", + "regex-lite", + "sha2", "tracing", "url", ] [[package]] name = "aws-sdk-sso" -version = "1.4.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e0b81eaef9eb951061b5a58f660815430e3f04eacaa4b2318e7474b0b7cbf17" +checksum = "b2be5ba83b077b67a6f7a1927eb6b212bf556e33bd74b5eaa5aa6e421910803a" dependencies = [ "aws-credential-types", - "aws-http", "aws-runtime", "aws-smithy-async", "aws-smithy-http", @@ -259,19 +269,19 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", - "http", - "regex", + "http 0.2.12", + "once_cell", + "regex-lite", "tracing", ] [[package]] name = "aws-sdk-ssooidc" -version = "1.4.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e322a916694038a7972a3bb12181151c1645914443a2c3be6379b27533bbb99" +checksum = "022ca669825f841aef17b12d4354ef2b8651e4664be49f2d9ea13e4062a80c9f" dependencies = [ "aws-credential-types", - "aws-http", "aws-runtime", "aws-smithy-async", "aws-smithy-http", @@ -281,19 +291,19 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", - "http", - "regex", + "http 0.2.12", + "once_cell", + "regex-lite", "tracing", ] [[package]] name = "aws-sdk-sts" -version = "1.4.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbee86e8d9b1be709bd0f38b9ab3f196e39b0b6f3262a0a919a9d30f25debd94" +checksum = "8e4a5f5cb007347c1ab34a6d56456301dfada921fc9e57d687ecb08baddd11ff" dependencies = [ "aws-credential-types", - "aws-http", "aws-runtime", "aws-smithy-async", "aws-smithy-http", @@ -304,16 +314,17 @@ dependencies = [ "aws-smithy-types", "aws-smithy-xml", "aws-types", - "http", - "regex", + "http 0.2.12", + "once_cell", + "regex-lite", "tracing", ] [[package]] name = "aws-sigv4" -version = "1.0.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bcbad6e0f130232b22e4b4e28834348ce5b79c23b5059b387c08fd0dc8f876" +checksum = "11d6f29688a4be9895c0ba8bef861ad0c0dac5c15e9618b9b7a6c233990fc263" dependencies = [ "aws-credential-types", "aws-smithy-eventstream", @@ -325,12 +336,12 @@ dependencies = [ "form_urlencoded", "hex", "hmac", - "http", + "http 0.2.12", + "http 1.1.0", "once_cell", "p256", "percent-encoding", - "regex", - "ring 0.17.7", + "ring 0.17.8", "sha2", "subtle", "time", @@ -340,9 +351,9 @@ dependencies = [ [[package]] name = "aws-smithy-async" -version = "1.0.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573441a5a0219e436e86a7f9a20b0f2505c5ae6fe7fe3eba6e3950991c9ad914" +checksum = "62220bc6e97f946ddd51b5f1361f78996e704677afc518a4ff66b7a72ea1378c" dependencies = [ "futures-util", "pin-project-lite", @@ -351,9 +362,9 @@ dependencies = [ [[package]] name = "aws-smithy-checksums" -version = "0.60.0" +version = "0.60.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5a373ec01aede3dd066ec018c1bc4e8f5dd11b2c11c59c8eef1a5c68101f397" +checksum = "83fa43bc04a6b2441968faeab56e68da3812f978a670a5db32accbdcafddd12f" dependencies = [ "aws-smithy-http", "aws-smithy-types", @@ -361,8 +372,8 @@ dependencies = [ "crc32c", "crc32fast", "hex", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "md-5", "pin-project-lite", "sha1", @@ -372,9 +383,9 @@ dependencies = [ [[package]] name = "aws-smithy-eventstream" -version = "0.60.0" +version = "0.60.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c669e1e5fc0d79561bf7a122b118bd50c898758354fe2c53eb8f2d31507cbc3" +checksum = "e6363078f927f612b970edf9d1903ef5cef9a64d1e8423525ebb1f0a1633c858" dependencies = [ "aws-smithy-types", "bytes", @@ -383,9 +394,9 @@ dependencies = [ [[package]] name = "aws-smithy-http" -version = "0.60.0" +version = "0.60.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b1de8aee22f67de467b2e3d0dd0fb30859dc53f579a63bd5381766b987db644" +checksum = "3f10fa66956f01540051b0aa7ad54574640f748f9839e843442d99b970d3aff9" dependencies = [ "aws-smithy-eventstream", "aws-smithy-runtime-api", @@ -393,8 +404,8 @@ dependencies = [ "bytes", "bytes-utils", "futures-core", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "once_cell", "percent-encoding", "pin-project-lite", @@ -404,18 +415,18 @@ dependencies = [ [[package]] name = "aws-smithy-json" -version = "0.60.0" +version = "0.60.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a46dd338dc9576d6a6a5b5a19bd678dcad018ececee11cf28ecd7588bd1a55c" +checksum = "4683df9469ef09468dad3473d129960119a0d3593617542b7d52086c8486f2d6" dependencies = [ "aws-smithy-types", ] [[package]] name = "aws-smithy-query" -version = "0.60.0" +version = "0.60.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feb5b8c7a86d4b6399169670723b7e6f21a39fc833a30f5c5a2f997608178129" +checksum = "f2fbd61ceb3fe8a1cb7352e42689cec5335833cd9f94103a61e98f9bb61c64bb" dependencies = [ "aws-smithy-types", "urlencoding", @@ -423,9 +434,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.0.3" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0c628feae802ab1589936e2aaef6f8ab2b8fc1ee1f947c276dd8a7c3cda1904" +checksum = "de34bcfa1fb3c82a80e252a753db34a6658e07f23d3a5b3fc96919518fa7a3f5" dependencies = [ "aws-smithy-async", "aws-smithy-http", @@ -434,8 +445,9 @@ dependencies = [ "bytes", "fastrand", "h2", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", + "http-body 1.0.0", "hyper", "hyper-rustls", "once_cell", @@ -448,14 +460,15 @@ dependencies = [ [[package]] name = "aws-smithy-runtime-api" -version = "1.0.3" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7460e5cc8e6eb0749608535854352f6e121433960ba05daf4dbde0e42c1199a5" +checksum = "4cc56a5c96ec741de6c5e6bf1ce6948be969d6506dfa9c39cffc284e31e4979b" dependencies = [ "aws-smithy-async", "aws-smithy-types", "bytes", - "http", + "http 0.2.12", + "http 1.1.0", "pin-project-lite", "tokio", "tracing", @@ -464,16 +477,19 @@ dependencies = [ [[package]] name = "aws-smithy-types" -version = "1.0.3" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ba838f43d0d72d76918895a93c3ad647f75a058541a60e85beefb6bb0a9bd40" +checksum = "abe14dceea1e70101d38fbf2a99e6a34159477c0fb95e68e05c66bd7ae4c3729" dependencies = [ "base64-simd", "bytes", "bytes-utils", "futures-core", - "http", - "http-body", + "http 0.2.12", + "http 1.1.0", + "http-body 0.4.6", + "http-body 1.0.0", + "http-body-util", "itoa", "num-integer", "pin-project-lite", @@ -487,33 +503,33 @@ dependencies = [ [[package]] name = "aws-smithy-xml" -version = "0.60.0" +version = "0.60.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec40d74a67fd395bc3f6b4ccbdf1543672622d905ef3f979689aea5b730cb95" +checksum = "872c68cf019c0e4afc5de7753c4f7288ce4b71663212771bf5e4542eb9346ca9" dependencies = [ "xmlparser", ] [[package]] name = "aws-types" -version = "1.0.3" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faa59f6f26a3472ca2ce7e7802d037a0a9a7ac23de5761eadd9b68f31ac4fd21" +checksum = "afb278e322f16f59630a83b6b2dc992a0b48aa74ed47b4130f193fae0053d713" dependencies = [ "aws-credential-types", "aws-smithy-async", "aws-smithy-runtime-api", "aws-smithy-types", - "http", + "http 0.2.12", "rustc_version", "tracing", ] [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -538,9 +554,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64-simd" @@ -566,9 +582,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "block-buffer" @@ -581,9 +597,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byteorder" @@ -593,9 +609,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" dependencies = [ "serde", ] @@ -639,14 +655,21 @@ dependencies = [ ] [[package]] -name = "cc" -version = "1.0.83" +name = "cargo_toml" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "a98356df42a2eb1bd8f1793ae4ee4de48e384dd974ce5eac8eee802edb7492be" dependencies = [ - "libc", + "serde", + "toml 0.8.12", ] +[[package]] +name = "cc" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" + [[package]] name = "cfg-if" version = "1.0.0" @@ -655,15 +678,15 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", "serde", - "windows-targets 0.48.5", + "windows-targets 0.52.4", ] [[package]] @@ -707,9 +730,9 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "core-foundation" @@ -729,22 +752,22 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] [[package]] name = "crates-index" -version = "2.5.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9efa03a974d583ad530bbfe00e3d0021de7f26217120437b128dc4c331aa4f" +checksum = "879bde76e7fb6166c3d36dd2b1e376d012e8b110b52cbec72bf59c40d20ec9fe" dependencies = [ "hex", "home", - "http", + "http 0.2.12", "memchr", "rustc-hash", "semver", @@ -753,35 +776,32 @@ dependencies = [ "serde_json", "smol_str", "thiserror", - "toml 0.8.10", + "toml 0.8.12", ] [[package]] name = "crc32c" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8f48d60e5b4d2c53d5c2b1d8a58c849a70ae5e5509b08a48d047e3b65714a74" +checksum = "89254598aa9b9fa608de44b3ae54c810f0f06d755e24c50177f1f8f31ff50ce2" dependencies = [ "rustc_version", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crypto-bigint" @@ -827,9 +847,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", ] @@ -853,9 +873,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "ecdsa" @@ -871,9 +891,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "elliptic-curve" @@ -897,9 +917,9 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -922,9 +942,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "ff" @@ -978,9 +998,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -993,9 +1013,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1003,15 +1023,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -1020,38 +1040,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", ] [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -1077,9 +1097,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", "js-sys", @@ -1107,17 +1127,17 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.22" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", - "http", - "indexmap 2.1.0", + "http 0.2.12", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -1135,6 +1155,10 @@ name = "hashbrown" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", + "allocator-api2", +] [[package]] name = "heck" @@ -1153,9 +1177,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -1186,9 +1210,20 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -1197,12 +1232,35 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http 1.1.0", + "http-body 1.0.0", "pin-project-lite", ] @@ -1220,22 +1278,22 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", "h2", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2", "tokio", "tower-service", "tracing", @@ -1249,7 +1307,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http", + "http 0.2.12", "hyper", "log", "rustls", @@ -1273,9 +1331,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1316,9 +1374,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -1344,15 +1402,15 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1363,7 +1421,7 @@ version = "8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "pem", "ring 0.16.20", "serde", @@ -1379,15 +1437,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" @@ -1401,13 +1459,22 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" dependencies = [ "serde", ] +[[package]] +name = "lru" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +dependencies = [ + "hashbrown 0.14.3", +] + [[package]] name = "matchers" version = "0.1.0" @@ -1435,9 +1502,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "mime" @@ -1457,18 +1524,18 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", @@ -1514,21 +1581,26 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] @@ -1539,15 +1611,15 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.3", + "hermit-abi 0.3.9", "libc", ] [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -1562,7 +1634,7 @@ dependencies = [ "async-trait", "bytes", "chrono", - "http", + "http 0.2.12", "jsonwebtoken", "log", "mime", @@ -1587,17 +1659,17 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl" -version = "0.10.61" +version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b8419dc8cc6d866deb801274bba2e6f8f6108c1bb7fcc10ee5ab864931dbb45" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.5.0", "cfg-if", "foreign-types", "libc", @@ -1614,7 +1686,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", ] [[package]] @@ -1625,9 +1697,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.97" +version = "0.9.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3eaad34cdd97d81de97964fc7f29e2d104f483840d906ef56daa1912338460b" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" dependencies = [ "cc", "libc", @@ -1718,7 +1790,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3687fe9debbbf2a019f381a8bc6b42049b22647449b39af54b3013985c0cf6de" dependencies = [ - "http", + "http 0.2.12", "lazy_static", "regex", ] @@ -1740,9 +1812,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -1762,9 +1834,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "powerfmt" @@ -1814,18 +1886,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -1880,14 +1952,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.3", - "regex-syntax 0.8.2", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", ] [[package]] @@ -1901,15 +1973,21 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] +[[package]] +name = "regex-lite" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b661b2f27137bdbc16f00eda72866a92bb28af1753ffbd56744fb6e2e9cd8e" + [[package]] name = "regex-syntax" version = "0.6.29" @@ -1918,24 +1996,24 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reqwest" -version = "0.11.22" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", "futures-util", "h2", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "hyper", "hyper-rustls", "hyper-tls", @@ -1953,6 +2031,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", "tokio-native-tls", @@ -1980,13 +2059,13 @@ dependencies = [ [[package]] name = "reqwest-middleware" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88a3e86aa6053e59030e7ce2d2a3b258dd08fc2d337d52f73f6cb480f5858690" +checksum = "5a735987236a8e238bf0296c7e351b999c188ccc11477f311b82b55c93984216" dependencies = [ "anyhow", "async-trait", - "http", + "http 0.2.12", "reqwest", "serde", "task-local-extensions", @@ -2004,7 +2083,7 @@ dependencies = [ "chrono", "futures", "getrandom", - "http", + "http 0.2.12", "hyper", "parking_lot 0.11.2", "reqwest", @@ -2018,9 +2097,9 @@ dependencies = [ [[package]] name = "reqwest-tracing" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b1e66540e0cac90acadaf7109bf99c90d95abcc94b4c096bfa16a2d7aa7a71" +checksum = "190838e54153d7a7e2ea98851304b3ce92daeabf14c54d32b01b84a3e636f683" dependencies = [ "anyhow", "async-trait", @@ -2071,16 +2150,17 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", "spin 0.9.8", "untrusted 0.9.0", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2106,11 +2186,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.26" +version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9470c4bf8246c8daf25f9598dca807fb6510347b1e1cfa55749113850c79d88a" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -2119,12 +2199,12 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.9" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", - "ring 0.17.7", + "ring 0.17.8", "rustls-webpki", "sct", ] @@ -2147,7 +2227,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", ] [[package]] @@ -2156,23 +2236,23 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.7", + "ring 0.17.8", "untrusted 0.9.0", ] [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2215,7 +2295,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.7", + "ring 0.17.8", "untrusted 0.9.0", ] @@ -2235,9 +2315,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -2248,9 +2328,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" dependencies = [ "core-foundation-sys", "libc", @@ -2258,28 +2338,28 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", ] [[package]] @@ -2295,9 +2375,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "itoa", "ryu", @@ -2398,9 +2478,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smithy-rs-tool-common" @@ -2408,6 +2488,7 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", + "cargo_toml", "crates-index", "lazy_static", "regex", @@ -2432,22 +2513,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2497,15 +2568,21 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "system-configuration" version = "0.5.1" @@ -2538,57 +2615,56 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.1" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.4.1", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "termcolor" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "textwrap" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -2596,12 +2672,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", + "num-conv", "powerfmt", "serde", "time-core", @@ -2616,10 +2693,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] @@ -2640,9 +2718,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.34.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -2652,7 +2730,7 @@ dependencies = [ "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.5", + "socket2", "tokio-macros", "windows-sys 0.48.0", ] @@ -2665,7 +2743,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", ] [[package]] @@ -2714,9 +2792,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.10" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" dependencies = [ "serde", "serde_spanned", @@ -2735,11 +2813,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.6" +version = "0.22.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" +checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", @@ -2771,7 +2849,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", ] [[package]] @@ -2815,9 +2893,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" @@ -2836,9 +2914,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -2848,9 +2926,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -2887,9 +2965,9 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] name = "uuid" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ "getrandom", "serde", @@ -2936,9 +3014,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2946,24 +3024,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -2973,9 +3051,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2983,22 +3061,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.58", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wasm-timer" @@ -3017,9 +3095,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -3027,9 +3105,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.3" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "winapi" @@ -3064,11 +3142,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.5", + "windows-targets 0.52.4", ] [[package]] @@ -3086,7 +3164,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.4", ] [[package]] @@ -3106,17 +3184,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] @@ -3127,9 +3205,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" @@ -3139,9 +3217,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" @@ -3151,9 +3229,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" @@ -3163,9 +3241,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" @@ -3175,9 +3253,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" @@ -3187,9 +3265,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" @@ -3199,15 +3277,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" dependencies = [ "memchr", ] @@ -3234,6 +3312,26 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + [[package]] name = "zeroize" version = "1.7.0" diff --git a/tools/ci-cdk/canary-runner/src/run.rs b/tools/ci-cdk/canary-runner/src/run.rs index c138c7699d..28421a8b02 100644 --- a/tools/ci-cdk/canary-runner/src/run.rs +++ b/tools/ci-cdk/canary-runner/src/run.rs @@ -153,15 +153,42 @@ impl Options { lambda_execution_role_arn: String, } #[derive(Deserialize)] - struct Outer { + enum Outer { #[serde(rename = "aws-sdk-rust-canary-stack")] - inner: Inner, + AwsSdkRust { + #[serde(flatten)] + aws_sdk_rust_canary_stack: Inner, + }, + #[serde(rename = "smithy-rs-canary-stack")] + SmithyRs { + #[serde(flatten)] + smithy_rs_canary_stack: Inner, + }, + } + impl Outer { + fn into_inner(self) -> Inner { + match self { + Outer::AwsSdkRust { + aws_sdk_rust_canary_stack, + } => aws_sdk_rust_canary_stack, + Outer::SmithyRs { + smithy_rs_canary_stack, + } => smithy_rs_canary_stack, + } + } } let value: Outer = serde_json::from_reader( std::fs::File::open(cdk_output).context("open cdk output")?, ) .context("read cdk output")?; + let Inner { + lambda_code_s3_bucket_name, + lambda_test_s3_bucket_name, + lambda_test_s3_mrap_bucket_arn, + lambda_test_s3_express_bucket_name, + lambda_execution_role_arn, + } = value.into_inner(); Ok(Options { rust_version: run_opt.rust_version, sdk_release_tag: run_opt.sdk_release_tag, @@ -171,11 +198,11 @@ impl Options { lambda_function_memory_size_in_mb: run_opt .lambda_function_memory_size_in_mb .unwrap_or(DEFAULT_LAMBDA_FUNCTION_MEMORY_SIZE_IN_MB), - lambda_code_s3_bucket_name: value.inner.lambda_code_s3_bucket_name, - lambda_test_s3_bucket_name: value.inner.lambda_test_s3_bucket_name, - lambda_test_s3_mrap_bucket_arn: value.inner.lambda_test_s3_mrap_bucket_arn, - lambda_test_s3_express_bucket_name: value.inner.lambda_test_s3_express_bucket_name, - lambda_execution_role_arn: value.inner.lambda_execution_role_arn, + lambda_code_s3_bucket_name, + lambda_test_s3_bucket_name, + lambda_test_s3_mrap_bucket_arn, + lambda_test_s3_express_bucket_name, + lambda_execution_role_arn, }) } else { Ok(Options { diff --git a/tools/ci-cdk/package-lock.json b/tools/ci-cdk/package-lock.json index ecdc4a10dd..3413afa1c6 100644 --- a/tools/ci-cdk/package-lock.json +++ b/tools/ci-cdk/package-lock.json @@ -8,7 +8,8 @@ "name": "ci-cdk", "version": "0.1.0", "bin": { - "rust-sdk-ci-cdk": "bin/ci-cdk.js" + "aws-rust-sdk-canary": "bin/aws-sdk-rust/canary.js", + "smithy-rs-ci-cdk": "bin/smithy-rs/ci-cdk.js" }, "devDependencies": { "@types/jest": "^27.0.0", @@ -63,9 +64,9 @@ "dev": true }, "node_modules/@aws-cdk/asset-node-proxy-agent-v6": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.0.1.tgz", - "integrity": "sha512-DDt4SLdLOwWCjGtltH4VCST7hpOI5DzieuhGZsBpZ+AgJdSI2GCjklCXm0GCTwJG/SolkL5dtQXyUKgg9luBDg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.0.3.tgz", + "integrity": "sha512-twhuEG+JPOYCYPx/xy5uH2+VUsIEhPTzDY0F1KuB+ocjWWB/KEDiOVL19nHvbPCB6fhWnkykXEMJ4HHcKvjtvg==", "dev": true }, "node_modules/@babel/code-frame": { @@ -82,27 +83,27 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.1.tgz", - "integrity": "sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", + "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz", - "integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", + "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.1", + "@babel/generator": "^7.24.4", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.1", - "@babel/parser": "^7.24.1", + "@babel/helpers": "^7.24.4", + "@babel/parser": "^7.24.4", "@babel/template": "^7.24.0", "@babel/traverse": "^7.24.1", "@babel/types": "^7.24.0", @@ -136,9 +137,9 @@ } }, "node_modules/@babel/generator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", - "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", + "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", "dev": true, "dependencies": { "@babel/types": "^7.24.0", @@ -301,9 +302,9 @@ } }, "node_modules/@babel/helpers": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz", - "integrity": "sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz", + "integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==", "dev": true, "dependencies": { "@babel/template": "^7.24.0", @@ -401,9 +402,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", - "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", + "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -744,9 +745,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { @@ -1208,9 +1209,9 @@ } }, "node_modules/@tsconfig/node10": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.10.tgz", - "integrity": "sha512-PiaIWIoPvO6qm6t114ropMCagj6YAF24j9OkCA2mJDXFnlionEwhsBCJ8yek4aib575BI3OkART/90WsgHgLWw==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", "dev": true }, "node_modules/@tsconfig/node12": { @@ -1733,9 +1734,9 @@ "dev": true }, "node_modules/aws-cdk": { - "version": "2.133.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.133.0.tgz", - "integrity": "sha512-EwH8VgQQ8ODeMwjE3p+WhbcbWNkCbvuJJl+Py9IB5znGf7GwLcEmOu4YWBsBGPVu41SXbSAf36twMBrJytCFZA==", + "version": "2.135.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.135.0.tgz", + "integrity": "sha512-id/kBxDvXQhcPYhkP/3fwhaKN0uD3raz1Z4RZcO9jJ4UoQV2RElQl+dYdmIrwNSoNVhtZeV1O4IdEtBHUhdShQ==", "dev": true, "bin": { "cdk": "bin/cdk" @@ -1748,9 +1749,9 @@ } }, "node_modules/aws-cdk-lib": { - "version": "2.133.0", - "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.133.0.tgz", - "integrity": "sha512-5/ezv8Ir2xyz3myeXQcODwrjVRN/cDD2OpBwU/ySFBe+uNac25OoHfTXwUPwE7oLj9qetSt6/i1QvY2iIs6yiQ==", + "version": "2.135.0", + "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.135.0.tgz", + "integrity": "sha512-0RcmhPqJyMFgXqjESv+LilL7TfOQ7uZ4G125hp5/sSoaM7IFz/L3KDAUKVW/01rrebOQo0NZR9M7WIU3JJ7ezQ==", "bundleDependencies": [ "@balena/dockerignore", "case", @@ -1778,7 +1779,7 @@ "minimatch": "^3.1.2", "punycode": "^2.3.1", "semver": "^7.6.0", - "table": "^6.8.1", + "table": "^6.8.2", "yaml": "1.10.2" }, "engines": { @@ -2097,7 +2098,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/table": { - "version": "6.8.1", + "version": "6.8.2", "dev": true, "inBundle": true, "license": "BSD-3-Clause", @@ -2349,9 +2350,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001600", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001600.tgz", - "integrity": "sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==", + "version": "1.0.30001605", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001605.tgz", + "integrity": "sha512-nXwGlFWo34uliI9z3n6Qc0wZaf7zaZWA1CPZ169La5mV3I/gem7bst0vr5XQH5TJXZIMfDeZyOrZnSlVzKxxHQ==", "dev": true, "funding": [ { @@ -2677,9 +2678,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.716", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.716.tgz", - "integrity": "sha512-t/MXMzFKQC3UfMDpw7V5wdB/UAB8dWx4hEsy+fpPYJWW3gqh3u5T1uXp6vR+H6dGCPBxkRo+YBcapBLvbGQHRw==", + "version": "1.4.725", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.725.tgz", + "integrity": "sha512-OGkMXLY7XH6ykHE5ZOVVIMHaGAvvxqw98cswTKB683dntBJre7ufm9wouJ0ExDm0VXhHenU8mREvxIbV5nNoVQ==", "dev": true }, "node_modules/emittery": { diff --git a/tools/ci-scripts/check-aws-sdk-standalone-integration-tests b/tools/ci-scripts/check-aws-sdk-standalone-integration-tests index 9ba41631dc..cf843112e8 100755 --- a/tools/ci-scripts/check-aws-sdk-standalone-integration-tests +++ b/tools/ci-scripts/check-aws-sdk-standalone-integration-tests @@ -42,7 +42,7 @@ cargo check --tests --all-features # Running WebAssembly (WASI) specific integration tests pushd "${tmp_dir}/aws/sdk/integration-tests/webassembly" &>/dev/null -cargo check --tests --all-features +cargo check --tests --all-features --all-targets popd popd diff --git a/tools/ci-scripts/generate-aws-sdk-for-canary b/tools/ci-scripts/generate-aws-sdk-for-canary new file mode 100755 index 0000000000..1d5d8bdf88 --- /dev/null +++ b/tools/ci-scripts/generate-aws-sdk-for-canary @@ -0,0 +1,14 @@ +#!/bin/bash +# +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +# + +set -eux + +cd smithy-rs + +# Generate only SDKs used by canary (see BASE_MANIFEST in build_bundle.rs of canary-runner) +./gradlew -Paws.services=+ec2,+s3,+sso,+ssooidc,+sts,+transcribestreaming :aws:sdk:assemble + +mv aws/sdk/build/aws-sdk ../artifacts/ diff --git a/tools/ci-scripts/run-canary b/tools/ci-scripts/run-canary new file mode 100755 index 0000000000..ef1ec14954 --- /dev/null +++ b/tools/ci-scripts/run-canary @@ -0,0 +1,23 @@ +#!/bin/bash +# +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +# + +set -eux + +CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME=$1 +export AWS_ACCESS_KEY_ID=$2 +export AWS_SECRET_ACCESS_KEY=$3 +export AWS_SESSION_TOKEN=$4 +export AWS_REGION=us-west-2 + +SDK_PATH="$(pwd)/aws-sdk/sdk" + +cd smithy-rs/tools/ci-cdk/canary-runner +aws s3 cp s3://"${CANARY_STACK_CDK_OUTPUTS_BUCKET_NAME}"/cdk-outputs.json . +cargo run -- \ + run --rust-version "${RUST_STABLE_VERSION}" \ + --sdk-path "${SDK_PATH}" \ + --cdk-output cdk-outputs.json \ + --musl diff --git a/tools/echo-server/Cargo.lock b/tools/echo-server/Cargo.lock index 1894c3dd97..f90bef57f2 100644 --- a/tools/echo-server/Cargo.lock +++ b/tools/echo-server/Cargo.lock @@ -19,18 +19,18 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", @@ -39,9 +39,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "axum" @@ -92,9 +92,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -113,18 +113,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cc" -version = "1.0.83" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" [[package]] name = "cfg-if" @@ -167,36 +164,36 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-core", "futures-task", @@ -212,9 +209,9 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "h2" -version = "0.3.22" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -237,15 +234,15 @@ checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -254,9 +251,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -283,9 +280,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -298,7 +295,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2", "tokio", "tower-service", "tracing", @@ -307,9 +304,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown", @@ -317,9 +314,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "lazy_static" @@ -329,9 +326,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "lock_api" @@ -345,9 +342,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "matchers" @@ -366,9 +363,9 @@ checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "mime" @@ -378,22 +375,22 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -418,9 +415,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -457,7 +454,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -468,18 +465,18 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", @@ -488,9 +485,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -500,18 +497,18 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -527,14 +524,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.3", - "regex-syntax 0.8.2", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", ] [[package]] @@ -548,13 +545,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -565,9 +562,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "rustc-demangle" @@ -577,9 +574,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "scopeguard" @@ -589,18 +586,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", @@ -609,9 +606,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "itoa", "ryu", @@ -659,35 +656,25 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.4.10" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" -dependencies = [ - "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "syn" -version = "2.0.39" +version = "2.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" dependencies = [ "proc-macro2", "quote", @@ -702,9 +689,9 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -712,9 +699,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.34.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -724,9 +711,9 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.5", + "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -924,7 +911,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.4", ] [[package]] @@ -933,13 +929,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] @@ -948,38 +959,80 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"