diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 9de059b7027..7b2a04b9c93 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,5 +1,5 @@ -FROM ghcr.io/containerbase/devcontainer:13.8.29 +FROM ghcr.io/containerbase/devcontainer:13.8.37 # https://github.com/pnpm/pnpm/issues/8971 # renovate: datasource=npm -RUN install-tool pnpm 10.11.0 +RUN install-tool pnpm 10.11.1 diff --git a/.github/label-actions.yml b/.github/label-actions.yml index 7be8579ee95..5d5a15cac06 100644 --- a/.github/label-actions.yml +++ b/.github/label-actions.yml @@ -370,7 +370,7 @@ Hi, please format any copy/pasted code or logs so they're readable. - You can find a Markdown code formatting guide [here](https://www.markdownguide.org/basic-syntax/#code) as well as some GitHub-specific information formatting code blocks [here](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks). + You can read a [Markdown code formatting guide](https://www.markdownguide.org/basic-syntax/#code) as well as [some GitHub-specific information formatting code blocks](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks). Thanks, the Renovate team diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 02e4664ff56..f63ffcc7d7a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -292,7 +292,7 @@ jobs: os: ${{ runner.os }} - name: Lint markdown - uses: DavidAnson/markdownlint-cli2-action@05f32210e84442804257b2a6f20b273450ec8265 # v19.1.0 + uses: DavidAnson/markdownlint-cli2-action@992badcdf24e3b8eb7e87ff9287fe931bcb00c6e # v20.0.0 - name: Lint fenced code blocks run: pnpm doc-fence-check @@ -389,7 +389,7 @@ jobs: done - name: Move coverage files - if: (success() || failure()) && github.event.pull_request.draft != true && matrix.coverage + if: success() && github.event.pull_request.draft != true && matrix.coverage run: | mkdir -p ./coverage/lcov mkdir -p ./coverage/json @@ -400,7 +400,7 @@ jobs: done - name: Save coverage artifacts - if: (success() || failure()) && github.event.pull_request.draft != true && matrix.coverage + if: success() && github.event.pull_request.draft != true && matrix.coverage uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: ${{ matrix.upload-artifact-name }} @@ -412,7 +412,7 @@ jobs: needs: [test] runs-on: ubuntu-latest timeout-minutes: 3 - if: (success() || failure()) && github.event_name != 'merge_group' && github.event.pull_request.draft != true + if: success() && github.event_name != 'merge_group' && github.event.pull_request.draft != true steps: - name: Checkout code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 @@ -441,7 +441,7 @@ jobs: - setup-build runs-on: ubuntu-latest timeout-minutes: 3 - if: (success() || failure()) && github.event.pull_request.draft != true + if: success() && github.event.pull_request.draft != true steps: - name: Checkout code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 @@ -559,7 +559,7 @@ jobs: - build runs-on: ubuntu-latest timeout-minutes: 15 - if: github.event.pull_request.draft != true + if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'ci:fulltest') steps: - name: Checkout code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 @@ -587,7 +587,7 @@ jobs: run: docker run -e LOG_LEVEL=debug --rm renovate/renovate --version - name: dry-run - if: github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && env.DO_REALEASE != 'true') || (github.repository == 'renovatebot/renovate' && github.event_name == 'pull_request') + if: github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && env.DO_REALEASE != 'true') run: docker run -e LOG_LEVEL=debug -e RENOVATE_TOKEN --rm renovate/renovate --dry-run=lookup ${{ github.repository }} env: RENOVATE_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -705,7 +705,7 @@ jobs: show-progress: false - name: docker-config - uses: containerbase/internal-tools@9f592003d567ccc3b850564299a2ec067bf97e87 # v3.10.39 + uses: containerbase/internal-tools@feca6cf1cfca09641ab497b50c52614e0eecf399 # v3.10.44 with: command: docker-config diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 6d70aa493e1..ca4ff30b3fe 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -41,7 +41,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 + uses: github/codeql-action/init@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 with: languages: javascript @@ -51,7 +51,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 + uses: github/codeql-action/autobuild@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -65,4 +65,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 + uses: github/codeql-action/analyze@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index f755f368262..f925f57f356 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -26,7 +26,7 @@ jobs: show-progress: false - name: 'Run analysis' - uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 + uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 with: results_file: results.sarif results_format: sarif @@ -51,6 +51,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 + uses: github/codeql-action/upload-sarif@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 with: sarif_file: results.sarif diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index f8b1f1f0ceb..94d1055f844 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -25,13 +25,13 @@ jobs: with: show-progress: false - - uses: aquasecurity/trivy-action@6c175e9c4083a92bbca2f9724c8a5e33bc2d97a5 # 0.30.0 + - uses: aquasecurity/trivy-action@76071ef0d7ec797419534a183b498b4d6366cf37 # 0.31.0 with: image-ref: ghcr.io/renovatebot/renovate:${{ matrix.tag }} format: 'sarif' output: 'trivy-results.sarif' - - uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 + - uses: github/codeql-action/upload-sarif@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 with: sarif_file: trivy-results.sarif category: 'docker-image-${{ matrix.tag }}' diff --git a/.python-version b/.python-version index 2c20ac9bea3..0d9339e0fad 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.13.3 +3.13.4 diff --git a/data/kubernetes-api.json5 b/data/kubernetes-api.json5 index e063edad480..929c438e643 100644 --- a/data/kubernetes-api.json5 +++ b/data/kubernetes-api.json5 @@ -148,9 +148,12 @@ ImageRepository: ['image.toolkit.fluxcd.io/v1beta2'], ImageUpdateAutomation: [ 'image.toolkit.fluxcd.io/v1beta1', - 'image.toolkit.fluxcd.io/v1beta2' - ], - OCIRepository: ['source.toolkit.fluxcd.io/v1beta2'], + 'image.toolkit.fluxcd.io/v1beta2', + ], + OCIRepository: [ + 'source.toolkit.fluxcd.io/v1beta2', + 'source.toolkit.fluxcd.io/v1', + ], Provider: [ 'notification.toolkit.fluxcd.io/v1beta2', 'notification.toolkit.fluxcd.io/v1beta3', diff --git a/docs/usage/assets/images/add-github-token-host-rule.png b/docs/usage/assets/images/add-github-token-host-rule.png new file mode 100644 index 00000000000..1491dcda98a Binary files /dev/null and b/docs/usage/assets/images/add-github-token-host-rule.png differ diff --git a/docs/usage/assets/images/github-token-warning.png b/docs/usage/assets/images/github-token-warning.png new file mode 100644 index 00000000000..9226e90fb96 Binary files /dev/null and b/docs/usage/assets/images/github-token-warning.png differ diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index dd51ddeebc7..981e1d621e3 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -151,6 +151,8 @@ This option _adds_ to the existing reviewer list, rather than _replacing_ it lik Use `additionalReviewers` when you want to add to a preset or base list, without replacing the original. For example, when adding focused reviewers for a specific package group. +Please note that Reviewers are only added during creation of a PR, but are not modified afterwards. + ## assignAutomerge By default, Renovate will not assign reviewers and assignees to an automerge-enabled PR unless it fails status checks. @@ -1411,6 +1413,15 @@ This feature is independent of the `osvVulnerabilityAlerts` option. The source of these CVEs is [OSV.dev](https://osv.dev/). +## dependencyDashboardReportAbandonment + +Controls whether abandoned packages are reported in the dependency dashboard. + +When enabled (default), Renovate will display a collapsible section in the dependency dashboard listing packages that have been identified as abandoned based on the `abandonmentThreshold` configuration. +This helps you identify dependencies that may need attention due to lack of maintenance. + +Set this to `false` if you prefer not to see abandoned packages in your dependency dashboard. + ## dependencyDashboardTitle Configure this option if you prefer a different title for the Dependency Dashboard. @@ -2372,6 +2383,8 @@ In the case that a user is automatically added as reviewer (such as Renovate App } ``` +Please note that Reviewers are only added during creation of a PR, but are not modified afterwards. + ## ignoreScripts By default, Renovate will disable package manager scripts. @@ -2502,28 +2515,29 @@ Renovate then commits that lock file to the update branch and creates the lock f Supported lock files: -- `.terraform.lock.hcl` -- `Cargo.lock` -- `Chart.lock` -- `composer.lock` -- `conan.lock` -- `flake.lock` -- `Gemfile.lock` -- `gradle.lockfile` -- `jsonnetfile.lock.json` -- `manifest.toml` -- `package-lock.json` -- `packages.lock.json` -- `pdm.lock` -- `Pipfile.lock` -- `pnpm-lock.yaml` -- `poetry.lock` -- `pubspec.lock` -- `pyproject.toml` -- `requirements.txt` -- `uv.lock` -- `yarn.lock` -- `pixi.lock` +| Manager | Lockfile | +| ----------------- | -------------------------------------------------- | +| `bun` | `bun.lockb`, `bun.lock` | +| `bundler` | `Gemfile.lock` | +| `cargo` | `Cargo.lock` | +| `composer` | `composer.lock` | +| `conan` | `conan.lock` | +| `devbox` | `devbox.lock` | +| `gleam` | `manifest.toml` | +| `gradle` | `gradle.lockfile` | +| `helmv3` | `Chart.lock` | +| `jsonnet-bundler` | `jsonnetfile.lock.json` | +| `mix` | `mix.lock` | +| `nix` | `flake.lock` | +| `npm` | `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock` | +| `nuget` | `packages.lock.json` | +| `pep621` | `pdm.lock`, `uv.lock` | +| `pip-compile` | `requirements.txt` | +| `pipenv` | `Pipfile.lock` | +| `pixi` | `pixi.lock` | +| `poetry` | `poetry.lock` | +| `pub` | `pubspec.lock` | +| `terraform` | `.terraform.lock.hcl` | Support for new lock files may be added via feature request. @@ -2874,9 +2888,13 @@ For example, if you want to upgrade to Angular v1.5 but _not_ to `angular` v1.6 Renovate calculates the valid syntax for this at runtime, because it depends on the dynamic versioning scheme. + +!!! warning + `allowedVersions` and `matchUpdateTypes` cannot be used in the same package rule. + #### Using regular expressions -You can use Regular Expressions in the `allowedVersion` config. +You can use Regular Expressions in the `allowedVersions` config. You must _begin_ and _end_ your Regular Expression with the `/` character! For example, this config only allows 3 or 4-part versions, without any prefixes in the version: @@ -3397,6 +3415,10 @@ For more details on supported syntax see Renovate's [string pattern matching doc When setting up automerge for dependencies, make sure to stop accidental automerges of `0.x` versions. Read the [automerge non-major updates](./key-concepts/automerge.md#automerge-non-major-updates) docs for a config example that blocks `0.x` updates. + +!!! warning + `matchUpdateTypes` and `allowedVersions` cannot be used in the same package rule. + Tokens can be configured via `hostRules` using the `"merge-confidence"` `hostType`: ```json @@ -4158,6 +4180,8 @@ For example: if the username or team name is `bar` then you would set the config } ``` +Please note that Reviewers are only added during creation of a PR, but are not modified afterwards. + ## reviewersFromCodeOwners If enabled Renovate tries to determine PR reviewers by matching rules defined in a CODEOWNERS file against the changes in the PR. @@ -4168,6 +4192,8 @@ Read the docs for your platform for details on syntax and allowed file locations - [GitLab, Code Owners](https://docs.gitlab.com/ee/user/project/codeowners/) - [Bitbucket, Set up and use code owners](https://support.atlassian.com/bitbucket-cloud/docs/set-up-and-use-code-owners/) +Please note that Reviewers are only added during creation of a PR, but are not modified afterwards. + !!! note GitLab `CODEOWNERS` files with default owners are _not_ supported. See [#29202](https://github.com/renovatebot/renovate/issues/29202). diff --git a/docs/usage/docker.md b/docs/usage/docker.md index 8aac0a2c6a3..af1b07cac69 100644 --- a/docs/usage/docker.md +++ b/docs/usage/docker.md @@ -307,7 +307,7 @@ Renovate will get the credentials with the [`google-auth-library`](https://www.n service_account: ${{ env.SERVICE_ACCOUNT }} - name: renovate - uses: renovatebot/github-action@v42.0.3 + uses: renovatebot/github-action@v42.0.5 env: RENOVATE_HOST_RULES: | [ @@ -478,7 +478,7 @@ Make sure to install the Google Cloud SDK into the custom image, as you need the For example: ```Dockerfile -FROM renovate/renovate:40.14.6 +FROM renovate/renovate:40.48.4 # Include the "Docker tip" which you can find here https://cloud.google.com/sdk/docs/install # under "Installation" for "Debian/Ubuntu" RUN ... diff --git a/docs/usage/examples/opentelemetry.md b/docs/usage/examples/opentelemetry.md index bf16ff3927f..0723becd762 100644 --- a/docs/usage/examples/opentelemetry.md +++ b/docs/usage/examples/opentelemetry.md @@ -14,7 +14,7 @@ name: renovate-otel-demo services: # Jaeger for storing traces jaeger: - image: jaegertracing/jaeger:2.6.0 + image: jaegertracing/jaeger:2.7.0 ports: - '16686:16686' # Web UI - '4317' # OTLP gRPC @@ -22,7 +22,7 @@ services: # Prometheus for storing metrics prometheus: - image: prom/prometheus:v3.4.0 + image: prom/prometheus:v3.4.1 ports: - '9090:9090' # Web UI - '4318' # OTLP HTTP @@ -36,7 +36,7 @@ services: otel-collector: # Using the Contrib version to access the spanmetrics connector. # If you don't need the spanmetrics connector, you can use the standard version - image: otel/opentelemetry-collector-contrib:0.126.0 + image: otel/opentelemetry-collector-contrib:0.128.0 volumes: - ./otel-collector-config.yml:/etc/otelcol-contrib/config.yaml ports: diff --git a/docs/usage/examples/self-hosting.md b/docs/usage/examples/self-hosting.md index a705222730d..649d531f239 100644 --- a/docs/usage/examples/self-hosting.md +++ b/docs/usage/examples/self-hosting.md @@ -25,8 +25,8 @@ It builds `latest` based on the `main` branch and all SemVer tags are published ```sh title="Example of valid tags" docker run --rm renovate/renovate docker run --rm renovate/renovate:40 -docker run --rm renovate/renovate:40.14 -docker run --rm renovate/renovate:40.14.6 +docker run --rm renovate/renovate:40.48 +docker run --rm renovate/renovate:40.48.4 ``` @@ -62,7 +62,7 @@ spec: - name: renovate # Update this to the latest available and then enable Renovate on # the manifest - image: renovate/renovate:40.14.6 + image: renovate/renovate:40.48.4 args: - user/repo # Environment Variables @@ -121,7 +121,7 @@ spec: template: spec: containers: - - image: renovate/renovate:40.14.6 + - image: renovate/renovate:40.48.4 name: renovate-bot env: # For illustration purposes, please use secrets. - name: RENOVATE_PLATFORM @@ -367,7 +367,7 @@ spec: containers: - name: renovate # Update this to the latest available and then enable Renovate on the manifest - image: renovate/renovate:40.14.6 + image: renovate/renovate:40.48.4 volumeMounts: - name: ssh-key-volume readOnly: true diff --git a/docs/usage/faq.md b/docs/usage/faq.md index 1901e2f268a..50690ca3f24 100644 --- a/docs/usage/faq.md +++ b/docs/usage/faq.md @@ -277,3 +277,39 @@ It can be nice to get patch PRs when you're using automerge: - Get weekly updates for minor and major updates This means you barely notice Renovate during the week, while you still get the benefits of patch level updates. + +## What's the difference between `depName` and `packageName`? + +Renovate uses two important config options to define a dependency's name: `depName` and `packageName`. + +The `depName` is the short "pretty name" of the dependency. +This is the user-facing name for the dependency. +By default, Renovate uses the `depName`: + +- in the title of Pull Requests/Merge Requests +- in commit messages +- on the Dependency Dashboard + +The `packageName` is the full _exact_ name. +Renovate uses the `packageName` to find the dependency in the package registry. + +Often `depName` and `packageName` are the same, but not always. + +Renovate uses the "pretty" `depName` in branch names and PR titles/content, because the `depName` is easier to read than the `packageName`. + +For instance, given the following Gradle plugin: + +```kotlin +plugins { + id("com.gradle.develocity").version("3.18.1") +} +``` + +Renovate will give the dependency these properties: + +- `depName=com.gradle.develocity` +- `packageName: com.gradle.develocity:com.gradle.develocity.gradle.plugin` + +Again, often the `depName` and `packageName` are equal. +The names Renovate uses for the `depName` and `packageName` depend on the package manager (and package ecosystem naming conventions). +For instance, `depName` and `packageName` may be different when you proxy Docker images. diff --git a/docs/usage/getting-started/running.md b/docs/usage/getting-started/running.md index 8009118c853..e1b3a9f614a 100644 --- a/docs/usage/getting-started/running.md +++ b/docs/usage/getting-started/running.md @@ -129,7 +129,6 @@ Forking Renovate needs only `read` level access to the code of any repository it If you use Forking Renovate, you'll miss out on these features of the regular Renovate app: - Automerge -- The `baseBranches` config option ### Hosting Renovate diff --git a/docs/usage/mend-hosted/.pages b/docs/usage/mend-hosted/.pages index db8790dd9eb..bd3c7771ff5 100644 --- a/docs/usage/mend-hosted/.pages +++ b/docs/usage/mend-hosted/.pages @@ -5,3 +5,4 @@ nav: - 'Job Scheduling': 'job-scheduling.md' - 'Credentials': 'credentials.md' - 'Migrating Secrets': 'migrating-secrets.md' + - 'Github.com Token': 'github-com-token.md' diff --git a/docs/usage/mend-hosted/github-com-token.md b/docs/usage/mend-hosted/github-com-token.md new file mode 100644 index 00000000000..997c49d8dc3 --- /dev/null +++ b/docs/usage/mend-hosted/github-com-token.md @@ -0,0 +1,64 @@ +# Purpose of github.com Token + +Users of Mend's Renovate apps on Bitbucket Cloud and Azure DevOps need to provide a github.com token retrieve release notes and changelogs, plus some package files. + +If github.com credentials are not provided, Renovate will continue to run, but with the following limitations: + +- release notes and changelogs will be disabled in Renovate pull requests +- lookups for packages hosted on github.com may fail due to rate limiting + +## Do I need to provide a github.com token? + +### github.com (Cloud) users + +If your repositories are hosted on github.com (Cloud) and you are using the Renovate App on GitHub, you do not need to provide a token for github.com because the Renovate App already has access to GitHub. + +### Bitbucket and Azure DevOps users + +If your repositories are hosted on Bitbucket or Azure DevOps, you will need to provide a github.com token if you want your Renovate PRs to contain release notes and changelogs, or if you want updates on packages that live exclusively on github.com. + +If the github.com token is not provided, a warning will be shown in the Developer Portal and in the Dependency Dashboard. + +![Portal warning about github.com token](../assets/images/github-token-warning.png) + +## How to provide a github.com token + +Renovate will accept a github.com token from any GitHub user. +The token requires no special access or permissions. + +### Step 1: Acquire a github.com token + +1. Log in to github.com (any user) +2. Navigate to [Personal access tokens](https://github.com/settings/tokens) in Developer settings +3. Choose `Generate new token` (either fine-grained or classic) +4. Provide a `Token name` (fine-grained) or `Note` (optional for classic token) +5. Choose the expiration date. (No additional scopes or repository permissions are required.) +6. Press `Generate token` +7. Copy the token when it is presented on the screen + +> [!IMPORTANT] +> +> Make sure to copy your personal access token now as you will not be able to see this again. + +### Step 2: Add the token to the Org/Repo credentials + +Use the token generated in the previous step to provide a secret and host rule for the Org or Repos. + +> [!NOTE] +> +> If a github.com token is added to the settings for an Org, Workspace or Project, the token will be inherited by of its all child repositories. + +1. Log in to [Developer Portal](https://developer.mend.io/) +2. Navigate to the Settings for an Org/Workspace/Project or a Repo +3. Go to the `Credentials` settings page +4. Choose `ADD SECRET` and create a secret to store the token + - Provide a `Secret Name` (e.g. `GITHUB_TOKEN`) + - Store the github.com token in the `Secret Value` +5. Choose `ADD HOST RULE` and create a host rule for `github` + - Select host type `github` + - Select Secret Type as `Token` + - Select the github.com token as the secret + +![Add a Host Rule UI](../assets/images/add-github-token-host-rule.png) + +For more information about providing Secrets and Host Rules in the Developer Portal UI, see the documentation for [Credentials](credentials.md). diff --git a/docs/usage/self-hosted-configuration.md b/docs/usage/self-hosted-configuration.md index c551ad94156..986e7b90615 100644 --- a/docs/usage/self-hosted-configuration.md +++ b/docs/usage/self-hosted-configuration.md @@ -1195,7 +1195,7 @@ JSON files will be stored inside the `cacheDir` beside the existing file-based p Renovate uses the [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/welcome.html) to connect to the S3 instance. Therefore, Renovate supports all the authentication methods supported by the AWS SDK. -Read more about the default credential provider chain for AWS SDK for JavaScript V3 [here](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-credential-providers/#fromnodeproviderchain). +Read more about [the default credential provider chain for AWS SDK for JavaScript V3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-credential-providers/#fromnodeproviderchain). !!! tip diff --git a/docs/usage/semantic-commits.md b/docs/usage/semantic-commits.md index 39b6c754dc7..1825b88ffc1 100644 --- a/docs/usage/semantic-commits.md +++ b/docs/usage/semantic-commits.md @@ -22,6 +22,8 @@ There are some exceptions: - if the `depType` is a known "production dependency" type (e.g. `dependencies` or `require`), then Renovate uses the `fix` prefix - if an update uses the `maven` datasource _and_ `matchDepTypes` is a known production type (e.g. `compile`, `provided`, `runtime`, `system`, `import` or `parent`) then Renovate uses the `fix` prefix +Be aware that the semantic commits feature does not work if you have a `commitMessagePrefix` configured - `commitMessagePrefix` will take priority. + ## Manually enabling or disabling semantic commits You can override the default settings, and disable or enable Semantic Commits. diff --git a/eslint.config.mjs b/eslint.config.mjs index cb209e21f0b..def8d0e92d4 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,12 +1,15 @@ import eslintContainerbase from '@containerbase/eslint-plugin'; import js from '@eslint/js'; -import eslintConfigPrettier from 'eslint-config-prettier'; -import eslintPluginImport from 'eslint-plugin-import'; import vitest from '@vitest/eslint-plugin'; +import eslintConfigPrettier from 'eslint-config-prettier'; +import { createTypeScriptImportResolver } from 'eslint-import-resolver-typescript'; +import * as importX from 'eslint-plugin-import-x'; import eslintPluginPromise from 'eslint-plugin-promise'; import globals from 'globals'; import tseslint from 'typescript-eslint'; +const jsFiles = { files: ['**/*.{js,cjs,mjs,mts,ts}'] }; + export default tseslint.config( { ignores: [ @@ -27,25 +30,23 @@ export default tseslint.config( '**/.venv/', 'tools/mkdocs/docs', 'tools/mkdocs/site', - - // TODO: fix me - 'eslint.config.mjs', ], }, + { + linterOptions: { + reportUnusedDisableDirectives: 'error', + }, + }, js.configs.recommended, ...tseslint.configs.recommendedTypeChecked, ...tseslint.configs.stylisticTypeChecked, - eslintPluginImport.flatConfigs.errors, - eslintPluginImport.flatConfigs.warnings, - eslintPluginImport.flatConfigs.recommended, - eslintPluginImport.flatConfigs.typescript, eslintPluginPromise.configs['flat/recommended'], eslintContainerbase.configs.all, { - linterOptions: { - reportUnusedDisableDirectives: 'error', - }, + ...jsFiles, + + extends: [importX.flatConfigs.recommended, importX.flatConfigs.typescript], languageOptions: { globals: { @@ -63,28 +64,22 @@ export default tseslint.config( }, settings: { - 'import/parsers': { - '@typescript-eslint/parser': ['.ts'], - }, - - 'import/resolver': { - typescript: { - alwaysTryTypes: true, - }, - }, + 'import-x/resolver-next': [ + createTypeScriptImportResolver({ project: 'tsconfig.json' }), + ], }, }, eslintConfigPrettier, { - files: ['**/*.{ts,js,cjs,mjs}'], + ...jsFiles, rules: { - 'import/default': 2, - 'import/named': 2, - 'import/namespace': 2, - 'import/no-named-as-default-member': 0, + 'import-x/default': 2, + 'import-x/named': 2, + 'import-x/namespace': 2, + 'import-x/no-named-as-default-member': 0, - 'import/no-extraneous-dependencies': [ + 'import-x/no-extraneous-dependencies': [ 'error', { devDependencies: [ @@ -96,8 +91,8 @@ export default tseslint.config( }, ], - 'import/prefer-default-export': 0, - 'import/no-cycle': 2, + 'import-x/prefer-default-export': 0, + 'import-x/no-cycle': 2, 'consistent-return': 0, eqeqeq: 'error', 'no-console': 'error', @@ -115,14 +110,14 @@ export default tseslint.config( }, ], - 'import/no-unresolved': [ + 'import-x/no-unresolved': [ 'error', { ignore: ['^mdast$'], }, ], - 'import/order': [ + 'import-x/order': [ 'error', { alphabetize: { @@ -131,7 +126,7 @@ export default tseslint.config( }, ], - 'import/no-restricted-paths': [ + 'import-x/no-restricted-paths': [ 2, { zones: [ @@ -263,7 +258,7 @@ export default tseslint.config( 'no-template-curly-in-string': 0, 'prefer-destructuring': 0, 'prefer-promise-reject-errors': 0, - 'import/no-dynamic-require': 0, + 'import-x/no-dynamic-require': 0, 'global-require': 0, '@typescript-eslint/no-var-requires': 0, '@typescript-eslint/no-object-literal-type-assertion': 0, @@ -283,7 +278,10 @@ export default tseslint.config( }, }, { - files: ['tools/**/*.{ts,js,mjs,cjs}'], + files: [ + '*.config.{cjs,cts,js,mjs,mts,ts}', + 'tools/**/*.{cjs,cts,js,mjs,mts,ts}', + ], languageOptions: { globals: { @@ -292,7 +290,7 @@ export default tseslint.config( }, rules: { - 'import/no-extraneous-dependencies': [ + 'import-x/no-extraneous-dependencies': [ 'error', { devDependencies: true, @@ -313,7 +311,7 @@ export default tseslint.config( files: ['**/*.mjs'], rules: { - 'import/extensions': 0, + 'import-x/extensions': 0, }, }, { diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts index 5a4b9cc6d1a..27f5fc36747 100644 --- a/lib/config/options/index.ts +++ b/lib/config/options/index.ts @@ -132,7 +132,6 @@ const options: RenovateOptions[] = [ description: 'The semver level to use when bumping versions. This is used by the `bumpVersions` feature.', type: 'string', - default: 'patch', parents: ['bumpVersions'], }, { @@ -148,7 +147,6 @@ const options: RenovateOptions[] = [ description: 'A name for the bumpVersion config. This is used for logging and debugging.', type: 'string', - default: null, parents: ['bumpVersions'], }, { @@ -1175,6 +1173,7 @@ const options: RenovateOptions[] = [ 'helmv3', 'kubernetes', 'kustomize', + 'maven', 'terraform', 'vendir', 'woodpecker', @@ -1445,7 +1444,8 @@ const options: RenovateOptions[] = [ }, { name: 'matchSourceUrls', - description: 'A list of source URLs to exact match against.', + description: + 'A list of exact match URLs (or URL patterns) to match sourceUrl against.', type: 'array', subType: 'string', allowString: true, @@ -1897,6 +1897,13 @@ const options: RenovateOptions[] = [ type: 'string', default: null, }, + { + name: 'dependencyDashboardReportAbandonment', + description: + 'Controls whether abandoned packages are reported in the dependency dashboard.', + type: 'boolean', + default: true, + }, { name: 'internalChecksAsSuccess', description: diff --git a/lib/config/presets/internal/index.spec.ts b/lib/config/presets/internal/index.spec.ts index 651792ea8ab..0920affe25e 100644 --- a/lib/config/presets/internal/index.spec.ts +++ b/lib/config/presets/internal/index.spec.ts @@ -8,11 +8,15 @@ import * as internal from '.'; vi.mock('../npm'); vi.mock('../../../modules/datasource/npm'); -vi.spyOn(npm, 'getPreset').mockResolvedValue(undefined); +const getPresetSpy = vi.spyOn(npm, 'getPreset'); const ignoredPresets = ['default:group', 'default:timezone']; describe('config/presets/internal/index', () => { + beforeEach(() => { + getPresetSpy.mockResolvedValue(undefined); + }); + it('fails for undefined internal preset', async () => { const preset = 'foo:bar'; const presetConfig = { extends: [preset] }; diff --git a/lib/config/presets/internal/workarounds.ts b/lib/config/presets/internal/workarounds.ts index baa6c0a5f07..e368b37716f 100644 --- a/lib/config/presets/internal/workarounds.ts +++ b/lib/config/presets/internal/workarounds.ts @@ -18,6 +18,7 @@ export const presets: Record = { 'workarounds:supportRedHatImageVersion', 'workarounds:javaLTSVersions', 'workarounds:disableEclipseLifecycleMapping', + 'workarounds:disableGradleReplacements', 'workarounds:disableMavenParentRoot', 'workarounds:containerbase', 'workarounds:bitnamiDockerImageVersioning', @@ -69,6 +70,16 @@ export const presets: Record = { }, ], }, + disableGradleReplacements: { + description: 'Disable package replacement updates for gradle dependencies.', + packageRules: [ + { + enabled: false, + matchManagers: ['gradle'], + matchUpdateTypes: ['replacement'], + }, + ], + }, disableMavenParentRoot: { description: 'Avoid version fetching for Maven packages detected as project root.', diff --git a/lib/config/types.ts b/lib/config/types.ts index 6afb9b377d4..2090109af60 100644 --- a/lib/config/types.ts +++ b/lib/config/types.ts @@ -268,6 +268,7 @@ export interface RenovateConfig dependencyDashboardFooter?: string; dependencyDashboardLabels?: string[]; dependencyDashboardOSVVulnerabilitySummary?: 'none' | 'all' | 'unresolved'; + dependencyDashboardReportAbandonment?: boolean; packageFile?: string; packageRules?: PackageRule[]; postUpdateOptions?: string[]; @@ -590,8 +591,8 @@ export interface ValidationResult { } export interface BumpVersionConfig { - bumpType: string; + bumpType?: string; filePatterns: string[]; matchStrings: string[]; - name: string | null; + name?: string; } diff --git a/lib/data/monorepo.json b/lib/data/monorepo.json index ff40693d2a4..cba591986a1 100644 --- a/lib/data/monorepo.json +++ b/lib/data/monorepo.json @@ -509,6 +509,7 @@ "https://github.com/remix-run/react-router" ], "react-spectrum": "https://github.com/adobe/react-spectrum", + "react-spring": "https://github.com/pmndrs/react-spring", "reactivestack-cookies": "https://github.com/reactivestack/cookies", "reakit": "https://github.com/reakit/reakit", "redwood": "https://github.com/redwoodjs/redwood", @@ -528,6 +529,7 @@ "sanity": "https://github.com/sanity-io/sanity", "serilog-ui": "https://github.com/serilog-contrib/serilog-ui", "scaffdog": "https://github.com/scaffdog/scaffdog", + "scalar": "https://github.com/scalar/scalar", "sea-orm": "https://github.com/SeaQL/sea-orm", "secretlint": "https://github.com/secretlint/secretlint", "sendgrid-nodejs": "https://github.com/sendgrid/sendgrid-nodejs", @@ -559,7 +561,11 @@ "strum": "https://github.com/Peternator7/strum", "stryker-js": "https://github.com/stryker-mutator/stryker-js", "stylex-swc": "https://github.com/Dwlad90/stylex-swc-plugin", - "surveyjs": "https://github.com/surveyjs/surveyjs", + "surveyjs": [ + "https://github.com/surveyjs/surveyjs", + "https://github.com/surveyjs/survey-library", + "https://github.com/surveyjs/survey-creator" + ], "swashbuckle-aspnetcore": "https://github.com/domaindrivendev/Swashbuckle.AspNetCore", "system.io.abstractions": "https://github.com/System-IO-Abstractions/System.IO.Abstractions/", "tailwindcss": "https://github.com/tailwindlabs/tailwindcss", @@ -568,6 +574,7 @@ "tanstack-query": "https://github.com/TanStack/query", "tanstack-router": "https://github.com/TanStack/router", "tanstack-table": "https://github.com/TanStack/table", + "tanstack-virtual": "https://github.com/TanStack/virtual", "tauri": "https://github.com/tauri-apps/tauri", "telus-tds": "https://github.com/telusdigital/tds", "telus-tds-core": "https://github.com/telus/tds-core", diff --git a/lib/modules/datasource/aws-eks-addon/readme.md b/lib/modules/datasource/aws-eks-addon/readme.md index 3205a5838f5..50d1f37e1b0 100644 --- a/lib/modules/datasource/aws-eks-addon/readme.md +++ b/lib/modules/datasource/aws-eks-addon/readme.md @@ -69,7 +69,8 @@ Here's an example of using the custom manager to configure this datasource: { "packageRules": [ { - "matchDatasources": ["aws-eks-addon"] + "matchDatasources": ["aws-eks-addon"], + "overrideDepName": "{{replace '.*\"addonName\":\"([^\"]+)\".*' '$1' depName}}" } ], "customManagers": [ diff --git a/lib/modules/datasource/aws-eks-addon/schema.ts b/lib/modules/datasource/aws-eks-addon/schema.ts index bc73927d819..1db85075e0b 100644 --- a/lib/modules/datasource/aws-eks-addon/schema.ts +++ b/lib/modules/datasource/aws-eks-addon/schema.ts @@ -1,18 +1,6 @@ -import { type ZodEffects, type ZodString, z } from 'zod'; +import { z } from 'zod/v4'; import { regEx } from '../../../util/regex'; -import { Json } from '../../../util/schema-utils'; - -const stringIsBoolSchema: ZodEffects = z - .string() - .transform((value) => { - if (value === 'true') { - return true; - } else if (value === 'false') { - return false; - } else { - return false; - } - }); +import { Json } from '../../../util/schema-utils/v4'; export const EksAddonsFilterSchema = z.object({ addonName: z.string().nonempty().regex(regEx('^[a-z0-9][a-z0-9-]*[a-z0-9]$')), @@ -20,7 +8,9 @@ export const EksAddonsFilterSchema = z.object({ .string() .regex(regEx('^(?\\d+)\\.(?\\d+)$')) .optional(), - default: z.oboolean().or(stringIsBoolSchema), + default: z + .union([z.boolean(), z.string().transform((value) => value === 'true')]) + .optional(), region: z.string().optional(), profile: z.string().optional(), }); diff --git a/lib/modules/datasource/aws-machine-image/__snapshots__/index.spec.ts.snap b/lib/modules/datasource/aws-machine-image/__snapshots__/index.spec.ts.snap deleted file mode 100644 index 3c199aa1da4..00000000000 --- a/lib/modules/datasource/aws-machine-image/__snapshots__/index.spec.ts.snap +++ /dev/null @@ -1,115 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`modules/datasource/aws-machine-image/index > getSortedAwsMachineImages() > with 1 returned image 1`] = ` -[ - DescribeImagesCommand { - "deserialize": [Function], - "input": { - "Filters": [ - { - "Name": "owner-id", - "Values": [ - "602401143452", - ], - }, - { - "Name": "name", - "Values": [ - "1image", - ], - }, - ], - }, - "middlewareStack": { - "add": [Function], - "addRelativeTo": [Function], - "applyToStack": [Function], - "clone": [Function], - "concat": [Function], - "identify": [Function], - "identifyOnResolve": [Function], - "remove": [Function], - "removeByTag": [Function], - "resolve": [Function], - "use": [Function], - }, - "serialize": [Function], - }, -] -`; - -exports[`modules/datasource/aws-machine-image/index > getSortedAwsMachineImages() > with 3 returned images 1`] = ` -[ - DescribeImagesCommand { - "deserialize": [Function], - "input": { - "Filters": [ - { - "Name": "owner-id", - "Values": [ - "602401143452", - ], - }, - { - "Name": "name", - "Values": [ - "3images", - ], - }, - ], - }, - "middlewareStack": { - "add": [Function], - "addRelativeTo": [Function], - "applyToStack": [Function], - "clone": [Function], - "concat": [Function], - "identify": [Function], - "identifyOnResolve": [Function], - "remove": [Function], - "removeByTag": [Function], - "resolve": [Function], - "use": [Function], - }, - "serialize": [Function], - }, -] -`; - -exports[`modules/datasource/aws-machine-image/index > getSortedAwsMachineImages() > without returned images 1`] = ` -[ - DescribeImagesCommand { - "deserialize": [Function], - "input": { - "Filters": [ - { - "Name": "owner-id", - "Values": [ - "602401143452", - ], - }, - { - "Name": "name", - "Values": [ - "noiamge", - ], - }, - ], - }, - "middlewareStack": { - "add": [Function], - "addRelativeTo": [Function], - "applyToStack": [Function], - "clone": [Function], - "concat": [Function], - "identify": [Function], - "identifyOnResolve": [Function], - "remove": [Function], - "removeByTag": [Function], - "resolve": [Function], - "use": [Function], - }, - "serialize": [Function], - }, -] -`; diff --git a/lib/modules/datasource/aws-machine-image/index.spec.ts b/lib/modules/datasource/aws-machine-image/index.spec.ts index 6cc304ceac4..06824ad8a65 100644 --- a/lib/modules/datasource/aws-machine-image/index.spec.ts +++ b/lib/modules/datasource/aws-machine-image/index.spec.ts @@ -142,7 +142,6 @@ describe('modules/datasource/aws-machine-image/index', () => { ); expect(res).toStrictEqual([image1, image2, image3]); expect(ec2Mock.calls()).toHaveLength(1); - expect(ec2Mock.calls()[0].args).toMatchSnapshot(); }); it('with 1 returned image', async () => { @@ -153,7 +152,6 @@ describe('modules/datasource/aws-machine-image/index', () => { ); expect(res).toStrictEqual([image3]); expect(ec2Mock.calls()).toHaveLength(1); - expect(ec2Mock.calls()[0].args).toMatchSnapshot(); }); it('without returned images', async () => { @@ -164,7 +162,6 @@ describe('modules/datasource/aws-machine-image/index', () => { ); expect(res).toStrictEqual([]); expect(ec2Mock.calls()).toHaveLength(1); - expect(ec2Mock.calls()[0].args).toMatchSnapshot(); }); }); diff --git a/lib/modules/datasource/aws-rds/readme.md b/lib/modules/datasource/aws-rds/readme.md index 37363c28bab..721e9777957 100644 --- a/lib/modules/datasource/aws-rds/readme.md +++ b/lib/modules/datasource/aws-rds/readme.md @@ -65,7 +65,7 @@ For example: "customType": "regex", "managerFilePatterns": ["**.yaml"], "matchStrings": [ - ".*rdsFilter=(?.+?)[ ]*\n[ ]*(?[a-zA-Z0-9-_:]*)[ ]*?:[ ]*?[\"|']?(?[.\\d]+)[\"|']?.*" + ".*rdsFilter=(?.+?)[ ]*\n[ ]*(?[a-zA-Z0-9-_:]*)[ ]*?:[ ]*?[\"|']?(?[.\\d]+)[\"|']?.*" ], "datasourceTemplate": "aws-rds" } @@ -93,7 +93,7 @@ Here is the Renovate configuration to use Terraform, `aws-rds` and Aurora MySQL: "customType": "regex", "managerFilePatterns": ["/.+\\.tf$/"], "matchStrings": [ - "\\s*#\\s*renovate:\\s*rdsFilter=(?.+?) depName=(?.*) versioning=(?.*)\\s*.*_version\\s*=\\s*\"(?.*)\"" + "\\s*#\\s*renovate:\\s*rdsFilter=(?.+?) depName=(?.*) versioning=(?.*)\\s*.*_version\\s*=\\s*\"(?.*)\"" ], "datasourceTemplate": "aws-rds" } diff --git a/lib/modules/datasource/docker/ecr.ts b/lib/modules/datasource/docker/ecr.ts index f05dfc960bb..8d3e1db2658 100644 --- a/lib/modules/datasource/docker/ecr.ts +++ b/lib/modules/datasource/docker/ecr.ts @@ -8,9 +8,9 @@ import { regEx } from '../../../util/regex'; import { addSecretForSanitizing } from '../../../util/sanitize'; export const ecrRegex = regEx( - /\d+\.dkr\.ecr(?:-fips)?\.([-a-z0-9]+)\.amazonaws\.com/, + /\d+\.(?:dkr\.ecr|dkr-ecr)(?:-fips)?\.([-a-z0-9]+)\.(?:amazonaws\.com|on\.aws)/, ); -export const ecrPublicRegex = regEx(/public\.ecr\.aws/); +export const ecrPublicRegex = regEx(/public\.ecr\.aws|ecr-public\.aws\.com/); export async function getECRAuthToken( region: string, diff --git a/lib/modules/datasource/docker/index.spec.ts b/lib/modules/datasource/docker/index.spec.ts index 51d661746e7..8aa513bbf5f 100644 --- a/lib/modules/datasource/docker/index.spec.ts +++ b/lib/modules/datasource/docker/index.spec.ts @@ -22,10 +22,15 @@ const ecrMock = mockClient(ECRClient); const baseUrl = 'https://index.docker.io/v2'; const authUrl = 'https://auth.docker.io'; -const amazonUrl = 'https://123456789.dkr.ecr.us-east-1.amazonaws.com/v2'; const gcrUrl = 'https://eu.gcr.io/v2'; const garUrl = 'https://europe-docker.pkg.dev/v2'; const dockerHubUrl = 'https://hub.docker.com/v2/repositories'; +const amazonHosts = [ + { host: '123456789.dkr.ecr.us-east-1.amazonaws.com' }, + { host: '123456789.dkr.ecr-fips.us-east-1.amazonaws.com' }, + { host: '123456789.dkr-ecr.us-east-1.on.aws' }, + { host: '123456789.dkr-ecr-fips.us-east-1.on.aws' }, +]; function mockEcrAuthResolve( res: Partial = {}, @@ -212,169 +217,191 @@ describe('modules/datasource/docker/index', () => { expect(res).toBeNull(); }); - it('passes credentials to ECR client', async () => { - httpMock - .scope(amazonUrl) - .get('/') - .reply(401, '', { - 'www-authenticate': 'Basic realm="My Private Docker Registry Server"', - }) - .head('/node/manifests/some-tag') - .matchHeader('authorization', 'Basic test_token') - .reply(200, '', { 'docker-content-digest': 'some-digest' }); + it.each(amazonHosts)( + 'passes credentials to ECR client for host $host', + async ({ host }) => { + httpMock + .scope(`https://${host}/v2`) + .get('/') + .reply(401, '', { + 'www-authenticate': + 'Basic realm="My Private Docker Registry Server"', + }) + .head('/node/manifests/some-tag') + .matchHeader('authorization', 'Basic test_token') + .reply(200, '', { 'docker-content-digest': 'some-digest' }); - mockEcrAuthResolve({ - authorizationData: [{ authorizationToken: 'test_token' }], - }); + mockEcrAuthResolve({ + authorizationData: [{ authorizationToken: 'test_token' }], + }); - expect( - await getDigest( - { - datasource: 'docker', - packageName: '123456789.dkr.ecr.us-east-1.amazonaws.com/node', + expect( + await getDigest( + { + datasource: 'docker', + packageName: `${host}/node`, + }, + 'some-tag', + ), + ).toBe('some-digest'); + + const ecr = ecrMock.call(0).thisValue as ECRClient; + expect(await ecr.config.region()).toBe('us-east-1'); + expect(await ecr.config.credentials()).toEqual({ + $source: { + CREDENTIALS_CODE: 'e', }, - 'some-tag', - ), - ).toBe('some-digest'); + accessKeyId: 'some-username', + secretAccessKey: 'some-password', + }); + }, + ); - const ecr = ecrMock.call(0).thisValue as ECRClient; - expect(await ecr.config.region()).toBe('us-east-1'); - expect(await ecr.config.credentials()).toEqual({ - $source: { - CREDENTIALS_CODE: 'e', - }, - accessKeyId: 'some-username', - secretAccessKey: 'some-password', - }); - }); + it.each(amazonHosts)( + 'passes session token to ECR client for host $host', + async ({ host }) => { + httpMock + .scope(`https://${host}/v2`) + .get('/') + .reply(401, '', { + 'www-authenticate': + 'Basic realm="My Private Docker Registry Server"', + }) + .head('/node/manifests/some-tag') + .matchHeader('authorization', 'Basic test_token') + .reply(200, '', { 'docker-content-digest': 'some-digest' }); + + hostRules.find.mockReturnValue({ + username: 'some-username', + password: 'some-password', + token: 'some-session-token', + }); - it('passes session token to ECR client', async () => { - httpMock - .scope(amazonUrl) - .get('/') - .reply(401, '', { - 'www-authenticate': 'Basic realm="My Private Docker Registry Server"', - }) - .head('/node/manifests/some-tag') - .matchHeader('authorization', 'Basic test_token') - .reply(200, '', { 'docker-content-digest': 'some-digest' }); + mockEcrAuthResolve({ + authorizationData: [{ authorizationToken: 'test_token' }], + }); - hostRules.find.mockReturnValue({ - username: 'some-username', - password: 'some-password', - token: 'some-session-token', - }); + expect( + await getDigest( + { + datasource: 'docker', + packageName: `${host}/node`, + }, + 'some-tag', + ), + ).toBe('some-digest'); + + const ecr = ecrMock.call(0).thisValue as ECRClient; + expect(await ecr.config.region()).toBe('us-east-1'); + expect(await ecr.config.credentials()).toEqual({ + $source: { + CREDENTIALS_CODE: 'e', + }, + accessKeyId: 'some-username', + secretAccessKey: 'some-password', + sessionToken: 'some-session-token', + }); + }, + ); - mockEcrAuthResolve({ - authorizationData: [{ authorizationToken: 'test_token' }], - }); + it.each(amazonHosts)( + 'supports ECR authentication for host $host', + async ({ host }) => { + httpMock + .scope(`https://${host}/v2`) + .get('/') + .reply(401, '', { + 'www-authenticate': + 'Basic realm="My Private Docker Registry Server"', + }) + .head('/node/manifests/some-tag') + .matchHeader('authorization', 'Basic test') + .reply(200, '', { 'docker-content-digest': 'some-digest' }); - expect( - await getDigest( + mockEcrAuthResolve({ + authorizationData: [{ authorizationToken: 'test' }], + }); + + const res = await getDigest( { datasource: 'docker', - packageName: '123456789.dkr.ecr.us-east-1.amazonaws.com/node', + packageName: `${host}/node`, }, 'some-tag', - ), - ).toBe('some-digest'); + ); - const ecr = ecrMock.call(0).thisValue as ECRClient; - expect(await ecr.config.region()).toBe('us-east-1'); - expect(await ecr.config.credentials()).toEqual({ - $source: { - CREDENTIALS_CODE: 'e', - }, - accessKeyId: 'some-username', - secretAccessKey: 'some-password', - sessionToken: 'some-session-token', - }); - }); + expect(res).toBe('some-digest'); + }, + ); - it('supports ECR authentication', async () => { - httpMock - .scope(amazonUrl) - .get('/') - .reply(401, '', { + it.each(amazonHosts)( + 'continues without token if ECR authentication could not be extracted for host $host', + async ({ host }) => { + httpMock.scope(`https://${host}/v2`).get('/').reply(401, '', { 'www-authenticate': 'Basic realm="My Private Docker Registry Server"', - }) - .head('/node/manifests/some-tag') - .matchHeader('authorization', 'Basic test') - .reply(200, '', { 'docker-content-digest': 'some-digest' }); - - mockEcrAuthResolve({ - authorizationData: [{ authorizationToken: 'test' }], - }); - - const res = await getDigest( - { - datasource: 'docker', - packageName: '123456789.dkr.ecr.us-east-1.amazonaws.com/node', - }, - 'some-tag', - ); - - expect(res).toBe('some-digest'); - }); - - it('continues without token if ECR authentication could not be extracted', async () => { - httpMock.scope(amazonUrl).get('/').reply(401, '', { - 'www-authenticate': 'Basic realm="My Private Docker Registry Server"', - }); - mockEcrAuthResolve(); - - const res = await getDigest( - { - datasource: 'docker', - packageName: '123456789.dkr.ecr.us-east-1.amazonaws.com/node', - }, - 'some-tag', - ); - expect(res).toBeNull(); - }); - - it('continues without token if ECR authentication fails', async () => { - hostRules.find.mockReturnValue({}); - httpMock.scope(amazonUrl).get('/').reply(401, '', { - 'www-authenticate': 'Basic realm="My Private Docker Registry Server"', - }); - mockEcrAuthReject('some error'); - const res = await getDigest( - { - datasource: 'docker', - packageName: '123456789.dkr.ecr.us-east-1.amazonaws.com/node', - }, - 'some-tag', - ); - expect(res).toBeNull(); - }); + }); + mockEcrAuthResolve(); - it('supports ECR authentication for private repositories', async () => { - httpMock - .scope(amazonUrl) - .get('/') - .reply(401, '', { + const res = await getDigest( + { + datasource: 'docker', + packageName: `${host}/node`, + }, + 'some-tag', + ); + expect(res).toBeNull(); + }, + ); + + it.each(amazonHosts)( + 'continues without token if ECR authentication fails for host $host', + async ({ host }) => { + hostRules.find.mockReturnValue({}); + httpMock.scope(`https://${host}/v2`).get('/').reply(401, '', { 'www-authenticate': 'Basic realm="My Private Docker Registry Server"', - }) - .head('/node/manifests/some-tag') - .matchHeader('authorization', 'Basic QVdTOnNvbWUtcGFzc3dvcmQ=') - .reply(200, '', { 'docker-content-digest': 'some-digest' }); + }); + mockEcrAuthReject('some error'); + const res = await getDigest( + { + datasource: 'docker', + packageName: `${host}/node`, + }, + 'some-tag', + ); + expect(res).toBeNull(); + }, + ); - hostRules.find.mockReturnValue({ - username: 'AWS', - password: 'some-password', - }); + it.each(amazonHosts)( + 'supports ECR authentication for private repositories for host $host', + async ({ host }) => { + httpMock + .scope(`https://${host}/v2`) + .get('/') + .reply(401, '', { + 'www-authenticate': + 'Basic realm="My Private Docker Registry Server"', + }) + .head('/node/manifests/some-tag') + .matchHeader('authorization', 'Basic QVdTOnNvbWUtcGFzc3dvcmQ=') + .reply(200, '', { 'docker-content-digest': 'some-digest' }); - const res = await getDigest( - { - datasource: 'docker', - packageName: '123456789.dkr.ecr.us-east-1.amazonaws.com/node', - }, - 'some-tag', - ); + hostRules.find.mockReturnValue({ + username: 'AWS', + password: 'some-password', + }); - expect(res).toBe('some-digest'); - }); + const res = await getDigest( + { + datasource: 'docker', + packageName: `${host}/node`, + }, + 'some-tag', + ); + + expect(res).toBe('some-digest'); + }, + ); it('supports Google ADC authentication for gcr', async () => { httpMock @@ -1555,83 +1582,87 @@ describe('modules/datasource/docker/index', () => { expect(res?.releases).toHaveLength(20050); }); - it('uses lower tag limit for ECR deps', async () => { - httpMock - .scope(amazonUrl) - .get('/node/tags/list?n=1000') - .reply(200, '', {}) - // The tag limit parameter `n` needs to be limited to 1000 for ECR - // See https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_DescribeRepositories.html#ECR-DescribeRepositories-request-maxResults - .get('/node/tags/list?n=1000') - .reply(200, { tags: ['some'] }, {}) - .get('/') - .reply(200, '', {}) - .get('/node/manifests/some') - .reply(200); - expect( - await getPkgReleases({ - datasource: DockerDatasource.id, - packageName: '123456789.dkr.ecr.us-east-1.amazonaws.com/node', - }), - ).toEqual({ - lookupName: 'node', - registryUrl: 'https://123456789.dkr.ecr.us-east-1.amazonaws.com', - releases: [], - }); - }); + it.each(amazonHosts)( + 'uses lower tag limit for ECR deps for host $host', + async ({ host }) => { + httpMock + .scope(`https://${host}/v2`) + .get('/node/tags/list?n=1000') + .reply(200, '', {}) + // The tag limit parameter `n` needs to be limited to 1000 for ECR + // See https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_DescribeRepositories.html#ECR-DescribeRepositories-request-maxResults + .get('/node/tags/list?n=1000') + .reply(200, { tags: ['some'] }, {}) + .get('/') + .reply(200, '', {}) + .get('/node/manifests/some') + .reply(200); + expect( + await getPkgReleases({ + datasource: DockerDatasource.id, + packageName: `${host}/node`, + }), + ).toEqual({ + lookupName: 'node', + registryUrl: `https://${host}`, + releases: [], + }); + }, + ); - it('uses lower tag limit for ECR Public deps', async () => { - httpMock - .scope('https://public.ecr.aws') - .get('/v2/amazonlinux/amazonlinux/tags/list?n=1000') - .reply(401, '', { - 'www-authenticate': - 'Bearer realm="https://public.ecr.aws/token",service="public.ecr.aws",scope="aws"', - }) - .get('/token?service=public.ecr.aws&scope=aws') - .reply(200, { token: 'test' }); - httpMock - .scope('https://public.ecr.aws', { - reqheaders: { - authorization: 'Bearer test', - }, - }) - // The tag limit parameter `n` needs to be limited to 1000 for ECR Public - // See https://docs.aws.amazon.com/AmazonECRPublic/latest/APIReference/API_DescribeRepositories.html#ecrpublic-DescribeRepositories-request-maxResults - .get('/v2/amazonlinux/amazonlinux/tags/list?n=1000') - .reply(200, { tags: ['some'] }, {}); + it.each([{ host: 'public.ecr.aws' }, { host: 'ecr-public.aws.com' }])( + 'uses lower tag limit for ECR Public deps for host $host', + async ({ host }) => { + httpMock + .scope(`https://${host}`) + .get('/v2/amazonlinux/amazonlinux/tags/list?n=1000') + .reply(401, '', { + 'www-authenticate': `Bearer realm="https://${host}/token",service="public.ecr.aws",scope="aws"`, + }) + .get('/token?service=public.ecr.aws&scope=aws') + .reply(200, { token: 'test' }); + httpMock + .scope(`https://${host}`, { + reqheaders: { + authorization: 'Bearer test', + }, + }) + // The tag limit parameter `n` needs to be limited to 1000 for ECR Public + // See https://docs.aws.amazon.com/AmazonECRPublic/latest/APIReference/API_DescribeRepositories.html#ecrpublic-DescribeRepositories-request-maxResults + .get('/v2/amazonlinux/amazonlinux/tags/list?n=1000') + .reply(200, { tags: ['some'] }, {}); - httpMock - .scope('https://public.ecr.aws') - .get('/v2/') - .reply(401, '', { - 'www-authenticate': - 'Bearer realm="https://public.ecr.aws/token",service="public.ecr.aws",scope="aws"', - }) - .get( - '/token?service=public.ecr.aws&scope=repository:amazonlinux/amazonlinux:pull', - ) - .reply(200, { token: 'test' }); - httpMock - .scope('https://public.ecr.aws', { - reqheaders: { - authorization: 'Bearer test', - }, - }) - .get('/v2/amazonlinux/amazonlinux/manifests/some') - .reply(200); + httpMock + .scope(`https://${host}`) + .get('/v2/') + .reply(401, '', { + 'www-authenticate': `Bearer realm="https://${host}/token",service="public.ecr.aws",scope="aws"`, + }) + .get( + '/token?service=public.ecr.aws&scope=repository:amazonlinux/amazonlinux:pull', + ) + .reply(200, { token: 'test' }); + httpMock + .scope(`https://${host}`, { + reqheaders: { + authorization: 'Bearer test', + }, + }) + .get('/v2/amazonlinux/amazonlinux/manifests/some') + .reply(200); - expect( - await getPkgReleases({ - datasource: DockerDatasource.id, - packageName: 'public.ecr.aws/amazonlinux/amazonlinux', - }), - ).toEqual({ - lookupName: 'amazonlinux/amazonlinux', - registryUrl: 'https://public.ecr.aws', - releases: [], - }); - }); + expect( + await getPkgReleases({ + datasource: DockerDatasource.id, + packageName: `${host}/amazonlinux/amazonlinux`, + }), + ).toEqual({ + lookupName: 'amazonlinux/amazonlinux', + registryUrl: `https://${host}`, + releases: [], + }); + }, + ); describe('when making requests that interact with an ECR proxy', () => { it('resolves requests to ECR proxy', async () => { diff --git a/lib/modules/datasource/github-releases/readme.md b/lib/modules/datasource/github-releases/readme.md new file mode 100644 index 00000000000..269bdf4d980 --- /dev/null +++ b/lib/modules/datasource/github-releases/readme.md @@ -0,0 +1,4 @@ +This datasource allows lookup releases from GitHub.com and GitHub Enterprise repositories. + +- `registryUrl`: The URL of the GitHub registry to use. Defaults to `https://github.com/`. +- `packageName`: The name of the repository to lookup. in the format `owner/repo`. e.g. `renovatebot/renovate`. diff --git a/lib/modules/datasource/github-tags/readme.md b/lib/modules/datasource/github-tags/readme.md new file mode 100644 index 00000000000..a5f3417d7a3 --- /dev/null +++ b/lib/modules/datasource/github-tags/readme.md @@ -0,0 +1,4 @@ +This datasource allows lookup Git tags from GitHub.com and GitHub Enterprise repositories. + +- `registryUrl`: The URL of the GitHub registry to use. Defaults to `https://github.com/`. +- `packageName`: The name of the repository to lookup. in the format `owner/repo`. e.g. `renovatebot/renovate`. diff --git a/lib/modules/manager/asdf/extract.spec.ts b/lib/modules/manager/asdf/extract.spec.ts index 16371509ef1..c5a787fcd83 100644 --- a/lib/modules/manager/asdf/extract.spec.ts +++ b/lib/modules/manager/asdf/extract.spec.ts @@ -56,6 +56,7 @@ bun 0.2.2 cargo-make 0.36.2 checkov 2.3.3 clojure 1.11.1.1182 +clusterctl 1.9.8 conftest 0.56.0 container-structure-test 1.19.2 cosign 2.2.4 @@ -232,6 +233,13 @@ dummy 1.2.3 'regex:^(?\\d+?)\\.(?\\d+?)\\.(?\\d+)\\.(?\\d+)$', depName: 'clojure', }, + { + currentValue: '1.9.8', + datasource: 'github-releases', + packageName: 'kubernetes-sigs/cluster-api', + depName: 'clusterctl', + extractVersion: '^v(?\\S+)', + }, { currentValue: '0.56.0', datasource: 'github-releases', diff --git a/lib/modules/manager/asdf/upgradeable-tooling.ts b/lib/modules/manager/asdf/upgradeable-tooling.ts index 58b712763f3..59d596b0202 100644 --- a/lib/modules/manager/asdf/upgradeable-tooling.ts +++ b/lib/modules/manager/asdf/upgradeable-tooling.ts @@ -132,6 +132,14 @@ export const upgradeableTooling: Record = { versioning: `${regexVersioning.id}:^(?\\d+?)\\.(?\\d+?)\\.(?\\d+)\\.(?\\d+)$`, }, }, + clusterctl: { + asdfPluginUrl: 'https://github.com/pfnet-research/asdf-clusterctl', + config: { + datasource: GithubReleasesDatasource.id, + packageName: 'kubernetes-sigs/cluster-api', + extractVersion: '^v(?\\S+)', + }, + }, conftest: { asdfPluginUrl: 'https://github.com/looztra/asdf-conftest', config: { diff --git a/lib/modules/manager/azure-pipelines/readme.md b/lib/modules/manager/azure-pipelines/readme.md index ff597220dff..de269e834ed 100644 --- a/lib/modules/manager/azure-pipelines/readme.md +++ b/lib/modules/manager/azure-pipelines/readme.md @@ -44,7 +44,7 @@ resources: - container: linux image: ubuntu:24.04 - container: python - image: python:3.13@sha256:a4b2b11a9faf847c52ad07f5e0d4f34da59bad9d8589b8f2c476165d94c6b377 + image: python:3.13@sha256:eb120d016adcbc8bac194e15826bbb4f1d1569d298d8817bb5049ed5e59f41d9 stages: - stage: StageOne diff --git a/lib/modules/manager/bazel-module/extract.spec.ts b/lib/modules/manager/bazel-module/extract.spec.ts index c85c4dda8c3..109ee78c469 100644 --- a/lib/modules/manager/bazel-module/extract.spec.ts +++ b/lib/modules/manager/bazel-module/extract.spec.ts @@ -62,10 +62,8 @@ describe('modules/manager/bazel-module/extract', () => { remote = "https://github.com/example/rules_foo.git", ) `; + const result = await extractPackageFile(input, 'MODULE.bazel'); - if (!result) { - throw new Error('Expected a result.'); - } expect(result).toEqual({ deps: [ @@ -102,10 +100,8 @@ describe('modules/manager/bazel-module/extract', () => { remote = "https://github.com/example/rules_foo.git", ) `; + const result = await extractPackageFile(input, 'MODULE.bazel'); - if (!result) { - throw new Error('Expected a result.'); - } expect(result).toEqual({ deps: [ { @@ -128,10 +124,8 @@ describe('modules/manager/bazel-module/extract', () => { it('returns dependencies and custom registry URLs when specified in a bazelrc', async () => { const packageFile = 'extract/multiple-bazelrcs/MODULE.bazel'; const input = Fixtures.get(packageFile); + const result = await extractPackageFile(input, packageFile); - if (!result) { - throw new Error('Expected a result.'); - } expect(result).toEqual({ registryUrls: [ 'https://example.com/custom_registry.git', @@ -158,10 +152,8 @@ describe('modules/manager/bazel-module/extract', () => { ], ) `; + const result = await extractPackageFile(input, 'MODULE.bazel'); - if (!result) { - throw new Error('Expected a result.'); - } expect(result).toEqual({ deps: [ @@ -191,10 +183,8 @@ describe('modules/manager/bazel-module/extract', () => { ], ) `; + const result = await extractPackageFile(input, 'MODULE.bazel'); - if (!result) { - throw new Error('Expected a result.'); - } expect(result).toEqual({ deps: [ @@ -221,10 +211,8 @@ describe('modules/manager/bazel-module/extract', () => { urls = "/path/to/repo", ) `; + const result = await extractPackageFile(input, 'MODULE.bazel'); - if (!result) { - throw new Error('Expected a result.'); - } expect(result).toEqual({ deps: [ @@ -252,10 +240,8 @@ describe('modules/manager/bazel-module/extract', () => { urls = "/path/to/repo", ) `; + const result = await extractPackageFile(input, 'MODULE.bazel'); - if (!result) { - throw new Error('Expected a result.'); - } expect(result).toEqual({ deps: [ @@ -283,10 +269,8 @@ describe('modules/manager/bazel-module/extract', () => { registry = "https://example.com/custom_registry", ) `; + const result = await extractPackageFile(input, 'MODULE.bazel'); - if (!result) { - throw new Error('Expected a result.'); - } expect(result).toEqual({ deps: [ @@ -318,10 +302,8 @@ describe('modules/manager/bazel-module/extract', () => { registry = "https://example.com/custom_registry", ) `; + const result = await extractPackageFile(input, 'MODULE.bazel'); - if (!result) { - throw new Error('Expected a result.'); - } expect(result).toEqual({ deps: [ @@ -351,10 +333,8 @@ describe('modules/manager/bazel-module/extract', () => { registry = "https://example.com/custom_registry", ) `; + const result = await extractPackageFile(input, 'MODULE.bazel'); - if (!result) { - throw new Error('Expected a result.'); - } expect(result).toEqual({ deps: [ @@ -412,10 +392,8 @@ describe('modules/manager/bazel-module/extract', () => { version_conflict_policy = "pinned", ) `; + const result = await extractPackageFile(input, 'MODULE.bazel'); - if (!result) { - throw new Error('Expected a result.'); - } expect(result).toEqual({ deps: [ @@ -459,9 +437,6 @@ describe('modules/manager/bazel-module/extract', () => { `; const result = await extractPackageFile(input, 'MODULE.bazel'); - if (!result) { - throw new Error('Expected a result.'); - } expect(result).toEqual({ deps: [ @@ -498,9 +473,6 @@ describe('modules/manager/bazel-module/extract', () => { `; const result = await extractPackageFile(input, 'MODULE.bazel'); - if (!result) { - throw new Error('Expected a result.'); - } expect(result).toEqual({ deps: [ @@ -542,10 +514,8 @@ describe('modules/manager/bazel-module/extract', () => { version_conflict_policy = "pinned", ) `; + const result = await extractPackageFile(input, 'MODULE.bazel'); - if (!result) { - throw new Error('Expected a result.'); - } expect(result).toEqual({ deps: [ @@ -575,24 +545,72 @@ describe('modules/manager/bazel-module/extract', () => { }); }); - it('returns git_repository dependencies', async () => { + it('returns git_repository dependencies with digest', async () => { const input = codeBlock` git_repository( + name = "rules_foo", + commit = "850cb49c8649e463b80ef7984e7c744279746170", + remote = "https://github.com/example/rules_foo.git" + ) + `; + + const result = await extractPackageFile(input, 'MODULE.bazel'); + + expect(result).toEqual({ + deps: [ + { + depType: 'git_repository', + depName: 'rules_foo', + currentDigest: '850cb49c8649e463b80ef7984e7c744279746170', + datasource: GithubTagsDatasource.id, + packageName: 'example/rules_foo', + }, + ], + }); + }); + + it('returns git_repository dependencies with tag', async () => { + const input = codeBlock` + git_repository( + name = "rules_foo", + tag = "1.2.3", + remote = "https://github.com/example/rules_foo.git" + ) + `; + + const result = await extractPackageFile(input, 'MODULE.bazel'); + + expect(result).toEqual({ + deps: [ + { + depType: 'git_repository', + depName: 'rules_foo', + currentValue: '1.2.3', + datasource: GithubTagsDatasource.id, + packageName: 'example/rules_foo', + }, + ], + }); + }); + + it('returns new_git_repository dependencies', async () => { + const input = codeBlock` + new_git_repository( name = "rules_foo", commit = "850cb49c8649e463b80ef7984e7c744279746170", remote = "https://github.com/example/rules_foo.git", + tag = "1.2.3" ) `; + const result = await extractPackageFile(input, 'MODULE.bazel'); - if (!result) { - throw new Error('Expected a result.'); - } expect(result).toEqual({ deps: [ { - depType: 'git_repository', + depType: 'new_git_repository', depName: 'rules_foo', + currentValue: '1.2.3', currentDigest: '850cb49c8649e463b80ef7984e7c744279746170', datasource: GithubTagsDatasource.id, packageName: 'example/rules_foo', diff --git a/lib/modules/manager/bazel-module/parser/rules.ts b/lib/modules/manager/bazel-module/parser/rules.ts index 016b0270f71..a71da4f3951 100644 --- a/lib/modules/manager/bazel-module/parser/rules.ts +++ b/lib/modules/manager/bazel-module/parser/rules.ts @@ -20,6 +20,7 @@ const supportedRules = [ 'local_path_override', 'single_version_override', 'git_repository', + 'new_git_repository', ]; const supportedRulesRegex = regEx(`^${supportedRules.join('|')}$`); diff --git a/lib/modules/manager/bazel-module/rules.ts b/lib/modules/manager/bazel-module/rules.ts index 342498f2c51..e5c159a1872 100644 --- a/lib/modules/manager/bazel-module/rules.ts +++ b/lib/modules/manager/bazel-module/rules.ts @@ -239,24 +239,35 @@ export function toPackageDependencies( } export const GitRepositoryToPackageDep = RuleFragmentSchema.extend({ - rule: z.literal('git_repository'), + rule: z.union([z.literal('git_repository'), z.literal('new_git_repository')]), children: z.object({ name: StringFragmentSchema, remote: StringFragmentSchema, - commit: StringFragmentSchema, + commit: StringFragmentSchema.optional(), + tag: StringFragmentSchema.optional(), }), -}).transform(({ rule, children: { name, remote, commit } }): BasePackageDep => { - const gitRepo: BasePackageDep = { - depType: rule, - depName: name.value, - currentDigest: commit.value, - }; - const ghPackageName = githubPackageName(remote.value); - if (is.nonEmptyString(ghPackageName)) { - gitRepo.datasource = GithubTagsDatasource.id; - gitRepo.packageName = ghPackageName; - } else { - gitRepo.skipReason = 'unsupported-datasource'; - } - return gitRepo; -}); +}).transform( + ({ rule, children: { name, remote, commit, tag } }): BasePackageDep => { + const gitRepo: BasePackageDep = { + depType: rule, + depName: name.value, + }; + + if (commit?.value) { + gitRepo.currentDigest = commit.value; + } + + if (tag?.value) { + gitRepo.currentValue = tag.value; + } + + const ghPackageName = githubPackageName(remote.value); + if (is.nonEmptyString(ghPackageName)) { + gitRepo.datasource = GithubTagsDatasource.id; + gitRepo.packageName = ghPackageName; + } else { + gitRepo.skipReason = 'unsupported-datasource'; + } + return gitRepo; + }, +); diff --git a/lib/modules/manager/bazel/__fixtures__/WORKSPACE1 b/lib/modules/manager/bazel/__fixtures__/WORKSPACE1 index 8d3b35bfb95..c54d3390c0b 100644 --- a/lib/modules/manager/bazel/__fixtures__/WORKSPACE1 +++ b/lib/modules/manager/bazel/__fixtures__/WORKSPACE1 @@ -28,7 +28,7 @@ git_repository( load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories") node_repositories(package_json = ["//:package.json"]) -git_repository( +new_git_repository( name = "build_bazel_rules_typescript", remote = "https://github.com/bazelbuild/rules_typescript.git", tag = "0.6.1", diff --git a/lib/modules/manager/bazel/__snapshots__/extract.spec.ts.snap b/lib/modules/manager/bazel/__snapshots__/extract.spec.ts.snap index aa33c1c31b7..2bc7e3a65e7 100644 --- a/lib/modules/manager/bazel/__snapshots__/extract.spec.ts.snap +++ b/lib/modules/manager/bazel/__snapshots__/extract.spec.ts.snap @@ -47,7 +47,7 @@ exports[`modules/manager/bazel/extract > extractPackageFile() > extracts multipl "currentValue": "0.6.1", "datasource": "github-releases", "depName": "build_bazel_rules_typescript", - "depType": "git_repository", + "depType": "new_git_repository", "managerData": { "idx": 4, }, diff --git a/lib/modules/manager/bazel/rules/git.ts b/lib/modules/manager/bazel/rules/git.ts index 9e7a4813ad6..b30bf647b62 100644 --- a/lib/modules/manager/bazel/rules/git.ts +++ b/lib/modules/manager/bazel/rules/git.ts @@ -19,7 +19,12 @@ function githubPackageName(input: string): string | undefined { return parseGithubUrl(input)?.match(githubUrlRegex)?.groups?.packageName; } -export const gitRules = ['git_repository', '_git_repository'] as const; +export const gitRules = [ + 'git_repository', + '_git_repository', + 'new_git_repository', + '_new_git_repository', +] as const; export const GitTarget = z .object({ diff --git a/lib/modules/manager/bazel/rules/index.spec.ts b/lib/modules/manager/bazel/rules/index.spec.ts index dd2507a5c9f..365b47c3074 100644 --- a/lib/modules/manager/bazel/rules/index.spec.ts +++ b/lib/modules/manager/bazel/rules/index.spec.ts @@ -98,6 +98,23 @@ describe('modules/manager/bazel/rules/index', () => { }, ]); + expect( + extractDepsFromFragmentData({ + rule: 'new_git_repository', + name: 'foo_bar', + commit: 'abcdef0123abcdef0123abcdef0123abcdef0123', + remote: 'https://github.com/foo/bar', + }), + ).toEqual([ + { + datasource: 'github-tags', + depType: 'new_git_repository', + depName: 'foo_bar', + packageName: 'foo/bar', + currentDigest: 'abcdef0123abcdef0123abcdef0123abcdef0123', + }, + ]); + expect( extractDepsFromFragmentData({ rule: 'git_repository', diff --git a/lib/modules/manager/docker-compose/extract.spec.ts b/lib/modules/manager/docker-compose/extract.spec.ts index df5a236de91..52170761f69 100644 --- a/lib/modules/manager/docker-compose/extract.spec.ts +++ b/lib/modules/manager/docker-compose/extract.spec.ts @@ -194,5 +194,40 @@ describe('modules/manager/docker-compose/extract', () => { ], }); }); + + it('extract images from fragments', () => { + const compose = codeBlock` + --- + x-shared_setting: &shared_settings + image: debian:11 + # Other shared properties here + + services: + service-a: + <<: *shared_settings + environment: + - SERVICE=a + service-b: + <<: *shared_settings + environment: + - SERVICE=b + `; + const res = extractPackageFile(compose, '', {}); + expect(res).toEqual({ + deps: [ + { + autoReplaceStringTemplate: + '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: undefined, + currentValue: '11', + datasource: 'docker', + depName: 'debian', + packageName: 'debian', + replaceString: 'debian:11', + versioning: 'debian', + }, + ], + }); + }); }); }); diff --git a/lib/modules/manager/docker-compose/extract.ts b/lib/modules/manager/docker-compose/extract.ts index c82a4fce207..26108974b95 100644 --- a/lib/modules/manager/docker-compose/extract.ts +++ b/lib/modules/manager/docker-compose/extract.ts @@ -56,12 +56,14 @@ export function extractPackageFile( // become optional and can no longer be used to differentiate // between v1 and v2. const services = config.services ?? config; + const extensions = config.extensions ?? {}; // Image name/tags for services are only eligible for update if they don't // use variables and if the image is not built locally const deps = Object.values( services || /* istanbul ignore next: can never happen */ {}, ) + .concat(Object.values(extensions)) .filter((service) => is.string(service?.image) && !service?.build) .map((service) => { const dep = getDep(service.image, true, extractConfig.registryAliases); diff --git a/lib/modules/manager/docker-compose/schema.ts b/lib/modules/manager/docker-compose/schema.ts index ec11990ccc6..e1e7f0975f2 100644 --- a/lib/modules/manager/docker-compose/schema.ts +++ b/lib/modules/manager/docker-compose/schema.ts @@ -1,3 +1,4 @@ +import is from '@sindresorhus/is'; import { z } from 'zod'; const DockerComposeService = z.object({ @@ -14,13 +15,52 @@ const DockerComposeService = z.object({ }); const DockerComposeFileV1 = z.record(DockerComposeService); -const DockerComposeFileModern = z.object({ - // compose does not use this strictly, so we shouldn't be either - // https://docs.docker.com/compose/compose-file/04-version-and-name/#version-top-level-element - version: z.string().optional(), - services: z.record(DockerComposeService), -}); +const DockerComposeFileModern = z + .object({ + /** + * compose does not use this strictly, so we shouldn't be either + * https://docs.docker.com/compose/compose-file/04-version-and-name/#version-top-level-element + */ + version: z.string().optional(), + services: z.record(DockerComposeService), + }) + // using catchall to capture fields starting with `x-` and collecting them in `extensions` field + // might need to replace this with something better once zod v4 is stable + .catchall(z.unknown()) + .transform( + ( + obj, + ): { + version?: string; + services: Record>; + extensions?: Record; + } => { + const { version, services, ...rest } = obj; + + let extensions: Record | undefined; + + // collect extensions which have image field + // https://docs.docker.com/reference/compose-file/extensions/ + for (const key in rest) { + if (key.startsWith('x-')) { + const value = rest[key]; + if (is.object(value) && 'image' in value && is.string(value.image)) { + extensions ??= {}; + extensions[key] = { image: value.image }; + } + } + } + + return { + version, + services, + ...(extensions && { extensions }), + }; + }, + ); -export const DockerComposeFile = - DockerComposeFileModern.or(DockerComposeFileV1); +export const DockerComposeFile = z.union([ + DockerComposeFileModern, + DockerComposeFileV1, +]); export type DockerComposeFile = z.infer; diff --git a/lib/modules/manager/fleet/__fixtures__/valid_fleet_helm_target_customization.yaml b/lib/modules/manager/fleet/__fixtures__/valid_fleet_helm_target_customization.yaml index 8078125b8a7..0df1668477e 100644 --- a/lib/modules/manager/fleet/__fixtures__/valid_fleet_helm_target_customization.yaml +++ b/lib/modules/manager/fleet/__fixtures__/valid_fleet_helm_target_customization.yaml @@ -1,3 +1,5 @@ +# This should generate two dependencies with different versions +# one with v1.8.0 and one with v1.9.2 defaultNamespace: cert-manager helm: chart: cert-manager @@ -11,6 +13,8 @@ targetCustomizations: helm: version: "v1.9.2" --- +# This should generate two dependencies with different repos +# one with https://charts.jetstack.io and one with https://charts.example.com defaultNamespace: cert-manager helm: chart: cert-manager @@ -26,6 +30,7 @@ targetCustomizations: repo: https://charts.example.com --- +# This should generate one dependency and a skipped dependency, as there is no version defaultNamespace: cert-manager helm: chart: cert-manager @@ -38,3 +43,18 @@ targetCustomizations: - name: cluster1 values: some: customization + +--- +# This is a valid target customization with no name +# It should generate one valid dependency, and one skipped dependency, like the one above +defaultNamespace: cert-manager +helm: + chart: cert-manager + repo: https://charts.jetstack.io + releaseName: custom-cert-manager + version: v1.8.0 + values: + installCRDs: true +targetCustomizations: + - values: + some: customization diff --git a/lib/modules/manager/fleet/extract.spec.ts b/lib/modules/manager/fleet/extract.spec.ts index 1f1cf489ff5..2833eff4ab0 100644 --- a/lib/modules/manager/fleet/extract.spec.ts +++ b/lib/modules/manager/fleet/extract.spec.ts @@ -137,6 +137,22 @@ kind: Fleet depType: 'fleet', skipReason: 'unspecified-version', }, + { + currentValue: 'v1.8.0', + datasource: 'helm', + depName: 'cert-manager', + packageName: 'cert-manager', + registryUrls: ['https://charts.jetstack.io'], + depType: 'fleet', + }, + { + datasource: 'helm', + depName: 'targetCustomization[0]', + packageName: 'cert-manager', + registryUrls: ['https://charts.jetstack.io'], + depType: 'fleet', + skipReason: 'unspecified-version', + }, ]); }); diff --git a/lib/modules/manager/fleet/extract.ts b/lib/modules/manager/fleet/extract.ts index 6470f40b4dc..47c055965de 100644 --- a/lib/modules/manager/fleet/extract.ts +++ b/lib/modules/manager/fleet/extract.ts @@ -109,7 +109,7 @@ function extractFleetFile(doc: FleetFile): PackageDependency[] { const helmBlockContext: FleetHelmBlock = { ...doc.helm }; delete helmBlockContext.version; - for (const custom of doc.targetCustomizations) { + for (const [index, custom] of doc.targetCustomizations.entries()) { const dep = extractFleetHelmBlock({ // merge base config with customization ...helmBlockContext, @@ -118,7 +118,7 @@ function extractFleetFile(doc: FleetFile): PackageDependency[] { result.push({ // overwrite name with customization name to allow splitting of PRs ...dep, - depName: custom.name, + depName: custom.name ?? `targetCustomization[${index}]`, // if no name is provided, use the index }); } } diff --git a/lib/modules/manager/fleet/schema.ts b/lib/modules/manager/fleet/schema.ts index fffc392e223..94f6f07e96a 100644 --- a/lib/modules/manager/fleet/schema.ts +++ b/lib/modules/manager/fleet/schema.ts @@ -33,7 +33,7 @@ export const FleetFile = z.object({ targetCustomizations: z .array( z.object({ - name: z.string(), + name: z.string().optional(), helm: FleetHelmBlock.partial().optional(), }), ) diff --git a/lib/modules/manager/gleam/artifacts.spec.ts b/lib/modules/manager/gleam/artifacts.spec.ts index 45f4a376bc6..deead2d71f0 100644 --- a/lib/modules/manager/gleam/artifacts.spec.ts +++ b/lib/modules/manager/gleam/artifacts.spec.ts @@ -1,13 +1,12 @@ import { GlobalConfig } from '../../../config/global'; import type { RepoGlobalConfig } from '../../../config/types'; import { TEMPORARY_ERROR } from '../../../constants/error-messages'; -import { exec } from '../../../util/exec'; import { ExecError } from '../../../util/exec/exec-error'; import type { UpdateArtifact } from '../types'; import { updateArtifacts } from '.'; +import { exec, mockExecAll } from '~test/exec-util'; import { fs } from '~test/util'; -vi.mock('../../../util/exec'); vi.mock('../../../util/fs'); const globalConfig: RepoGlobalConfig = { @@ -49,14 +48,20 @@ describe('modules/manager/gleam/artifacts', () => { fs.readLocalFile.mockResolvedValueOnce('old'); fs.readLocalFile.mockResolvedValueOnce(null); fs.getSiblingFileName.mockReturnValueOnce('manifest.toml'); + const execSnapshots = mockExecAll(); expect(await updateArtifacts(updateArtifact)).toBeNull(); + expect(execSnapshots).toBeArrayOfSize(1); + expect(execSnapshots[0].cmd).toEqual('gleam deps update'); }); it('returns null if lock content unchanged', async () => { updateArtifact.updatedDeps = [{ manager: 'gleam' }]; fs.readLocalFile.mockResolvedValueOnce('old'); fs.readLocalFile.mockResolvedValueOnce('old'); + const execSnapshots = mockExecAll(); expect(await updateArtifacts(updateArtifact)).toBeNull(); + expect(execSnapshots).toBeArrayOfSize(1); + expect(execSnapshots[0].cmd).toEqual('gleam deps update'); }); it('returns updated lock content', async () => { @@ -64,6 +69,7 @@ describe('modules/manager/gleam/artifacts', () => { fs.readLocalFile.mockResolvedValueOnce('old'); fs.readLocalFile.mockResolvedValueOnce('new'); fs.getSiblingFileName.mockReturnValueOnce('manifest.toml'); + const execSnapshots = mockExecAll(); expect(await updateArtifacts(updateArtifact)).toEqual([ { file: { @@ -73,6 +79,8 @@ describe('modules/manager/gleam/artifacts', () => { }, }, ]); + expect(execSnapshots).toBeArrayOfSize(1); + expect(execSnapshots[0].cmd).toEqual('gleam deps update'); }); it('supports lockFileMaintenance', async () => { @@ -81,6 +89,7 @@ describe('modules/manager/gleam/artifacts', () => { fs.readLocalFile.mockResolvedValueOnce('old'); fs.readLocalFile.mockResolvedValueOnce('new'); fs.getSiblingFileName.mockReturnValueOnce('manifest.toml'); + const execSnapshots = mockExecAll(); expect(await updateArtifacts(updateArtifact)).toEqual([ { file: { @@ -90,6 +99,8 @@ describe('modules/manager/gleam/artifacts', () => { }, }, ]); + expect(execSnapshots).toBeArrayOfSize(1); + expect(execSnapshots[0].cmd).toEqual('gleam deps update'); }); it('returns null if lockfile content unchanged', async () => { @@ -98,7 +109,10 @@ describe('modules/manager/gleam/artifacts', () => { fs.readLocalFile.mockResolvedValueOnce('old'); fs.readLocalFile.mockResolvedValueOnce('old'); fs.getSiblingFileName.mockReturnValueOnce('manifest.toml'); + const execSnapshots = mockExecAll(); expect(await updateArtifacts(updateArtifact)).toBeNull(); + expect(execSnapshots).toBeArrayOfSize(1); + expect(execSnapshots[0].cmd).toEqual('gleam deps update'); }); it('handles temporary error', async () => { @@ -111,7 +125,7 @@ describe('modules/manager/gleam/artifacts', () => { updateArtifact.updatedDeps = [{ manager: 'gleam' }]; fs.readLocalFile.mockResolvedValueOnce('old'); fs.getSiblingFileName.mockReturnValueOnce('manifest.toml'); - vi.mocked(exec).mockRejectedValueOnce(execError); + exec.mockRejectedValueOnce(execError); await expect(updateArtifacts(updateArtifact)).rejects.toThrow( TEMPORARY_ERROR, ); @@ -138,7 +152,7 @@ describe('modules/manager/gleam/artifacts', () => { updateArtifact.updatedDeps = [{ manager: 'gleam' }]; const oldLock = Buffer.from('old'); fs.readLocalFile.mockResolvedValueOnce(oldLock.toString()); - vi.mocked(exec).mockRejectedValueOnce(execError); + exec.mockRejectedValueOnce(execError); fs.getSiblingFileName.mockReturnValueOnce('manifest.toml'); expect(await updateArtifacts(updateArtifact)).toEqual([ { @@ -149,5 +163,19 @@ describe('modules/manager/gleam/artifacts', () => { }, ]); }); + + it('prevents injections', async () => { + updateArtifact.updatedDeps = [{ depName: '|| date' }]; + fs.readLocalFile.mockResolvedValueOnce('old'); + fs.readLocalFile.mockResolvedValueOnce('new'); + fs.getSiblingFileName.mockReturnValueOnce('manifest.toml'); + const execSnapshots = mockExecAll(); + await updateArtifacts(updateArtifact); + expect(execSnapshots).toMatchObject([ + { + cmd: `gleam deps update '|| date'`, + }, + ]); + }); }); }); diff --git a/lib/modules/manager/gleam/artifacts.ts b/lib/modules/manager/gleam/artifacts.ts index d848a9251f6..45b0fe698f4 100644 --- a/lib/modules/manager/gleam/artifacts.ts +++ b/lib/modules/manager/gleam/artifacts.ts @@ -1,4 +1,5 @@ import is from '@sindresorhus/is'; +import { quote } from 'shlex'; import { TEMPORARY_ERROR } from '../../../constants/error-messages'; import { logger } from '../../../logger'; import { exec } from '../../../util/exec'; @@ -54,7 +55,10 @@ export async function updateArtifacts( ? [] : updatedDeps.map((dep) => dep.depName).filter(is.string); - const updateCommand = ['gleam deps update', ...packagesToUpdate].join(' '); + const updateCommand = [ + 'gleam deps update', + ...packagesToUpdate.map(quote), + ].join(' '); await exec(updateCommand, execOptions); const newLockFileContent = await readLocalFile(lockFileName, 'utf8'); if (!newLockFileContent) { diff --git a/lib/modules/manager/gradle/parser.spec.ts b/lib/modules/manager/gradle/parser.spec.ts index e9fce9721ba..fbd4325d893 100644 --- a/lib/modules/manager/gradle/parser.spec.ts +++ b/lib/modules/manager/gradle/parser.spec.ts @@ -386,6 +386,7 @@ describe('modules/manager/gradle/parser', () => { ${'"foo:bar:1.2.3"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }} ${'"foo:bar:1.2+"'} | ${{ depName: 'foo:bar', currentValue: '1.2+' }} ${'"foo:bar:1.2.3@zip"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', dataType: 'zip' }} + ${'"foo:bar:1.2.3:docs@jar"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', dataType: 'jar' }} ${'"foo:bar1:1"'} | ${{ depName: 'foo:bar1', currentValue: '1', managerData: { fileReplacePosition: 10 } }} ${'"foo:bar:[1.2.3, )"'} | ${{ depName: 'foo:bar', currentValue: '[1.2.3, )', managerData: { fileReplacePosition: 9 } }} ${'"foo:bar:[1.2.3, 1.2.4)"'} | ${{ depName: 'foo:bar', currentValue: '[1.2.3, 1.2.4)', managerData: { fileReplacePosition: 9 } }} diff --git a/lib/modules/manager/gradle/utils.spec.ts b/lib/modules/manager/gradle/utils.spec.ts index 2d9b25c4d19..e0cba122642 100644 --- a/lib/modules/manager/gradle/utils.spec.ts +++ b/lib/modules/manager/gradle/utils.spec.ts @@ -57,6 +57,7 @@ describe('modules/manager/gradle/utils', () => { ${'foo.foo:bar.bar:1.2.3'} | ${true} ${'foo.bar:baz:1.2.3'} | ${true} ${'foo.bar:baz:1.2.3:linux-cpu-x86_64'} | ${true} + ${'foo.bar:baz:1.2.3:sources@zip'} | ${true} ${'foo:bar:1.2.3@zip'} | ${true} ${'foo:bar:x86@x86'} | ${true} ${'foo.bar:baz:1.2.+'} | ${true} @@ -86,6 +87,8 @@ describe('modules/manager/gradle/utils', () => { ${'foo:bar:1.2.+'} | ${{ depName: 'foo:bar', currentValue: '1.2.+' }} ${'foo.bar:baz:[1.6.0, ]'} | ${{ depName: 'foo.bar:baz', currentValue: '[1.6.0, ]' }} ${'foo:bar:1.2.3@zip'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', dataType: 'zip' }} + ${'foo:bar:1.2.3:docs'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }} + ${'foo:bar:1.2.3:docs@jar'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', dataType: 'jar' }} ${'foo:bar:baz:qux'} | ${null} ${'foo:bar:baz:qux:quux'} | ${null} ${"foo:bar:1.2.3'"} | ${null} diff --git a/lib/modules/manager/gradle/utils.ts b/lib/modules/manager/gradle/utils.ts index 58bd904678a..99886f88d1b 100644 --- a/lib/modules/manager/gradle/utils.ts +++ b/lib/modules/manager/gradle/utils.ts @@ -36,24 +36,17 @@ export function versionLikeSubstring( } export function isDependencyString(input: string): boolean { - const parts = input.split(':'); - if (parts.length !== 3 && parts.length !== 4) { + const [depNotation, ...extra] = input.split('@'); + if (extra.length > 1) { return false; } - const [groupId, artifactId, versionPart, optionalClassifier] = parts; - if (optionalClassifier && !artifactRegex.test(optionalClassifier)) { + const parts = depNotation.split(':'); + if (parts.length !== 3 && parts.length !== 4) { return false; } - let version = versionPart; - if (versionPart.includes('@')) { - const [actualVersion, ...rest] = versionPart.split('@'); - if (rest.length !== 1) { - return false; - } - version = actualVersion; - } + const [groupId, artifactId, version, classifier] = parts; return !!( groupId && @@ -61,6 +54,7 @@ export function isDependencyString(input: string): boolean { version && artifactRegex.test(groupId) && artifactRegex.test(artifactId) && + (!classifier || artifactRegex.test(classifier)) && version === versionLikeSubstring(version) ); } @@ -72,8 +66,8 @@ export function parseDependencyString( return null; } - const [groupId, artifactId, fullValue] = input.split(':'); - const [currentValue, dataType] = fullValue.split('@'); + const [depNotation, dataType] = input.split('@'); + const [groupId, artifactId, currentValue] = depNotation.split(':'); return { depName: `${groupId}:${artifactId}`, diff --git a/lib/modules/manager/helmv3/artifacts.spec.ts b/lib/modules/manager/helmv3/artifacts.spec.ts index f4aa3a3b941..8d475ef600a 100644 --- a/lib/modules/manager/helmv3/artifacts.spec.ts +++ b/lib/modules/manager/helmv3/artifacts.spec.ts @@ -1,6 +1,7 @@ import type { GetAuthorizationTokenCommandOutput } from '@aws-sdk/client-ecr'; import { ECRClient, GetAuthorizationTokenCommand } from '@aws-sdk/client-ecr'; import { mockClient } from 'aws-sdk-client-mock'; +import { codeBlock } from 'common-tags'; import { join } from 'upath'; import { mockDeep } from 'vitest-mock-extended'; import { GlobalConfig } from '../../../config/global'; @@ -111,6 +112,45 @@ describe('modules/manager/helmv3/artifacts', () => { expect(execSnapshots).toMatchSnapshot(); }); + it('returns null if only "generated" is changed', async () => { + fs.readLocalFile.mockResolvedValueOnce(codeBlock` + dependencies: + - name: renovate-test + repository: oci://registry.gitlab.com/user/oci-helm-test + version: 0.1.0 + digest: sha256:886f204516ea48785fe615d22071d742f7fb0d6519ed3cd274f4ec0978d8b82b + generated: "2022-01-20T17:48:47.610371241+01:00" + `); + fs.getSiblingFileName.mockReturnValueOnce('Chart.lock'); + const execMocks = mockExecAll(); + fs.readLocalFile.mockResolvedValueOnce(codeBlock` + dependencies: + - name: renovate-test + repository: oci://registry.gitlab.com/user/oci-helm-test + version: 0.1.0 + digest: sha256:886f204516ea48785fe615d22071d742f7fb0d6519ed3cd274f4ec0978d8b82b + generated: "2025-01-20T17:48:47.610371241+01:00" + `); + fs.privateCacheDir.mockReturnValue( + '/tmp/renovate/cache/__renovate-private-cache', + ); + fs.getParentDir.mockReturnValue(''); + const updatedDeps = [{ depName: 'dep1' }]; + expect( + await helmv3.updateArtifacts({ + packageFileName: 'Chart.yaml', + updatedDeps, + newPackageFileContent: chartFile, + config, + }), + ).toBeNull(); + expect(execMocks).toBeArrayOfSize(2); + expect(execMocks[0].cmd).toBe( + 'helm repo add repo-test https://gitlab.com/api/v4/projects/xxxxxxx/packages/helm/stable --force-update', + ); + expect(execMocks[1].cmd).toBe("helm dependency update ''"); + }); + it('returns updated Chart.lock', async () => { fs.readLocalFile.mockResolvedValueOnce(ociLockFile1 as never); fs.getSiblingFileName.mockReturnValueOnce('Chart.lock'); @@ -1097,4 +1137,41 @@ describe('modules/manager/helmv3/artifacts', () => { ).toBeArrayOfSize(1); expect(execSnapshots).toMatchSnapshot(); }); + + it('prevents injections', async () => { + const username = 'user'; + const password = 'pass>word'; + mockEcrAuthResolve({ + authorizationData: [ + { authorizationToken: toBase64(username + ':' + password) }, + ], + }); + + hostRules.add({ + token: 'some-session-token', + hostType: 'docker', + matchHost: '123456789.dkr.ecr.us-east-1.amazonaws.com', + }); + fs.getSiblingFileName.mockReturnValueOnce('Chart.lock'); + fs.readLocalFile.mockResolvedValueOnce(ociLockFile1ECR as never); + fs.privateCacheDir.mockReturnValue( + '/tmp/renovate/cache/__renovate-private-cache', + ); + fs.getParentDir.mockReturnValue(''); + const execSnapshots = mockExecAll(); + await helmv3.updateArtifacts({ + packageFileName: 'Chart.yaml', + updatedDeps: [{}], + newPackageFileContent: `dependencies: { repository: oci://123456789.dkr.ecr.us-east-1.amazonaws.com/bitnami || date }`, + config: { ...config }, + }); + expect(execSnapshots).toMatchObject([ + { + cmd: `helm registry login --username ${username} --password '${password}' '123456789.dkr.ecr.us-east-1.amazonaws.com/bitnami || date'`, + }, + { + cmd: "helm dependency update ''", + }, + ]); + }); }); diff --git a/lib/modules/manager/helmv3/artifacts.ts b/lib/modules/manager/helmv3/artifacts.ts index e7f089a8fe8..c76e8b88040 100644 --- a/lib/modules/manager/helmv3/artifacts.ts +++ b/lib/modules/manager/helmv3/artifacts.ts @@ -13,6 +13,7 @@ import { } from '../../../util/fs'; import { getRepoStatus } from '../../../util/git'; import * as hostRules from '../../../util/host-rules'; +import { regEx } from '../../../util/regex'; import * as yaml from '../../../util/yaml'; import { DockerDatasource } from '../../datasource/docker'; import { HelmDatasource } from '../../datasource/helm'; @@ -152,7 +153,9 @@ export async function updateArtifacts({ if (is.truthy(existingLockFileContent)) { const newHelmLockContent = await readLocalFile(lockFileName, 'utf8'); - const isLockFileChanged = existingLockFileContent !== newHelmLockContent; + const isLockFileChanged = + !is.string(newHelmLockContent) || + isHelmLockChanged(existingLockFileContent, newHelmLockContent); if (isLockFileChanged) { fileChanges.push({ file: { @@ -218,3 +221,8 @@ export async function updateArtifacts({ ]; } } + +function isHelmLockChanged(oldContent: string, newContent: string): boolean { + const regex = regEx(/^generated: ".+"$/m); + return newContent.replace(regex, '') !== oldContent.replace(regex, ''); +} diff --git a/lib/modules/manager/helmv3/common.ts b/lib/modules/manager/helmv3/common.ts index 96a472f8c7f..05793a5a746 100644 --- a/lib/modules/manager/helmv3/common.ts +++ b/lib/modules/manager/helmv3/common.ts @@ -32,7 +32,7 @@ export async function generateLoginCmd( addSecretForSanitizing(password); return `${loginCMD} --username ${quote(username)} --password ${quote( password, - )} ${repository}`; + )} ${quote(repository)}`; } if (username && password) { logger.trace({ repository }, `Using basic auth for Helm registry`); @@ -40,7 +40,7 @@ export async function generateLoginCmd( const hostPart = repository.split('/')[0]; const cmd = `${loginCMD} --username ${quote(username)} --password ${quote( password, - )} ${hostPart}`; + )} ${quote(hostPart)}`; logger.trace({ cmd }, 'Generated Helm registry login command'); return cmd; } diff --git a/lib/modules/manager/hermit/artifacts.spec.ts b/lib/modules/manager/hermit/artifacts.spec.ts index 5a0d35b5452..f345da4e2fd 100644 --- a/lib/modules/manager/hermit/artifacts.spec.ts +++ b/lib/modules/manager/hermit/artifacts.spec.ts @@ -520,5 +520,40 @@ describe('modules/manager/hermit/artifacts', () => { }, ]); }); + + it('prevents injections', async () => { + lstatsMock.mockResolvedValue(true); + + readlinkMock.mockResolvedValue('hermit'); + GlobalConfig.set({ localDir: '' }); + const execSnapshots = mockExecAll(); + await updateArtifacts({ + updatedDeps: [ + { + depName: '|| date; echo ', + currentVersion: '1.0.0', + newValue: '1.0.1', + }, + { + depName: '|| whoami', + currentVersion: '1.18.0', + newName: 'go', + newValue: '1.24.1', + updateType: 'replacement', + }, + ], + packageFileName: './bin/hermit', + newPackageFileContent: '', + config: {}, + }); + expect(execSnapshots).toMatchObject([ + { + cmd: "./hermit uninstall '|| whoami'", + }, + { + cmd: "./hermit install '|| date; echo -1.0.1' go-1.24.1", + }, + ]); + }); }); }); diff --git a/lib/modules/manager/hermit/artifacts.ts b/lib/modules/manager/hermit/artifacts.ts index fd6a4f8495a..70a1da781ad 100644 --- a/lib/modules/manager/hermit/artifacts.ts +++ b/lib/modules/manager/hermit/artifacts.ts @@ -222,7 +222,7 @@ async function updateHermitPackage(update: UpdateArtifact): Promise { // when a name replacement happens, need to uninstall the old package if (toUninstall.length > 0) { - const packagesToUninstall = toUninstall.join(' '); + const packagesToUninstall = toUninstall.map(quote).join(' '); const uninstallCommands = `./hermit uninstall ${packagesToUninstall}`; try { @@ -242,7 +242,7 @@ async function updateHermitPackage(update: UpdateArtifact): Promise { } } - const packagesToInstall = toInstall.join(' '); + const packagesToInstall = toInstall.map(quote).join(' '); const execCommands = `./hermit install ${packagesToInstall}`; logger.debug( diff --git a/lib/modules/manager/jenkins/readme.md b/lib/modules/manager/jenkins/readme.md index 7add1839a96..623b1cbb1b9 100644 --- a/lib/modules/manager/jenkins/readme.md +++ b/lib/modules/manager/jenkins/readme.md @@ -1,4 +1,4 @@ -The Jenkins manager supports a custom text or YAML format of the plugin list as described [here](https://github.com/jenkinsci/plugin-installation-manager-tool#plugin-input-format). +The Jenkins manager supports a custom text or YAML format of the plugin list as described [on their github page](https://github.com/jenkinsci/plugin-installation-manager-tool#plugin-input-format). By default, Renovate gets the versions from the main [Jenkins update center](https://updates.jenkins.io/). diff --git a/lib/modules/manager/kustomize/artifacts.spec.ts b/lib/modules/manager/kustomize/artifacts.spec.ts index 704de5e1094..da0169befbb 100644 --- a/lib/modules/manager/kustomize/artifacts.spec.ts +++ b/lib/modules/manager/kustomize/artifacts.spec.ts @@ -674,4 +674,31 @@ describe('modules/manager/kustomize/artifacts', () => { expect(fs.deleteLocalFile).not.toHaveBeenCalled(); expect(execSnapshots).toBeEmptyArray(); }); + + it('prevents injections', async () => { + const execSnapshots = mockExecAll(); + fs.localPathExists.mockResolvedValueOnce(false); + + expect( + await kustomize.updateArtifacts({ + packageFileName, + updatedDeps: [ + { + depType: 'HelmChart', + depName: 'example && ls -lart; ', + currentVersion: '1.0.0', + registryUrls: ['https://github.com.com/example/example'], + datasource: HelmDatasource.id, + }, + ], + newPackageFileContent, + config, + }), + ).toBeNull(); + expect(execSnapshots).toMatchObject([ + { + cmd: "helm pull --untar --untardir 'charts/example && ls -lart; -1.0.0' --version 1.0.0 --repo https://github.com.com/example/example 'example && ls -lart; '", + }, + ]); + }); }); diff --git a/lib/modules/manager/kustomize/artifacts.ts b/lib/modules/manager/kustomize/artifacts.ts index 41ca747f9b0..0c7cd712a23 100644 --- a/lib/modules/manager/kustomize/artifacts.ts +++ b/lib/modules/manager/kustomize/artifacts.ts @@ -37,7 +37,7 @@ function helmRepositoryArgs( ): string { switch (datasource) { case HelmDatasource.id: - return `--repo ${quote(repository)} ${depName}`; + return `--repo ${quote(repository)} ${quote(depName)}`; case DockerDatasource.id: return quote(`oci://${repository}`); /* v8 ignore next 2: should never happen */ diff --git a/lib/modules/manager/maven/__fixtures__/basic_cnb.pom.xml b/lib/modules/manager/maven/__fixtures__/basic_cnb.pom.xml new file mode 100644 index 00000000000..4d2e6c786b6 --- /dev/null +++ b/lib/modules/manager/maven/__fixtures__/basic_cnb.pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.2.2 + + + test.example + demo + 1.0.0 + demo + Demo project for Spring Boot + + 11 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + repository.local/demo-spring-boot + paketobuildpacks/builder-jammy-base:0.4.316 + + + + + + diff --git a/lib/modules/manager/maven/__fixtures__/empty_cnb.pom.xml b/lib/modules/manager/maven/__fixtures__/empty_cnb.pom.xml new file mode 100644 index 00000000000..3b2bb1acc81 --- /dev/null +++ b/lib/modules/manager/maven/__fixtures__/empty_cnb.pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + test.example + demo + 1.0.0 + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + + diff --git a/lib/modules/manager/maven/__fixtures__/full_cnb.pom.xml b/lib/modules/manager/maven/__fixtures__/full_cnb.pom.xml new file mode 100644 index 00000000000..f9de27f0a4d --- /dev/null +++ b/lib/modules/manager/maven/__fixtures__/full_cnb.pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.2.2 + + + test.example + demo + 1.0.0 + demo + Demo project for Spring Boot + + 11 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + repository.local/demo-spring-boot + paketobuildpacks/builder-jammy-base:0.4.316 + paketobuildpacks/run-noble-full:0.0.28 + + paketo-buildpacks/nodejs@6.1.1 + urn:cnb:builder:paketo-buildpacks/php@2.13.1 + gcr.io/paketo-buildpacks/nodejs:1.8.0 + + docker://docker.io/paketobuildpacks/python:2.22.1@sha256:2c27cd0b4482a4aa5aeb38104f6d934511cd87c1af34a10d1d6cdf2d9d16f138 + + docker://docker.io/paketobuildpacks/ruby@sha256:080f4cfa5c8fe43837b2b83f69ae16e320ea67c051173e4934a015590b2ca67a + + paketobuildpacks/java:12.1.0 + + paketobuildpacks/go + + + + + + + diff --git a/lib/modules/manager/maven/__fixtures__/invalid_cnb.pom.xml b/lib/modules/manager/maven/__fixtures__/invalid_cnb.pom.xml new file mode 100644 index 00000000000..a15ffb48969 --- /dev/null +++ b/lib/modules/manager/maven/__fixtures__/invalid_cnb.pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + test.example + demo + 1.0.0 + + + + + org.springframework.boot + spring-boot-maven-plugin + + + repository.local/demo-spring-boot + invalid-builder + invalid-run + + invalid-image + urn:cnb:builder:buildpacks:invalid@2.13.1 + invalid://identifier/type:1.8.0 + + + + + + + diff --git a/lib/modules/manager/maven/extract.spec.ts b/lib/modules/manager/maven/extract.spec.ts index 97b9ae4d5d1..1fd81b61a0f 100644 --- a/lib/modules/manager/maven/extract.spec.ts +++ b/lib/modules/manager/maven/extract.spec.ts @@ -274,6 +274,143 @@ describe('modules/manager/maven/extract', () => { packageFileVersion: '0.0.1-SNAPSHOT', }); }); + + it('extracts builder and buildpack images from spring-boot plugin', () => { + const res = extractPackage( + Fixtures.get('full_cnb.pom.xml'), + 'full_cnb.pom.xml', + {}, + ); + expect(res?.deps).toEqual([ + { + currentValue: '3.2.2', + datasource: 'maven', + depName: 'org.springframework.boot:spring-boot-starter-parent', + depType: 'parent', + fileReplacePosition: 404, + registryUrls: [], + }, + { + autoReplaceStringTemplate: + '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentValue: '0.4.316', + datasource: 'docker', + depName: 'paketobuildpacks/builder-jammy-base', + packageName: 'paketobuildpacks/builder-jammy-base', + replaceString: 'paketobuildpacks/builder-jammy-base:0.4.316', + fileReplacePosition: 1273, + }, + { + autoReplaceStringTemplate: + '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentValue: '0.0.28', + datasource: 'docker', + depName: 'paketobuildpacks/run-noble-full', + packageName: 'paketobuildpacks/run-noble-full', + replaceString: 'paketobuildpacks/run-noble-full:0.0.28', + fileReplacePosition: 1343, + }, + { + autoReplaceStringTemplate: + '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentValue: '6.1.1', + datasource: 'buildpacks-registry', + packageName: 'paketo-buildpacks/nodejs', + fileReplacePosition: 1430, + }, + { + autoReplaceStringTemplate: + '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentValue: '1.8.0', + datasource: 'docker', + depName: 'gcr.io/paketo-buildpacks/nodejs', + fileReplacePosition: 1566, + packageName: 'gcr.io/paketo-buildpacks/nodejs', + replaceString: 'gcr.io/paketo-buildpacks/nodejs:1.8.0', + }, + { + autoReplaceStringTemplate: + '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: + 'sha256:2c27cd0b4482a4aa5aeb38104f6d934511cd87c1af34a10d1d6cdf2d9d16f138', + currentValue: '2.22.1', + datasource: 'docker', + depName: 'docker.io/paketobuildpacks/python', + fileReplacePosition: 1634, + packageName: 'docker.io/paketobuildpacks/python', + replaceString: + 'docker.io/paketobuildpacks/python:2.22.1@sha256:2c27cd0b4482a4aa5aeb38104f6d934511cd87c1af34a10d1d6cdf2d9d16f138', + }, + { + autoReplaceStringTemplate: + '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: + 'sha256:080f4cfa5c8fe43837b2b83f69ae16e320ea67c051173e4934a015590b2ca67a', + datasource: 'docker', + depName: 'docker.io/paketobuildpacks/ruby', + fileReplacePosition: 1795, + packageName: 'docker.io/paketobuildpacks/ruby', + replaceString: + 'docker.io/paketobuildpacks/ruby@sha256:080f4cfa5c8fe43837b2b83f69ae16e320ea67c051173e4934a015590b2ca67a', + }, + { + autoReplaceStringTemplate: + '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentValue: '12.1.0', + datasource: 'docker', + depName: 'paketobuildpacks/java', + packageName: 'paketobuildpacks/java', + replaceString: 'paketobuildpacks/java:12.1.0', + fileReplacePosition: 2001, + }, + ]); + }); + + it('extracts only builder if defaults are used in spring-boot plugin', () => { + const res = extractPackage( + Fixtures.get('basic_cnb.pom.xml'), + 'basic_cnb.pom.xml', + {}, + ); + expect(res?.deps).toEqual([ + { + currentValue: '3.2.2', + datasource: 'maven', + depName: 'org.springframework.boot:spring-boot-starter-parent', + depType: 'parent', + fileReplacePosition: 404, + registryUrls: [], + }, + { + autoReplaceStringTemplate: + '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentValue: '0.4.316', + datasource: 'docker', + depName: 'paketobuildpacks/builder-jammy-base', + packageName: 'paketobuildpacks/builder-jammy-base', + replaceString: 'paketobuildpacks/builder-jammy-base:0.4.316', + fileReplacePosition: 1273, + }, + ]); + }); + + it('returns no buildpack dependencies when image tag is missing in spring boot plugin configuration', () => { + const res = extractPackage( + Fixtures.get('empty_cnb.pom.xml'), + 'empty_cnb.pom.xml', + {}, + ); + expect(res?.deps).toEqual([]); + }); + + it('returns no buildpack dependencies when dependencies are invalid in spring boot plugin', () => { + const res = extractPackage( + Fixtures.get('invalid_cnb.pom.xml'), + 'invalid_cnb.pom.xml', + {}, + ); + expect(res?.deps).toEqual([]); + }); }); describe('resolveParents', () => { diff --git a/lib/modules/manager/maven/extract.ts b/lib/modules/manager/maven/extract.ts index e9bce2ebef1..522ee4b15a3 100644 --- a/lib/modules/manager/maven/extract.ts +++ b/lib/modules/manager/maven/extract.ts @@ -7,6 +7,14 @@ import { readLocalFile } from '../../../util/fs'; import { regEx } from '../../../util/regex'; import { MavenDatasource } from '../../datasource/maven'; import { MAVEN_REPO } from '../../datasource/maven/common'; +import { + BUILDPACK_REGISTRY_PREFIX, + DOCKER_PREFIX, + getDep as getBuildpackDep, + isBuildpackRegistryRef, + isDockerRef, +} from '../buildpacks/extract'; +import { getDep as getDockerDep } from '../dockerfile/extract'; import type { ExtractConfig, PackageDependency, PackageFile } from '../types'; import type { MavenProp } from './types'; @@ -76,6 +84,80 @@ function containsPlaceholder(str: string | null | undefined): boolean { return !!str && regEx(/\${[^}]*?}/).test(str); } +function getCNBDependencies( + nodes: XmlElement[], + config: ExtractConfig, +): PackageDependency[] { + const deps: PackageDependency[] = []; + for (const node of nodes) { + const depString = node.val.trim(); + if (isDockerRef(depString)) { + const dep = getDockerDep( + depString.replace(DOCKER_PREFIX, ''), + true, + config.registryAliases, + ); + + dep.fileReplacePosition = node.position; + if (dep.currentValue || dep.currentDigest) { + deps.push(dep); + } + } else if (isBuildpackRegistryRef(depString)) { + const dep = getBuildpackDep( + depString.replace(BUILDPACK_REGISTRY_PREFIX, ''), + ); + + if (dep?.currentValue) { + dep.fileReplacePosition = node.position; + deps.push(dep); + } + } + } + return deps; +} + +function getAllCNBDependencies( + node: XmlDocument, + config: ExtractConfig, +): PackageDependency[] | null { + const pluginNodes = + node.childNamed('build')?.childNamed('plugins')?.childrenNamed('plugin') ?? + []; + + const pluginNode = pluginNodes.find((pluginNode) => { + return ( + pluginNode.valueWithPath('groupId')?.trim() === + 'org.springframework.boot' && + pluginNode.valueWithPath('artifactId')?.trim() === + 'spring-boot-maven-plugin' + ); + }); + if (!pluginNode) { + return null; + } + + const deps: PackageDependency[] = []; + const imageNode = pluginNode.childNamed('configuration')?.childNamed('image'); + if (!imageNode) { + return null; + } + const builder = getCNBDependencies( + imageNode.childrenNamed('builder'), + config, + ); + const runImage = getCNBDependencies( + imageNode.childrenNamed('runImage'), + config, + ); + const buildpacks = getCNBDependencies( + imageNode.childNamed('buildpacks')?.childrenNamed('buildpack') ?? [], + config, + ); + deps.push(...builder, ...runImage, ...buildpacks); + + return deps.length ? deps : null; +} + function depFromNode( node: XmlElement, underBuildSettingsElement: boolean, @@ -229,9 +311,10 @@ function applyPropsInternal( let fileReplacePosition = dep.fileReplacePosition; let propSource = dep.propSource; let sharedVariableName: string | null = null; - const currentValue = dep.currentValue!.replace( - regEx(/^\${[^}]*?}$/), - (substr) => { + let currentValue: string | null = null; + + if (dep.currentValue) { + currentValue = dep.currentValue.replace(regEx(/^\${[^}]*?}$/), (substr) => { const propKey = substr.slice(2, -1).trim(); // TODO: wrong types here, props is already `MavenProp` const propValue = (props as any)[propKey] as MavenProp; @@ -251,8 +334,8 @@ function applyPropsInternal( return propValue.val; } return substr; - }, - ); + }); + } const result: PackageDependency = { ...dep, @@ -297,7 +380,7 @@ interface MavenInterimPackageFile extends PackageFile { export function extractPackage( rawContent: string, packageFile: string, - _config: ExtractConfig, + config: ExtractConfig, ): PackageFile | null { if (!rawContent) { return null; @@ -316,6 +399,11 @@ export function extractPackage( result.deps = deepExtract(project); + const CNBDependencies = getAllCNBDependencies(project, config); + if (CNBDependencies) { + result.deps.push(...CNBDependencies); + } + const propsNode = project.childNamed('properties'); const props: Record = {}; if (propsNode?.children) { @@ -463,7 +551,10 @@ export function resolveParents(packages: PackageFile[]): PackageFile[] { packageFileNames.forEach((name) => { const pkg = extractedPackages[name]; pkg.deps.forEach((rawDep) => { - const urlsSet = new Set([...rawDep.registryUrls!, ...registryUrls[name]]); + const urlsSet = new Set([ + ...(rawDep.registryUrls ?? []), + ...registryUrls[name], + ]); rawDep.registryUrls = [...urlsSet]; }); }); @@ -582,7 +673,9 @@ export async function extractAllPackageFiles( if (additionalRegistryUrls) { for (const pkgFile of packages) { for (const dep of pkgFile.deps) { - dep.registryUrls!.unshift(...additionalRegistryUrls); + if (dep.registryUrls) { + dep.registryUrls.unshift(...additionalRegistryUrls); + } } } } diff --git a/lib/modules/manager/maven/index.ts b/lib/modules/manager/maven/index.ts index d46d10797c0..2aa4fad3039 100644 --- a/lib/modules/manager/maven/index.ts +++ b/lib/modules/manager/maven/index.ts @@ -1,6 +1,6 @@ import type { Category } from '../../../constants'; +import { DockerDatasource } from '../../datasource/docker'; import { MavenDatasource } from '../../datasource/maven'; -import * as mavenVersioning from '../../versioning/maven'; export { extractAllPackageFiles } from './extract'; export { bumpPackageVersion, updateDependency } from './update'; @@ -14,7 +14,6 @@ export const defaultConfig = { '/^(((\\.mvn)|(\\.m2))/)?settings\\.xml$/', '/(^|/)\\.mvn/extensions\\.xml$/', ], - versioning: mavenVersioning.id, }; -export const supportedDatasources = [MavenDatasource.id]; +export const supportedDatasources = [MavenDatasource.id, DockerDatasource.id]; diff --git a/lib/modules/manager/maven/readme.md b/lib/modules/manager/maven/readme.md index 1a6beadccbf..53bbf8819f9 100644 --- a/lib/modules/manager/maven/readme.md +++ b/lib/modules/manager/maven/readme.md @@ -1 +1,7 @@ The `maven` manager focuses on extracting dependencies from `pom.xml`. It uses the official Maven versioning scheme. + +It also supports [Image Customizations](https://docs.spring.io/spring-boot/maven-plugin/build-image.html#build-image.customization) of `spring-boot`'s OCI packaging. Usage of `registryAliases` is possible only for container image references. + +### Limitations + +Currently maven properties are not supported for buildpack related dependencies. diff --git a/lib/modules/manager/maven/update.spec.ts b/lib/modules/manager/maven/update.spec.ts index c3bc3bd6587..a8751ea3a1c 100644 --- a/lib/modules/manager/maven/update.spec.ts +++ b/lib/modules/manager/maven/update.spec.ts @@ -8,6 +8,7 @@ const simpleContent = Fixtures.get(`simple.pom.xml`); const minimumContent = Fixtures.get(`minimum.pom.xml`); const minimumSnapshotContent = Fixtures.get(`minimum_snapshot.pom.xml`); const prereleaseContent = Fixtures.get(`prerelease.pom.xml`); +const cnbContent = Fixtures.get(`full_cnb.pom.xml`); describe('modules/manager/maven/update', () => { describe('updateDependency', () => { @@ -141,6 +142,66 @@ describe('modules/manager/maven/update', () => { expect(res).toBe(simpleContent); }); + + it('should update a cloud native buildpack version', () => { + const res = updateDependency({ + fileContent: cnbContent, + upgrade: { + datasource: 'docker', + updateType: 'patch', + depName: 'paketo-buildpacks/nodejs', + currentValue: '6.1.1', + fileReplacePosition: 1430, + newValue: '6.1.2', + }, + }); + + const project = new XmlDocument(res!); + expect( + project.valueWithPath( + 'build.plugins.plugin.configuration.image.buildpacks.buildpack', + ), + ).toBe('paketo-buildpacks/nodejs@6.1.2'); + }); + + it('should update a cloud native buildpack digest', () => { + const res = updateDependency({ + fileContent: cnbContent, + upgrade: { + updateType: 'patch', + currentDigest: + 'sha256:2c27cd0b4482a4aa5aeb38104f6d934511cd87c1af34a10d1d6cdf2d9d16f138', + currentValue: '2.22.1', + newDigest: + 'sha256:ab0cf962a92158f15d9e4fed6f905d5d292ed06a8e6291aa1ce3c33a5c78bde1', + newValue: '2.24.3', + datasource: 'docker', + depName: 'docker.io/paketobuildpacks/python', + fileReplacePosition: 1634, + }, + }); + + const project = new XmlDocument(res!); + const buildpacks = project + .childNamed('build')! + .childNamed('plugins')! + .childNamed('plugin')! + .childNamed('configuration')! + .childNamed('image')! + .childNamed('buildpacks')! + .childrenNamed('buildpack'); + const buildpackWithDigest = []; + for (const buildpack of buildpacks) { + const buildpackValue = buildpack.val; + if (buildpackValue.includes('docker://')) { + buildpackWithDigest.push(buildpackValue.trim()); + } + } + expect(buildpackWithDigest).toEqual([ + 'docker://docker.io/paketobuildpacks/python:2.24.3@sha256:ab0cf962a92158f15d9e4fed6f905d5d292ed06a8e6291aa1ce3c33a5c78bde1', + 'docker://docker.io/paketobuildpacks/ruby@sha256:080f4cfa5c8fe43837b2b83f69ae16e320ea67c051173e4934a015590b2ca67a', + ]); + }); }); describe('bumpPackageVersion', () => { diff --git a/lib/modules/manager/maven/update.ts b/lib/modules/manager/maven/update.ts index 65a4573a54c..80b3ea0964c 100644 --- a/lib/modules/manager/maven/update.ts +++ b/lib/modules/manager/maven/update.ts @@ -69,6 +69,25 @@ export function updateAtPosition( // TODO: validate newValue (#22198) const replacedPart = versionPart.replace(version, newValue!); return leftPart + replacedPart + restPart; + } else if ( + upgrade.datasource === 'docker' || + upgrade.datasource === 'buildpacks-registry' + ) { + // In contrast to maven dependencies, cloud native buildpacks are not contained in specific version tags. + // Instead they are contained in the value of the buildpack tag and we have to update it differently. + let replacedPart = version; + if (currentValue) { + replacedPart = version.replace(currentValue, newValue!); + } + if (upgrade.currentDigest && upgrade.newDigest) { + replacedPart = replacedPart.replace( + upgrade.currentDigest, + upgrade.newDigest, + ); + } + if (replacedPart !== version) { + return leftPart + replacedPart + restPart; + } } logger.debug({ depName, version, currentValue, newValue }, 'Unknown value'); return null; diff --git a/lib/modules/manager/mise/backends.spec.ts b/lib/modules/manager/mise/backends.spec.ts new file mode 100644 index 00000000000..18c34a812f0 --- /dev/null +++ b/lib/modules/manager/mise/backends.spec.ts @@ -0,0 +1,311 @@ +import { + createAquaToolConfig, + createCargoToolConfig, + createDotnetToolConfig, + createGemToolConfig, + createGoToolConfig, + createNpmToolConfig, + createPipxToolConfig, + createSpmToolConfig, + createUbiToolConfig, +} from './backends'; + +describe('modules/manager/mise/backends', () => { + describe('createAquaToolConfig()', () => { + it('should create a tooling config', () => { + expect( + createAquaToolConfig('BurntSushi/ripgrep', '14.1.1'), + ).toStrictEqual({ + packageName: 'BurntSushi/ripgrep', + datasource: 'github-tags', + currentValue: '14.1.1', + extractVersion: '^v?(?.+)', + }); + }); + + it('should trim the leading v from version', () => { + expect( + createAquaToolConfig('BurntSushi/ripgrep', 'v14.1.1'), + ).toStrictEqual({ + packageName: 'BurntSushi/ripgrep', + datasource: 'github-tags', + currentValue: '14.1.1', + extractVersion: '^v?(?.+)', + }); + }); + }); + + describe('createCargoToolConfig()', () => { + it('should create a tooling config for crate', () => { + expect(createCargoToolConfig('eza', '')).toStrictEqual({ + packageName: 'eza', + datasource: 'crate', + }); + }); + + it('should create a tooling config for git tag', () => { + expect( + createCargoToolConfig('https://github.com/username/demo', 'tag:v0.1.0'), + ).toStrictEqual({ + packageName: 'https://github.com/username/demo', + currentValue: 'v0.1.0', + datasource: 'git-tags', + }); + }); + + it('should provide skipReason for git branch', () => { + expect( + createCargoToolConfig( + 'https://github.com/username/demo', + 'branch:main', + ), + ).toStrictEqual({ + packageName: 'https://github.com/username/demo', + currentValue: 'main', + datasource: 'git-refs', + }); + }); + + it('should create a tooling config for git rev', () => { + expect( + createCargoToolConfig('https://github.com/username/demo', 'rev:abcdef'), + ).toStrictEqual({ + packageName: 'https://github.com/username/demo', + currentValue: 'abcdef', + datasource: 'git-refs', + }); + }); + + it('should provide skipReason for invalid version', () => { + expect( + createCargoToolConfig('https://github.com/username/demo', 'v0.1.0'), + ).toStrictEqual({ + packageName: 'https://github.com/username/demo', + skipReason: 'invalid-version', + }); + }); + }); + + describe('createDotnetToolConfig()', () => { + it('should create a tooling config', () => { + expect(createDotnetToolConfig('GitVersion.Tool')).toStrictEqual({ + packageName: 'GitVersion.Tool', + datasource: 'nuget', + }); + }); + }); + + describe('createGemToolConfig()', () => { + it('should create a tooling config', () => { + expect(createGemToolConfig('rubocop')).toStrictEqual({ + packageName: 'rubocop', + datasource: 'rubygems', + }); + }); + }); + + describe('createGoToolConfig()', () => { + it('should create a tooling config', () => { + expect(createGoToolConfig('github.com/DarthSim/hivemind')).toStrictEqual({ + packageName: 'github.com/DarthSim/hivemind', + datasource: 'go', + }); + }); + }); + + describe('createNpmToolConfig()', () => { + it('should create a tooling config', () => { + expect(createNpmToolConfig('prettier')).toStrictEqual({ + packageName: 'prettier', + datasource: 'npm', + }); + }); + }); + + describe('createPipxToolConfig()', () => { + it('should create a tooling config for pypi package', () => { + expect(createPipxToolConfig('yamllint')).toStrictEqual({ + packageName: 'yamllint', + datasource: 'pypi', + }); + }); + + it('should create a tooling config for github shorthand', () => { + expect(createPipxToolConfig('psf/black')).toStrictEqual({ + packageName: 'psf/black', + datasource: 'github-tags', + }); + }); + + it('should create a tooling config for github url', () => { + expect( + createPipxToolConfig('git+https://github.com/psf/black.git'), + ).toStrictEqual({ + packageName: 'psf/black', + datasource: 'github-tags', + }); + }); + + it('should create a tooling config for git url', () => { + expect( + createPipxToolConfig('git+https://gitlab.com/user/repo.git'), + ).toStrictEqual({ + packageName: 'https://gitlab.com/user/repo', + datasource: 'git-refs', + }); + }); + + it('provides skipReason for zip file url', () => { + expect( + createPipxToolConfig('https://github.com/psf/black/archive/18.9b0.zip'), + ).toStrictEqual({ + packageName: 'https://github.com/psf/black/archive/18.9b0.zip', + skipReason: 'unsupported-url', + }); + }); + }); + + describe('createSpmToolConfig()', () => { + it('should create a tooling config for github shorthand', () => { + expect(createSpmToolConfig('tuist/tuist')).toStrictEqual({ + packageName: 'tuist/tuist', + datasource: 'github-releases', + }); + }); + + it('should create a tooling config for github url', () => { + expect( + createSpmToolConfig('https://github.com/tuist/tuist.git'), + ).toStrictEqual({ + packageName: 'tuist/tuist', + datasource: 'github-releases', + }); + }); + + it('provides skipReason for other url', () => { + expect( + createSpmToolConfig('https://gitlab.com/user/repo.git'), + ).toStrictEqual({ + packageName: 'https://gitlab.com/user/repo.git', + skipReason: 'unsupported-url', + }); + }); + }); + + describe('createUbiToolConfig()', () => { + it('should create a tooling config with empty options', () => { + expect(createUbiToolConfig('nekto/act', '0.2.70', {})).toStrictEqual({ + packageName: 'nekto/act', + datasource: 'github-releases', + currentValue: '0.2.70', + extractVersion: '^v?(?.+)', + }); + }); + + it('should set extractVersion if the version does not have leading v', () => { + expect(createUbiToolConfig('cli/cli', '2.64.0', {})).toStrictEqual({ + packageName: 'cli/cli', + datasource: 'github-releases', + currentValue: '2.64.0', + extractVersion: '^v?(?.+)', + }); + }); + + it('should not set extractVersion if the version has leading v', () => { + expect(createUbiToolConfig('cli/cli', 'v2.64.0', {})).toStrictEqual({ + packageName: 'cli/cli', + datasource: 'github-releases', + currentValue: 'v2.64.0', + }); + }); + + it('should ignore options unless tag_regex is provided', () => { + expect( + createUbiToolConfig('cli/cli', '2.64.0', { exe: 'gh' } as any), + ).toStrictEqual({ + packageName: 'cli/cli', + datasource: 'github-releases', + currentValue: '2.64.0', + extractVersion: '^v?(?.+)', + }); + }); + + it('should set extractVersion if tag_regex is provided', () => { + expect( + createUbiToolConfig('cargo-bins/cargo-binstall', '1.10.17', { + tag_regex: '^\\d+\\.\\d+\\.', + }), + ).toStrictEqual({ + packageName: 'cargo-bins/cargo-binstall', + datasource: 'github-releases', + currentValue: '1.10.17', + extractVersion: '^v?(?\\d+\\.\\d+\\.)', + }); + }); + + it('should set extractVersion without v? when tag_regex is provided and version starts with v', () => { + expect( + createUbiToolConfig('cargo-bins/cargo-binstall', 'v1.10.17', { + tag_regex: '^\\d+\\.\\d+\\.', + }), + ).toStrictEqual({ + packageName: 'cargo-bins/cargo-binstall', + datasource: 'github-releases', + currentValue: 'v1.10.17', + extractVersion: '^(?\\d+\\.\\d+\\.)', + }); + }); + + it('should trim the leading ^ from tag_regex', () => { + expect( + createUbiToolConfig('cargo-bins/cargo-binstall', 'v1.10.17', { + tag_regex: '^\\d+\\.\\d+\\.', + }), + ).toStrictEqual({ + packageName: 'cargo-bins/cargo-binstall', + datasource: 'github-releases', + currentValue: 'v1.10.17', + extractVersion: '^(?\\d+\\.\\d+\\.)', + }); + }); + + it('should only trim the leading ^ from tag_regex when version starts with v', () => { + expect( + createUbiToolConfig('cargo-bins/cargo-binstall', 'v1.10.17', { + tag_regex: '^v\\d+\\.\\d+\\.', + }), + ).toStrictEqual({ + packageName: 'cargo-bins/cargo-binstall', + datasource: 'github-releases', + currentValue: 'v1.10.17', + extractVersion: '^(?v\\d+\\.\\d+\\.)', + }); + }); + + it('should trim the leading ^v from tag_regex', () => { + expect( + createUbiToolConfig('cargo-bins/cargo-binstall', '1.10.17', { + tag_regex: '^v\\d+\\.\\d+\\.', + }), + ).toStrictEqual({ + packageName: 'cargo-bins/cargo-binstall', + datasource: 'github-releases', + currentValue: '1.10.17', + extractVersion: '^v?(?\\d+\\.\\d+\\.)', + }); + }); + + it('should trim the leading ^v? from tag_regex', () => { + expect( + createUbiToolConfig('cargo-bins/cargo-binstall', '1.10.17', { + tag_regex: '^v?\\d+\\.\\d+\\.', + }), + ).toStrictEqual({ + packageName: 'cargo-bins/cargo-binstall', + datasource: 'github-releases', + currentValue: '1.10.17', + extractVersion: '^v?(?\\d+\\.\\d+\\.)', + }); + }); + }); +}); diff --git a/lib/modules/manager/mise/backends.ts b/lib/modules/manager/mise/backends.ts new file mode 100644 index 00000000000..209ab4fa6e7 --- /dev/null +++ b/lib/modules/manager/mise/backends.ts @@ -0,0 +1,239 @@ +import is from '@sindresorhus/is'; +import { regEx } from '../../../util/regex'; +import { CrateDatasource } from '../../datasource/crate'; +import { GitRefsDatasource } from '../../datasource/git-refs'; +import { GitTagsDatasource } from '../../datasource/git-tags'; +import { GithubReleasesDatasource } from '../../datasource/github-releases'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; +import { GoDatasource } from '../../datasource/go'; +import { NpmDatasource } from '../../datasource/npm'; +import { NugetDatasource } from '../../datasource/nuget'; +import { PypiDatasource } from '../../datasource/pypi'; +import { normalizePythonDepName } from '../../datasource/pypi/common'; +import { RubygemsDatasource } from '../../datasource/rubygems'; +import type { PackageDependency } from '../types'; +import type { MiseToolOptionsSchema } from './schema'; + +export type BackendToolingConfig = Omit & + Required< + | Pick + | Pick + >; + +/** + * Create a tooling config for aqua backend + * @link https://mise.jdx.dev/dev-tools/backends/aqua.html + */ +export function createAquaToolConfig( + name: string, + version: string, +): BackendToolingConfig { + // mise supports http aqua package type but we cannot determine it from the tool name + // An error will be thrown afterwards if the package type is http + // ref: https://github.com/jdx/mise/blob/d1b9749d8f3e13ef705c1ea471d96c5935b79136/src/aqua/aqua_registry.rs#L39-L45 + return { + packageName: name, + datasource: GithubTagsDatasource.id, + // Trim the leading 'v' from both the current and extracted version + currentValue: version.replace(regEx(/^v/), ''), + extractVersion: '^v?(?.+)', + }; +} + +const cargoGitVersionRegex = regEx(/^(?tag|branch|rev):(?.+)$/); + +/** + * Create a tooling config for cargo backend + * @link https://mise.jdx.dev/dev-tools/backends/cargo.html + */ +export function createCargoToolConfig( + name: string, + version: string, +): BackendToolingConfig { + if (!is.urlString(name)) { + return { + packageName: name as string, // `is.urlString` type issue + datasource: CrateDatasource.id, + }; + } + // tag: branch: or rev: is required for git repository url + // e.g. branch:main, tag:0.1.0, rev:abcdef + const matchGroups = cargoGitVersionRegex.exec(version)?.groups; + if (is.undefined(matchGroups)) { + return { + packageName: name, + skipReason: 'invalid-version', + }; + } + const { type, version: gitVersion } = matchGroups; + switch (type as 'tag' | 'branch' | 'rev') { + case 'tag': + return { + packageName: name, + datasource: GitTagsDatasource.id, + currentValue: gitVersion, + }; + case 'branch': + return { + packageName: name, + datasource: GitRefsDatasource.id, + currentValue: gitVersion, + }; + case 'rev': + return { + packageName: name, + datasource: GitRefsDatasource.id, + currentValue: gitVersion, + }; + } +} + +/** + * Create a tooling config for dotnet backend + * @link https://mise.jdx.dev/dev-tools/backends/dotnet.html + */ +export function createDotnetToolConfig(name: string): BackendToolingConfig { + return { + packageName: name, + datasource: NugetDatasource.id, + }; +} + +/** + * Create a tooling config for gem backend + * @link https://mise.jdx.dev/dev-tools/backends/gem.html + */ +export function createGemToolConfig(name: string): BackendToolingConfig { + return { + packageName: name, + datasource: RubygemsDatasource.id, + }; +} + +/** + * Create a tooling config for go backend + * @link https://mise.jdx.dev/dev-tools/backends/go.html + */ +export function createGoToolConfig(name: string): BackendToolingConfig { + return { + packageName: name, + datasource: GoDatasource.id, + }; +} + +/** + * Create a tooling config for npm backend + * @link https://mise.jdx.dev/dev-tools/backends/npm.html + */ +export function createNpmToolConfig(name: string): BackendToolingConfig { + return { + packageName: name, + datasource: NpmDatasource.id, + }; +} + +const pipxGitHubRegex = regEx(/^git\+https:\/\/github\.com\/(?.+)\.git$/); + +/** + * Create a tooling config for pipx backend + * @link https://mise.jdx.dev/dev-tools/backends/pipx.html + */ +export function createPipxToolConfig(name: string): BackendToolingConfig { + const isGitSyntax = name.startsWith('git+'); + // Does not support zip file url + // Avoid type narrowing to prevent type error + if (!isGitSyntax && (is.urlString as (value: unknown) => boolean)(name)) { + return { + packageName: name, + skipReason: 'unsupported-url', + }; + } + if (isGitSyntax || name.includes('/')) { + let repoName: string | undefined; + if (isGitSyntax) { + repoName = pipxGitHubRegex.exec(name)?.groups?.repo; + // If the url is not a github repo, treat the version as a git ref + if (is.undefined(repoName)) { + return { + packageName: name.replace(/^git\+/g, '').replaceAll(/\.git$/g, ''), + datasource: GitRefsDatasource.id, + }; + } + } else { + repoName = name; + } + return { + packageName: repoName, + datasource: GithubTagsDatasource.id, + }; + } + return { + packageName: normalizePythonDepName(name), + datasource: PypiDatasource.id, + }; +} + +const spmGitHubRegex = regEx(/^https:\/\/github.com\/(?.+).git$/); + +/** + * Create a tooling config for spm backend + * @link https://mise.jdx.dev/dev-tools/backends/spm.html + */ +export function createSpmToolConfig(name: string): BackendToolingConfig { + let repoName: string | undefined; + // Avoid type narrowing to prevent type error + if ((is.urlString as (value: unknown) => boolean)(name)) { + repoName = spmGitHubRegex.exec(name)?.groups?.repo; + // spm backend only supports github repos + if (!repoName) { + return { + packageName: name, + skipReason: 'unsupported-url', + }; + } + } + return { + packageName: repoName ?? name, + datasource: GithubReleasesDatasource.id, + }; +} + +/** + * Create a tooling config for ubi backend + * @link https://mise.jdx.dev/dev-tools/backends/ubi.html + */ +export function createUbiToolConfig( + name: string, + version: string, + toolOptions: MiseToolOptionsSchema, +): BackendToolingConfig { + let extractVersion: string | undefined = undefined; + + const hasVPrefix = version.startsWith('v'); + const setsTagRegex = !hasVPrefix || is.string(toolOptions.tag_regex); + + if (setsTagRegex) { + // By default, use a regex that matches any tag + let tagRegex = '.+'; + // Filter versions by tag_regex if it is specified + // ref: https://mise.jdx.dev/dev-tools/backends/ubi.html#ubi-uses-weird-versions + if (is.string(toolOptions.tag_regex)) { + // Remove the leading '^' if it exists to avoid duplication + tagRegex = toolOptions.tag_regex.replace(/^\^/, ''); + if (!hasVPrefix) { + // Remove the leading 'v?' if it exists to avoid duplication + tagRegex = tagRegex.replace(/^v\??/, ''); + } + } + + // Trim the 'v' prefix if the current version does not have it + extractVersion = `^${hasVPrefix ? '' : 'v?'}(?${tagRegex})`; + } + + return { + packageName: name, + datasource: GithubReleasesDatasource.id, + currentValue: version, + ...(is.string(extractVersion) ? { extractVersion } : {}), + }; +} diff --git a/lib/modules/manager/mise/extract.spec.ts b/lib/modules/manager/mise/extract.spec.ts index 833f0fba8a6..2c9da9dbfe9 100644 --- a/lib/modules/manager/mise/extract.spec.ts +++ b/lib/modules/manager/mise/extract.spec.ts @@ -4,7 +4,7 @@ import { Fixtures } from '~test/fixtures'; vi.mock('../../../util/fs'); -const miseFilename = '.mise.toml'; +const miseFilename = 'mise.toml'; const mise1toml = Fixtures.get('Mise.1.toml'); @@ -58,13 +58,17 @@ describe('modules/manager/mise/extract', () => { buf = "1.27.0" ccache = "4.11.3" consul = "1.14.3" + committed = "1.1.7" hivemind = "1.1.0" + hk = "1.1.2" jq = "1.7.1" kafka = "apache-3.9.0" + lefthook = "1.11.13" localstack = "4.3.0" opentofu = "1.6.1" protoc = "30.2" redis = "8.0.1" + ruff = "0.11.12" shellcheck = "0.10.0" skeema = "1.12.3" sops = "3.10.2" @@ -124,6 +128,13 @@ describe('modules/manager/mise/extract', () => { extractVersion: '^v(?\\S+)', packageName: 'hashicorp/consul', }, + { + currentValue: '1.1.7', + datasource: 'github-releases', + depName: 'committed', + extractVersion: '^v(?\\S+)', + packageName: 'crate-ci/committed', + }, { currentValue: '1.1.0', datasource: 'github-releases', @@ -131,6 +142,13 @@ describe('modules/manager/mise/extract', () => { extractVersion: '^v(?\\S+)', packageName: 'DarthSim/hivemind', }, + { + currentValue: '1.1.2', + datasource: 'github-releases', + depName: 'hk', + extractVersion: '^v(?\\S+)', + packageName: 'jdx/hk', + }, { currentValue: '1.7.1', datasource: 'github-releases', @@ -144,6 +162,13 @@ describe('modules/manager/mise/extract', () => { depName: 'kafka', packageName: 'apache/kafka', }, + { + currentValue: '1.11.13', + datasource: 'github-releases', + depName: 'lefthook', + extractVersion: '^v(?\\S+)', + packageName: 'evilmartians/lefthook', + }, { currentValue: '4.3.0', datasource: 'github-releases', @@ -171,6 +196,12 @@ describe('modules/manager/mise/extract', () => { depName: 'redis', packageName: 'redis/redis', }, + { + currentValue: '0.11.12', + datasource: 'github-releases', + depName: 'ruff', + packageName: 'astral-sh/ruff', + }, { currentValue: '0.10.0', datasource: 'github-releases', @@ -279,10 +310,303 @@ describe('modules/manager/mise/extract', () => { }); }); + it('extracts tools in the default registry with backends', () => { + const content = codeBlock` + [tools] + "core:node" = "16" + "asdf:rust" = "1.82.0" + "vfox:scala" = "3.5.2" + "aqua:act" = "0.2.70" + `; + const result = extractPackageFile(content, miseFilename); + expect(result).toMatchObject({ + deps: [ + { + depName: 'core:node', + currentValue: '16', + packageName: 'nodejs', + datasource: 'node-version', + }, + { + depName: 'asdf:rust', + currentValue: '1.82.0', + packageName: 'rust-lang/rust', + datasource: 'github-tags', + }, + { + depName: 'vfox:scala', + currentValue: '3.5.2', + packageName: 'lampepfl/dotty', + datasource: 'github-tags', + }, + { + depName: 'aqua:act', + currentValue: '0.2.70', + packageName: 'nektos/act', + datasource: 'github-releases', + }, + ], + }); + }); + + it('extracts aqua backend tool', () => { + const content = codeBlock` + [tools] + "aqua:BurntSushi/ripgrep" = "14.1.0" + "aqua:cli/cli" = "v2.64.0" + `; + const result = extractPackageFile(content, miseFilename); + expect(result).toMatchObject({ + deps: [ + { + depName: 'aqua:BurntSushi/ripgrep', + currentValue: '14.1.0', + packageName: 'BurntSushi/ripgrep', + datasource: 'github-tags', + extractVersion: '^v?(?.+)', + }, + { + depName: 'aqua:cli/cli', + currentValue: '2.64.0', + packageName: 'cli/cli', + datasource: 'github-tags', + extractVersion: '^v?(?.+)', + }, + ], + }); + }); + + it('extracts cargo backend tools', () => { + const content = codeBlock` + [tools] + "cargo:eza" = "0.18.21" + "cargo:https://github.com/username/demo1" = "tag:v0.1.0" + "cargo:https://github.com/username/demo2" = "branch:main" + "cargo:https://github.com/username/demo3" = "rev:abcdef" + `; + const result = extractPackageFile(content, miseFilename); + expect(result).toMatchObject({ + deps: [ + { + depName: 'cargo:eza', + currentValue: '0.18.21', + packageName: 'eza', + datasource: 'crate', + }, + { + depName: 'cargo:https://github.com/username/demo1', + currentValue: 'v0.1.0', + packageName: 'https://github.com/username/demo1', + datasource: 'git-tags', + }, + { + depName: 'cargo:https://github.com/username/demo2', + currentValue: 'main', + packageName: 'https://github.com/username/demo2', + datasource: 'git-refs', + }, + { + depName: 'cargo:https://github.com/username/demo3', + currentValue: 'abcdef', + packageName: 'https://github.com/username/demo3', + datasource: 'git-refs', + }, + ], + }); + }); + + it('extracts dotnet backend tool', () => { + const content = codeBlock` + [tools] + "dotnet:GitVersion.Tool" = "5.12.0" + `; + const result = extractPackageFile(content, miseFilename); + expect(result).toMatchObject({ + deps: [ + { + depName: 'dotnet:GitVersion.Tool', + currentValue: '5.12.0', + packageName: 'GitVersion.Tool', + datasource: 'nuget', + }, + ], + }); + }); + + it('extracts gem backend tool', () => { + const content = codeBlock` + [tools] + "gem:rubocop" = "1.69.2" + `; + const result = extractPackageFile(content, miseFilename); + expect(result).toMatchObject({ + deps: [ + { + depName: 'gem:rubocop', + currentValue: '1.69.2', + packageName: 'rubocop', + datasource: 'rubygems', + }, + ], + }); + }); + + it('extracts go backend tool', () => { + const content = codeBlock` + [tools] + "go:github.com/DarthSim/hivemind" = "1.0.6" + `; + const result = extractPackageFile(content, miseFilename); + expect(result).toMatchObject({ + deps: [ + { + depName: 'go:github.com/DarthSim/hivemind', + currentValue: '1.0.6', + packageName: 'github.com/DarthSim/hivemind', + datasource: 'go', + }, + ], + }); + }); + + it('extracts npm backend tool', () => { + const content = codeBlock` + [tools] + "npm:prettier" = "3.3.2" + `; + const result = extractPackageFile(content, miseFilename); + expect(result).toMatchObject({ + deps: [ + { + depName: 'npm:prettier', + currentValue: '3.3.2', + packageName: 'prettier', + datasource: 'npm', + }, + ], + }); + }); + + it('extracts pipx backend tools', () => { + const content = codeBlock` + [tools] + "pipx:yamllint" = "1.35.0" + "pipx:psf/black" = "24.4.1" + "pipx:git+https://github.com/psf/black.git" = "24.4.1" + `; + const result = extractPackageFile(content, miseFilename); + expect(result).toMatchObject({ + deps: [ + { + depName: 'pipx:yamllint', + currentValue: '1.35.0', + packageName: 'yamllint', + datasource: 'pypi', + }, + { + depName: 'pipx:psf/black', + currentValue: '24.4.1', + packageName: 'psf/black', + datasource: 'github-tags', + }, + { + depName: 'pipx:git+https://github.com/psf/black.git', + currentValue: '24.4.1', + packageName: 'psf/black', + datasource: 'github-tags', + }, + ], + }); + }); + + it('extracts spm backend tools', () => { + const content = codeBlock` + [tools] + "spm:tuist/tuist" = "4.15.0" + "spm:https://github.com/tuist/tuist.git" = "4.13.0" + `; + const result = extractPackageFile(content, miseFilename); + expect(result).toMatchObject({ + deps: [ + { + depName: 'spm:tuist/tuist', + currentValue: '4.15.0', + packageName: 'tuist/tuist', + datasource: 'github-releases', + }, + { + depName: 'spm:https://github.com/tuist/tuist.git', + currentValue: '4.13.0', + packageName: 'tuist/tuist', + datasource: 'github-releases', + }, + ], + }); + }); + + it('extracts ubi backend tools', () => { + const content = codeBlock` + [tools] + "ubi:nekto/act" = "v0.2.70" + "ubi:cli/cli" = { exe = "gh", version = "1.14.0" } + "ubi:cli/cli[exe=gh]" = "1.14.0" + "ubi:cargo-bins/cargo-binstall" = { tag_regex = "^\\\\d+\\\\.\\\\d+\\\\.", version = "1.0.0" } + "ubi:cargo-bins/cargo-binstall[tag_regex=^\\\\d+\\\\.]" = "1.0.0" + 'ubi:cargo-bins/cargo-binstall[tag_regex=^\\d+\\.\\d+\\.]' = { tag_regex = '^\\d+\\.', version = "1.0.0" } + `; + const result = extractPackageFile(content, miseFilename); + expect(result).toMatchObject({ + deps: [ + { + depName: 'ubi:nekto/act', + currentValue: 'v0.2.70', + packageName: 'nekto/act', + datasource: 'github-releases', + }, + { + depName: 'ubi:cli/cli', + currentValue: '1.14.0', + packageName: 'cli/cli', + datasource: 'github-releases', + extractVersion: '^v?(?.+)', + }, + { + depName: 'ubi:cli/cli', + currentValue: '1.14.0', + packageName: 'cli/cli', + datasource: 'github-releases', + extractVersion: '^v?(?.+)', + }, + { + depName: 'ubi:cargo-bins/cargo-binstall', + currentValue: '1.0.0', + packageName: 'cargo-bins/cargo-binstall', + datasource: 'github-releases', + extractVersion: '^v?(?\\d+\\.\\d+\\.)', + }, + { + depName: 'ubi:cargo-bins/cargo-binstall', + currentValue: '1.0.0', + packageName: 'cargo-bins/cargo-binstall', + datasource: 'github-releases', + extractVersion: '^v?(?\\d+\\.)', + }, + { + depName: 'ubi:cargo-bins/cargo-binstall', + currentValue: '1.0.0', + packageName: 'cargo-bins/cargo-binstall', + datasource: 'github-releases', + extractVersion: '^v?(?\\d+\\.)', + }, + ], + }); + }); + it('provides skipReason for lines with unsupported tooling', () => { const content = codeBlock` [tools] fake-tool = '1.0.0' + 'fake:tool' = '1.0.0' `; const result = extractPackageFile(content, miseFilename); expect(result).toMatchObject({ @@ -291,6 +615,10 @@ describe('modules/manager/mise/extract', () => { depName: 'fake-tool', skipReason: 'unsupported-datasource', }, + { + depName: 'fake:tool', + skipReason: 'unsupported-datasource', + }, ], }); }); @@ -348,7 +676,7 @@ describe('modules/manager/mise/extract', () => { }); }); - it('complete .mise.toml example', () => { + it('complete mise.toml example', () => { const result = extractPackageFile(mise1toml, miseFilename); expect(result).toMatchObject({ deps: [ diff --git a/lib/modules/manager/mise/extract.ts b/lib/modules/manager/mise/extract.ts index 9530336bfad..bb7e1911aae 100644 --- a/lib/modules/manager/mise/extract.ts +++ b/lib/modules/manager/mise/extract.ts @@ -1,12 +1,29 @@ import is from '@sindresorhus/is'; import { logger } from '../../../logger'; +import { regEx } from '../../../util/regex'; import type { ToolingConfig } from '../asdf/upgradeable-tooling'; import type { PackageDependency, PackageFileContent } from '../types'; -import type { MiseToolSchema } from './schema'; +import type { BackendToolingConfig } from './backends'; +import { + createAquaToolConfig, + createCargoToolConfig, + createDotnetToolConfig, + createGemToolConfig, + createGoToolConfig, + createNpmToolConfig, + createPipxToolConfig, + createSpmToolConfig, + createUbiToolConfig, +} from './backends'; +import type { MiseToolOptionsSchema, MiseToolSchema } from './schema'; import type { ToolingDefinition } from './upgradeable-tooling'; import { asdfTooling, miseTooling } from './upgradeable-tooling'; import { parseTomlFile } from './utils'; +// Tool names can have options in the tool name +// e.g. ubi:tamasfe/taplo[matching=full,exe=taplo] +const optionInToolNameRegex = regEx(/^(?.+?)(?:\[(?.+)\])?$/); + export function extractPackageFile( content: string, packageFile: string, @@ -24,8 +41,20 @@ export function extractPackageFile( if (tools) { for (const [name, toolData] of Object.entries(tools)) { const version = parseVersion(toolData); - const depName = name.trim(); - const toolConfig = getToolConfig(depName, version); + // Parse the tool options in the tool name + const { name: depName, options: optionsInName } = + optionInToolNameRegex.exec(name.trim())!.groups!; + const delimiterIndex = name.indexOf(':'); + const backend = depName.substring(0, delimiterIndex); + const toolName = depName.substring(delimiterIndex + 1); + const options = parseOptions( + optionsInName, + is.nonEmptyObject(toolData) ? toolData : {}, + ); + const toolConfig = + version === null + ? null + : getToolConfig(backend, toolName, version, options); const dep = createDependency(depName, version, toolConfig); deps.push(dep); } @@ -53,18 +82,79 @@ function parseVersion(toolData: MiseToolSchema): string | null { return null; // Return null if no version is found } +function parseOptions( + optionsInName: string, + toolOptions: MiseToolOptionsSchema, +): MiseToolOptionsSchema { + const options = is.nonEmptyString(optionsInName) + ? Object.fromEntries( + optionsInName.split(',').map((option) => option.split('=', 2)), + ) + : {}; + // Options in toolOptions will override options in the tool name + return { + ...options, + ...toolOptions, + }; +} + function getToolConfig( - name: string, - version: string | null, -): ToolingConfig | null { - if (version === null) { - return null; // Early return if version is null + backend: string, + toolName: string, + version: string, + toolOptions: MiseToolOptionsSchema, +): ToolingConfig | BackendToolingConfig | null { + switch (backend) { + case '': + // If the tool name does not specify a backend, it should be a short name or an alias defined by users + return getRegistryToolConfig(toolName, version); + // We can specify core, asdf, vfox, aqua backends for tools in the default registry + // e.g. 'core:rust', 'asdf:rust', 'vfox:clang', 'aqua:act' + case 'core': + return getConfigFromTooling(miseTooling, toolName, version); + case 'asdf': + return getConfigFromTooling(asdfTooling, toolName, version); + case 'vfox': + return getRegistryToolConfig(toolName, version); + case 'aqua': + return ( + getRegistryToolConfig(toolName, version) ?? + createAquaToolConfig(toolName, version) + ); + case 'cargo': + return createCargoToolConfig(toolName, version); + case 'dotnet': + return createDotnetToolConfig(toolName); + case 'gem': + return createGemToolConfig(toolName); + case 'go': + return createGoToolConfig(toolName); + case 'npm': + return createNpmToolConfig(toolName); + case 'pipx': + return createPipxToolConfig(toolName); + case 'spm': + return createSpmToolConfig(toolName); + case 'ubi': + return createUbiToolConfig(toolName, version, toolOptions); + default: + // Unsupported backend + return null; } +} +/** + * Get the tooling config for a short name defined in the default registry + * @link https://mise.jdx.dev/registry.html + */ +function getRegistryToolConfig( + short: string, + version: string, +): ToolingConfig | null { // Try to get the config from miseTooling first, then asdfTooling return ( - getConfigFromTooling(miseTooling, name, version) ?? - getConfigFromTooling(asdfTooling, name, version) + getConfigFromTooling(miseTooling, short, version) ?? + getConfigFromTooling(asdfTooling, short, version) ); } @@ -79,7 +169,7 @@ function getConfigFromTooling( } // Return null if no toolDefinition is found return ( - (typeof toolDefinition.config === 'function' + (is.function(toolDefinition.config) ? toolDefinition.config(version) : toolDefinition.config) ?? null ); // Ensure null is returned instead of undefined @@ -88,17 +178,25 @@ function getConfigFromTooling( function createDependency( name: string, version: string | null, - config: ToolingConfig | null, + config: ToolingConfig | BackendToolingConfig | null, ): PackageDependency { if (version === null) { - return { depName: name, skipReason: 'unspecified-version' }; + return { + depName: name, + skipReason: 'unspecified-version', + }; } if (config === null) { - return { depName: name, skipReason: 'unsupported-datasource' }; + return { + depName: name, + skipReason: 'unsupported-datasource', + }; } + return { depName: name, currentValue: version, + // Spread the config last to override other properties ...config, }; } diff --git a/lib/modules/manager/mise/index.ts b/lib/modules/manager/mise/index.ts index 031df564863..f26b2036496 100644 --- a/lib/modules/manager/mise/index.ts +++ b/lib/modules/manager/mise/index.ts @@ -1,3 +1,17 @@ +import { deduplicateArray } from '../../../util/array'; +import { CrateDatasource } from '../../datasource/crate'; +import { GitRefsDatasource } from '../../datasource/git-refs'; +import { GitTagsDatasource } from '../../datasource/git-tags'; +import { GithubReleasesDatasource } from '../../datasource/github-releases'; +import { GithubTagsDatasource } from '../../datasource/github-tags'; +import { GoDatasource } from '../../datasource/go'; +import { JavaVersionDatasource } from '../../datasource/java-version'; +import { NodeVersionDatasource } from '../../datasource/node-version'; +import { NpmDatasource } from '../../datasource/npm'; +import { NugetDatasource } from '../../datasource/nuget'; +import { PypiDatasource } from '../../datasource/pypi'; +import { RubyVersionDatasource } from '../../datasource/ruby-version'; +import { RubygemsDatasource } from '../../datasource/rubygems'; import { supportedDatasources as asdfSupportedDatasources } from '../asdf'; export { extractPackageFile } from './extract'; @@ -12,5 +26,29 @@ export const defaultConfig = { ], }; -// Re-use the asdf datasources, as mise and asdf support the same plugins. -export const supportedDatasources = asdfSupportedDatasources; +const backendDatasources = { + core: [ + GithubReleasesDatasource.id, + GithubTagsDatasource.id, + JavaVersionDatasource.id, + NodeVersionDatasource.id, + RubyVersionDatasource.id, + ], + // Re-use the asdf datasources, as mise and asdf support the same plugins. + asdf: asdfSupportedDatasources, + aqua: [GithubTagsDatasource.id], + cargo: [CrateDatasource.id, GitTagsDatasource.id, GitRefsDatasource.id], + dotnet: [NugetDatasource.id], + gem: [RubygemsDatasource.id], + go: [GoDatasource.id], + npm: [NpmDatasource.id], + pipx: [PypiDatasource.id, GithubTagsDatasource.id, GitRefsDatasource.id], + spm: [GithubReleasesDatasource.id], + ubi: [GithubReleasesDatasource.id], + // not supported + vfox: [], +}; + +export const supportedDatasources = deduplicateArray( + Object.values(backendDatasources).flat(), +).sort(); diff --git a/lib/modules/manager/mise/readme.md b/lib/modules/manager/mise/readme.md index 4def797b88a..a499ba172d7 100644 --- a/lib/modules/manager/mise/readme.md +++ b/lib/modules/manager/mise/readme.md @@ -1,19 +1,14 @@ -Renovate can update the [mise](https://mise.jdx.dev/configuration.html#mise-toml) `.mise.toml` file. - -Renovate's `mise` manager can version these tools: - - - +Renovate can update the [mise](https://mise.jdx.dev/configuration.html#mise-toml) `mise.toml` file. ### Renovate only updates primary versions -Renovate's `mise` manager is designed to automatically update the _first_ (primary) version listed for each tool in the `.mise.toml` file. +Renovate's `mise` manager is designed to automatically update the _first_ (primary) version listed for each tool in the `mise.toml` file. Secondary or fallback versions require manual updates. #### Example -Given a `.mise.toml` entry like: +Given a `mise.toml` entry like: ```toml [tools] @@ -30,16 +25,11 @@ To maintain consistency and reliability, Renovate opts to only manage the _first This follows the same workflow that Renovate's `asdf` manager uses. -### Plugin/tool support - -Renovate uses: +### Short names support -- [mise's plugins](https://github.com/jdx/mise/tree/main/src/plugins/core) -- [asdf's plugins](https://mise.jdx.dev/registry.html) +Renovate uses [mise registry](https://mise.jdx.dev/registry.html) to understand tools short names. -to understand and manage tool versioning. - -Support for new tools/plugins needs to be _manually_ added to Renovate's logic. +Support for new tool short names needs to be _manually_ added to Renovate's logic. #### Adding new tool support @@ -48,8 +38,60 @@ There are 2 ways to integrate versioning for a new tool: - Renovate's `mise` manager: ensure upstream `mise` supports the tool, then add support to the `mise` manager in Renovate - Renovate's `asdf` manager: improve the `asdf` manager in Renovate, which automatically extends support to `mise` -If `mise` adds support for more tools via its own [core plugins](https://mise.jdx.dev/plugins.html#core-plugins), you can create a PR to extend Renovate's `mise` manager to add support for the new tooling. +If `mise` adds support for more tools via its own [core tools](https://mise.jdx.dev/core-tools.html), you can create a PR to extend Renovate's `mise` manager to add support for the new core tools. + +If you want to add support for other tools' short names to `mise`, you can create a PR to extend Renovate's `asdf` manager, which indirectly helps Renovate's `mise` manager as well. +Even if the tool does not use the `asdf` backend in the registry, the short names added to the `asdf` manager will still be used in the `mise` manager. + +### Backends support + +Renovate's `mise` manager supports the following [backends](https://mise.jdx.dev/dev-tools/backends/): + +- [`core`](https://mise.jdx.dev/core-tools.html) +- [`asdf`](https://mise.jdx.dev/dev-tools/backends/asdf.html) +- [`aqua`](https://mise.jdx.dev/dev-tools/backends/aqua.html) +- [`cargo`](https://mise.jdx.dev/dev-tools/backends/cargo.html) +- [`go`](https://mise.jdx.dev/dev-tools/backends/go.html) +- [`npm`](https://mise.jdx.dev/dev-tools/backends/npm.html) +- [`pipx`](https://mise.jdx.dev/dev-tools/backends/pipx.html) +- [`spm`](https://mise.jdx.dev/dev-tools/backends/spm.html) +- [`ubi`](https://mise.jdx.dev/dev-tools/backends/ubi.html) +- [`vfox`](https://mise.jdx.dev/dev-tools/backends/vfox.html) -You may be able to add support for new tooling upstream in the core plugins - create an issue and see if the community agrees whether it belongs there, or if it would be better as an `asdf-` plugin. +#### Limitations -If you are wanting to add support for an existing `asdf-x` plugin to `mise`, you can create a PR to extend Renovate's `asdf` manager, which indirectly helps Renovate's `mise` manager as well. +Renovate's `mise` manager does not support the following tool syntax: + +- `asdf` and `vfox` plugins + e.g. `asdf:mise-plugins/asdf-yarn` or `vfox:version-fox/vfox-elixir` + Short names with backends like `asdf:yarn` or `vfox:elixir` are supported if the short names (`yarn`, `elixir`) are supported. + +- `aqua` packages with `http` [package type](https://aquaproj.github.io/docs/reference/registry-config/#package-types). + However if the short name using `aqua` backend is supported by Renovate, it will be updated. + e.g. [`aqua:helm/helm`](https://github.com/aquaproj/aqua-registry/blob/main/pkgs/helm/helm/registry.yaml) is not supported, but `helm` or `aqua:helm` is supported. + +- `aqua` packages with [`version_filter`](https://aquaproj.github.io/docs/reference/registry-config/version-prefix). + We don't read the aqua registry itself, so we can't support this feature. + If some packages using `version_filter` like [`aqua:biomejs/biome`](https://github.com/aquaproj/aqua-registry/blob/main/pkgs/biomejs/biome/registry.yaml) are not updated or updated incorrectly, set `extractVersion` in the Renovate config manually like below. + + ```json + { + "packageRules": [ + { + "depNames": ["aqua:biomejs/biome"], + "extractVersion": "cli/(?.+)" + } + ] + } + ``` + +- Some of `ubi` backend tools with [`tag_regex`](https://mise.jdx.dev/dev-tools/backends/ubi.html#ubi-uses-weird-versions) option. + The `tag_regex` option is used as `extractVersion`, but the regex engines are not the same between mise and Renovate. + If the version is not updated or updated incorrectly, override `extractVersion` manually in the Renovate config. + +### Supported default registry tool short names + +Renovate's `mise` manager can only version these tool short names: + + + diff --git a/lib/modules/manager/mise/schema.ts b/lib/modules/manager/mise/schema.ts index b4614ebff9c..2e264fd9279 100644 --- a/lib/modules/manager/mise/schema.ts +++ b/lib/modules/manager/mise/schema.ts @@ -1,9 +1,17 @@ import { z } from 'zod'; import { Toml } from '../../../util/schema-utils'; +const MiseToolOptionsSchema = z.object({ + // ubi backend only + tag_regex: z.string().optional(), +}); +export type MiseToolOptionsSchema = z.infer; + const MiseToolSchema = z.union([ z.string(), - z.object({ version: z.string().optional() }), + MiseToolOptionsSchema.extend({ + version: z.string().optional(), + }), z.array(z.string()), ]); export type MiseToolSchema = z.infer; diff --git a/lib/modules/manager/mise/upgradeable-tooling.ts b/lib/modules/manager/mise/upgradeable-tooling.ts index 99722633f1f..99d6bc37af0 100644 --- a/lib/modules/manager/mise/upgradeable-tooling.ts +++ b/lib/modules/manager/mise/upgradeable-tooling.ts @@ -223,6 +223,14 @@ const miseRegistryTooling: Record = { extractVersion: '^v(?\\S+)', }, }, + committed: { + misePluginUrl: 'https://mise.jdx.dev/registry.html#tools', + config: { + packageName: 'crate-ci/committed', + datasource: GithubReleasesDatasource.id, + extractVersion: '^v(?\\S+)', + }, + }, consul: { misePluginUrl: 'https://mise.jdx.dev/registry.html#tools', config: { @@ -247,6 +255,14 @@ const miseRegistryTooling: Record = { extractVersion: '^jq-v(?\\S+)', }, }, + hk: { + misePluginUrl: 'https://mise.jdx.dev/registry.html#tools', + config: { + packageName: 'jdx/hk', + datasource: GithubReleasesDatasource.id, + extractVersion: '^v(?\\S+)', + }, + }, kafka: { misePluginUrl: 'https://mise.jdx.dev/registry.html#tools', config: (version) => { @@ -262,6 +278,14 @@ const miseRegistryTooling: Record = { return undefined; }, }, + lefthook: { + misePluginUrl: 'https://mise.jdx.dev/registry.html#tools', + config: { + packageName: 'evilmartians/lefthook', + datasource: GithubReleasesDatasource.id, + extractVersion: '^v(?\\S+)', + }, + }, localstack: { misePluginUrl: 'https://mise.jdx.dev/registry.html#tools', config: { @@ -293,6 +317,13 @@ const miseRegistryTooling: Record = { datasource: GithubReleasesDatasource.id, }, }, + ruff: { + misePluginUrl: 'https://mise.jdx.dev/registry.html#tools', + config: { + packageName: 'astral-sh/ruff', + datasource: GithubReleasesDatasource.id, + }, + }, shellcheck: { misePluginUrl: 'https://mise.jdx.dev/registry.html#tools', config: { diff --git a/lib/modules/manager/npm/extract/__snapshots__/index.spec.ts.snap b/lib/modules/manager/npm/extract/__snapshots__/index.spec.ts.snap index 8502d319ec1..0fc148c2cf3 100644 --- a/lib/modules/manager/npm/extract/__snapshots__/index.spec.ts.snap +++ b/lib/modules/manager/npm/extract/__snapshots__/index.spec.ts.snap @@ -14,6 +14,7 @@ exports[`modules/manager/npm/extract/index > .extractPackageFile() > catches inv "managerData": { "hasPackageManager": false, "npmLock": undefined, + "npmrcFileName": undefined, "packageJsonName": undefined, "pnpmShrinkwrap": undefined, "workspaces": undefined, @@ -132,6 +133,7 @@ exports[`modules/manager/npm/extract/index > .extractPackageFile() > extracts en "managerData": { "hasPackageManager": false, "npmLock": undefined, + "npmrcFileName": undefined, "packageJsonName": undefined, "pnpmShrinkwrap": undefined, "workspaces": undefined, @@ -345,6 +347,7 @@ exports[`modules/manager/npm/extract/index > .extractPackageFile() > extracts no "managerData": { "hasPackageManager": false, "npmLock": undefined, + "npmrcFileName": undefined, "packageJsonName": undefined, "pnpmShrinkwrap": undefined, "workspaces": undefined, @@ -428,6 +431,7 @@ exports[`modules/manager/npm/extract/index > .extractPackageFile() > extracts np "managerData": { "hasPackageManager": false, "npmLock": "package-lock.json", + "npmrcFileName": undefined, "packageJsonName": undefined, "pnpmShrinkwrap": undefined, "workspaces": undefined, @@ -460,6 +464,7 @@ exports[`modules/manager/npm/extract/index > .extractPackageFile() > extracts pa "managerData": { "hasPackageManager": true, "npmLock": undefined, + "npmrcFileName": undefined, "packageJsonName": undefined, "pnpmShrinkwrap": undefined, "workspaces": undefined, @@ -529,6 +534,7 @@ exports[`modules/manager/npm/extract/index > .extractPackageFile() > extracts vo "managerData": { "hasPackageManager": false, "npmLock": undefined, + "npmrcFileName": undefined, "packageJsonName": undefined, "pnpmShrinkwrap": undefined, "workspaces": undefined, @@ -577,6 +583,7 @@ exports[`modules/manager/npm/extract/index > .extractPackageFile() > extracts vo "managerData": { "hasPackageManager": false, "npmLock": undefined, + "npmrcFileName": undefined, "packageJsonName": undefined, "pnpmShrinkwrap": undefined, "workspaces": undefined, @@ -711,6 +718,7 @@ exports[`modules/manager/npm/extract/index > .extractPackageFile() > finds a loc "managerData": { "hasPackageManager": false, "npmLock": undefined, + "npmrcFileName": undefined, "packageJsonName": "renovate", "pnpmShrinkwrap": undefined, "workspaces": undefined, @@ -731,6 +739,7 @@ exports[`modules/manager/npm/extract/index > .extractPackageFile() > finds compl "managerData": { "hasPackageManager": false, "npmLock": undefined, + "npmrcFileName": undefined, "packageJsonName": "@a/b", "pnpmShrinkwrap": undefined, "workspaces": { @@ -887,6 +896,7 @@ exports[`modules/manager/npm/extract/index > .extractPackageFile() > returns an "managerData": { "hasPackageManager": false, "npmLock": undefined, + "npmrcFileName": undefined, "packageJsonName": "renovate", "pnpmShrinkwrap": undefined, "workspaces": undefined, @@ -1003,6 +1013,7 @@ exports[`modules/manager/npm/extract/index > .extractPackageFile() > returns an "managerData": { "hasPackageManager": false, "npmLock": undefined, + "npmrcFileName": undefined, "packageJsonName": "renovate", "pnpmShrinkwrap": undefined, "workspaces": [], @@ -1137,6 +1148,7 @@ exports[`modules/manager/npm/extract/index > .extractPackageFile() > sets skipIn "managerData": { "hasPackageManager": false, "npmLock": undefined, + "npmrcFileName": null, "packageJsonName": "renovate", "pnpmShrinkwrap": undefined, "workspaces": undefined, diff --git a/lib/modules/manager/npm/extract/index.spec.ts b/lib/modules/manager/npm/extract/index.spec.ts index e9dfb74096e..bd16d18314f 100644 --- a/lib/modules/manager/npm/extract/index.spec.ts +++ b/lib/modules/manager/npm/extract/index.spec.ts @@ -188,6 +188,14 @@ describe('modules/manager/npm/extract/index', () => { }); it('finds and filters .npmrc', async () => { + fs.findLocalSiblingOrParent.mockImplementation( + (packageFile, configFile): Promise => { + if (packageFile === 'package.json' && configFile === '.npmrc') { + return Promise.resolve('.npmrc'); + } + return Promise.resolve(null); + }, + ); fs.readLocalFile.mockImplementation((fileName): Promise => { if (fileName === '.npmrc') { return Promise.resolve('save-exact = true\npackage-lock = false\n'); @@ -202,6 +210,15 @@ describe('modules/manager/npm/extract/index', () => { expect(res?.npmrc).toBe('save-exact = true\n'); }); + it('uses config.npmrc if no .npmrc is returned from search', async () => { + const res = await npmExtract.extractPackageFile( + input01Content, + 'package.json', + { ...defaultExtractConfig, npmrc: 'config-npmrc' }, + ); + expect(res?.npmrc).toBe('config-npmrc'); + }); + it('uses config.npmrc if no .npmrc exists', async () => { fs.readLocalFile.mockResolvedValueOnce(null); const res = await npmExtract.extractPackageFile( @@ -213,6 +230,14 @@ describe('modules/manager/npm/extract/index', () => { }); it('uses config.npmrc if .npmrc does exist but npmrcMerge=false', async () => { + fs.findLocalSiblingOrParent.mockImplementation( + (packageFile, configFile): Promise => { + if (packageFile === 'package.json' && configFile === '.npmrc') { + return Promise.resolve('.npmrc'); + } + return Promise.resolve(null); + }, + ); fs.readLocalFile.mockImplementation((fileName): Promise => { if (fileName === '.npmrc') { return Promise.resolve('repo-npmrc\n'); @@ -228,6 +253,14 @@ describe('modules/manager/npm/extract/index', () => { }); it('merges config.npmrc and repo .npmrc when npmrcMerge=true', async () => { + fs.findLocalSiblingOrParent.mockImplementation( + (packageFile, configFile): Promise => { + if (packageFile === 'package.json' && configFile === '.npmrc') { + return Promise.resolve('.npmrc'); + } + return Promise.resolve(null); + }, + ); fs.readLocalFile.mockImplementation((fileName): Promise => { if (fileName === '.npmrc') { return Promise.resolve('repo-npmrc\n'); @@ -243,6 +276,14 @@ describe('modules/manager/npm/extract/index', () => { }); it('finds and filters .npmrc with variables', async () => { + fs.findLocalSiblingOrParent.mockImplementation( + (packageFile, configFile): Promise => { + if (packageFile === 'package.json' && configFile === '.npmrc') { + return Promise.resolve('.npmrc'); + } + return Promise.resolve(null); + }, + ); fs.readLocalFile.mockImplementation((fileName): Promise => { if (fileName === '.npmrc') { return Promise.resolve( diff --git a/lib/modules/manager/npm/extract/index.ts b/lib/modules/manager/npm/extract/index.ts index 95a1b6dab2c..82843e4f4d9 100644 --- a/lib/modules/manager/npm/extract/index.ts +++ b/lib/modules/manager/npm/extract/index.ts @@ -88,40 +88,42 @@ export async function extractPackageFile( } let npmrc: string | undefined; - const npmrcFileName = getSiblingFileName(packageFile, '.npmrc'); - let repoNpmrc = await readLocalFile(npmrcFileName, 'utf8'); - if (is.string(repoNpmrc)) { - if (is.string(config.npmrc) && !config.npmrcMerge) { - logger.debug( - { npmrcFileName }, - 'Repo .npmrc file is ignored due to config.npmrc with config.npmrcMerge=false', - ); - npmrc = config.npmrc; - } else { - npmrc = config.npmrc ?? ''; - if (npmrc.length) { - if (!npmrc.endsWith('\n')) { - npmrc += '\n'; - } - } - if (repoNpmrc?.includes('package-lock')) { - logger.debug('Stripping package-lock setting from .npmrc'); - repoNpmrc = repoNpmrc.replace( - regEx(/(^|\n)package-lock.*?(\n|$)/g), - '\n', - ); - } - if (repoNpmrc.includes('=${') && !GlobalConfig.get('exposeAllEnv')) { + const npmrcFileName = await findLocalSiblingOrParent(packageFile, '.npmrc'); + if (npmrcFileName) { + let repoNpmrc = await readLocalFile(npmrcFileName, 'utf8'); + if (is.string(repoNpmrc)) { + if (is.string(config.npmrc) && !config.npmrcMerge) { logger.debug( { npmrcFileName }, - 'Stripping .npmrc file of lines with variables', + 'Repo .npmrc file is ignored due to config.npmrc with config.npmrcMerge=false', ); - repoNpmrc = repoNpmrc - .split(newlineRegex) - .filter((line) => !line.includes('=${')) - .join('\n'); + npmrc = config.npmrc; + } else { + npmrc = config.npmrc ?? ''; + if (npmrc.length) { + if (!npmrc.endsWith('\n')) { + npmrc += '\n'; + } + } + if (repoNpmrc?.includes('package-lock')) { + logger.debug('Stripping package-lock setting from .npmrc'); + repoNpmrc = repoNpmrc.replace( + regEx(/(^|\n)package-lock.*?(\n|$)/g), + '\n', + ); + } + if (repoNpmrc.includes('=${') && !GlobalConfig.get('exposeAllEnv')) { + logger.debug( + { npmrcFileName }, + 'Stripping .npmrc file of lines with variables', + ); + repoNpmrc = repoNpmrc + .split(newlineRegex) + .filter((line) => !line.includes('=${')) + .join('\n'); + } + npmrc += repoNpmrc; } - npmrc += repoNpmrc; } } else if (is.string(config.npmrc)) { npmrc = config.npmrc; @@ -215,6 +217,7 @@ export async function extractPackageFile( packageJson.packageManager, ), workspacesPackages, + npmrcFileName, // store npmrc file name so we can later tell if it came from the workspace or not }, skipInstalls, extractedConstraints, diff --git a/lib/modules/manager/npm/post-update/index.ts b/lib/modules/manager/npm/post-update/index.ts index 4715dba6937..a22e2c56b90 100644 --- a/lib/modules/manager/npm/post-update/index.ts +++ b/lib/modules/manager/npm/post-update/index.ts @@ -136,7 +136,13 @@ export async function writeExistingFiles( const basedir = upath.dirname(packageFile.packageFile!); const npmrc = packageFile.npmrc; const npmrcFilename = upath.join(basedir, '.npmrc'); - if (is.string(npmrc)) { + // Write out the file unless the npmrc came from the workspace + // npmrcFilename will be set whenever the file was read from disk during extract + if ( + is.string(npmrc) && + (npmrcFilename === packageFile.managerData.npmrcFileName || + !packageFile.managerData.npmrcFileName) + ) { try { await writeLocalFile(npmrcFilename, npmrc.replace(/\n?$/, '\n')); } catch (err) /* istanbul ignore next */ { diff --git a/lib/modules/manager/npm/post-update/npm.spec.ts b/lib/modules/manager/npm/post-update/npm.spec.ts index f623c93240e..2932e600e23 100644 --- a/lib/modules/manager/npm/post-update/npm.spec.ts +++ b/lib/modules/manager/npm/post-update/npm.spec.ts @@ -724,4 +724,81 @@ describe('modules/manager/npm/post-update/npm', () => { }); }); }); + + describe('prevents injections', () => { + it('while performing lockfileUpdate (npm-workspaces)', async () => { + const execSnapshots = mockExecAll(); + // package.json + fs.readLocalFile.mockResolvedValue('{}'); + fs.readLocalFile.mockResolvedValueOnce('package-lock content'); + const skipInstalls = true; + const res = await npmHelper.generateLockFile( + 'some-dir', + {}, + 'package-lock.json', + { skipInstalls }, + [ + { + packageFile: 'some-dir/web/b/package.json', + packageName: ' && echo "hi";', + depType: 'dependencies', + newVersion: '2.2.0', + newValue: '^2.0.0', + isLockfileUpdate: true, + managerData: { + workspacesPackages: ['docs/*', 'web/*'], + }, + }, + { + packageFile: 'some-dir/docs/a || date; /package.json', + packageName: 'hello', + depType: 'dependencies', + newVersion: '1.1.1', + newValue: '^1.0.0', + isLockfileUpdate: true, + managerData: { + workspacesPackages: ['docs/*', 'web/*'], + }, + }, + ], + ); + expect(fs.readLocalFile).toHaveBeenCalledTimes(3); + expect(res.error).toBeFalse(); + expect(execSnapshots).toMatchObject([ + { + cmd: `npm install --package-lock-only --no-audit --ignore-scripts --workspace=web/b ' && echo "hi";@2.2.0'`, + }, + { + cmd: `npm install --package-lock-only --no-audit --ignore-scripts --workspace='docs/a || date; ' hello@1.1.1`, + }, + ]); + }); + + it('while performing lockfileUpdate (npm)', async () => { + const execSnapshots = mockExecAll(); + // package.json + fs.readLocalFile.mockResolvedValue('{}'); + fs.readLocalFile.mockResolvedValue('package-lock-contents'); + await npmHelper.generateLockFile( + 'some-dir', + {}, + 'package-lock.json', + {}, + [ + { + depName: 'uuid', + currentVersion: '^11.0.0', + newVersion: '11.1.0', + packageName: '; date; echo ', + isLockfileUpdate: true, + }, + ], + ); + expect(execSnapshots).toMatchObject([ + { + cmd: "npm install --package-lock-only --no-audit --ignore-scripts '; date; echo @11.1.0'", + }, + ]); + }); + }); }); diff --git a/lib/modules/manager/npm/post-update/npm.ts b/lib/modules/manager/npm/post-update/npm.ts index e92969cf445..fd98a3c04d0 100644 --- a/lib/modules/manager/npm/post-update/npm.ts +++ b/lib/modules/manager/npm/post-update/npm.ts @@ -1,6 +1,7 @@ // TODO: types (#22198) import is from '@sindresorhus/is'; import semver from 'semver'; +import { quote } from 'shlex'; import upath from 'upath'; import { GlobalConfig } from '../../../../config/global'; import { @@ -149,9 +150,9 @@ export async function generateLockFile( .filter((packageKey) => !rootDeps.has(packageKey)); if (currentWorkspaceUpdates.length) { - const updateCmd = `npm install ${cmdOptions} --workspace=${workspace} ${currentWorkspaceUpdates.join( - ' ', - )}`; + const updateCmd = `npm install ${cmdOptions} --workspace=${quote(workspace)} ${currentWorkspaceUpdates + .map(quote) + .join(' ')}`; commands.push(updateCmd); } } @@ -159,11 +160,10 @@ export async function generateLockFile( if (lockRootUpdates.length) { logger.debug('Performing lockfileUpdate (npm)'); - const updateCmd = - `npm install ${cmdOptions} ` + - lockRootUpdates - .map((update) => update.managerData?.packageKey) - .join(' '); + const updateCmd = `npm install ${cmdOptions} ${lockRootUpdates + .map((update) => update.managerData?.packageKey) + .map(quote) + .join(' ')}`; commands.push(updateCmd); } diff --git a/lib/modules/manager/npm/post-update/pnpm.spec.ts b/lib/modules/manager/npm/post-update/pnpm.spec.ts index 0d927dc6e07..5c53ea1ded3 100644 --- a/lib/modules/manager/npm/post-update/pnpm.spec.ts +++ b/lib/modules/manager/npm/post-update/pnpm.spec.ts @@ -1,3 +1,4 @@ +import { codeBlock } from 'common-tags'; import { GlobalConfig } from '../../../../config/global'; import type { PostUpdateConfig, Upgrade } from '../../types'; import { getNodeToolConstraint } from './node-version'; @@ -284,6 +285,61 @@ describe('modules/manager/npm/post-update/pnpm', () => { ]); }); + it('uses volta version and puts it into constraint', async () => { + const execSnapshots = mockExecAll(); + const configTemp = partial(); + const fileContent = codeBlock` + { + "name": "parent", + "version": "1.0.0", + "engines": { + "pnpm": "^6.0.0" + }, + "engine-strict": true, + "volta": { + "pnpm": "6.15.0" + } +} + + `; + fs.readLocalFile + .mockResolvedValueOnce(fileContent) + .mockResolvedValue('package-lock-contents'); + const res = await pnpmHelper.generateLockFile( + 'some-folder', + {}, + configTemp, + [ + { + depType: 'volta', + depName: 'pnpm', + }, + ], + ); + expect(fs.readLocalFile).toHaveBeenCalledTimes(2); + expect(res.lockFile).toBe('package-lock-contents'); + expect(execSnapshots).toMatchObject([ + { + cmd: 'pnpm install --lockfile-only --ignore-scripts --ignore-pnpmfile', + options: { + cwd: 'some-folder', + encoding: 'utf-8', + env: { + HTTP_PROXY: 'http://example.com', + HTTPS_PROXY: 'https://example.com', + NO_PROXY: 'localhost', + HOME: '/home/user', + PATH: '/tmp/path', + LANG: 'en_US.UTF-8', + LC_ALL: 'en_US', + }, + maxBuffer: 10485760, + timeout: 900000, + }, + }, + ]); + }); + it('uses skips pnpm v7 if lockfileVersion indicates <7', async () => { mockExecAll(); const configTemp = partial(); diff --git a/lib/modules/manager/npm/post-update/utils.ts b/lib/modules/manager/npm/post-update/utils.ts index 3df4cc0e168..e37550ca640 100644 --- a/lib/modules/manager/npm/post-update/utils.ts +++ b/lib/modules/manager/npm/post-update/utils.ts @@ -1,3 +1,4 @@ +import is from '@sindresorhus/is'; import semver from 'semver'; import upath from 'upath'; import { logger } from '../../../../logger'; @@ -32,6 +33,25 @@ export function getPackageManagerVersion( name: string, pkg: PackageJsonSchema, ): string | null { + if (pkg.volta?.[name]) { + const version = pkg.volta[name]; + logger.debug(`Found ${name} constraint in package.json volta: ${version}`); + + return version; + } + if (pkg.devEngines?.packageManager) { + const packageManagers = is.array(pkg.devEngines.packageManager) + ? pkg.devEngines.packageManager + : [pkg.devEngines.packageManager]; + const packageMgr = packageManagers.find((pm) => pm.name === name); + const version = packageMgr?.version; + if (version) { + logger.debug( + `Found ${name} constraint in package.json devEngines: ${version}`, + ); + return version; + } + } if (pkg.packageManager?.name === name) { const version = pkg.packageManager.version; logger.debug( diff --git a/lib/modules/manager/npm/post-update/yarn.spec.ts b/lib/modules/manager/npm/post-update/yarn.spec.ts index 461786ae158..32e29ebde9e 100644 --- a/lib/modules/manager/npm/post-update/yarn.spec.ts +++ b/lib/modules/manager/npm/post-update/yarn.spec.ts @@ -635,6 +635,84 @@ describe('modules/manager/npm/post-update/yarn', () => { ]); }); + it('uses devEngine.packageManager(object) instead of corepack', async () => { + // sanity check for later refactorings + expect(plocktest1YarnLockV1).toBeTruthy(); + process.env.CONTAINERBASE = 'true'; + GlobalConfig.set({ + localDir: '.', + binarySource: 'install', + cacheDir: '/tmp/cache', + }); + Fixtures.mock( + { + 'package.json': + '{ "devEngines": {"packageManager": { "name": "yarn", "version": "1.22.19" } }, "packageManager": "yarn@1.22.18", "dependencies": { "chalk": "^2.4.1" } }', + 'yarn.lock': plocktest1YarnLockV1, + }, + 'some-dir', + ); + vi.mocked(getPkgReleases).mockResolvedValueOnce({ + releases: [{ version: '1.22.19' }, { version: '2.4.3' }], + }); + const execSnapshots = mockExecAll({ + stdout: '2.1.0', + stderr: '', + }); + const config = util.partial>({ + managerData: { hasPackageManager: true }, + }); + const res = await yarnHelper.generateLockFile('some-dir', {}, config); + expect(res.lockFile).toBe(plocktest1YarnLockV1); + expect(execSnapshots).toMatchObject([ + { cmd: 'install-tool node 16.16.0', options: { cwd: 'some-dir' } }, + { cmd: 'install-tool yarn-slim 1.22.19', options: { cwd: 'some-dir' } }, + { + cmd: 'yarn install --ignore-engines --ignore-platform --network-timeout 100000 --ignore-scripts', + options: { cwd: 'some-dir' }, + }, + ]); + }); + + it('uses devEngine.packageManager(array) instead of corepack', async () => { + // sanity check for later refactorings + expect(plocktest1YarnLockV1).toBeTruthy(); + process.env.CONTAINERBASE = 'true'; + GlobalConfig.set({ + localDir: '.', + binarySource: 'install', + cacheDir: '/tmp/cache', + }); + Fixtures.mock( + { + 'package.json': + '{ "devEngines": {"packageManager": [{ "name": "yarn", "version": "1.22.19" }] }, "packageManager": "yarn@1.22.18", "dependencies": { "chalk": "^2.4.1" } }', + 'yarn.lock': plocktest1YarnLockV1, + }, + 'some-dir', + ); + vi.mocked(getPkgReleases).mockResolvedValueOnce({ + releases: [{ version: '1.22.19' }, { version: '2.4.3' }], + }); + const execSnapshots = mockExecAll({ + stdout: '2.1.0', + stderr: '', + }); + const config = util.partial>({ + managerData: { hasPackageManager: true }, + }); + const res = await yarnHelper.generateLockFile('some-dir', {}, config); + expect(res.lockFile).toBe(plocktest1YarnLockV1); + expect(execSnapshots).toMatchObject([ + { cmd: 'install-tool node 16.16.0', options: { cwd: 'some-dir' } }, + { cmd: 'install-tool yarn-slim 1.22.19', options: { cwd: 'some-dir' } }, + { + cmd: 'yarn install --ignore-engines --ignore-platform --network-timeout 100000 --ignore-scripts', + options: { cwd: 'some-dir' }, + }, + ]); + }); + it('patches local yarn', async () => { // sanity check for later refactorings expect(plocktest1YarnLockV1).toBeTruthy(); diff --git a/lib/modules/manager/npm/schema.ts b/lib/modules/manager/npm/schema.ts index 7efbf9a0f91..a3e9aec5501 100644 --- a/lib/modules/manager/npm/schema.ts +++ b/lib/modules/manager/npm/schema.ts @@ -17,12 +17,25 @@ export const PackageManagerSchema = z .transform((val) => val.split('@')) .transform(([name, ...version]) => ({ name, version: version.join('@') })); +const DevEngineDependency = z.object({ + name: z.string(), + version: z.string().optional(), +}); + +const DevEngineSchema = z.object({ + packageManager: DevEngineDependency.or( + z.array(DevEngineDependency), + ).optional(), +}); + export const PackageJsonSchema = z.object({ + devEngines: DevEngineSchema.optional(), engines: LooseRecord(z.string()).optional(), dependencies: LooseRecord(z.string()).optional(), devDependencies: LooseRecord(z.string()).optional(), peerDependencies: LooseRecord(z.string()).optional(), packageManager: PackageManagerSchema.optional(), + volta: LooseRecord(z.string()).optional(), }); export type PackageJsonSchema = z.infer; diff --git a/lib/modules/manager/npm/utils.ts b/lib/modules/manager/npm/utils.ts index ed58e4b202c..59ce1a9dfc3 100644 --- a/lib/modules/manager/npm/utils.ts +++ b/lib/modules/manager/npm/utils.ts @@ -49,7 +49,7 @@ export async function updateNpmrcContent( ? [originalContent, ...additionalLines] : additionalLines; try { - const newContent = newNpmrc.join('\n'); + const newContent = newNpmrc.length ? newNpmrc.join('\n') : null; if (newContent !== originalContent) { logger.debug(`Writing updated .npmrc file to ${npmrcFilePath}`); await writeLocalFile(npmrcFilePath, `${newContent}\n`); diff --git a/lib/modules/platform/default-scm.spec.ts b/lib/modules/platform/default-scm.spec.ts index ba11d9d97c5..ef926576f2c 100644 --- a/lib/modules/platform/default-scm.spec.ts +++ b/lib/modules/platform/default-scm.spec.ts @@ -1,3 +1,4 @@ +import { RENOVATE_FORK_UPSTREAM } from '../../util/git'; import type { CommitFilesConfig, LongCommitSha } from '../../util/git/types'; import { DefaultGitScm } from './default-scm'; import { git, partial } from '~test/util'; @@ -70,4 +71,13 @@ describe('modules/platform/default-scm', () => { await defaultGitScm.mergeToLocal('branchName'); expect(git.mergeToLocal).toHaveBeenCalledWith('branchName'); }); + + it('syncs fork with upstream', async () => { + git.getRemotes.mockResolvedValueOnce([ + 'somebranch', + RENOVATE_FORK_UPSTREAM, + ]); + await defaultGitScm.syncForkWithUpstream('branchName'); + expect(git.syncForkWithUpstream).toHaveBeenCalledWith('branchName'); + }); }); diff --git a/lib/modules/platform/default-scm.ts b/lib/modules/platform/default-scm.ts index edf27c2e391..4846947df2f 100644 --- a/lib/modules/platform/default-scm.ts +++ b/lib/modules/platform/default-scm.ts @@ -48,4 +48,8 @@ export class DefaultGitScm implements PlatformScm { mergeToLocal(branchName: string): Promise { return git.mergeToLocal(branchName); } + + syncForkWithUpstream(branchName: string): Promise { + return git.syncForkWithUpstream(branchName); + } } diff --git a/lib/modules/platform/gerrit/client.spec.ts b/lib/modules/platform/gerrit/client.spec.ts index 17670eb5839..cdd60a7630c 100644 --- a/lib/modules/platform/gerrit/client.spec.ts +++ b/lib/modules/platform/gerrit/client.spec.ts @@ -108,7 +108,7 @@ describe('modules/platform/gerrit/client', () => { { branchName: 'dependency-xyz', targetBranch: 'otherTarget' }, ], [ - 'status:closed', + 'status:abandoned', { branchName: 'dependency-xyz', state: 'closed' as FindPRConfig['state'], @@ -122,7 +122,7 @@ describe('modules/platform/gerrit/client', () => { }, ], [ - 'message:"fix(deps): update dependency react-router-dom to ~> v6.21.2"', + 'message:"fix(deps): update dependency react-router-dom to ~> \\"v6.21.2\\""', { branchName: 'dependency-xyz', prTitle: @@ -130,7 +130,7 @@ describe('modules/platform/gerrit/client', () => { }, ], [ - 'message:"fix(deps): update dependency react-router-dom to ~> v6.21.2"', + 'message:"fix(deps): \\"update dependency react-router-dom to ~> \\"v6.21.2\\"\\""', { branchName: 'dependency-xyz', prTitle: @@ -155,6 +155,46 @@ describe('modules/platform/gerrit/client', () => { ]); }, ); + + it('sets query.n when limit is provided', async () => { + httpMock + .scope(gerritEndpointUrl) + .get('/a/changes/') + .query((query) => query.n === '5' && !('no-limit' in query)) + .reply(200, gerritRestResponse([{ _number: 1 }]), jsonResultHeader); + await expect( + client.findChanges('repo', { branchName: 'dependency-xyz', limit: 5 }), + ).resolves.toEqual([{ _number: 1 }]); + }); + + it('sets query["no-limit"] when limit is not provided', async () => { + httpMock + .scope(gerritEndpointUrl) + .get('/a/changes/') + .query((query) => query['no-limit'] === 'true') + .reply(200, gerritRestResponse([{ _number: 2 }]), jsonResultHeader); + await expect( + client.findChanges('repo', { branchName: 'dependency-xyz' }), + ).resolves.toEqual([{ _number: 2 }]); + }); + + it('sets query.o when requestDetails is provided', async () => { + httpMock + .scope(gerritEndpointUrl) + .get('/a/changes/') + .query( + (query) => + Array.isArray(query.o) && + query.o.toString() === ['LABELS', 'MESSAGES'].toString(), + ) + .reply(200, gerritRestResponse([{ _number: 3 }]), jsonResultHeader); + await expect( + client.findChanges('repo', { + branchName: 'dependency-xyz', + requestDetails: ['LABELS', 'MESSAGES'], + }), + ).resolves.toEqual([{ _number: 3 }]); + }); }); describe('getChange()', () => { @@ -162,11 +202,14 @@ describe('modules/platform/gerrit/client', () => { const change = partial({}); httpMock .scope(gerritEndpointUrl) - .get( - '/a/changes/123456?o=SUBMITTABLE&o=CHECK&o=MESSAGES&o=DETAILED_ACCOUNTS&o=LABELS&o=CURRENT_ACTIONS&o=CURRENT_REVISION&o=CURRENT_COMMIT', - ) + .get('/a/changes/123456?o=CURRENT_REVISION&o=COMMIT_FOOTERS') .reply(200, gerritRestResponse(change), jsonResultHeader); - await expect(client.getChange(123456)).resolves.toEqual(change); + await expect( + client.getChange(123456, undefined, [ + 'CURRENT_REVISION', + 'COMMIT_FOOTERS', + ]), + ).resolves.toEqual(change); }); }); @@ -190,10 +233,24 @@ describe('modules/platform/gerrit/client', () => { it('abandon', async () => { httpMock .scope(gerritEndpointUrl) - .post('/a/changes/123456/abandon') + .post('/a/changes/123456/abandon', { + notify: 'OWNER_REVIEWERS', + }) .reply(200, gerritRestResponse({}), jsonResultHeader); await expect(client.abandonChange(123456)).toResolve(); }); + it('abandon with message', async () => { + httpMock + .scope(gerritEndpointUrl) + .post('/a/changes/123456/abandon', { + message: 'The abandon reason is important.', + notify: 'OWNER_REVIEWERS', + }) + .reply(200, gerritRestResponse({}), jsonResultHeader); + await expect( + client.abandonChange(123456, 'The abandon reason is important.'), + ).toResolve(); + }); }); describe('submitChange()', () => { diff --git a/lib/modules/platform/gerrit/client.ts b/lib/modules/platform/gerrit/client.ts index 09306171cb3..5b631240a3a 100644 --- a/lib/modules/platform/gerrit/client.ts +++ b/lib/modules/platform/gerrit/client.ts @@ -3,7 +3,6 @@ import { logger } from '../../../logger'; import { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider'; import { GerritHttp } from '../../../util/http/gerrit'; import type { HttpOptions } from '../../../util/http/types'; -import { regEx } from '../../../util/regex'; import { getQueryString } from '../../../util/url'; import type { GerritAccountInfo, @@ -13,29 +12,16 @@ import type { GerritFindPRConfig, GerritMergeableInfo, GerritProjectInfo, + GerritRequestDetail, } from './types'; import { mapPrStateToGerritFilter } from './utils'; -const QUOTES_REGEX = regEx('"', 'g'); - class GerritClient { - private requestDetails = [ - 'SUBMITTABLE', //include the submittable field in ChangeInfo, which can be used to tell if the change is reviewed and ready for submit. - 'CHECK', // include potential consistency problems with the change (not related to labels) - 'MESSAGES', - 'DETAILED_ACCOUNTS', - 'LABELS', - 'CURRENT_ACTIONS', //to check if current_revision can be "rebased" - 'CURRENT_REVISION', //get RevisionInfo::ref to fetch - 'CURRENT_COMMIT', // to get the commit message - ] as const; - private gerritHttp = new GerritHttp(); async getRepos(): Promise { const res = await this.gerritHttp.getJsonUnchecked( 'a/projects/?type=CODE&state=ACTIVE', - {}, ); return Object.keys(res.body); } @@ -61,36 +47,54 @@ class GerritClient { async findChanges( repository: string, findPRConfig: GerritFindPRConfig, - refreshCache?: boolean, ): Promise { - const opts: HttpOptions = {}; /* v8 ignore start: temporary code */ + // Disables memCache (enabled by default) to be replaced by memCacheProvider + const opts: HttpOptions = { memCache: false }; // TODO: should refresh the cache rather than just ignore it - if (refreshCache) { - opts.memCache = false; - } else { + if (!findPRConfig.refreshCache) { opts.cacheProvider = memCacheProvider; } /* v8 ignore stop */ + const query: Record = {}; + if (findPRConfig.requestDetails) { + query.o = findPRConfig.requestDetails; + } + if (findPRConfig.limit) { + query.n = findPRConfig.limit; + } else { + // TODO: handle pagination instead + query['no-limit'] = true; + } const filters = GerritClient.buildSearchFilters(repository, findPRConfig); - const queryString = getQueryString({ - o: this.requestDetails, - }); + const queryString = `q=${filters.join('+')}&${getQueryString(query)}`; const changes = await this.gerritHttp.getJsonUnchecked( - `a/changes/?q=${filters.join('+')}&${queryString}`, + `a/changes/?${queryString}`, opts, ); - logger.trace( - `findChanges(${filters.join(', ')}) => ${changes.body.length}`, - ); + logger.trace(`findChanges(${queryString}) => ${changes.body.length}`); return changes.body; } - async getChange(changeNumber: number): Promise { - const queryString = getQueryString({ o: this.requestDetails }); + async getChange( + changeNumber: number, + refreshCache?: boolean, + requestDetails?: GerritRequestDetail[], + ): Promise { + /* v8 ignore start: temporary code */ + // Disables memCache (enabled by default) to be replaced by memCacheProvider + const opts: HttpOptions = { memCache: false }; + // TODO: should refresh the cache rather than just ignore it + if (!refreshCache) { + opts.cacheProvider = memCacheProvider; + } + /* v8 ignore stop */ + + const queryString = getQueryString({ o: requestDetails }); const changes = await this.gerritHttp.getJsonUnchecked( `a/changes/${changeNumber}?${queryString}`, + opts, ); return changes.body; } @@ -103,8 +107,13 @@ class GerritClient { return mergeable.body; } - async abandonChange(changeNumber: number): Promise { - await this.gerritHttp.postJson(`a/changes/${changeNumber}/abandon`); + async abandonChange(changeNumber: number, message?: string): Promise { + await this.gerritHttp.postJson(`a/changes/${changeNumber}/abandon`, { + body: { + message, + notify: 'OWNER_REVIEWERS', // Avoids notifying cc's + }, + }); } async submitChange(changeNumber: number): Promise { @@ -137,9 +146,11 @@ class GerritClient { changeNumber: number, newMessage: string, msgType?: string, + messages?: GerritChangeMessageInfo[], ): Promise { - const messages = await this.getMessages(changeNumber); - return messages.some( + const messagesToSearch = messages ?? (await this.getMessages(changeNumber)); + + return messagesToSearch.some( (existingMsg) => (msgType === undefined || msgType === existingMsg.tag) && existingMsg.message.includes(newMessage), @@ -150,9 +161,12 @@ class GerritClient { changeNumber: number, message: string, tag?: string, + messages?: GerritChangeMessageInfo[], ): Promise { const newMsg = this.normalizeMessage(message); - if (!(await this.checkForExistingMessage(changeNumber, newMsg, tag))) { + if ( + !(await this.checkForExistingMessage(changeNumber, newMsg, tag, messages)) + ) { await this.addMessage(changeNumber, newMsg, tag); } } @@ -212,11 +226,21 @@ class GerritClient { repository: string, searchConfig: GerritFindPRConfig, ): string[] { + const filters = [ + 'owner:self', + `project:${repository}`, + '-is:wip', + '-is:private', + ]; const filterState = mapPrStateToGerritFilter(searchConfig.state); - const filters = ['owner:self', 'project:' + repository, filterState]; + if (filterState) { + filters.push(filterState); + } if (searchConfig.branchName) { filters.push(`footer:Renovate-Branch=${searchConfig.branchName}`); } + // TODO: Use Gerrit 3.6+ hasfooter:Renovate-Branch when branchName is empty: + // https://gerrit-review.googlesource.com/c/gerrit/+/329488 if (searchConfig.targetBranch) { filters.push(`branch:${searchConfig.targetBranch}`); } @@ -224,10 +248,12 @@ class GerritClient { filters.push(`label:Code-Review=${searchConfig.label}`); } if (searchConfig.prTitle) { - // escaping support in Gerrit is not great, so we need to remove quotes - // special characters are ignored anyway in the search so it does not create any issues + // Quotes in the commit message must be escaped with a backslash: + // https://gerrit-review.googlesource.com/Documentation/user-search.html#search-operators + // TODO: Use Gerrit 3.8+ subject query instead: + // https://gerrit-review.googlesource.com/c/gerrit/+/354037 filters.push( - `message:${encodeURIComponent('"' + searchConfig.prTitle.replace(QUOTES_REGEX, '') + '"')}`, + `message:${encodeURIComponent('"' + searchConfig.prTitle.replaceAll('"', '\\"') + '"')}`, ); } return filters; diff --git a/lib/modules/platform/gerrit/index.spec.ts b/lib/modules/platform/gerrit/index.spec.ts index 6619b7376a0..3d9f67058ab 100644 --- a/lib/modules/platform/gerrit/index.spec.ts +++ b/lib/modules/platform/gerrit/index.spec.ts @@ -1,3 +1,4 @@ +import { DateTime } from 'luxon'; import { REPOSITORY_ARCHIVED } from '../../../constants/error-messages'; import type { BranchStatus } from '../../../types'; import { repoFingerprint } from '../util'; @@ -11,7 +12,11 @@ import type { GerritProjectInfo, GerritRevisionInfo, } from './types'; -import { TAG_PULL_REQUEST_BODY, mapGerritChangeToPr } from './utils'; +import { + REQUEST_DETAILS_FOR_PRS, + TAG_PULL_REQUEST_BODY, + mapGerritChangeToPr, +} from './utils'; import { writeToConfig } from '.'; import * as gerrit from '.'; import { git, hostRules, partial } from '~test/util'; @@ -34,6 +39,15 @@ vi.mock('./client'); const clientMock = vi.mocked(_client); describe('modules/platform/gerrit/index', () => { + const t0 = DateTime.fromISO('2025-04-14T16:33:37.000000000', { + zone: 'utc', + }) as DateTime; + + beforeAll(() => { + vi.useFakeTimers(); + vi.setSystemTime(t0.toMillis()); + }); + beforeEach(async () => { hostRules.find.mockReturnValue({ username: 'user', @@ -130,7 +144,16 @@ describe('modules/platform/gerrit/index', () => { 'test/repo', { branchName: '', label: '-2', state: 'open' }, ]); - expect(clientMock.abandonChange.mock.calls).toEqual([[1], [2]]); + expect(clientMock.abandonChange.mock.calls).toEqual([ + [ + 1, + 'This change has been abandoned as it was voted with Code-Review -2.', + ], + [ + 2, + 'This change has been abandoned as it was voted with Code-Review -2.', + ], + ]); }); }); @@ -138,23 +161,39 @@ describe('modules/platform/gerrit/index', () => { it('findPr() - no results', async () => { clientMock.findChanges.mockResolvedValueOnce([]); await expect( - gerrit.findPr({ branchName: 'branch', state: 'open' }), + gerrit.findPr({ + branchName: 'branch', + state: 'open', + targetBranch: 'master', + }), ).resolves.toBeNull(); - expect(clientMock.findChanges).toHaveBeenCalledWith( - 'test/repo', - { branchName: 'branch', state: 'open' }, - undefined, - ); + expect(clientMock.findChanges).toHaveBeenCalledWith('test/repo', { + branchName: 'branch', + state: 'open', + targetBranch: 'master', + limit: 1, + requestDetails: REQUEST_DETAILS_FOR_PRS, + }); }); - it('findPr() - return the last change from search results', async () => { - clientMock.findChanges.mockResolvedValueOnce([ - partial({ _number: 1 }), - partial({ _number: 2 }), - ]); + it('findPr() - found', async () => { + const change = partial({ + _number: 123456, + current_revision: 'some-revision', + revisions: { + 'some-revision': partial({ + commit_with_footers: 'Renovate-Branch: source', + }), + }, + }); + clientMock.findChanges.mockResolvedValueOnce([change]); await expect( - gerrit.findPr({ branchName: 'branch', state: 'open' }), - ).resolves.toHaveProperty('number', 2); + gerrit.findPr({ + branchName: 'branch', + state: 'open', + targetBranch: 'master', + }), + ).resolves.toHaveProperty('number', 123456); }); }); @@ -165,7 +204,11 @@ describe('modules/platform/gerrit/index', () => { await expect(gerrit.getPr(123456)).resolves.toEqual( mapGerritChangeToPr(change), ); - expect(clientMock.getChange).toHaveBeenCalledWith(123456); + expect(clientMock.getChange).toHaveBeenCalledWith( + 123456, + undefined, + REQUEST_DETAILS_FOR_PRS, + ); }); it('getPr() - not found', async () => { @@ -200,9 +243,7 @@ describe('modules/platform/gerrit/index', () => { current_revision: 'some-revision', revisions: { 'some-revision': partial({ - commit: { - message: 'some message', - }, + commit_with_footers: 'some message', }), }, }); @@ -238,7 +279,7 @@ describe('modules/platform/gerrit/index', () => { }); }); - describe('createPr() - error', () => { + describe('createPr()', () => { it('createPr() - no existing found => rejects', async () => { clientMock.findChanges.mockResolvedValueOnce([]); await expect( @@ -252,39 +293,42 @@ describe('modules/platform/gerrit/index', () => { `the change should be created automatically from previous push to refs/for/source`, ); }); - }); - - describe('createPr() - success', () => { - beforeAll(() => { - gerrit.writeToConfig({ labels: {} }); - }); - - const message = 'some subject\n\nsome body\n\nChange-Id: some-change-id'; - const change = partial({ - _number: 123456, - current_revision: 'some-revision', - revisions: { - 'some-revision': partial({ - commit: { - message, - }, - }), - }, - }); - - beforeEach(() => { + it('createPr() - found existing but not created in the last 5 minutes => rejects', async () => { + const change = partial({ + _number: 123456, + created: t0.minus({ minutes: 6 }).toISO().replace('T', ' '), + current_revision: 'some-revision', + revisions: { + 'some-revision': partial({ + commit_with_footers: 'Renovate-Branch: source', + }), + }, + }); clientMock.findChanges.mockResolvedValueOnce([change]); - clientMock.getChange.mockResolvedValueOnce(change); - clientMock.getMessages.mockResolvedValueOnce([ - partial({ - tag: TAG_PULL_REQUEST_BODY, - message: 'Last PR-Body', + await expect( + gerrit.createPr({ + sourceBranch: 'source', + targetBranch: 'target', + prTitle: 'title', + prBody: 'body', }), - ]); + ).rejects.toThrow(/it was not created in the last 5 minutes/); }); it('createPr() - update body', async () => { + const change = partial({ + _number: 123456, + current_revision: 'some-revision', + created: t0.minus({ seconds: 30 }).toISO().replace('T', ' '), + revisions: { + 'some-revision': partial({ + commit_with_footers: 'Renovate-Branch: source', + }), + }, + messages: [], + }); + clientMock.findChanges.mockResolvedValueOnce([change]); const pr = await gerrit.createPr({ sourceBranch: 'source', targetBranch: 'target', @@ -299,49 +343,111 @@ describe('modules/platform/gerrit/index', () => { 123456, 'body', TAG_PULL_REQUEST_BODY, + [], ); }); }); describe('getBranchPr()', () => { it('getBranchPr() - no result', async () => { - clientMock.findChanges.mockResolvedValue([]); + clientMock.findChanges.mockResolvedValueOnce([]); await expect( gerrit.getBranchPr('renovate/dependency-1.x'), ).resolves.toBeNull(); expect(clientMock.findChanges).toHaveBeenCalledWith('test/repo', { branchName: 'renovate/dependency-1.x', state: 'open', + limit: 1, + refreshCache: undefined, + requestDetails: REQUEST_DETAILS_FOR_PRS, }); }); it('getBranchPr() - found', async () => { const change = partial({ _number: 123456, + current_revision: 'some-revision', + revisions: { + 'some-revision': partial({ + commit_with_footers: 'Renovate-Branch: renovate/dependency-1.x', + }), + }, }); - clientMock.findChanges.mockResolvedValue([change]); + clientMock.findChanges.mockResolvedValueOnce([change]); await expect( - gerrit.getBranchPr('renovate/dependency-1.x'), + gerrit.getBranchPr('renovate/dependency-1.x', 'master'), + ).resolves.toHaveProperty('number', 123456); + expect(clientMock.findChanges.mock.lastCall).toEqual([ + 'test/repo', + { + state: 'open', + branchName: 'renovate/dependency-1.x', + limit: 1, + targetBranch: 'master', + requestDetails: REQUEST_DETAILS_FOR_PRS, + }, + ]); + }); + + it('getBranchPr() - found even without targetBranch', async () => { + const change = partial({ + _number: 123456, + current_revision: 'some-revision', + revisions: { + 'some-revision': partial({ + commit_with_footers: 'Renovate-Branch: renovate/dependency-1.x', + }), + }, + }); + clientMock.findChanges.mockResolvedValueOnce([change]); + await expect( + gerrit.getBranchPr('renovate/dependency-1.x', undefined), ).resolves.toHaveProperty('number', 123456); expect(clientMock.findChanges.mock.lastCall).toEqual([ 'test/repo', - { state: 'open', branchName: 'renovate/dependency-1.x' }, + { + state: 'open', + branchName: 'renovate/dependency-1.x', + limit: 1, + targetBranch: undefined, + requestDetails: REQUEST_DETAILS_FOR_PRS, + }, ]); }); }); + describe('refreshPr()', () => { + it('refreshPr()', async () => { + clientMock.getChange.mockResolvedValueOnce(partial({})); + await expect(gerrit.refreshPr(123456)).toResolve(); + expect(clientMock.getChange).toHaveBeenCalledWith( + 123456, + true, + REQUEST_DETAILS_FOR_PRS, + ); + }); + }); + describe('getPrList()', () => { it('getPrList() - empty list', async () => { - clientMock.findChanges.mockResolvedValue([]); + clientMock.findChanges.mockResolvedValueOnce([]); await expect(gerrit.getPrList()).resolves.toEqual([]); expect(clientMock.findChanges).toHaveBeenCalledWith('test/repo', { branchName: '', + requestDetails: REQUEST_DETAILS_FOR_PRS, }); }); it('getPrList() - multiple results', async () => { - const change = partial({}); - clientMock.findChanges.mockResolvedValue([change, change, change]); + const change = partial({ + current_revision: 'abc', + revisions: { + abc: partial({ + commit_with_footers: 'Renovate-Branch: renovate/dependency-1.x', + }), + }, + }); + clientMock.findChanges.mockResolvedValueOnce([change, change, change]); await expect(gerrit.getPrList()).resolves.toHaveLength(3); }); }); @@ -372,14 +478,14 @@ describe('modules/platform/gerrit/index', () => { }); describe('getBranchStatus()', () => { - it('getBranchStatus() - branchname/change not found => yellow', async () => { + it('getBranchStatus() - change not found => yellow', async () => { clientMock.findChanges.mockResolvedValueOnce([]); await expect( gerrit.getBranchStatus('renovate/dependency-1.x'), ).resolves.toBe('yellow'); }); - it('getBranchStatus() - branchname/changes found, submittable and not hasProblems => green', async () => { + it('getBranchStatus() - change found, submittable and not hasProblems => green', async () => { const change = partial({ submittable: true, }); @@ -389,41 +495,55 @@ describe('modules/platform/gerrit/index', () => { ).resolves.toBe('green'); }); - it('getBranchStatus() - branchname/changes found and hasProblems => red', async () => { - const submittableChange = partial({ + it('getBranchStatus() - change found, submittable but hasProblems => red', async () => { + const change = partial({ submittable: true, - problems: [], + problems: [{ message: 'error1' }, { message: 'error2' }], + current_revision: 'abc', + revisions: { + abc: partial({ + commit_with_footers: 'Renovate-Branch: renovate/dependency-1.x', + }), + }, }); - const changeWithProblems = { ...submittableChange }; - changeWithProblems.submittable = false; - changeWithProblems.problems = [ - { message: 'error1' }, - { message: 'error2' }, - ]; - clientMock.findChanges.mockResolvedValueOnce([ - changeWithProblems, - submittableChange, - ]); + clientMock.findChanges.mockResolvedValueOnce([change]); + await expect( + gerrit.getBranchStatus('renovate/dependency-1.x'), + ).resolves.toBe('red'); + }); + + it('getBranchStatus() - change found and hasProblems => red', async () => { + const change = partial({ + submittable: false, + problems: [{ message: 'error1' }, { message: 'error2' }], + current_revision: 'abc', + revisions: { + abc: partial({ + commit_with_footers: 'Renovate-Branch: renovate/dependency-1.x', + }), + }, + }); + clientMock.findChanges.mockResolvedValueOnce([change]); await expect( gerrit.getBranchStatus('renovate/dependency-1.x'), ).resolves.toBe('red'); }); - it('getBranchStatus() - branchname/changes found and hasBlockingLabels but no problems => red', async () => { - const submittableChange = partial({ + it('getBranchStatus() - changes found and hasBlockingLabels but no problems => red', async () => { + const change = partial({ submittable: true, problems: [], + labels: { + Verified: { blocking: true }, + }, + current_revision: 'abc', + revisions: { + abc: partial({ + commit_with_footers: 'Renovate-Branch: renovate/dependency-1.x', + }), + }, }); - const changeWithProblems = { ...submittableChange }; - changeWithProblems.submittable = false; - changeWithProblems.problems = []; - changeWithProblems.labels = { - Verified: { blocking: true }, - }; - clientMock.findChanges.mockResolvedValueOnce([ - changeWithProblems, - submittableChange, - ]); + clientMock.findChanges.mockResolvedValueOnce([change]); await expect( gerrit.getBranchStatus('renovate/dependency-1.x'), ).resolves.toBe('red'); @@ -479,6 +599,15 @@ describe('modules/platform/gerrit/index', () => { }, expectedState: 'red' as BranchStatus, }, + { + label: 'Renovate-Merge-Confidence', + labelValue: { + approved: partial({}), + rejected: partial({}), + blocking: true, + }, + expectedState: 'red' as BranchStatus, + }, ])('$ctx/$labels', async ({ label, labelValue, expectedState }) => { const change = partial({ labels: { @@ -494,7 +623,7 @@ describe('modules/platform/gerrit/index', () => { }); describe('setBranchStatus()', () => { - describe('GerritLabel is not available', () => { + describe('GerritLabel is not configured in Renovate', () => { beforeEach(() => { writeToConfig({ labels: {} }); }); @@ -520,10 +649,11 @@ describe('modules/platform/gerrit/index', () => { description: 'desc', }), ).resolves.toBeUndefined(); + expect(clientMock.setLabel).not.toHaveBeenCalled(); }); }); - describe('GerritLabel is available', () => { + describe('GerritLabel is configured in Renovate', () => { beforeEach(() => { writeToConfig({ labels: { @@ -557,7 +687,21 @@ describe('modules/platform/gerrit/index', () => { ])( '$ctx/$branchState', async ({ ctx, branchState, expectedVote, expectedLabel }) => { - const change = partial({ _number: 123456 }); + const change = partial({ + _number: 123456, + current_revision: 'abc', + revisions: { + abc: partial({ + commit_with_footers: 'Renovate-Branch: renovate/dependency-1.x', + }), + }, + labels: { + [ctx]: partial({ + approved: partial({}), + rejected: partial({}), + }), + }, + }); clientMock.findChanges.mockResolvedValueOnce([change]); await gerrit.setBranchStatus({ branchName: 'renovate/dependency-1.x', @@ -585,6 +729,28 @@ describe('modules/platform/gerrit/index', () => { ).resolves.toBeUndefined(); expect(clientMock.setLabel).not.toHaveBeenCalled(); }); + + it('does not call setLabel() if label does not exist in change', async () => { + const change = partial({ + _number: 123456, + current_revision: 'abc', + revisions: { + abc: partial({ + commit_with_footers: 'Renovate-Branch: renovate/dependency-1.x', + }), + }, + }); + clientMock.findChanges.mockResolvedValueOnce([change]); + await expect( + gerrit.setBranchStatus({ + branchName: 'branch', + context: 'renovate/merge-confidence', + state: 'red', + description: 'desc', + }), + ).resolves.toBeUndefined(); + expect(clientMock.setLabel).not.toHaveBeenCalled(); + }); }); }); @@ -673,19 +839,29 @@ describe('modules/platform/gerrit/index', () => { ); }); - it('getRawFile() - repo/branch defaults', async () => { + it('getRawFile() - branch defaults', async () => { writeToConfig({ - repository: undefined, + repository: 'repo', head: undefined, labels: {}, }); await expect(gerrit.getRawFile('renovate.json')).resolves.toBe('{}'); expect(clientMock.getFile).toHaveBeenCalledWith( - 'All-Projects', + 'repo', 'HEAD', 'renovate.json', ); }); + + it('getRawFile() - no repo', async () => { + writeToConfig({ + repository: undefined, + head: 'master', + labels: {}, + }); + await expect(gerrit.getRawFile('renovate.json')).resolves.toBe(null); + expect(clientMock.getFile).not.toHaveBeenCalled(); + }); }); describe('getJsonFile()', () => { diff --git a/lib/modules/platform/gerrit/index.ts b/lib/modules/platform/gerrit/index.ts index 66b35a9b1cc..7d141443533 100644 --- a/lib/modules/platform/gerrit/index.ts +++ b/lib/modules/platform/gerrit/index.ts @@ -1,3 +1,5 @@ +import { isTruthy } from '@sindresorhus/is'; +import { DateTime } from 'luxon'; import { logger } from '../../../logger'; import type { BranchStatus } from '../../../types'; import { parseJson } from '../../../util/common'; @@ -31,6 +33,7 @@ import { client } from './client'; import { configureScm } from './scm'; import type { GerritLabelTypeInfo, GerritProjectInfo } from './types'; import { + REQUEST_DETAILS_FOR_PRS, TAG_PULL_REQUEST_BODY, getGerritRepoUrl, mapBranchStatusToLabel, @@ -119,7 +122,13 @@ export async function initRepo({ label: '-2', }); for (const change of rejectedChanges) { - await client.abandonChange(change._number); + await client.abandonChange( + change._number, + 'This change has been abandoned as it was voted with Code-Review -2.', + ); + logger.info( + `Abandoned change ${change._number} with Code-Review -2 in repository ${repository}`, + ); } const repoConfig: RepoResult = { defaultBranch: config.head!, @@ -129,19 +138,31 @@ export async function initRepo({ return repoConfig; } -export async function findPr( - findPRConfig: FindPRConfig, - refreshCache?: boolean, -): Promise { +export async function findPr(findPRConfig: FindPRConfig): Promise { const change = ( - await client.findChanges(config.repository!, findPRConfig, refreshCache) + await client.findChanges(config.repository!, { + ...findPRConfig, + limit: 1, + requestDetails: REQUEST_DETAILS_FOR_PRS, + }) ).pop(); - return change ? mapGerritChangeToPr(change) : null; + return change + ? mapGerritChangeToPr(change, { + sourceBranch: findPRConfig.branchName, + }) + : null; } -export async function getPr(number: number): Promise { +export async function getPr( + number: number, + refreshCache?: boolean, +): Promise { try { - const change = await client.getChange(number); + const change = await client.getChange( + number, + refreshCache, + REQUEST_DETAILS_FOR_PRS, + ); return mapGerritChangeToPr(change); } catch (err) { if (err.statusCode === 404) { @@ -171,41 +192,71 @@ export async function createPr(prConfig: CreatePRConfig): Promise { prConfig.labels?.toString() ?? '' })`, ); - const pr = ( - await client.findChanges( - config.repository!, - { - branchName: prConfig.sourceBranch, - targetBranch: prConfig.targetBranch, - state: 'open', - }, - true, - ) + const change = ( + await client.findChanges(config.repository!, { + branchName: prConfig.sourceBranch, + targetBranch: prConfig.targetBranch, + state: 'open', + limit: 1, + refreshCache: true, + requestDetails: REQUEST_DETAILS_FOR_PRS, + }) ).pop(); - if (pr === undefined) { + if (change === undefined) { throw new Error( `the change should be created automatically from previous push to refs/for/${prConfig.sourceBranch}`, ); } + const created = DateTime.fromISO(change.created.replace(' ', 'T'), {}); + const fiveMinutesAgo = DateTime.utc().minus({ minutes: 5 }); + if (created < fiveMinutesAgo) { + throw new Error( + `the change should have been created automatically from previous push to refs/for/${prConfig.sourceBranch}, but it was not created in the last 5 minutes (${change.created})`, + ); + } await client.addMessageIfNotAlreadyExists( - pr._number, + change._number, prConfig.prBody, TAG_PULL_REQUEST_BODY, + change.messages, ); - return getPr(pr._number); + return mapGerritChangeToPr(change, { + sourceBranch: prConfig.sourceBranch, + prBody: prConfig.prBody, + }); } -export async function getBranchPr(branchName: string): Promise { +export async function getBranchPr( + branchName: string, + targetBranch?: string, +): Promise { const change = ( - await client.findChanges(config.repository!, { branchName, state: 'open' }) + await client.findChanges(config.repository!, { + branchName, + state: 'open', + targetBranch, + limit: 1, + requestDetails: REQUEST_DETAILS_FOR_PRS, + }) ).pop(); - return change ? mapGerritChangeToPr(change) : null; + return change + ? mapGerritChangeToPr(change, { + sourceBranch: branchName, + }) + : null; +} + +export async function refreshPr(number: number): Promise { + // refresh cache + await getPr(number, true); } -export function getPrList(): Promise { - return client - .findChanges(config.repository!, { branchName: '' }) - .then((res) => res.map((change) => mapGerritChangeToPr(change))); +export async function getPrList(): Promise { + const changes = await client.findChanges(config.repository!, { + branchName: '', + requestDetails: REQUEST_DETAILS_FOR_PRS, + }); + return changes.map((change) => mapGerritChangeToPr(change)).filter(isTruthy); } export async function mergePr(config: MergePRConfig): Promise { @@ -235,30 +286,29 @@ export async function getBranchStatus( branchName: string, ): Promise { logger.debug(`getBranchStatus(${branchName})`); - const changes = await client.findChanges( - config.repository!, - { state: 'open', branchName }, - true, - ); - if (changes.length > 0) { - const allSubmittable = - changes.filter((change) => change.submittable === true).length === - changes.length; - if (allSubmittable) { - return 'green'; - } - const hasProblems = - changes.filter((change) => change.problems.length > 0).length > 0; + const change = ( + await client.findChanges(config.repository!, { + state: 'open', + branchName, + limit: 1, + refreshCache: true, + requestDetails: ['LABELS', 'SUBMITTABLE', 'CHECK'], + }) + ).pop(); + if (change) { + const hasProblems = change.problems && change.problems.length > 0; if (hasProblems) { return 'red'; } - const hasBlockingLabels = - changes.filter((change) => - Object.values(change.labels ?? {}).some((label) => label.blocking), - ).length > 0; + const hasBlockingLabels = Object.values(change.labels ?? {}).some( + (label) => label.blocking, + ); if (hasBlockingLabels) { return 'red'; } + if (change.submittable) { + return 'green'; + } } return 'yellow'; } @@ -273,23 +323,25 @@ export async function getBranchStatusCheck( branchName: string, context: string, ): Promise { - const label = config.labels[context]; - if (label) { + const labelConfig = config.labels[context]; + if (labelConfig) { const change = ( - await client.findChanges( - config.repository!, - { branchName, state: 'open' }, - true, - ) + await client.findChanges(config.repository!, { + branchName, + state: 'open', + limit: 1, + refreshCache: true, + requestDetails: ['LABELS'], + }) ).pop(); if (change) { - const labelRes = change.labels?.[context]; - if (labelRes) { - // Check for rejected first, as a label could have both rejected and approved - if (labelRes.rejected) { + const label = change.labels![context]; + if (label) { + // Check for rejected or blocking first, as a label could have both rejected and approved + if (label.rejected || label.blocking) { return 'red'; } - if (labelRes.approved) { + if (label.approved) { return 'green'; } } @@ -310,23 +362,39 @@ export async function setBranchStatus( const labelValue = label && mapBranchStatusToLabel(branchStatusConfig.state, label); if (branchStatusConfig.context && labelValue) { - const pr = await getBranchPr(branchStatusConfig.branchName); - if (pr === null) { + const change = ( + await client.findChanges(config.repository!, { + branchName: branchStatusConfig.branchName, + state: 'open', + limit: 1, + requestDetails: ['LABELS'], + }) + ).pop(); + + const labelKey = branchStatusConfig.context; + if (!change?.labels || !Object.hasOwn(change.labels, labelKey)) { return; } - await client.setLabel(pr.number, branchStatusConfig.context, labelValue); + + await client.setLabel(change._number, labelKey, labelValue); } } -export function getRawFile( +export async function getRawFile( fileName: string, repoName?: string, branchOrTag?: string, ): Promise { - const repo = repoName ?? config.repository ?? 'All-Projects'; + const repo = repoName ?? config.repository; + if (!repo) { + logger.debug('No repo so cannot getRawFile'); + return null; + } const branch = - branchOrTag ?? (repo === config.repository ? config.head! : 'HEAD'); - return client.getFile(repo, branch, fileName); + branchOrTag ?? + (repo === config.repository ? (config.head ?? 'HEAD') : 'HEAD'); + const result = await client.getFile(repo, branch, fileName); + return result; } export async function getJsonFile( diff --git a/lib/modules/platform/gerrit/scm.spec.ts b/lib/modules/platform/gerrit/scm.spec.ts index ea15a3b4f2d..a07f4c9fe3e 100644 --- a/lib/modules/platform/gerrit/scm.spec.ts +++ b/lib/modules/platform/gerrit/scm.spec.ts @@ -24,15 +24,14 @@ describe('modules/platform/gerrit/scm', () => { await expect( gerritScm.isBranchBehindBase('myBranchName', 'baseBranch'), ).resolves.toBeTrue(); - expect(clientMock.findChanges).toHaveBeenCalledWith( - 'test/repo', - { - branchName: 'myBranchName', - state: 'open', - targetBranch: 'baseBranch', - }, - true, - ); + expect(clientMock.findChanges).toHaveBeenCalledWith('test/repo', { + branchName: 'myBranchName', + state: 'open', + targetBranch: 'baseBranch', + limit: 1, + refreshCache: true, + requestDetails: ['CURRENT_REVISION', 'CURRENT_ACTIONS'], + }); }); it('open change found for branchname, rebase action is available -> isBehind == true', async () => { @@ -76,13 +75,16 @@ describe('modules/platform/gerrit/scm', () => { it('no open change for with branchname found -> not modified', async () => { clientMock.findChanges.mockResolvedValueOnce([]); await expect( - gerritScm.isBranchModified('myBranchName'), + gerritScm.isBranchModified('myBranchName', 'master'), ).resolves.toBeFalse(); - expect(clientMock.findChanges).toHaveBeenCalledWith( - 'test/repo', - { branchName: 'myBranchName', state: 'open' }, - true, - ); + expect(clientMock.findChanges).toHaveBeenCalledWith('test/repo', { + branchName: 'myBranchName', + state: 'open', + targetBranch: 'master', + limit: 1, + refreshCache: true, + requestDetails: ['CURRENT_REVISION', 'DETAILED_ACCOUNTS'], + }); }); it('open change found for branchname, but not modified', async () => { @@ -96,7 +98,7 @@ describe('modules/platform/gerrit/scm', () => { }); clientMock.findChanges.mockResolvedValueOnce([change]); await expect( - gerritScm.isBranchModified('myBranchName'), + gerritScm.isBranchModified('myBranchName', 'master'), ).resolves.toBeFalse(); }); @@ -111,7 +113,7 @@ describe('modules/platform/gerrit/scm', () => { }); clientMock.findChanges.mockResolvedValueOnce([change]); await expect( - gerritScm.isBranchModified('myBranchName'), + gerritScm.isBranchModified('myBranchName', 'master'), ).resolves.toBeTrue(); }); }); @@ -126,6 +128,7 @@ describe('modules/platform/gerrit/scm', () => { branchName: 'myBranchName', state: 'open', targetBranch: 'target', + limit: 1, }); }); @@ -161,14 +164,12 @@ describe('modules/platform/gerrit/scm', () => { clientMock.findChanges.mockResolvedValueOnce([]); git.branchExists.mockReturnValueOnce(true); await expect(gerritScm.branchExists('myBranchName')).resolves.toBeTrue(); - expect(clientMock.findChanges).toHaveBeenCalledWith( - 'test/repo', - { - branchName: 'myBranchName', - state: 'open', - }, - true, - ); + expect(clientMock.findChanges).toHaveBeenCalledWith('test/repo', { + branchName: 'myBranchName', + state: 'open', + limit: 1, + refreshCache: true, + }); expect(git.branchExists).toHaveBeenCalledWith('myBranchName'); }); @@ -187,14 +188,13 @@ describe('modules/platform/gerrit/scm', () => { await expect(gerritScm.getBranchCommit('myBranchName')).resolves.toBe( 'shaHashValue', ); - expect(clientMock.findChanges).toHaveBeenCalledWith( - 'test/repo', - { - branchName: 'myBranchName', - state: 'open', - }, - true, - ); + expect(clientMock.findChanges).toHaveBeenCalledWith('test/repo', { + branchName: 'myBranchName', + state: 'open', + limit: 1, + refreshCache: true, + requestDetails: ['CURRENT_REVISION'], + }); }); it('open change found for branchname -> return true', async () => { @@ -217,14 +217,13 @@ describe('modules/platform/gerrit/scm', () => { await expect(gerritScm.mergeToLocal('nonExistingChange')).toResolve(); - expect(clientMock.findChanges).toHaveBeenCalledWith( - 'test/repo', - { - branchName: 'nonExistingChange', - state: 'open', - }, - true, - ); + expect(clientMock.findChanges).toHaveBeenCalledWith('test/repo', { + branchName: 'nonExistingChange', + state: 'open', + limit: 1, + refreshCache: true, + requestDetails: ['CURRENT_REVISION'], + }); expect(git.mergeToLocal).toHaveBeenCalledWith('nonExistingChange'); }); @@ -242,14 +241,13 @@ describe('modules/platform/gerrit/scm', () => { await expect(gerritScm.mergeToLocal('existingChange')).toResolve(); - expect(clientMock.findChanges).toHaveBeenCalledWith( - 'test/repo', - { - branchName: 'existingChange', - state: 'open', - }, - true, - ); + expect(clientMock.findChanges).toHaveBeenCalledWith('test/repo', { + branchName: 'existingChange', + state: 'open', + limit: 1, + refreshCache: true, + requestDetails: ['CURRENT_REVISION'], + }); expect(git.mergeToLocal).toHaveBeenCalledWith('refs/changes/34/1234/1'); }); }); @@ -268,15 +266,14 @@ describe('modules/platform/gerrit/scm', () => { prTitle: 'pr title', }), ).resolves.toBeNull(); - expect(clientMock.findChanges).toHaveBeenCalledWith( - 'test/repo', - { - branchName: 'renovate/dependency-1.x', - state: 'open', - targetBranch: 'main', - }, - true, - ); + expect(clientMock.findChanges).toHaveBeenCalledWith('test/repo', { + branchName: 'renovate/dependency-1.x', + state: 'open', + targetBranch: 'main', + limit: 1, + refreshCache: true, + requestDetails: ['CURRENT_REVISION'], + }); }); it('commitFiles() - create first Patch', async () => { diff --git a/lib/modules/platform/gerrit/scm.ts b/lib/modules/platform/gerrit/scm.ts index a6676f54e80..9a5b48551f4 100644 --- a/lib/modules/platform/gerrit/scm.ts +++ b/lib/modules/platform/gerrit/scm.ts @@ -16,10 +16,13 @@ export function configureScm(repo: string, login: string): void { export class GerritScm extends DefaultGitScm { override async branchExists(branchName: string): Promise { - const searchConfig: GerritFindPRConfig = { state: 'open', branchName }; - const change = await client - .findChanges(repository, searchConfig, true) - .then((res) => res.pop()); + const searchConfig: GerritFindPRConfig = { + state: 'open', + branchName, + limit: 1, + refreshCache: true, + }; + const change = (await client.findChanges(repository, searchConfig)).pop(); if (change) { return true; } @@ -29,10 +32,14 @@ export class GerritScm extends DefaultGitScm { override async getBranchCommit( branchName: string, ): Promise { - const searchConfig: GerritFindPRConfig = { state: 'open', branchName }; - const change = await client - .findChanges(repository, searchConfig, true) - .then((res) => res.pop()); + const searchConfig: GerritFindPRConfig = { + state: 'open', + branchName, + limit: 1, + refreshCache: true, + requestDetails: ['CURRENT_REVISION'], + }; + const change = (await client.findChanges(repository, searchConfig)).pop(); if (change) { return change.current_revision as LongCommitSha; } @@ -47,13 +54,14 @@ export class GerritScm extends DefaultGitScm { state: 'open', branchName, targetBranch: baseBranch, + limit: 1, + refreshCache: true, + requestDetails: ['CURRENT_REVISION', 'CURRENT_ACTIONS'], }; - const change = await client - .findChanges(repository, searchConfig, true) - .then((res) => res.pop()); + const change = (await client.findChanges(repository, searchConfig)).pop(); if (change) { - const currentGerritPatchset = change.revisions[change.current_revision]; - return currentGerritPatchset.actions?.rebase.enabled === true; + const currentRevision = change.revisions![change.current_revision!]; + return currentRevision.actions!.rebase.enabled === true; } return true; } @@ -66,6 +74,7 @@ export class GerritScm extends DefaultGitScm { state: 'open', branchName: branch, targetBranch: baseBranch, + limit: 1, }; const change = (await client.findChanges(repository, searchConfig)).pop(); if (change) { @@ -80,14 +89,22 @@ export class GerritScm extends DefaultGitScm { } } - override async isBranchModified(branchName: string): Promise { - const searchConfig: GerritFindPRConfig = { state: 'open', branchName }; - const change = await client - .findChanges(repository, searchConfig, true) - .then((res) => res.pop()); + override async isBranchModified( + branchName: string, + baseBranch: string, + ): Promise { + const searchConfig: GerritFindPRConfig = { + state: 'open', + branchName, + targetBranch: baseBranch, + limit: 1, + refreshCache: true, + requestDetails: ['CURRENT_REVISION', 'DETAILED_ACCOUNTS'], + }; + const change = (await client.findChanges(repository, searchConfig)).pop(); if (change) { - const currentGerritPatchset = change.revisions[change.current_revision]; - return currentGerritPatchset.uploader.username !== username; + const currentRevision = change.revisions![change.current_revision!]; + return currentRevision.uploader.username !== username; } return false; } @@ -100,10 +117,13 @@ export class GerritScm extends DefaultGitScm { state: 'open', branchName: commit.branchName, targetBranch: commit.baseBranch, + limit: 1, + refreshCache: true, + requestDetails: ['CURRENT_REVISION'], }; - const existingChange = await client - .findChanges(repository, searchConfig, true) - .then((res) => res.pop()); + const existingChange = ( + await client.findChanges(repository, searchConfig) + ).pop(); let hasChanges = true; const message = @@ -116,18 +136,20 @@ export class GerritScm extends DefaultGitScm { message[0] = firstMessageLines.join('\n'); } + const changeId = existingChange?.change_id ?? generateChangeId(); commit.message = [ ...message, - `Renovate-Branch: ${commit.branchName}\nChange-Id: ${existingChange?.change_id ?? generateChangeId()}`, + `Renovate-Branch: ${commit.branchName}\nChange-Id: ${changeId}`, ]; const commitResult = await git.prepareCommit({ ...commit, force: true }); if (commitResult) { const { commitSha } = commitResult; - if (existingChange?.revisions && existingChange.current_revision) { - const fetchRefSpec = - existingChange.revisions[existingChange.current_revision].ref; - await git.fetchRevSpec(fetchRefSpec); //fetch current ChangeSet for git diff - hasChanges = await git.hasDiff('HEAD', 'FETCH_HEAD'); //avoid empty patchsets + if (existingChange) { + const currentRevision = + existingChange.revisions![existingChange.current_revision!]; + const fetchRefSpec = currentRevision.ref; + await git.fetchRevSpec(fetchRefSpec); // fetch current ChangeSet for git diff + hasChanges = await git.hasDiff('HEAD', 'FETCH_HEAD'); // avoid pushing empty patch sets } if (hasChanges || commit.force) { const pushOptions = ['notify=NONE']; @@ -144,7 +166,7 @@ export class GerritScm extends DefaultGitScm { } } } - return null; //empty commit, no changes in this Gerrit-Change + return null; // empty commit, no changes in this Gerrit Change } override deleteBranch(branchName: string): Promise { @@ -152,12 +174,17 @@ export class GerritScm extends DefaultGitScm { } override async mergeToLocal(branchName: string): Promise { - const searchConfig: GerritFindPRConfig = { state: 'open', branchName }; - const change = await client - .findChanges(repository, searchConfig, true) - .then((res) => res.pop()); + const searchConfig: GerritFindPRConfig = { + state: 'open', + branchName, + limit: 1, + refreshCache: true, + requestDetails: ['CURRENT_REVISION'], + }; + const change = (await client.findChanges(repository, searchConfig)).pop(); if (change) { - return super.mergeToLocal(change.revisions[change.current_revision].ref); + const currentRevision = change.revisions![change.current_revision!]; + return super.mergeToLocal(currentRevision.ref); } return super.mergeToLocal(branchName); } diff --git a/lib/modules/platform/gerrit/types.ts b/lib/modules/platform/gerrit/types.ts index 4664a054185..014bf7ae57b 100644 --- a/lib/modules/platform/gerrit/types.ts +++ b/lib/modules/platform/gerrit/types.ts @@ -2,6 +2,8 @@ import type { FindPRConfig } from '../types'; export interface GerritFindPRConfig extends FindPRConfig { label?: string; + limit?: number; + requestDetails?: GerritRequestDetail[]; } /** @@ -30,7 +32,15 @@ export interface GerritBranchInfo { export type GerritChangeStatus = 'NEW' | 'MERGED' | 'ABANDONED'; -export type GerritReviewersType = 'REVIEWER' | 'CC' | 'REMOVED'; +export type GerritRequestDetail = + | 'SUBMITTABLE' + | 'CHECK' + | 'MESSAGES' + | 'DETAILED_ACCOUNTS' + | 'LABELS' + | 'CURRENT_ACTIONS' + | 'CURRENT_REVISION' + | 'COMMIT_FOOTERS'; export interface GerritChange { branch: string; @@ -38,31 +48,38 @@ export interface GerritChange { subject: string; status: GerritChangeStatus; created: string; + /** Requires o=SUBMITTABLE. */ submittable?: boolean; _number: number; + /** Requires o=LABELS. */ labels?: Record; - reviewers?: Record; + /** Requires o=LABELS. */ + reviewers?: { + REVIEWER?: GerritAccountInfo[]; + }; + /** Requires o=MESSAGES. */ messages?: GerritChangeMessageInfo[]; - current_revision: string; + /** Requires o=CURRENT_REVISION. */ + current_revision?: string; /** * All patch sets of this change as a map that maps the commit ID of the patch set to a RevisionInfo entity. + * Requires o=CURRENT_REVISION. */ - revisions: Record; - problems: unknown[]; -} - -export interface GerritCommitInfo { - message: string; + revisions?: Record; + /** + * Potential consistency issues with the change (not related to labels). + * Requires o=CHECKS. */ + problems?: unknown[]; } export interface GerritRevisionInfo { uploader: GerritAccountInfo; - /** - * The Git reference for the patch set. - */ + /** The Git reference for the patch set. */ ref: string; + /** Requires o=CURRENT_ACTIONS. */ actions?: Record; - commit: GerritCommitInfo; + /** Requires o=COMMIT_FOOTERS. */ + commit_with_footers?: string; } export interface GerritChangeMessageInfo { @@ -85,6 +102,7 @@ export interface GerritActionInfo { export interface GerritAccountInfo { _account_id: number; + /** Requires o=DETAILED_ACCOUNTS. */ username?: string; } diff --git a/lib/modules/platform/gerrit/utils.spec.ts b/lib/modules/platform/gerrit/utils.spec.ts index 9c4bb6dede7..d8a0a20572a 100644 --- a/lib/modules/platform/gerrit/utils.spec.ts +++ b/lib/modules/platform/gerrit/utils.spec.ts @@ -49,15 +49,15 @@ describe('modules/platform/gerrit/utils', () => { describe('mapPrStateToGerritFilter()', () => { it.each([ - ['closed', 'status:closed'], + ['closed', 'status:abandoned'], ['merged', 'status:merged'], ['!open', '-status:open'], ['open', 'status:open'], - ['all', '-is:wip'], - [undefined, '-is:wip'], + ['all', null], + [undefined, null], ])( 'maps pr state %p to gerrit filter %p', - (prState: any, filter: string) => { + (prState: any, filter: string | null) => { expect(utils.mapPrStateToGerritFilter(prState)).toEqual(filter); }, ); @@ -68,7 +68,7 @@ describe('modules/platform/gerrit/utils', () => { ['NEW' as GerritChangeStatus, 'open'], ['MERGED' as GerritChangeStatus, 'merged'], ['ABANDONED' as GerritChangeStatus, 'closed'], - ['unknown' as GerritChangeStatus, 'all'], + ['unknown' as GerritChangeStatus, undefined], ])( 'maps gerrit change state %p to PrState %p', (state: GerritChangeStatus, prState: any) => { @@ -87,16 +87,12 @@ describe('modules/platform/gerrit/utils', () => { created: '2025-04-14 16:33:37.000000000', reviewers: { REVIEWER: [partial({ username: 'username' })], - REMOVED: [], - CC: [], }, current_revision: 'abc', revisions: { abc: partial({ - commit: { - message: - 'Some change\n\nRenovate-Branch: renovate/dependency-1.x\nChange-Id: ...', - }, + commit_with_footers: + 'Some change\n\nRenovate-Branch: renovate/dependency-1.x\nChange-Id: ...', }), }, messages: [ @@ -128,28 +124,119 @@ describe('modules/platform/gerrit/utils', () => { bodyStruct: { hash: hashBody('Last PR-Body'), }, + sha: 'abc', }); }); - it('map a gerrit change without source branch info and reviewers to Pr', () => { + it('map a gerrit change without reviewers to Pr', () => { const change = partial({ _number: 123456, status: 'NEW', branch: 'main', subject: 'Fix for', + reviewers: {}, + current_revision: 'abc', + revisions: { + abc: partial({ + commit_with_footers: + 'Some change\n\nRenovate-Branch: renovate/dependency-1.x\nChange-Id: ...', + }), + }, }); expect(utils.mapGerritChangeToPr(change)).toEqual({ number: 123456, state: 'open', title: 'Fix for', - sourceBranch: 'main', + sourceBranch: 'renovate/dependency-1.x', + targetBranch: 'main', + reviewers: [], + sha: 'abc', + bodyStruct: { + hash: hashBody(''), + }, + }); + }); + + it('does not map a gerrit change without source branch to Pr', () => { + const change = partial({ + _number: 123456, + status: 'NEW', + branch: 'main', + subject: 'Fix for', + current_revision: 'abc', + revisions: { + abc: partial({ + commit_with_footers: + 'Some change\n\nRenovate-Broke: renovate/dependency-1.x\nChange-Id: ...', + }), + }, + }); + expect(utils.mapGerritChangeToPr(change)).toBeNull(); + }); + + it('does not reject a broken commit message if knownProperties.sourceBranch is passed', () => { + const change = partial({ + _number: 123456, + status: 'NEW', + branch: 'main', + subject: 'Fix for', + current_revision: 'abc', + revisions: { + abc: partial({ + commit_with_footers: + 'Some change\n\nRenovate-Broke: renovate/dependency-1.x\nChange-Id: ...', + }), + }, + }); + expect( + utils.mapGerritChangeToPr(change, { + sourceBranch: 'renovate/dependency-1.x', + }), + ).toEqual({ + number: 123456, + state: 'open', + title: 'Fix for', + sourceBranch: 'renovate/dependency-1.x', targetBranch: 'main', reviewers: [], + sha: 'abc', bodyStruct: { hash: hashBody(''), }, }); }); + + it('avoids iterating through change messages knownProperties.prBody is passed', () => { + const change = partial({ + _number: 123456, + status: 'NEW', + branch: 'main', + subject: 'Fix for', + current_revision: 'abc', + revisions: { + abc: partial({ + commit_with_footers: + 'Some change\n\nRenovate-Branch: renovate/dependency-1.x\nChange-Id: ...', + }), + }, + }); + expect( + utils.mapGerritChangeToPr(change, { + prBody: 'PR Body', + }), + ).toEqual({ + number: 123456, + state: 'open', + title: 'Fix for', + sourceBranch: 'renovate/dependency-1.x', + targetBranch: 'main', + reviewers: [], + sha: 'abc', + bodyStruct: { + hash: hashBody('PR Body'), + }, + }); + }); }); describe('extractSourceBranch()', () => { @@ -163,9 +250,7 @@ describe('modules/platform/gerrit/utils', () => { current_revision: 'abc', revisions: { abc: partial({ - commit: { - message: 'some message...', - }, + commit_with_footers: 'some message...', }), }, }); @@ -177,10 +262,8 @@ describe('modules/platform/gerrit/utils', () => { current_revision: 'abc', revisions: { abc: partial({ - commit: { - message: - 'Some change\n\nRenovate-Branch: renovate/dependency-1.x\nChange-Id: ...', - }, + commit_with_footers: + 'Some change\n\nRenovate-Branch: renovate/dependency-1.x\nChange-Id: ...', }), }, }); diff --git a/lib/modules/platform/gerrit/utils.ts b/lib/modules/platform/gerrit/utils.ts index 64926b0321a..cfef0cee573 100644 --- a/lib/modules/platform/gerrit/utils.ts +++ b/lib/modules/platform/gerrit/utils.ts @@ -1,6 +1,7 @@ import { CONFIG_GIT_URL_UNAVAILABLE } from '../../../constants/error-messages'; import { logger } from '../../../logger'; import type { BranchStatus, PrState } from '../../../types'; +import type { LongCommitSha } from '../../../util/git/types'; import * as hostRules from '../../../util/host-rules'; import { regEx } from '../../../util/regex'; import { joinUrlParts, parseUrl } from '../../../util/url'; @@ -10,10 +11,19 @@ import type { GerritChange, GerritChangeStatus, GerritLabelTypeInfo, + GerritRequestDetail, } from './types'; export const TAG_PULL_REQUEST_BODY = 'pull-request'; +export const REQUEST_DETAILS_FOR_PRS: GerritRequestDetail[] = [ + 'MESSAGES', // to get the pr body + 'LABELS', // to get the reviewers + 'DETAILED_ACCOUNTS', // to get the reviewers usernames + 'CURRENT_REVISION', // to get the commit message + 'COMMIT_FOOTERS', // to get the commit message +] as const; + export function getGerritRepoUrl(repository: string, endpoint: string): string { // Find options for current host and determine Git endpoint const opts = hostRules.find({ @@ -44,43 +54,53 @@ export function getGerritRepoUrl(repository: string, endpoint: string): string { return url.toString(); } -export function mapPrStateToGerritFilter(state?: PrState): string { +export function mapPrStateToGerritFilter(state?: PrState): string | null { switch (state) { - case 'closed': - return 'status:closed'; case 'merged': return 'status:merged'; - case '!open': - return '-status:open'; case 'open': return 'status:open'; + case 'closed': + return 'status:abandoned'; + case '!open': + return '-status:open'; case 'all': default: - return '-is:wip'; + return null; } } -export function mapGerritChangeToPr(change: GerritChange): Pr { +export function mapGerritChangeToPr( + change: GerritChange, + knownProperties?: { + sourceBranch?: string; + prBody?: string; + }, +): Pr | null { + const sourceBranch = + knownProperties?.sourceBranch ?? extractSourceBranch(change); + if (!sourceBranch) { + return null; + } return { number: change._number, state: mapGerritChangeStateToPrState(change.status), - sourceBranch: extractSourceBranch(change) ?? change.branch, + sourceBranch, targetBranch: change.branch, title: change.subject, createdAt: change.created?.replace(' ', 'T'), reviewers: - change.reviewers?.REVIEWER?.filter( - (reviewer) => typeof reviewer.username === 'string', - ).map((reviewer) => reviewer.username!) ?? [], + change.reviewers?.REVIEWER?.map((reviewer) => reviewer.username!) ?? [], bodyStruct: { - hash: hashBody(findPullRequestBody(change)), + hash: hashBody(knownProperties?.prBody ?? findPullRequestBody(change)), }, + sha: change.current_revision as LongCommitSha, }; } export function mapGerritChangeStateToPrState( - state: GerritChangeStatus | 'UNKNOWN', // suppress default path code removal -): PrState { + state: GerritChangeStatus, +): 'merged' | 'open' | 'closed' { switch (state) { case 'NEW': return 'open'; @@ -89,14 +109,15 @@ export function mapGerritChangeStateToPrState( case 'ABANDONED': return 'closed'; } - return 'all'; } + export function extractSourceBranch(change: GerritChange): string | undefined { let sourceBranch: string | undefined = undefined; if (change.current_revision) { const re = regEx(/^Renovate-Branch: (.+)$/m); - const message = change.revisions[change.current_revision]?.commit?.message; + const currentRevision = change.revisions![change.current_revision]; + const message = currentRevision.commit_with_footers; if (message) { sourceBranch = re.exec(message)?.[1]; } diff --git a/lib/modules/platform/gitea/gitea-helper.spec.ts b/lib/modules/platform/gitea/gitea-helper.spec.ts index f81a51ea22a..832f5f01a09 100644 --- a/lib/modules/platform/gitea/gitea-helper.spec.ts +++ b/lib/modules/platform/gitea/gitea-helper.spec.ts @@ -71,6 +71,7 @@ describe('modules/platform/gitea/gitea-helper', () => { const mockRepo: Repo = partial({ id: 123, + allow_fast_forward_only_merge: true, allow_rebase: true, allow_rebase_explicit: true, allow_merge_commits: true, diff --git a/lib/modules/platform/gitea/index.spec.ts b/lib/modules/platform/gitea/index.spec.ts index 0d3a84949b7..08990d9fd6c 100644 --- a/lib/modules/platform/gitea/index.spec.ts +++ b/lib/modules/platform/gitea/index.spec.ts @@ -555,6 +555,26 @@ describe('modules/platform/gitea/index', () => { ); }); + it('should fall back to merge method "fast-forward"', async () => { + const scope = httpMock + .scope('https://gitea.com/api/v1') + .get(`/repos/${initRepoCfg.repository}`) + .reply(200, { + ...mockRepo, + allow_rebase: false, + allow_fast_forward_only_merge: true, + }); + await initFakePlatform(scope); + + await gitea.initRepo(initRepoCfg); + + expect(git.initRepo).toHaveBeenCalledExactlyOnceWith( + expect.objectContaining({ + mergeMethod: 'fast-forward', + }), + ); + }); + it('should fall back to merge method "rebase-merge"', async () => { const scope = httpMock .scope('https://gitea.com/api/v1') diff --git a/lib/modules/platform/gitea/index.ts b/lib/modules/platform/gitea/index.ts index 3965ee7334d..7a3e05694f2 100644 --- a/lib/modules/platform/gitea/index.ts +++ b/lib/modules/platform/gitea/index.ts @@ -328,6 +328,8 @@ const platform: Platform = { config.mergeMethod = 'squash'; } else if (repo.allow_merge_commits) { config.mergeMethod = 'merge'; + } else if (repo.allow_fast_forward_only_merge) { + config.mergeMethod = 'fast-forward'; } else { logger.debug( 'Repository has no allowed merge methods - aborting renovation', diff --git a/lib/modules/platform/gitea/types.ts b/lib/modules/platform/gitea/types.ts index efa2682f95d..a8793c6d35c 100644 --- a/lib/modules/platform/gitea/types.ts +++ b/lib/modules/platform/gitea/types.ts @@ -15,7 +15,12 @@ export type CommitStatusType = | 'failure' | 'warning' | 'unknown'; -export type PRMergeMethod = 'merge' | 'rebase' | 'rebase-merge' | 'squash'; +export type PRMergeMethod = + | 'fast-forward' + | 'merge' + | 'rebase' + | 'rebase-merge' + | 'squash'; export interface GiteaLabel { id: number; @@ -69,6 +74,7 @@ export interface User { export interface Repo { id: number; + allow_fast_forward_only_merge: boolean; allow_merge_commits: boolean; allow_rebase: boolean; allow_rebase_explicit: boolean; diff --git a/lib/modules/platform/github/index.spec.ts b/lib/modules/platform/github/index.spec.ts index 1c0c9f42719..c069e4c32db 100644 --- a/lib/modules/platform/github/index.spec.ts +++ b/lib/modules/platform/github/index.spec.ts @@ -648,7 +648,6 @@ describe('modules/platform/github/index', () => { it('should update fork when using forkToken and forkOrg', async () => { const scope = httpMock.scope(githubApiHost); forkInitRepoMock(scope, 'some/repo', true); - scope.patch('/repos/forked/repo/git/refs/heads/master').reply(200); const config = await github.initRepo({ repository: 'some/repo', forkToken: 'true', @@ -666,7 +665,6 @@ describe('modules/platform/github/index', () => { }); scope.post('/repos/forked/repo/git/refs').reply(200); scope.patch('/repos/forked/repo').reply(200); - scope.patch('/repos/forked/repo/git/refs/heads/master').reply(200); const config = await github.initRepo({ repository: 'some/repo', forkToken: 'true', @@ -3562,7 +3560,9 @@ describe('modules/platform/github/index', () => { await expect(github.reattemptPlatformAutomerge(pr)).toResolve(); expect(logger.logger.warn).toHaveBeenCalledWith( - { err: new ExternalHostError(expect.any(RequestError), 'github') }, + { + err: new ExternalHostError(expect.any(RequestError) as any, 'github'), + }, 'Error re-attempting PR platform automerge', ); }); diff --git a/lib/modules/platform/github/index.ts b/lib/modules/platform/github/index.ts index 94832a555c5..b2b20530e65 100644 --- a/lib/modules/platform/github/index.ts +++ b/lib/modules/platform/github/index.ts @@ -42,7 +42,7 @@ import type { HttpResponse } from '../../../util/http/types'; import { coerceObject } from '../../../util/object'; import { regEx } from '../../../util/regex'; import { sanitize } from '../../../util/sanitize'; -import { coerceString, fromBase64, looseEquals } from '../../../util/string'; +import { fromBase64, looseEquals } from '../../../util/string'; import { ensureTrailingSlash } from '../../../util/url'; import { incLimitedValue } from '../../../workers/global/limits'; import type { @@ -680,31 +680,6 @@ export async function initRepo({ logger.warn({ err }, 'Could not set default branch'); } /* v8 ignore stop */ } - // This is a lovely "hack" by GitHub that lets us force update our fork's default branch - // with the base commit from the parent repository - const url = `repos/${config.repository}/git/refs/heads/${config.defaultBranch}`; - const sha = repo.defaultBranchRef.target.oid; - try { - logger.debug( - `Updating forked repository default sha ${sha} to match upstream`, - ); - await githubApi.patchJson(url, { - body: { - sha, - force: true, - }, - token: coerceString(forkToken, opts.token), - }); - } catch (err) /* v8 ignore start */ { - logger.warn( - { url, sha, err: err.err ?? err }, - 'Error updating fork from upstream - cannot continue', - ); - if (err instanceof ExternalHostError) { - throw err; - } - throw new ExternalHostError(err); - } /* v8 ignore stop */ } else if (forkCreation) { logger.debug('Forked repo is not found - attempting to create it'); forkedRepo = await createFork(forkToken, repository, forkOrg); @@ -733,9 +708,15 @@ export async function initRepo({ ); parsedEndpoint.pathname = `${config.repository}.git`; const url = URL.format(parsedEndpoint); + let upstreamUrl = undefined; + if (forkCreation && config.parentRepo) { + parsedEndpoint.pathname = config.parentRepo + '.git'; + upstreamUrl = URL.format(parsedEndpoint); + } await git.initRepo({ ...config, url, + upstreamUrl, }); const repoConfig: RepoResult = { defaultBranch: config.defaultBranch, @@ -1966,10 +1947,10 @@ export function massageMarkdown(input: string): string { regEx(/]: https:\/\/github\.com\//g), ']: https://redirect.github.com/', ) - .replace('> ℹ **Note**\n> \n', '> [!NOTE]\n') - .replace('> ⚠ **Warning**\n> \n', '> [!WARNING]\n') - .replace('> âš ī¸ **Warning**\n> \n', '> [!WARNING]\n') - .replace('> ❗ **Important**\n> \n', '> [!IMPORTANT]\n'); + .replaceAll('> ℹ **Note**\n> \n', '> [!NOTE]\n') + .replaceAll('> ⚠ **Warning**\n> \n', '> [!WARNING]\n') + .replaceAll('> âš ī¸ **Warning**\n> \n', '> [!WARNING]\n') + .replaceAll('> ❗ **Important**\n> \n', '> [!IMPORTANT]\n'); return smartTruncate(massagedInput, maxBodyLength()); } diff --git a/lib/modules/platform/gitlab/code-owners.spec.ts b/lib/modules/platform/gitlab/code-owners.spec.ts new file mode 100644 index 00000000000..06c3df0ca9d --- /dev/null +++ b/lib/modules/platform/gitlab/code-owners.spec.ts @@ -0,0 +1,61 @@ +import { extractRulesFromCodeOwnersLines } from './code-owners'; + +describe('modules/platform/gitlab/code-owners', () => { + describe('CodeOwnersParser', () => { + it('should extract an owner rule from a line', () => { + const rules = extractRulesFromCodeOwnersLines([ + 'pattern username1 username2', + ]); + + expect(rules).toEqual([ + { + pattern: 'pattern', + usernames: ['username1', 'username2'], + score: 7, + match: expect.any(Function), + }, + ]); + }); + + it('should extract an owner rule from a line with no usernames', () => { + const rules = extractRulesFromCodeOwnersLines(['pattern']); + + expect(rules).toEqual([ + { + pattern: 'pattern', + usernames: [], + score: 7, + match: expect.any(Function), + }, + ]); + }); + + it('should extract an owner rule from a line after a section header', () => { + const lines = ['[team] username1 username2', 'filename']; + const rules = extractRulesFromCodeOwnersLines(lines); + + expect(rules).toEqual([ + { + pattern: 'filename', + usernames: ['username1', 'username2'], + score: 8, + match: expect.any(Function), + }, + ]); + }); + + it('should extract an owner rule from a line after a section header with no usernames', () => { + const lines = ['[team]', 'filename']; + const rules = extractRulesFromCodeOwnersLines(lines); + + expect(rules).toEqual([ + { + pattern: 'filename', + usernames: [], + score: 8, + match: expect.any(Function), + }, + ]); + }); + }); +}); diff --git a/lib/modules/platform/gitlab/code-owners.ts b/lib/modules/platform/gitlab/code-owners.ts new file mode 100644 index 00000000000..c98afc45eb7 --- /dev/null +++ b/lib/modules/platform/gitlab/code-owners.ts @@ -0,0 +1,49 @@ +import ignore from 'ignore'; +import { regEx } from '../../../util/regex'; +import type { FileOwnerRule } from '../types'; + +interface CodeOwnersSection { + name: string; + defaultUsers: string[]; +} + +export function extractRulesFromCodeOwnersLines( + cleanedLines: string[], +): FileOwnerRule[] { + let currentSection: CodeOwnersSection = { name: '', defaultUsers: [] }; + const internalRules = []; + + for (const line of cleanedLines) { + if (isSectionHeader(line)) { + currentSection = changeCurrentSection(line); + } else { + const rule = extractOwnersFromLine(line, currentSection.defaultUsers); + internalRules.push(rule); + } + } + + return internalRules; +} + +function changeCurrentSection(line: string): CodeOwnersSection { + const [name, ...usernames] = line.split(regEx(/\s+/)); + return { name, defaultUsers: usernames }; +} + +function extractOwnersFromLine( + line: string, + defaultUsernames: string[], +): FileOwnerRule { + const [pattern, ...usernames] = line.split(regEx(/\s+/)); + const matchPattern = ignore().add(pattern); + return { + usernames: usernames.length > 0 ? usernames : defaultUsernames, + pattern, + score: pattern.length, + match: (path: string) => matchPattern.ignores(path), + }; +} + +function isSectionHeader(line: string): boolean { + return line.startsWith('[') || line.startsWith('^['); +} diff --git a/lib/modules/platform/gitlab/index.spec.ts b/lib/modules/platform/gitlab/index.spec.ts index d353b407bdc..f2198f4eb28 100644 --- a/lib/modules/platform/gitlab/index.spec.ts +++ b/lib/modules/platform/gitlab/index.spec.ts @@ -11,9 +11,10 @@ import { REPOSITORY_MIRRORED, } from '../../../constants/error-messages'; import type { BranchStatus } from '../../../types'; +import * as memCache from '../../../util/cache/memory'; +import * as repoCache from '../../../util/cache/repository'; import type { LongCommitSha } from '../../../util/git/types'; import { toBase64 } from '../../../util/string'; -import { getPrBodyStruct } from '../pr-body'; import * as prBodyModule from '../utils/pr-body'; import * as gitlab from '.'; import * as httpMock from '~test/http-mock'; @@ -46,6 +47,8 @@ describe('modules/platform/gitlab/index', () => { delete process.env.RENOVATE_X_PLATFORM_VERSION; gitlab.resetPlatform(); + memCache.init(); + repoCache.resetCache(); }); async function initFakePlatform(version: string) { @@ -519,6 +522,7 @@ describe('modules/platform/gitlab/index', () => { '/api/v4/projects/some%2Frepo/merge_requests?per_page=100&scope=created_by_me', ) .reply(200, []); + const pr = await gitlab.getBranchPr('some-branch'); expect(pr).toBeNull(); }); @@ -2012,6 +2016,10 @@ describe('modules/platform/gitlab/index', () => { await initPlatform('13.3.6-ee'); httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .post('/api/v4/projects/undefined/merge_requests') .reply(200, { id: 1, @@ -2040,6 +2048,10 @@ describe('modules/platform/gitlab/index', () => { await initPlatform('13.3.6-ee'); httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .post('/api/v4/projects/undefined/merge_requests') .reply(200, { id: 1, @@ -2068,6 +2080,10 @@ describe('modules/platform/gitlab/index', () => { await initPlatform('13.1.0-ee'); httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .post('/api/v4/projects/undefined/merge_requests') .reply(200, { id: 1, @@ -2096,6 +2112,10 @@ describe('modules/platform/gitlab/index', () => { await initPlatform('13.2.0-ee'); httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .post('/api/v4/projects/undefined/merge_requests') .reply(200, { id: 1, @@ -2124,6 +2144,10 @@ describe('modules/platform/gitlab/index', () => { await initPlatform('13.3.6-ee'); httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .post('/api/v4/projects/undefined/merge_requests') .reply(200, { id: 1, @@ -2166,6 +2190,10 @@ describe('modules/platform/gitlab/index', () => { }; httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .post('/api/v4/projects/undefined/merge_requests') .reply(200, { id: 1, @@ -2224,6 +2252,10 @@ describe('modules/platform/gitlab/index', () => { }; httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .post('/api/v4/projects/undefined/merge_requests') .reply(200, { id: 1, @@ -2275,6 +2307,10 @@ describe('modules/platform/gitlab/index', () => { }; httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .post('/api/v4/projects/undefined/merge_requests') .reply(200, { id: 1, @@ -2347,6 +2383,10 @@ describe('modules/platform/gitlab/index', () => { }; httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .post('/api/v4/projects/undefined/merge_requests') .reply(200, { id: 1, @@ -2382,6 +2422,10 @@ describe('modules/platform/gitlab/index', () => { httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/some%2Frepo/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .get('/api/v4/projects/some%2Frepo') .reply(200, { squash_option: 'default_on', @@ -2421,6 +2465,10 @@ describe('modules/platform/gitlab/index', () => { httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/some%2Frepo/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .get('/api/v4/projects/some%2Frepo') .reply(200, { squash_option: 'always', @@ -2459,6 +2507,10 @@ describe('modules/platform/gitlab/index', () => { await initPlatform('13.3.6-ee'); httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .post('/api/v4/projects/undefined/merge_requests') .reply(200, { id: 1, @@ -2509,6 +2561,10 @@ describe('modules/platform/gitlab/index', () => { await initPlatform('13.3.6-ee'); httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .post('/api/v4/projects/undefined/merge_requests') .reply(200, { id: 1, @@ -2553,6 +2609,10 @@ describe('modules/platform/gitlab/index', () => { await initPlatform('13.3.6-ee'); httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .post('/api/v4/projects/undefined/merge_requests') .reply(200, { id: 1, @@ -2611,6 +2671,10 @@ describe('modules/platform/gitlab/index', () => { await initPlatform('13.3.6-ee'); httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .post('/api/v4/projects/undefined/merge_requests') .reply(200, { id: 1, @@ -2680,6 +2744,10 @@ describe('modules/platform/gitlab/index', () => { await initPlatform('13.3.6-ee'); httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .post('/api/v4/projects/undefined/merge_requests') .reply(200, { id: 1, @@ -2759,6 +2827,10 @@ describe('modules/platform/gitlab/index', () => { await initPlatform('13.3.6-ee'); httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .post('/api/v4/projects/undefined/merge_requests') .reply(200, { id: 1, @@ -2809,6 +2881,10 @@ describe('modules/platform/gitlab/index', () => { await initPlatform('13.3.6-ee'); httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .post('/api/v4/projects/undefined/merge_requests') .reply(200, { id: 1, @@ -2859,6 +2935,10 @@ describe('modules/platform/gitlab/index', () => { await initPlatform('13.3.6-ee'); httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .post('/api/v4/projects/undefined/merge_requests') .reply(200, { id: 1, @@ -2892,6 +2972,10 @@ describe('modules/platform/gitlab/index', () => { await initPlatform('13.3.6-ee'); httpMock .scope(gitlabApiHost) + .get( + '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', + ) + .reply(200, []) .post('/api/v4/projects/undefined/merge_requests') .reply(200, { id: 1, @@ -3317,41 +3401,6 @@ describe('modules/platform/gitlab/index', () => { }), ).toResolve(); }); - - it('updates runtime pr list when pr is updated', async () => { - await initPlatform('13.3.6-ee'); - httpMock - .scope(gitlabApiHost) - .get( - '/api/v4/projects/undefined/merge_requests?per_page=100&scope=created_by_me', - ) - .reply(200, [ - { - iid: 1, - source_branch: 'branch-a', - title: 'branch a pr', - description: 'a merge request', - state: 'opened', - }, - ]) - .put('/api/v4/projects/undefined/merge_requests/1') - .reply(200, { - iid: 1, - source_branch: 'branch-a', - title: 'new_title', - description: 'body', - state: 'opened', - }); - await gitlab.updatePr({ - number: 1, - prTitle: 'new_title', - prBody: 'body', - }); - const prList = await gitlab.getPrList(); - const updatedPr = prList.find((pr) => pr.number === 1); - expect(updatedPr?.title).toBe('new_title'); - expect(updatedPr?.bodyStruct).toMatchObject(getPrBodyStruct('body')); - }); }); describe('reattemptPlatformAutomerge(number, platformPrOptions)', () => { diff --git a/lib/modules/platform/gitlab/index.ts b/lib/modules/platform/gitlab/index.ts index 02cc8b9bdec..dc1aac1be89 100644 --- a/lib/modules/platform/gitlab/index.ts +++ b/lib/modules/platform/gitlab/index.ts @@ -5,7 +5,6 @@ import pMap from 'p-map'; import semver from 'semver'; import { CONFIG_GIT_URL_UNAVAILABLE, - PLATFORM_AUTHENTICATION_ERROR, REPOSITORY_ACCESS_FORBIDDEN, REPOSITORY_ARCHIVED, REPOSITORY_CHANGED, @@ -65,6 +64,7 @@ import { isUserBusy, } from './http'; import { getMR, updateMR } from './merge-request'; +import { GitlabPrCache } from './pr-cache'; import { LastPipelineId } from './schema'; import type { GitLabMergeRequest, @@ -75,11 +75,11 @@ import type { RepoResponse, } from './types'; import { DRAFT_PREFIX, DRAFT_PREFIX_DEPRECATED, prInfo } from './utils'; +export { extractRulesFromCodeOwnersLines } from './code-owners'; let config: { repository: string; email: string; - prList: GitlabPr[] | undefined; issueList: GitlabIssue[] | undefined; mergeMethod: MergeMethod; defaultBranch: string; @@ -107,9 +107,11 @@ const defaults = { export const id = 'gitlab'; let draftPrefix = DRAFT_PREFIX; +let botUserName: string; export async function initPlatform({ endpoint, + username, token, gitAuthor, }: PlatformParams): Promise { @@ -139,6 +141,7 @@ export async function initPlatform({ platformConfig.gitAuthor = `${user.name} <${ user.commit_email ?? user.email }>`; + botUserName = user.name; } const env = getEnv(); /* v8 ignore start: experimental feature */ @@ -167,6 +170,8 @@ export async function initPlatform({ ? DRAFT_PREFIX_DEPRECATED : DRAFT_PREFIX; + botUserName ??= username!; + return platformConfig; } @@ -376,7 +381,6 @@ export async function initRepo({ res.body.squash_option === 'default_on'; } logger.debug(`${repository} default branch = ${config.defaultBranch}`); - delete config.prList; logger.debug('Enabling Git FS'); const url = getRepoUrl(repository, gitUrl, res); await git.initRepo({ @@ -557,37 +561,13 @@ export async function getBranchStatus( } // Pull Request - -async function fetchPrList(): Promise { - const searchParams = { - per_page: '100', - } as any; - /* v8 ignore start */ - if (!config.ignorePrAuthor) { - searchParams.scope = 'created_by_me'; - } /* v8 ignore stop */ - const query = getQueryString(searchParams); - const urlString = `projects/${config.repository}/merge_requests?${query}`; - try { - const res = await gitlabApi.getJsonUnchecked( - urlString, - { - paginate: true, - }, - ); - return res.body.map((pr) => prInfo(pr)); - } catch (err) /* v8 ignore start */ { - logger.debug({ err }, 'Error fetching PR list'); - if (err.statusCode === 403) { - throw new Error(PLATFORM_AUTHENTICATION_ERROR); - } - throw err; - } /* v8 ignore stop */ -} - export async function getPrList(): Promise { - config.prList ??= await fetchPrList(); - return config.prList; + return await GitlabPrCache.getPrs( + gitlabApi, + config.repository, + botUserName, + !!config.ignorePrAuthor, + ); } async function ignoreApprovals(pr: number): Promise { @@ -736,10 +716,11 @@ async function tryPrAutomerge( } /* v8 ignore stop */ } -async function approvePr(pr: number): Promise { +async function approveMr(mrNumber: number): Promise { + logger.debug(`approveMr(${mrNumber})`); try { await gitlabApi.postJson( - `projects/${config.repository}/merge_requests/${pr}/approve`, + `projects/${config.repository}/merge_requests/${mrNumber}/approve`, ); } catch (err) { logger.warn({ err }, 'GitLab: Error approving merge request'); @@ -777,14 +758,16 @@ export async function createPr({ ); const pr = prInfo(res.body); - - /* v8 ignore start */ - if (config.prList) { - config.prList.push(pr); - } /* v8 ignore stop */ + await GitlabPrCache.setPr( + gitlabApi, + config.repository, + botUserName, + pr, + !!config.ignorePrAuthor, + ); if (platformPrOptions?.autoApprove) { - await approvePr(pr.number); + await approveMr(pr.number); } await tryPrAutomerge(pr.number, platformPrOptions); @@ -845,25 +828,16 @@ export async function updatePr({ ).body; const updatedPr = prInfo(updatedPrInfo); - - if (config.prList) { - const existingIndex = config.prList.findIndex( - (pr) => pr.number === updatedPr.number, - ); - /* v8 ignore start: should not happen */ - if (existingIndex === -1) { - logger.warn( - { pr: updatedPr }, - 'Possible error: Updated PR was not found in the PRs that were returned from getPrList().', - ); - config.prList.push(updatedPr); - } /* v8 ignore stop */ else { - config.prList[existingIndex] = updatedPr; - } - } + await GitlabPrCache.setPr( + gitlabApi, + config.repository, + botUserName, + updatedPr, + !!config.ignorePrAuthor, + ); if (platformPrOptions?.autoApprove) { - await approvePr(iid); + await approveMr(iid); } } diff --git a/lib/modules/platform/gitlab/pr-cache.spec.ts b/lib/modules/platform/gitlab/pr-cache.spec.ts new file mode 100644 index 00000000000..005e9c9f719 --- /dev/null +++ b/lib/modules/platform/gitlab/pr-cache.spec.ts @@ -0,0 +1,228 @@ +import * as httpMock from '../../../../test/http-mock'; +import { reset as memCacheReset } from '../../../util/cache/memory'; +import { + getCache, + resetCache as repoCacheReset, +} from '../../../util/cache/repository'; +import type { LongCommitSha } from '../../../util/git/types'; +import { GitlabHttp, setBaseUrl } from '../../../util/http/gitlab'; +import { GitlabPrCache } from './pr-cache'; +import type { GitLabMergeRequest } from './types'; +import { prInfo } from './utils'; + +const http = new GitlabHttp(); + +const pr1: GitLabMergeRequest = { + iid: 1, + title: 'title', + state: 'opened', + source_branch: 'branch', + target_branch: 'master', + reviewers: [], + updated_at: '2020-01-01T00:00:00.000Z', + created_at: '2020-01-01T00:00:00.000Z', + diverged_commits_count: 5, + labels: [], + merge_status: 'cannot_be_merged', + description: 'a merge request', + sha: 'defg' as LongCommitSha, +}; + +const pr2: GitLabMergeRequest = { + iid: 2, + title: 'title', + state: 'opened', + source_branch: 'branch', + target_branch: 'master', + updated_at: '2023-01-01T00:00:00.000Z', + created_at: '2023-01-01T00:00:00.000Z', + diverged_commits_count: 5, + labels: [], + merge_status: 'cannot_be_merged', + description: 'a merge request', + sha: 'defg' as LongCommitSha, +}; + +const pr3: GitLabMergeRequest = { + iid: 3, + title: 'title', + state: 'opened', + source_branch: 'branch', + target_branch: 'master', + updated_at: '2023-01-01T00:00:00.000Z', + created_at: '2023-01-01T00:00:00.000Z', + diverged_commits_count: 5, + labels: [], + merge_status: 'cannot_be_merged', + description: 'a merge request', + sha: 'defg' as LongCommitSha, +}; + +describe('modules/platform/gitlab/pr-cache', () => { + let cache = getCache(); + + beforeEach(() => { + memCacheReset(); + repoCacheReset(); + cache = getCache(); + }); + + it('fetches cache', async () => { + httpMock + .scope('https://gitlab.com/api/v4/') + .get('/projects/repo/merge_requests?per_page=100&scope=created_by_me') + .reply(200, [pr1]); + + const res = await GitlabPrCache.getPrs(http, 'repo', 'some-author', false); + + expect(res).toMatchObject([ + { + number: 1, + title: 'title', + }, + ]); + expect(cache).toEqual({ + platform: { + gitlab: { + pullRequestsCache: { + author: 'some-author', + items: { + '1': prInfo(pr1), + }, + updated_at: '2020-01-01T00:00:00.000Z', + }, + }, + }, + }); + }); + + it('resets cache for not matching authors', async () => { + cache.platform = { + gitlab: { + pullRequestsCache: { + items: { + '1': prInfo(pr1), + }, + author: 'some-other-author', + updated_at: '2020-01-01T00:00:00.000Z', + }, + }, + }; + + httpMock + .scope('https://gitlab.com/api/v4/') + .get(`/projects/repo/merge_requests?per_page=100&scope=created_by_me`) + .reply(200, [pr1]); + + const res = await GitlabPrCache.getPrs(http, 'repo', 'some-author', false); + + expect(res).toMatchObject([ + { + number: 1, + title: 'title', + }, + ]); + expect(cache).toEqual({ + platform: { + gitlab: { + pullRequestsCache: { + author: 'some-author', + items: { + '1': prInfo(pr1), + }, + updated_at: '2020-01-01T00:00:00.000Z', + }, + }, + }, + }); + }); + + it('syncs cache', async () => { + cache.platform = { + gitlab: { + pullRequestsCache: { + items: { + '1': prInfo(pr1), + }, + author: 'some-author', + updated_at: '2023-01-01T00:00:00.000Z', + }, + }, + }; + + httpMock + .scope('https://gitlab.com/api/v4') + .get(`/projects/repo/merge_requests?per_page=20&scope=created_by_me`) + .reply(200, [pr2, pr1]); + + const res = await GitlabPrCache.getPrs(http, 'repo', 'some-author', false); + + expect(res).toMatchObject([ + { number: 2, title: 'title' }, + { number: 1, title: 'title' }, + ]); + expect(cache).toEqual({ + platform: { + gitlab: { + pullRequestsCache: { + items: { + '1': prInfo(pr1), + '2': prInfo(pr2), + }, + author: 'some-author', + updated_at: '2023-01-01T00:00:00.000Z', + }, + }, + }, + }); + }); + + it('syncs cache - GITLAB_IGNORE_REPO_URL:true', async () => { + process.env.GITLAB_IGNORE_REPO_URL = 'true'; + const selfHostedUrl = 'http://mycompany.com/gitlab'; + setBaseUrl(selfHostedUrl); + httpMock + .scope(selfHostedUrl) + .get(`/projects/repo/merge_requests?per_page=20&scope=created_by_me`) + .reply(200, [pr2, { ...pr1, title: 'new title' }], { + link: '; rel="next",', + }) + .get(`/projects/repo/merge_requests?page=2&per_page=20`) + .reply(200, [pr3]); + + cache.platform = { + gitlab: { + pullRequestsCache: { + items: { + '1': prInfo(pr1), + }, + author: 'some-author', + updated_at: '2023-01-01T00:00:00.000Z', + }, + }, + }; + + const res = await GitlabPrCache.getPrs(http, 'repo', 'some-author', false); + + expect(res).toMatchObject([ + { number: 3, title: 'title' }, + { number: 2, title: 'title' }, + { number: 1, title: 'new title' }, + ]); + expect(cache).toEqual({ + platform: { + gitlab: { + pullRequestsCache: { + items: { + '1': prInfo({ ...pr1, title: 'new title' }), + '2': prInfo(pr2), + '3': prInfo(pr3), + }, + author: 'some-author', + updated_at: '2023-01-01T00:00:00.000Z', + }, + }, + }, + }); + }); +}); diff --git a/lib/modules/platform/gitlab/pr-cache.ts b/lib/modules/platform/gitlab/pr-cache.ts new file mode 100644 index 00000000000..c9a5429a31b --- /dev/null +++ b/lib/modules/platform/gitlab/pr-cache.ts @@ -0,0 +1,174 @@ +import { dequal } from 'dequal'; +import { DateTime } from 'luxon'; +import { logger } from '../../../logger'; +import * as memCache from '../../../util/cache/memory'; +import { getCache } from '../../../util/cache/repository'; +import type { GitlabHttp } from '../../../util/http/gitlab'; +import { getQueryString, parseLinkHeader, parseUrl } from '../../../util/url'; +import type { GitLabMergeRequest, GitlabPr, GitlabPrCacheData } from './types'; +import { prInfo } from './utils'; + +export class GitlabPrCache { + private items: GitlabPr[] = []; + private cache: GitlabPrCacheData; + + private constructor( + private repo: string, + author: string | null, + private ignorePrAuthor: boolean, + ) { + const repoCache = getCache(); + repoCache.platform ??= {}; + repoCache.platform.gitlab ??= {}; + + let pullRequestCache = repoCache.platform.gitlab + .pullRequestsCache as GitlabPrCacheData; + if (!pullRequestCache) { + logger.debug('Initializing new PR cache at repository cache'); + pullRequestCache = { + items: {}, + updated_at: null, + author, + }; + } else if (pullRequestCache.author !== author) { + logger.debug('Resetting PR cache because authors do not match'); + pullRequestCache = { + items: {}, + updated_at: null, + author, + }; + } + repoCache.platform.gitlab.pullRequestsCache = pullRequestCache; + this.cache = pullRequestCache; + this.updateItems(); + } + + private static async init( + http: GitlabHttp, + repo: string, + author: string | null, + ignorePrAuthor: boolean, + ): Promise { + const res = new GitlabPrCache(repo, author, ignorePrAuthor); + const isSynced = memCache.get('gitlab-pr-cache-synced'); + + if (!isSynced) { + await res.sync(http); + memCache.set('gitlab-pr-cache-synced', true); + } + + return res; + } + + private getPrs(): GitlabPr[] { + return this.items; + } + + static async getPrs( + http: GitlabHttp, + repo: string, + author: string | null, + ignorePrAuthor: boolean, + ): Promise { + const prCache = await GitlabPrCache.init( + http, + repo, + author, + ignorePrAuthor, + ); + return prCache.getPrs(); + } + + private setPr(pr: GitlabPr): void { + logger.debug(`Adding PR #${pr.number} to the PR cache`); + this.cache.items[pr.number] = pr; + this.updateItems(); + } + + static async setPr( + http: GitlabHttp, + repo: string, + author: string | null, + item: GitlabPr, + ignorePrAuthor: boolean, + ): Promise { + const prCache = await GitlabPrCache.init( + http, + repo, + author, + ignorePrAuthor, + ); + prCache.setPr(item); + } + + private reconcile(rawItems: GitLabMergeRequest[]): boolean { + const { items: oldItems } = this.cache; + let { updated_at } = this.cache; + + let needNextPage = true; + + for (const rawItem of rawItems) { + const id = rawItem.iid; + + const oldItem = oldItems[id]; + const newItem = prInfo(rawItem); + + const itemNewTime = DateTime.fromISO(rawItem.updated_at); + + if (dequal(oldItem, newItem)) { + needNextPage = false; + continue; + } + + oldItems[id] = newItem; + + const cacheOldTime = updated_at ? DateTime.fromISO(updated_at) : null; + if (!cacheOldTime || itemNewTime > cacheOldTime) { + updated_at = rawItem.updated_at; + } + } + + this.cache.updated_at = updated_at; + return needNextPage; + } + + private async sync(http: GitlabHttp): Promise { + logger.debug('Syncing PR list'); + const searchParams = { + per_page: this.items.length ? '20' : '100', + } as Record; + if (!this.ignorePrAuthor) { + searchParams.scope = 'created_by_me'; + } + let query: string | null = getQueryString(searchParams); + + while (query) { + const res = await http.getJsonUnchecked( + `/projects/${this.repo}/merge_requests?${query}`, + { + memCache: false, + }, + ); + + const needNextPage = this.reconcile(res.body); + if (!needNextPage) { + break; + } + + const uri = parseUrl(parseLinkHeader(res.headers.link)?.next?.url); + query = uri ? uri.search : null; + } + + this.updateItems(); + + return this; + } + + /** + * Ensure the pr cache starts with the most recent PRs. + * JavaScript ensures that the cache is sorted by PR number. + */ + private updateItems(): void { + this.items = Object.values(this.cache.items).reverse(); + } +} diff --git a/lib/modules/platform/gitlab/types.ts b/lib/modules/platform/gitlab/types.ts index 92d04f61f7b..27bc0c97ec3 100644 --- a/lib/modules/platform/gitlab/types.ts +++ b/lib/modules/platform/gitlab/types.ts @@ -38,6 +38,7 @@ export interface GitLabMergeRequest { status: string; sha: string; }; + updated_at: string; } export interface GitlabPr extends Pr { @@ -78,3 +79,9 @@ export interface GitlabUserStatus { emoji?: string; availability: 'not_set' | 'busy'; } + +export interface GitlabPrCacheData { + items: Record; + updated_at: string | null; + author: string | null; +} diff --git a/lib/modules/platform/types.ts b/lib/modules/platform/types.ts index 74a4542980a..1ea761f48fd 100644 --- a/lib/modules/platform/types.ts +++ b/lib/modules/platform/types.ts @@ -221,6 +221,13 @@ export interface AutodiscoverConfig { projects?: string[]; } +export interface FileOwnerRule { + usernames: string[]; + pattern: string; + score: number; + match: (path: string) => boolean; +} + export interface Platform { findIssue(title: string): Promise; getIssueList(): Promise; @@ -280,6 +287,7 @@ export interface Platform { filterUnavailableUsers?(users: string[]): Promise; commitFiles?(config: CommitFilesConfig): Promise; expandGroupMembers?(reviewersOrAssignees: string[]): Promise; + extractRulesFromCodeOwnersLines?(cleanedLines: string[]): FileOwnerRule[]; maxBodyLength(): number; labelCharLimit?(): number; @@ -297,4 +305,5 @@ export interface PlatformScm { checkoutBranch(branchName: string): Promise; mergeToLocal(branchName: string): Promise; mergeAndPush(branchName: string): Promise; + syncForkWithUpstream?(baseBranch: string): Promise; } diff --git a/lib/modules/versioning/pep440/index.spec.ts b/lib/modules/versioning/pep440/index.spec.ts index f81906bd8e4..3799b89f551 100644 --- a/lib/modules/versioning/pep440/index.spec.ts +++ b/lib/modules/versioning/pep440/index.spec.ts @@ -10,6 +10,7 @@ describe('modules/versioning/pep440/index', () => { ${'==1.2.3'} | ${true} ${'==1.2.3.0'} | ${true} ${'==1.2.3rc0'} | ${true} + ${'==1.2.3b0'} | ${true} ${'~=1.2.3'} | ${true} ${'==1.2.*'} | ${true} ${'>1.2.3'} | ${true} @@ -39,11 +40,12 @@ describe('modules/versioning/pep440/index', () => { }); it.each` - a | b | expected - ${'1.0'} | ${'>=1.0.0'} | ${true} - ${'3.0.0'} | ${'3.0.0'} | ${true} - ${'1.6.2'} | ${'<2.2.1.0'} | ${true} - ${'>=3.8'} | ${'>=3.9'} | ${false} + a | b | expected + ${'1.0'} | ${'>=1.0.0'} | ${true} + ${'3.0.0'} | ${'3.0.0'} | ${true} + ${'1.6.2'} | ${'<2.2.1.0'} | ${true} + ${'>=3.8'} | ${'>=3.9'} | ${false} + ${'0.43b0'} | ${'>=0.43b0, <1.0'} | ${true} `('matches($a, $b) === $expected', ({ a, b, expected }) => { expect(pep440.matches(a, b)).toBe(expected); }); @@ -52,6 +54,7 @@ describe('modules/versioning/pep440/index', () => { version | isSingle ${'1.2.3'} | ${true} ${'1.2.3rc0'} | ${true} + ${'1.2.3b0'} | ${true} ${'==1.2.3'} | ${true} ${'==1.2'} | ${true} ${'== 1.2.3'} | ${true} diff --git a/lib/modules/versioning/pep440/index.ts b/lib/modules/versioning/pep440/index.ts index 7fbe6d83839..e31fc3715d8 100644 --- a/lib/modules/versioning/pep440/index.ts +++ b/lib/modules/versioning/pep440/index.ts @@ -81,7 +81,7 @@ function matches(version: string, range: string): boolean { if (isVersion(range)) { return equals(version, range); } - return isValid(range) && satisfies(version, range); + return isValid(range) && satisfies(version, range, { prereleases: true }); } export const api: VersioningApi = { diff --git a/lib/util/cache/package/types.ts b/lib/util/cache/package/types.ts index 694ac3bbbd9..f67588ed1b3 100644 --- a/lib/util/cache/package/types.ts +++ b/lib/util/cache/package/types.ts @@ -16,6 +16,11 @@ export interface DecoratorCachedRecord { cachedAt: string; } +/* IMPORTANT: + * These namespaces below are used as part of the cacheTtlOverride feature + * It's OK to add to them (e.g. for new datasources) but we should avoid + * backwards-incompatible changes in non-major releases + */ export type PackageCacheNamespace = | '_test-namespace' | 'changelog-bitbucket-notes@v2' diff --git a/lib/util/cache/repository/types.ts b/lib/util/cache/repository/types.ts index 58e63f9e675..217f64953d4 100644 --- a/lib/util/cache/repository/types.ts +++ b/lib/util/cache/repository/types.ts @@ -146,6 +146,9 @@ export interface RepoCacheData { bitbucket?: { pullRequestsCache?: unknown; }; + gitlab?: { + pullRequestsCache?: unknown; + }; bitbucketServer?: { pullRequestsCache?: unknown; }; diff --git a/lib/util/exec/env.ts b/lib/util/exec/env.ts index 2bf84be36ca..bfdeb20b43d 100644 --- a/lib/util/exec/env.ts +++ b/lib/util/exec/env.ts @@ -1,6 +1,7 @@ import { GlobalConfig } from '../../config/global'; const basicEnvVars = [ + 'CI', 'HTTP_PROXY', 'HTTPS_PROXY', 'NO_PROXY', diff --git a/lib/util/git/index.spec.ts b/lib/util/git/index.spec.ts index eec91f38636..ef3e1d96b3b 100644 --- a/lib/util/git/index.spec.ts +++ b/lib/util/git/index.spec.ts @@ -5,6 +5,8 @@ import { GlobalConfig } from '../../config/global'; import { CONFIG_VALIDATION, INVALID_PATH, + TEMPORARY_ERROR, + UNKNOWN_ERROR, } from '../../constants/error-messages'; import { newlineRegex, regEx } from '../regex'; import * as _behindBaseCache from './behind-base-branch-cache'; @@ -1227,4 +1229,167 @@ describe('util/git/index', { timeout: 10000 }, () => { expect(branch).toBe('develop'); }); }); + + describe('forkMode - normal working', () => { + let upstreamBase: tmp.DirectoryResult; + let upstreamOrigin: tmp.DirectoryResult; + let tmpDir2: tmp.DirectoryResult; + + beforeAll(async () => { + // create an upstream branch and one extra branch in it + upstreamBase = await tmp.dir({ unsafeCleanup: true }); + const upstream = Git(upstreamBase.path); + await upstream.init(); + const defaultUpsBranch = ( + await upstream.raw('branch', '--show-current') + ).trim(); + await upstream.addConfig('user.email', 'other@example.com'); + await upstream.addConfig('user.name', 'Other'); + await fs.writeFile(upstreamBase.path + '/past_file', 'past'); + await upstream.addConfig('commit.gpgsign', 'false'); + await upstream.add(['past_file']); + await upstream.commit('past message'); + await upstream.raw(['checkout', '-B', defaultUpsBranch]); + await upstream.checkout(['-b', 'develop', defaultUpsBranch]); + + // clone of upstream on local path + upstreamOrigin = await tmp.dir({ unsafeCleanup: true }); + const upstreamRepo = Git(upstreamOrigin.path); + await upstreamRepo.clone(upstreamBase.path, '.', ['--bare']); + await upstreamRepo.addConfig('commit.gpgsign', 'false'); + }); + + afterAll(async () => { + await upstreamBase?.cleanup(); + await upstreamOrigin?.cleanup(); + }); + + afterEach(async () => { + await tmpDir2?.cleanup(); + }); + + describe('syncForkWithUpstream()', () => { + it('throws unknown error', async () => { + tmpDir2 = await tmp.dir({ unsafeCleanup: true }); + GlobalConfig.set({ localDir: tmpDir2.path }); + + await git.initRepo({ + url: origin.path, + defaultBranch, + upstreamUrl: upstreamOrigin.path, + }); + + await git.syncGit(); + await expect( + git.syncForkWithUpstream('non-existing-branch'), + ).rejects.toThrow(UNKNOWN_ERROR); + }); + + it('syncs fork when local for branch absent', async () => { + tmpDir2 = await tmp.dir({ unsafeCleanup: true }); + GlobalConfig.set({ localDir: tmpDir2.path }); + + // init fork repo + await git.initRepo({ + url: origin.path, + defaultBranch, + upstreamUrl: upstreamOrigin.path, + }); + + await git.syncGit(); + await expect(git.syncForkWithUpstream('develop')).toResolve(); + expect(logger.logger.debug).toHaveBeenCalledWith( + 'Checking out branch develop from remote renovate-fork-upstream', + ); + }); + }); + + describe('syncGit()', () => { + it('should fetch from upstream and update local branch', async () => { + tmpDir2 = await tmp.dir({ unsafeCleanup: true }); + GlobalConfig.set({ localDir: tmpDir2.path }); + + await git.initRepo({ + url: origin.path, + defaultBranch, + upstreamUrl: upstreamOrigin.path, + }); + + await git.syncGit(); + const tmpGit = Git(tmpDir2.path); + + // make sure origin exists ie. fork repo is cloned + const originRemote = ( + await tmpGit.raw(['remote', 'get-url', 'origin']) + ).trim(); + expect(originRemote.trim()).toBe(origin.path); + + // make sure upstream exists + const upstreamRemote = ( + await tmpGit.raw(['remote', 'get-url', git.RENOVATE_FORK_UPSTREAM]) + ).trim(); + expect(upstreamRemote).toBe(upstreamOrigin.path); + + // verify fetch from upstream happened + // by checking the `${RENOVATE_FORK_UPSTREAM}/main` branch in the forked repo's remote branches + const branches = await tmpGit.branch(['-r']); + expect(branches.all).toContain( + `${git.RENOVATE_FORK_UPSTREAM}/${defaultBranch}`, + ); + + // verify that the HEAD's match + const headSha = (await tmpGit.revparse(['HEAD'])).trim(); + const upstreamSha = ( + await tmpGit.revparse([ + `${git.RENOVATE_FORK_UPSTREAM}/${defaultBranch}`, + ]) + ).trim(); + expect(headSha).toBe(upstreamSha); + }); + }); + }); + + // for coverage mostly + describe('forkMode - errors', () => { + it('resetHardFromRemote()', async () => { + const resetSpy = vi.spyOn(SimpleGit.prototype, 'reset'); + resetSpy.mockRejectedValueOnce(new Error('reset error')); + await expect(git.resetHardFromRemote('branchName')).rejects.toThrow( + 'reset error', + ); + }); + + it('forcePushToRemote()', async () => { + const pushSpy = vi.spyOn(SimpleGit.prototype, 'push'); + pushSpy.mockRejectedValueOnce(new Error('push error')); + await expect(git.forcePushToRemote('branch', 'origin')).rejects.toThrow( + 'push error', + ); + }); + + it('checkoutBranchFromRemote()', async () => { + const checkoutSpy = vi.spyOn(SimpleGit.prototype, 'checkoutBranch'); + checkoutSpy.mockRejectedValueOnce(new Error('checkout error')); + await expect( + git.checkoutBranchFromRemote('branch', git.RENOVATE_FORK_UPSTREAM), + ).rejects.toThrow('checkout error'); + }); + + it('checkoutBranchFromRemote() - temporary error', async () => { + const checkoutSpy = vi.spyOn(SimpleGit.prototype, 'checkoutBranch'); + checkoutSpy.mockRejectedValueOnce(new Error('fatal: ambiguous argument')); + await expect( + git.checkoutBranchFromRemote('branch', git.RENOVATE_FORK_UPSTREAM), + ).rejects.toThrow(TEMPORARY_ERROR); + }); + + it('syncForkWithRemote() - returns if no upstream exists', async () => { + await git.initRepo({ + url: origin.path, + defaultBranch, + }); + + await expect(git.syncForkWithUpstream(defaultBranch)).toResolve(); + }); + }); }); diff --git a/lib/util/git/index.ts b/lib/util/git/index.ts index 55850130701..70ac19c933f 100644 --- a/lib/util/git/index.ts +++ b/lib/util/git/index.ts @@ -17,6 +17,7 @@ import { REPOSITORY_EMPTY, SYSTEM_INSUFFICIENT_DISK_SPACE, TEMPORARY_ERROR, + UNKNOWN_ERROR, } from '../../constants/error-messages'; import { logger } from '../../logger'; import { ExternalHostError } from '../../types/errors/external-host-error'; @@ -65,6 +66,8 @@ const retryCount = 5; const delaySeconds = 3; const delayFactor = 2; +export const RENOVATE_FORK_UPSTREAM = 'renovate-fork-upstream'; + // A generic wrapper for simpleGit.* calls to make them more fault-tolerant export async function gitRetry(gitFunc: () => Promise): Promise { let round = 0; @@ -118,6 +121,7 @@ async function isDirectory(dir: string): Promise { } async function getDefaultBranch(git: SimpleGit): Promise { + logger.debug('getDefaultBranch()'); // see https://stackoverflow.com/a/62352647/3005034 try { let res = await git.raw(['rev-parse', '--abbrev-ref', 'origin/HEAD']); @@ -135,6 +139,7 @@ async function getDefaultBranch(git: SimpleGit): Promise { return res.replace('origin/', '').trim(); /* v8 ignore start -- TODO: add test */ } catch (err) { + logger.debug({ err }, 'Error getting default branch'); const errChecked = checkForPlatformFailure(err); if (errChecked) { throw errChecked; @@ -147,7 +152,7 @@ async function getDefaultBranch(git: SimpleGit): Promise { throw new Error(REPOSITORY_EMPTY); } if (err.message.includes("fatal: ambiguous argument 'origin/HEAD'")) { - logger.warn({ err }, 'Error getting default branch'); + logger.warn('Error getting default branch'); throw new Error(TEMPORARY_ERROR); } throw err; @@ -194,9 +199,12 @@ export async function validateGitVersion(): Promise { return true; } -async function fetchBranchCommits(): Promise { +async function fetchBranchCommits(preferUpstream = true): Promise { config.branchCommits = {}; - const opts = ['ls-remote', '--heads', config.url]; + const url = + preferUpstream && config.upstreamUrl ? config.upstreamUrl : config.url; + logger.debug(`fetchBranchCommits(): url=${url}`); + const opts = ['ls-remote', '--heads', url]; if (config.extraCloneOpts) { Object.entries(config.extraCloneOpts).forEach((e) => // TODO: types (#22198) @@ -399,11 +407,14 @@ export async function syncGit(): Promise { } gitInitialized = true; const localDir = GlobalConfig.get('localDir')!; - logger.debug(`Initializing git repository into ${localDir}`); + logger.debug(`syncGit(): Initializing git repository into ${localDir}`); const gitHead = upath.join(localDir, '.git/HEAD'); let clone = true; if (await fs.pathExists(gitHead)) { + logger.debug( + `syncGit(): Found existing git repository, attempting git fetch`, + ); try { await git.raw(['remote', 'set-url', 'origin', config.url]); const fetchStart = Date.now(); @@ -420,7 +431,7 @@ export async function syncGit(): Promise { if (err.message === REPOSITORY_EMPTY) { throw err; } - logger.info({ err }, 'git fetch error'); + logger.info({ err }, 'git fetch error, falling back to git clone'); } } if (clone) { @@ -494,6 +505,27 @@ export async function syncGit(): Promise { (await getDefaultBranch(git)); /* v8 ignore next -- TODO: add test */ delete getCache()?.semanticCommits; + + // If upstreamUrl is set then the bot is running in fork mode + // The "upstream" remote is the original repository which was forked from + if (config.upstreamUrl) { + logger.debug( + `Bringing default branch up-to-date with ${RENOVATE_FORK_UPSTREAM}, to get latest config`, + ); + // Add remote if it does not exist + const remotes = await git.getRemotes(true); + if (!remotes.some((remote) => remote.name === RENOVATE_FORK_UPSTREAM)) { + logger.debug(`Adding remote ${RENOVATE_FORK_UPSTREAM}`); + await git.addRemote(RENOVATE_FORK_UPSTREAM, config.upstreamUrl); + } + await syncForkWithUpstream(config.currentBranch); + await fetchBranchCommits(false); + } + + config.currentBranchSha = ( + await git.revparse('HEAD') + ).trim() as LongCommitSha; + logger.debug(`Current branch SHA: ${config.currentBranchSha}`); } export async function getRepoStatus(path?: string): Promise { @@ -558,7 +590,10 @@ export async function checkoutBranch( ).trim() as LongCommitSha; const latestCommitDate = (await git.log({ n: 1 }))?.latest?.date; if (latestCommitDate) { - logger.debug({ branchName, latestCommitDate }, 'latest commit'); + logger.debug( + { branchName, latestCommitDate, sha: config.currentBranchSha }, + 'latest commit', + ); } await git.reset(ResetMode.HARD); return config.currentBranchSha; @@ -576,6 +611,62 @@ export async function checkoutBranch( } } +export async function checkoutBranchFromRemote( + branchName: string, + remoteName: string, +): Promise { + logger.debug(`Checking out branch ${branchName} from remote ${remoteName}`); + await syncGit(); + try { + await gitRetry(() => + git.checkoutBranch(branchName, `${remoteName}/${branchName}`), + ); + config.currentBranch = branchName; + config.currentBranchSha = ( + await git.revparse('HEAD') + ).trim() as LongCommitSha; + logger.debug(`Checked out branch ${branchName} from remote ${remoteName}`); + config.branchCommits[branchName] = config.currentBranchSha; + return config.currentBranchSha; + } catch (err) { + const errChecked = checkForPlatformFailure(err); + /* v8 ignore next 3 -- hard to test */ + if (errChecked) { + throw errChecked; + } + if (err.message?.includes('fatal: ambiguous argument')) { + logger.warn({ err }, 'Failed to checkout branch'); + throw new Error(TEMPORARY_ERROR); + } + throw err; + } +} + +export async function resetHardFromRemote( + remoteAndBranch: string, +): Promise { + try { + const resetLog = await git.reset(['--hard', remoteAndBranch]); + logger.debug({ resetLog }, 'git reset log'); + } catch (err) { + logger.error({ err }, 'Error during git reset --hard'); + throw err; + } +} + +export async function forcePushToRemote( + branchName: string, + remote: string, +): Promise { + try { + const pushLog = await git.push([remote, branchName, '--force']); + logger.debug({ pushLog }, 'git push log'); + } catch (err) { + logger.error({ err }, 'Error during git push --force'); + throw err; + } +} + export async function getFileList(): Promise { await syncGit(); const branch = config.currentBranch; @@ -1396,3 +1487,63 @@ export async function listCommitTree( } return result; } + +async function localBranchExists(branchName: string): Promise { + await syncGit(); + const localBranches = await git.branchLocal(); + return localBranches.all.includes(branchName); +} + +/** + * Synchronize a forked branch with its upstream counterpart. + * + * syncForkWithUpstream updates the fork's branch, to match the corresponding branch in the upstream repository. + * The steps are: + * 1. Check if the branch exists locally. + * 2. If the branch exists locally: checkout the local branch. + * 3. If the branch does _not_ exist locally: checkout the upstream branch. + * 4. Reset the local branch to match the upstream branch. + * 5. Force push the (updated) local branch to the origin repository. + * + * @param {string} branchName - The name of the branch to synchronize. + * @returns A promise that resolves to True if the synchronization is successful, or `false` if an error occurs. + */ +export async function syncForkWithUpstream(branchName: string): Promise { + if (!config.upstreamUrl) { + return; + } + logger.debug( + `Synchronizing fork with "${RENOVATE_FORK_UPSTREAM}" remote for branch ${branchName}`, + ); + const remotes = await getRemotes(); + /* v8 ignore next 3 -- this should not be possible if upstreamUrl exists */ + if (!remotes.some((r) => r === RENOVATE_FORK_UPSTREAM)) { + throw new Error('No upstream remote exists, cannot sync fork'); + } + try { + await git.fetch([RENOVATE_FORK_UPSTREAM]); + if (await localBranchExists(branchName)) { + await checkoutBranch(branchName); + } else { + await checkoutBranchFromRemote(branchName, RENOVATE_FORK_UPSTREAM); + } + await resetHardFromRemote(`${RENOVATE_FORK_UPSTREAM}/${branchName}`); + await forcePushToRemote(branchName, 'origin'); + } catch (err) /* v8 ignore next 3 -- shouldn't happen */ { + logger.error({ err }, 'Error synchronizing fork'); + throw new Error(UNKNOWN_ERROR); + } +} + +export async function getRemotes(): Promise { + logger.debug('git.getRemotes()'); + try { + await syncGit(); + const remotes = await git.getRemotes(); + logger.debug(`Found remotes: ${remotes.map((r) => r.name).join(', ')}`); + return remotes.map((remote) => remote.name); + } catch (err) /* v8 ignore start */ { + logger.error({ err }, 'Error getting remotes'); + throw err; + } /* v8 ignore stop */ +} diff --git a/lib/util/git/types.ts b/lib/util/git/types.ts index 58a66b4106e..b634f24088b 100644 --- a/lib/util/git/types.ts +++ b/lib/util/git/types.ts @@ -19,6 +19,7 @@ export interface StorageConfig { currentBranch?: string; defaultBranch?: string; url: string; + upstreamUrl?: string | undefined; extraCloneOpts?: GitOptions; cloneSubmodules?: boolean; cloneSubmodulesFilter?: string[]; diff --git a/lib/util/github/graphql/datasource-fetcher.spec.ts b/lib/util/github/graphql/datasource-fetcher.spec.ts index 4ac7ee91108..b8bd0463df7 100644 --- a/lib/util/github/graphql/datasource-fetcher.spec.ts +++ b/lib/util/github/graphql/datasource-fetcher.spec.ts @@ -1,4 +1,3 @@ -import AggregateError from 'aggregate-error'; import * as _packageCache from '../../../util/cache/package'; import type { Timestamp } from '../../../util/timestamp'; import type { GithubGraphqlResponse } from '../../http/github'; @@ -194,7 +193,7 @@ describe('util/github/graphql/datasource-fetcher', () => { )) as AggregateError; expect(res).toBeInstanceOf(AggregateError); - expect([...res]).toEqual([ + expect(res.errors).toEqual([ new Error('first error'), new Error('second error'), ]); diff --git a/lib/util/github/graphql/datasource-fetcher.ts b/lib/util/github/graphql/datasource-fetcher.ts index 2992dc081c4..1a124f73655 100644 --- a/lib/util/github/graphql/datasource-fetcher.ts +++ b/lib/util/github/graphql/datasource-fetcher.ts @@ -1,4 +1,3 @@ -import AggregateError from 'aggregate-error'; import { GlobalConfig } from '../../../config/global'; import { logger } from '../../../logger'; import { ExternalHostError } from '../../../types/errors/external-host-error'; @@ -37,7 +36,7 @@ function isUnknownGraphqlError(err: Error): boolean { } function canBeSolvedByShrinking(err: Error): boolean { - const errors: Error[] = err instanceof AggregateError ? [...err] : [err]; + const errors: Error[] = err instanceof AggregateError ? err.errors : [err]; return errors.some( (e) => err instanceof ExternalHostError || isUnknownGraphqlError(e), ); diff --git a/lib/util/github/graphql/index.spec.ts b/lib/util/github/graphql/index.spec.ts index b9656c1d92b..4bf6fa0da7f 100644 --- a/lib/util/github/graphql/index.spec.ts +++ b/lib/util/github/graphql/index.spec.ts @@ -19,7 +19,7 @@ describe('util/github/graphql/index', () => { version: '1.2.3', target: { type: 'Tag', - target: { oid: 'abc123' }, + target: { type: 'Commit', oid: 'abc123' }, tagger: { releaseTimestamp: '2022-09-24' }, }, }, diff --git a/lib/util/github/graphql/query-adapters/tags-query-adapter.spec.ts b/lib/util/github/graphql/query-adapters/tags-query-adapter.spec.ts index ac6f68968f3..555b8cc46aa 100644 --- a/lib/util/github/graphql/query-adapters/tags-query-adapter.spec.ts +++ b/lib/util/github/graphql/query-adapters/tags-query-adapter.spec.ts @@ -26,7 +26,25 @@ describe('util/github/graphql/query-adapters/tags-query-adapter', () => { version: '1.2.3', target: { type: 'Tag', - target: { oid: 'abc123' }, + target: { type: 'Commit', oid: 'abc123' }, + tagger: { releaseTimestamp: '2022-09-24' as Timestamp }, + }, + }), + ).toEqual({ + version: '1.2.3', + gitRef: '1.2.3', + hash: 'abc123', + releaseTimestamp: '2022-09-24' as Timestamp, + }); + }); + + it('transforms nested Tag type', () => { + expect( + adapter.transform({ + version: '1.2.3', + target: { + type: 'Tag', + target: { type: 'Tag', target: { oid: 'abc123' } }, tagger: { releaseTimestamp: '2022-09-24' as Timestamp }, }, }), diff --git a/lib/util/github/graphql/query-adapters/tags-query-adapter.ts b/lib/util/github/graphql/query-adapters/tags-query-adapter.ts index bdc847b55d9..dc61f528684 100644 --- a/lib/util/github/graphql/query-adapters/tags-query-adapter.ts +++ b/lib/util/github/graphql/query-adapters/tags-query-adapter.ts @@ -15,9 +15,16 @@ const GithubGraphqlTag = z.object({ }), z.object({ type: z.literal('Tag'), - target: z.object({ - oid: z.string(), - }), + target: z.union([ + z.object({ + type: z.literal('Commit'), + oid: z.string(), + }), + z.object({ + type: z.literal('Tag'), + target: z.object({ oid: z.string() }), + }), + ]), tagger: z.object({ releaseTimestamp: Timestamp, }), @@ -47,9 +54,15 @@ const query = prepareQuery(` } ... on Tag { target { + type: __typename ... on Commit { oid } + ... on Tag { + target { + oid + } + } } tagger { releaseTimestamp: date @@ -64,12 +77,21 @@ function transform(item: GithubGraphqlTag): GithubTagItem | null { if (!res.success) { return null; } + const { version, target } = item; - const releaseTimestamp = - target.type === 'Commit' - ? target.releaseTimestamp - : target.tagger.releaseTimestamp; - const hash = target.type === 'Commit' ? target.oid : target.target.oid; + if (target.type === 'Commit') { + const releaseTimestamp = target.releaseTimestamp; + const hash = target.oid; + return { version, gitRef: version, hash, releaseTimestamp }; + } + + const releaseTimestamp = target.tagger.releaseTimestamp; + if (target.target.type === 'Commit') { + const hash = target.target.oid; + return { version, gitRef: version, hash, releaseTimestamp }; + } + + const hash = target.target.target.oid; return { version, gitRef: version, hash, releaseTimestamp }; } diff --git a/lib/util/host-rules.spec.ts b/lib/util/host-rules.spec.ts index 9caa4a36570..9df9533be2f 100644 --- a/lib/util/host-rules.spec.ts +++ b/lib/util/host-rules.spec.ts @@ -55,6 +55,30 @@ describe('util/host-rules', () => { password: 'pass1', username: 'user1', }); + expect(find({ url: 'https://some.endpoint/' })).toEqual({ + password: 'pass1', + username: 'user1', + }); + expect(find({ url: 'https://some.endpoint' })).toEqual({ + password: 'pass1', + username: 'user1', + }); + expect(find({ url: 'https://some.endpoint:443' })).toEqual({ + password: 'pass1', + username: 'user1', + }); + }); + + it('does not match subpart of hostname', () => { + add({ + matchHost: 'https://some.endpoint', + username: 'user1', + password: 'pass1', + }); + expect(find({ url: 'https://some.endpoint.example.com' })).toEqual({}); + expect(find({ url: 'https://some.endpoint:blub@example.com' })).toEqual( + {}, + ); }); it('massages host url', () => { diff --git a/lib/util/host-rules.ts b/lib/util/host-rules.ts index 8d6ea789759..dc71461059a 100644 --- a/lib/util/host-rules.ts +++ b/lib/util/host-rules.ts @@ -78,15 +78,16 @@ export interface HostRuleSearch { } export function matchesHost(url: string, matchHost: string): boolean { - if (isHttpUrl(url) && isHttpUrl(matchHost)) { - return url.startsWith(matchHost); - } - const parsedUrl = parseUrl(url); if (!parsedUrl) { return false; } + const parsedMatchHost = parseUrl(matchHost); + if (isHttpUrl(parsedUrl) && isHttpUrl(parsedMatchHost)) { + return parsedUrl.href.startsWith(parsedMatchHost!.href); + } + const { hostname } = parsedUrl; if (!hostname) { return false; diff --git a/lib/util/http/github.spec.ts b/lib/util/http/github.spec.ts index bf0c872b501..96923d6cc9c 100644 --- a/lib/util/http/github.spec.ts +++ b/lib/util/http/github.spec.ts @@ -14,6 +14,7 @@ import * as hostRules from '../host-rules'; import { GithubHttp, setBaseUrl } from './github'; import type { GraphqlPageCache } from './github'; import * as httpMock from '~test/http-mock'; +import { logger } from '~test/util'; vi.mock('../cache/repository'); const repositoryCache = vi.mocked(_repositoryCache); @@ -306,6 +307,12 @@ describe('util/http/github', () => { }); describe('handleGotError', () => { + it('should log a once warning for github.com 401', async () => { + await expect( + fail(401, { message: 'Some unauthorized' }), + ).rejects.toThrow('Response code 401 (Some unauthorized)'); + expect(logger.logger.once.warn).toHaveBeenCalled(); + }); async function fail( code: number, body: any = undefined, diff --git a/lib/util/http/github.ts b/lib/util/http/github.ts index 06b0e0a4b54..bcba4bedab8 100644 --- a/lib/util/http/github.ts +++ b/lib/util/http/github.ts @@ -14,7 +14,7 @@ import { maskToken } from '../mask'; import * as p from '../promises'; import { range } from '../range'; import { regEx } from '../regex'; -import { joinUrlParts, parseLinkHeader } from '../url'; +import { joinUrlParts, parseLinkHeader, parseUrl } from '../url'; import { findMatchingRule } from './host-rules'; import { HttpBase, @@ -123,19 +123,26 @@ function handleGotError( ); return new Error(PLATFORM_INTEGRATION_UNAUTHORIZED); } - if (err.statusCode === 401 && message.includes('Bad credentials')) { - const rateLimit = err.headers?.['x-ratelimit-limit'] ?? -1; - logger.debug( - { - token: maskToken(opts.token), - err, - }, - 'GitHub failure: Bad credentials', - ); - if (rateLimit === '60') { - return new ExternalHostError(err, 'github'); + if (err.statusCode === 401) { + // Warn once for github.com token if unauthorized + const hostname = parseUrl(url)?.hostname; + if (hostname === 'github.com' || hostname === 'api.github.com') { + logger.once.warn('github.com token 401 unauthorized'); + } + if (message.includes('Bad credentials')) { + const rateLimit = err.headers?.['x-ratelimit-limit'] ?? -1; + logger.debug( + { + token: maskToken(opts.token), + err, + }, + 'GitHub failure: Bad credentials', + ); + if (rateLimit === '60') { + return new ExternalHostError(err, 'github'); + } + return new Error(PLATFORM_BAD_CREDENTIALS); } - return new Error(PLATFORM_BAD_CREDENTIALS); } if (err.statusCode === 422) { if ( diff --git a/lib/util/http/http.ts b/lib/util/http/http.ts index e0518bcedb2..31bc94c0173 100644 --- a/lib/util/http/http.ts +++ b/lib/util/http/http.ts @@ -161,6 +161,7 @@ export abstract class HttpBase< const { cacheProvider } = options; const memCacheKey = + !process.env.RENOVATE_X_DISABLE_HTTP_MEMCACHE && !cacheProvider && options.memCache !== false && (options.method === 'get' || options.method === 'head') @@ -206,7 +207,9 @@ export abstract class HttpBase< const throttledTask = throttle ? () => throttle.add(httpTask) : httpTask; const queue = getQueue(url); - const queuedTask = queue ? () => queue.add(throttledTask) : throttledTask; + const queuedTask = queue + ? () => queue.add(throttledTask, { throwOnTimeout: true }) + : throttledTask; const { maxRetryAfter = 60 } = hostRule; resPromise = wrapWithRetry(queuedTask, url, getRetryAfter, maxRetryAfter); diff --git a/lib/util/http/queue.spec.ts b/lib/util/http/queue.spec.ts index 69069522393..4e7a483530a 100644 --- a/lib/util/http/queue.spec.ts +++ b/lib/util/http/queue.spec.ts @@ -6,7 +6,7 @@ describe('util/http/queue', () => { clear(); hostRules.clear(); hostRules.add({ - matchHost: 'https://example.com', + matchHost: 'example.com', concurrentRequestLimit: 143, }); }); diff --git a/lib/util/http/throttle.spec.ts b/lib/util/http/throttle.spec.ts index 5163f23defb..67f06d7933d 100644 --- a/lib/util/http/throttle.spec.ts +++ b/lib/util/http/throttle.spec.ts @@ -6,7 +6,7 @@ describe('util/http/throttle', () => { clear(); hostRules.clear(); hostRules.add({ - matchHost: 'https://example.com', + matchHost: 'example.com', maxRequestsPerSecond: 143, }); }); diff --git a/lib/util/promises.ts b/lib/util/promises.ts index 736437bc1db..05297969440 100644 --- a/lib/util/promises.ts +++ b/lib/util/promises.ts @@ -1,5 +1,6 @@ -import AggregateError from 'aggregate-error'; +import type { Options as PAllOptions } from 'p-all'; import pAll from 'p-all'; +import type { Mapper, Options as PMapOptions } from 'p-map'; import pMap from 'p-map'; import { logger } from '../logger'; import { ExternalHostError } from '../types/errors/external-host-error'; @@ -32,12 +33,12 @@ function handleError(err: any): never { } logger.debug({ err }, 'Aggregate error is thrown'); - handleMultipleErrors([...err]); + handleMultipleErrors(err.errors); } export async function all( tasks: PromiseFactory[], - options?: pAll.Options, + options?: PAllOptions, ): Promise { try { const res = await pAll(tasks, { @@ -53,8 +54,8 @@ export async function all( export async function map( input: Iterable, - mapper: pMap.Mapper, - options?: pMap.Options, + mapper: Mapper, + options?: PMapOptions, ): Promise { try { const res = await pMap(input, mapper, { diff --git a/lib/util/schema-utils.spec.ts b/lib/util/schema-utils/index.spec.ts similarity index 99% rename from lib/util/schema-utils.spec.ts rename to lib/util/schema-utils/index.spec.ts index 87cca4905a1..eeaef833716 100644 --- a/lib/util/schema-utils.spec.ts +++ b/lib/util/schema-utils/index.spec.ts @@ -14,10 +14,10 @@ import { multidocYaml, withDebugMessage, withTraceMessage, -} from './schema-utils'; +} from '.'; import { logger } from '~test/util'; -describe('util/schema-utils', () => { +describe('util/schema-utils/index', () => { describe('LooseArray', () => { it('parses array', () => { const s = LooseArray(z.string()); diff --git a/lib/util/schema-utils.ts b/lib/util/schema-utils/index.ts similarity index 96% rename from lib/util/schema-utils.ts rename to lib/util/schema-utils/index.ts index 8fd0597cb8c..44b784fa77b 100644 --- a/lib/util/schema-utils.ts +++ b/lib/util/schema-utils/index.ts @@ -8,12 +8,12 @@ import { type ZodTypeDef, z, } from 'zod'; -import { logger } from '../logger'; -import type { PackageDependency } from '../modules/manager/types'; -import { parseJsonc } from './common'; -import { parse as parseToml } from './toml'; -import type { YamlOptions } from './yaml'; -import { parseSingleYaml, parseYaml } from './yaml'; +import { logger } from '../../logger'; +import type { PackageDependency } from '../../modules/manager/types'; +import { parseJsonc } from '../common'; +import { parse as parseToml } from '../toml'; +import type { YamlOptions } from '../yaml'; +import { parseSingleYaml, parseYaml } from '../yaml'; interface ErrorContext { error: z.ZodError; diff --git a/lib/util/schema-utils/v4.spec.ts b/lib/util/schema-utils/v4.spec.ts new file mode 100644 index 00000000000..ccad9729d63 --- /dev/null +++ b/lib/util/schema-utils/v4.spec.ts @@ -0,0 +1,266 @@ +import { codeBlock } from 'common-tags'; +import { Json, Json5, Jsonc, MultidocYaml, Toml, Yaml } from './v4'; + +describe('util/schema-utils/v4', () => { + describe('Json', () => { + it('parses valid JSON', () => { + const input = codeBlock` + { + "name": "test", + "version": "1.0.0", + "dependencies": { + "lodash": "^4.17.21" + } + } + `; + const result = Json.safeParse(input); + expect(result).toMatchObject({ + success: true, + data: { + name: 'test', + version: '1.0.0', + dependencies: { + lodash: '^4.17.21', + }, + }, + }); + }); + + it('fails for invalid JSON', () => { + const input = codeBlock` + { + "name": "test", + "version": "1.0.0" + "dependencies": { + "lodash": "^4.17.21" + } + } + `; + const result = Json.safeParse(input); + expect(result).toMatchObject({ + success: false, + error: { + issues: [{ message: 'Invalid JSON' }], + }, + }); + }); + }); + + describe('Json5', () => { + it('parses valid JSON5', () => { + const input = codeBlock` + { + name: 'test', + version: '1.0.0', + // This is a comment + dependencies: { + lodash: '^4.17.21', + } + } + `; + const result = Json5.safeParse(input); + expect(result).toMatchObject({ + success: true, + data: { + name: 'test', + version: '1.0.0', + dependencies: { + lodash: '^4.17.21', + }, + }, + }); + }); + + it('fails for invalid JSON5', () => { + const input = codeBlock` + { + name: 'test' + version: 'invalid + dependencies: { + lodash: '^4.17.21' + } + } + `; + const result = Json5.safeParse(input); + expect(result).toMatchObject({ + success: false, + error: { + issues: [{ message: 'Invalid JSON5' }], + }, + }); + }); + }); + + describe('Jsonc', () => { + it('parses valid JSONC', () => { + const input = codeBlock` + { + "name": "test", + "version": "1.0.0", + // This is a comment + "dependencies": { + "lodash": "^4.17.21" + } + } + `; + const result = Jsonc.safeParse(input); + expect(result).toMatchObject({ + success: true, + data: { + name: 'test', + version: '1.0.0', + dependencies: { + lodash: '^4.17.21', + }, + }, + }); + }); + + it('fails for invalid JSONC', () => { + const input = codeBlock` + { + "name": "test" + "version": "1.0.0" + "dependencies": { + "lodash": "^4.17.21" + } + } + `; + const result = Jsonc.safeParse(input); + expect(result).toMatchObject({ + success: false, + error: { + issues: [{ message: 'Invalid JSONC' }], + }, + }); + }); + }); + + describe('Yaml', () => { + it('parses valid YAML', () => { + const input = codeBlock` + name: test + version: 1.0.0 + dependencies: + lodash: ^4.17.21 + express: ^4.18.0 + `; + const result = Yaml.safeParse(input); + expect(result).toMatchObject({ + success: true, + data: { + name: 'test', + version: '1.0.0', + dependencies: { + lodash: '^4.17.21', + express: '^4.18.0', + }, + }, + }); + }); + + it('fails for invalid YAML', () => { + const input = codeBlock` + name: test + version: 1.0.0 + dependencies: + lodash: ^4.17.21 + invalid: indentation + `; + const result = Yaml.safeParse(input); + expect(result).toMatchObject({ + success: false, + error: { + issues: [{ message: 'Invalid YAML' }], + }, + }); + }); + }); + + describe('MultidocYaml', () => { + it('parses valid multidoc YAML', () => { + const input = codeBlock` + --- + name: test1 + version: 1.0.0 + --- + name: test2 + version: 2.0.0 + `; + const result = MultidocYaml.safeParse(input); + expect(result).toMatchObject({ + success: true, + data: [ + { + name: 'test1', + version: '1.0.0', + }, + { + name: 'test2', + version: '2.0.0', + }, + ], + }); + }); + + it('fails for invalid multidoc YAML', () => { + const input = codeBlock` + --- + name: test1 + version: 1.0.0 + --- + name: test2 + invalid: indentation + `; + const result = MultidocYaml.safeParse(input); + expect(result).toMatchObject({ + success: false, + error: { + issues: [{ message: 'Invalid YAML' }], + }, + }); + }); + }); + + describe('Toml', () => { + it('parses valid TOML', () => { + const input = codeBlock` + name = "test" + version = "1.0.0" + + [dependencies] + lodash = "^4.17.21" + express = "^4.18.0" + `; + const result = Toml.safeParse(input); + expect(result).toMatchObject({ + success: true, + data: { + name: 'test', + version: '1.0.0', + dependencies: { + lodash: '^4.17.21', + express: '^4.18.0', + }, + }, + }); + }); + + it('fails for invalid TOML', () => { + const input = codeBlock` + name = "test" + version = "1.0.0" + invalid toml syntax here + [dependencies] + lodash = "^4.17.21" + `; + const result = Toml.safeParse(input); + expect(result).toMatchObject({ + success: false, + error: { + issues: [{ message: 'Invalid TOML' }], + }, + }); + }); + }); +}); diff --git a/lib/util/schema-utils/v4.ts b/lib/util/schema-utils/v4.ts new file mode 100644 index 00000000000..12e9a470adb --- /dev/null +++ b/lib/util/schema-utils/v4.ts @@ -0,0 +1,59 @@ +import JSON5 from 'json5'; +import { z } from 'zod/v4'; +import { parseJsonc } from '../common'; +import { parse as parseToml } from '../toml'; +import { parseSingleYaml, parseYaml } from '../yaml'; + +export const Json = z.string().transform((str, ctx): unknown => { + try { + return JSON.parse(str); + } catch { + ctx.addIssue({ code: 'custom', message: 'Invalid JSON' }); + return z.NEVER; + } +}); + +export const Json5 = z.string().transform((str, ctx): unknown => { + try { + return JSON5.parse(str); + } catch { + ctx.addIssue({ code: 'custom', message: 'Invalid JSON5' }); + return z.NEVER; + } +}); + +export const Jsonc = z.string().transform((str, ctx): unknown => { + try { + return parseJsonc(str); + } catch { + ctx.addIssue({ code: 'custom', message: 'Invalid JSONC' }); + return z.NEVER; + } +}); + +export const Yaml = z.string().transform((str, ctx): unknown => { + try { + return parseSingleYaml(str); + } catch { + ctx.addIssue({ code: 'custom', message: 'Invalid YAML' }); + return z.NEVER; + } +}); + +export const MultidocYaml = z.string().transform((str, ctx): unknown => { + try { + return parseYaml(str); + } catch { + ctx.addIssue({ code: 'custom', message: 'Invalid YAML' }); + return z.NEVER; + } +}); + +export const Toml = z.string().transform((str, ctx) => { + try { + return parseToml(str); + } catch { + ctx.addIssue({ code: 'custom', message: 'Invalid TOML' }); + return z.NEVER; + } +}); diff --git a/lib/workers/repository/config-migration/branch/migrated-data.spec.ts b/lib/workers/repository/config-migration/branch/migrated-data.spec.ts index 650f674d857..b4a5b9eda1b 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.spec.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.spec.ts @@ -174,6 +174,17 @@ describe('workers/repository/config-migration/branch/migrated-data', () => { ).resolves.toEqual(formatted); }); + it('formats without prettier if in .renovaterc', async () => { + vi.mocked(scm.getFileList).mockResolvedValue(['.prettierrc']); + await MigratedDataFactory.getAsync(); + await expect( + MigratedDataFactory.applyPrettierFormatting({ + ...migratedData, + filename: '.renovaterc', + }), + ).resolves.toEqual(migratedData.content); + }); + it('formats when finds prettier config inside the package.json file', async () => { const formatted = formattedMigratedData.content; vi.mocked(detectRepoFileConfig).mockResolvedValueOnce({ diff --git a/lib/workers/repository/config-migration/branch/migrated-data.ts b/lib/workers/repository/config-migration/branch/migrated-data.ts index c7492a76905..0ddca41e9c9 100644 --- a/lib/workers/repository/config-migration/branch/migrated-data.ts +++ b/lib/workers/repository/config-migration/branch/migrated-data.ts @@ -70,7 +70,7 @@ export async function applyPrettierFormatting( } } - if (!prettierExists) { + if (!prettierExists || !parser) { return content; } diff --git a/lib/workers/repository/dependency-dashboard.spec.ts b/lib/workers/repository/dependency-dashboard.spec.ts index 4f52a74355d..3d05c082509 100644 --- a/lib/workers/repository/dependency-dashboard.spec.ts +++ b/lib/workers/repository/dependency-dashboard.spec.ts @@ -13,6 +13,7 @@ import type { Platform } from '../../modules/platform'; import { massageMarkdown } from '../../modules/platform/github'; import { clone } from '../../util/clone'; import { regEx } from '../../util/regex'; +import { asTimestamp } from '../../util/timestamp'; import type { BranchConfig, BranchUpgradeConfig } from '../types'; import * as dependencyDashboard from './dependency-dashboard'; import { getDashboardMarkdownVulnerabilities } from './dependency-dashboard'; @@ -1302,6 +1303,77 @@ None detected // same with dry run await dryRun(branches, platform, 0, 1); }); + + it('handles missing version/digest values correctly', async () => { + const branches: BranchConfig[] = []; + const packageFilesWithMissingVersions = { + npm: [ + { + packageFile: 'package.json', + deps: [ + { + depName: 'dep-with-version-only', + currentValue: '1.0.0', + }, + { + depName: 'dep-with-digest-only', + currentDigest: 'sha256:1234567890', + }, + { + depName: 'dep-with-version-and-digest', + currentValue: '2.0.0', + currentDigest: 'sha256:0987654321', + }, + { + depName: 'dep-with-locked-version-only', + lockedVersion: '3.0.0', + }, + { + depName: 'dep-with-no-version-info', + }, + ], + }, + ], + }; + PackageFiles.add('main', packageFilesWithMissingVersions); + await dependencyDashboard.ensureDependencyDashboard( + config, + branches, + packageFilesWithMissingVersions, + { result: 'no-migration' }, + ); + expect(platform.ensureIssue).toHaveBeenCalledTimes(1); + const dashboardBody = platform.ensureIssue.mock.calls[0][0].body; + + // Version only case + expect(dashboardBody).toInclude('`dep-with-version-only 1.0.0`'); + + // Digest only case + expect(dashboardBody).toInclude( + '`dep-with-digest-only sha256:1234567890`', + ); + + // Version and digest case + expect(dashboardBody).toInclude( + '`dep-with-version-and-digest 2.0.0@sha256:0987654321`', + ); + + // Locked version fallback case + expect(dashboardBody).toInclude( + '`dep-with-locked-version-only lock file @ 3.0.0`', + ); + + // No version info case + expect(dashboardBody).toInclude( + '`dep-with-no-version-info unknown version`', + ); + + // Verify no 'undefined' appears in the output + expect(dashboardBody).not.toInclude('undefined'); + + // same with dry run + await dryRun(branches, platform, 0, 1); + }); }); describe('multi base branch repo', () => { @@ -1656,4 +1728,126 @@ See [\`osvVulnerabilityAlerts\`](https://docs.renovatebot.com/configuration-opti `); }); }); + + describe('getAbandonedPackagesMd()', () => { + it('returns empty string when no abandoned packages exist', () => { + const packageFiles: Record = { + npm: [ + { + packageFile: 'package.json', + deps: [ + { depName: 'lodash', isAbandoned: false }, + { depName: 'express', isAbandoned: false }, + ], + }, + ], + }; + + const result = dependencyDashboard.getAbandonedPackagesMd(packageFiles); + expect(result).toEqual(''); + }); + + it('returns formatted markdown when abandoned packages exist', () => { + const packageFiles: Record = { + npm: [ + { + packageFile: 'package.json', + deps: [ + { + depName: 'abandoned-pkg', + isAbandoned: true, + mostRecentTimestamp: asTimestamp('2020-05-15T12:00:00.000Z')!, + }, + ], + }, + ], + }; + + const result = dependencyDashboard.getAbandonedPackagesMd(packageFiles); + + expect(result).toContain('> ℹ **Note**'); + expect(result).toContain('| Datasource | Name | Last Updated |'); + expect(result).toContain('| npm | `abandoned-pkg` | `2020-05-15` |'); + expect(result).toContain('abandonmentThreshold'); + }); + + it('handles multiple abandoned packages across different managers', () => { + const packageFiles: Record = { + npm: [ + { + packageFile: 'package.json', + deps: [ + { + depName: 'pkg1', + isAbandoned: true, + mostRecentTimestamp: asTimestamp('2021-01-10T10:00:00.000Z')!, + }, + { depName: 'pkg2', isAbandoned: false }, + { + depName: 'pkg3', + isAbandoned: true, + mostRecentTimestamp: asTimestamp('2020-11-05T15:30:00.000Z')!, + }, + ], + }, + ], + gradle: [ + { + packageFile: 'build.gradle', + deps: [ + { + depName: 'org.example:lib', + isAbandoned: true, + mostRecentTimestamp: asTimestamp('2019-07-22T08:15:00.000Z')!, + }, + ], + }, + ], + }; + + const result = dependencyDashboard.getAbandonedPackagesMd(packageFiles); + + expect(result).toContain('| gradle | `org.example:lib` | `2019-07-22` |'); + expect(result).toContain('| npm | `pkg1` | `2021-01-10` |'); + expect(result).toContain('| npm | `pkg3` | `2020-11-05` |'); + expect(result).not.toContain('pkg2'); + }); + + it('displays "unknown" when mostRecentTimestamp is missing', () => { + const packageFiles: Record = { + npm: [ + { + packageFile: 'package.json', + deps: [ + { + depName: 'pkg-with-date', + isAbandoned: true, + mostRecentTimestamp: asTimestamp('2021-03-17T14:30:00.000Z')!, + }, + { depName: 'pkg-no-date', isAbandoned: true }, + ], + }, + ], + }; + + const result = dependencyDashboard.getAbandonedPackagesMd(packageFiles); + + expect(result).toContain('| npm | `pkg-with-date` | `2021-03-17` |'); + expect(result).toContain('| npm | `pkg-no-date` | `unknown` |'); + }); + + it('handles empty deps array', () => { + const packageFiles: Record = { + npm: [ + { + packageFile: 'package.json', + deps: [], + }, + ], + }; + + const result = dependencyDashboard.getAbandonedPackagesMd(packageFiles); + expect(result).toEqual(''); + }); + }); }); diff --git a/lib/workers/repository/dependency-dashboard.ts b/lib/workers/repository/dependency-dashboard.ts index 5e10f157070..e2053decc83 100644 --- a/lib/workers/repository/dependency-dashboard.ts +++ b/lib/workers/repository/dependency-dashboard.ts @@ -1,9 +1,11 @@ import is from '@sindresorhus/is'; +import { DateTime } from 'luxon'; import { GlobalConfig } from '../../config/global'; import type { RenovateConfig } from '../../config/types'; import { logger } from '../../logger'; import type { PackageFile } from '../../modules/manager/types'; import { platform } from '../../modules/platform'; +import { coerceArray } from '../../util/array'; import { regEx } from '../../util/regex'; import { coerceString } from '../../util/string'; import * as template from '../../util/template'; @@ -324,6 +326,10 @@ export async function ensureDependencyDashboard( issueBody += '\n'; } + if (config.dependencyDashboardReportAbandonment) { + issueBody += getAbandonedPackagesMd(packageFiles); + } + const pendingApprovals = branches.filter( (branch) => branch.result === 'needs-approval', ); @@ -557,6 +563,60 @@ export async function ensureDependencyDashboard( } } +export function getAbandonedPackagesMd( + packageFiles: Record, +): string { + const abandonedPackages: Record< + string, + Record + > = {}; + let abandonedCount = 0; + + for (const [manager, managerPackageFiles] of Object.entries(packageFiles)) { + for (const packageFile of managerPackageFiles) { + for (const dep of coerceArray(packageFile.deps)) { + if (dep.depName && dep.isAbandoned) { + abandonedCount++; + abandonedPackages[manager] = abandonedPackages[manager] || {}; + abandonedPackages[manager][dep.depName] = dep.mostRecentTimestamp; + } + } + } + } + + if (abandonedCount === 0) { + return ''; + } + + let abandonedMd = '> ℹ **Note**\n> \n'; + abandonedMd += + 'These dependencies have not received updates for an extended period and may be unmaintained:\n\n'; + + abandonedMd += '
\n'; + abandonedMd += `View abandoned dependencies (${abandonedCount})\n\n`; + abandonedMd += '| Datasource | Name | Last Updated |\n'; + abandonedMd += '|------------|------|-------------|\n'; + + for (const manager of Object.keys(abandonedPackages).sort()) { + const deps = abandonedPackages[manager]; + for (const depName of Object.keys(deps).sort()) { + const mostRecentTimestamp = deps[depName]; + const formattedDate = mostRecentTimestamp + ? DateTime.fromISO(mostRecentTimestamp).toFormat('yyyy-MM-dd') + : 'unknown'; + abandonedMd += `| ${manager} | \`${depName}\` | \`${formattedDate}\` |\n`; + } + } + + abandonedMd += '\n
\n\n'; + abandonedMd += + 'Packages are marked as abandoned when they exceed the [`abandonmentThreshold`](https://docs.renovatebot.com/configuration-options/#abandonmentthreshold) since their last release.\n'; + abandonedMd += + 'Unlike deprecated packages with official notices, abandonment is detected by release inactivity.\n\n'; + + return abandonedMd + '\n'; +} + function getFooter(config: RenovateConfig): string { let footer = ''; if (config.dependencyDashboardFooter?.length) { diff --git a/lib/workers/repository/init/inherited.spec.ts b/lib/workers/repository/init/inherited.spec.ts index 28b9e9b4590..bfd540c8608 100644 --- a/lib/workers/repository/init/inherited.spec.ts +++ b/lib/workers/repository/init/inherited.spec.ts @@ -1,3 +1,4 @@ +import * as decrypt from '../../../config/decrypt'; import * as presets_ from '../../../config/presets'; import type { RenovateConfig } from '../../../config/types'; import * as validation from '../../../config/validation'; @@ -113,6 +114,41 @@ describe('workers/repository/init/inherited', () => { expect(res.hostRules).toBeUndefined(); }); + it('should decrypt encrypted values from inherited config', async () => { + platform.getRawFile.mockResolvedValue( + `{ + "hostRules": [ + { + "matchHost": "some-host-url", + "encrypted": { + "token": "some-secret-token" + } + } + ] + }`, + ); + + vi.spyOn(decrypt, 'decryptConfig').mockResolvedValueOnce({ + hostRules: [ + { + matchHost: 'some-host-url', + token: 'some-secret-token', + }, + ], + }); + + const res = await mergeInheritedConfig({ + ...config, + }); + expect(hostRules.getAll()).toMatchObject([ + { + matchHost: 'some-host-url', + token: 'some-secret-token', + }, + ]); + expect(res.hostRules).toBeUndefined(); + }); + it('should apply secrets to inherited config', async () => { platform.getRawFile.mockResolvedValue( `{ diff --git a/lib/workers/repository/init/inherited.ts b/lib/workers/repository/init/inherited.ts index aa7266d7089..a568530da06 100644 --- a/lib/workers/repository/init/inherited.ts +++ b/lib/workers/repository/init/inherited.ts @@ -1,6 +1,7 @@ import is from '@sindresorhus/is'; import { dequal } from 'dequal'; import { mergeChildConfig, removeGlobalConfig } from '../../../config'; +import { decryptConfig } from '../../../config/decrypt'; import { parseFileConfig } from '../../../config/parse'; import { resolveConfigPresets } from '../../../config/presets'; import { applySecretsToConfig } from '../../../config/secrets'; @@ -97,10 +98,13 @@ export async function mergeInheritedConfig( 'Found warnings in inherited configuration.', ); } - let filteredConfig = removeGlobalConfig(inheritedConfig, true); - if (!dequal(inheritedConfig, filteredConfig)) { + + let decryptedConfig = await decryptConfig(inheritedConfig, config.repository); + + let filteredConfig = removeGlobalConfig(decryptedConfig, true); + if (!dequal(decryptedConfig, filteredConfig)) { logger.debug( - { inheritedConfig, filteredConfig }, + { inheritedConfig: decryptedConfig, filteredConfig }, 'Removed global config from inherited config.', ); } @@ -134,11 +138,14 @@ export async function mergeInheritedConfig( ); } + // decrypt again, as resolved presets could contain encrypted values + decryptedConfig = await decryptConfig(resolvedConfig, config.repository); + // remove global config options once again, as resolved presets could have added some - filteredConfig = removeGlobalConfig(resolvedConfig, true); - if (!dequal(resolvedConfig, filteredConfig)) { + filteredConfig = removeGlobalConfig(decryptedConfig, true); + if (!dequal(decryptedConfig, filteredConfig)) { logger.debug( - { inheritedConfig: resolvedConfig, filteredConfig }, + { inheritedConfig: decryptedConfig, filteredConfig }, 'Removed global config from inherited config presets.', ); } diff --git a/lib/workers/repository/init/merge.spec.ts b/lib/workers/repository/init/merge.spec.ts index b94796bf4c3..cb33af7e6e7 100644 --- a/lib/workers/repository/init/merge.spec.ts +++ b/lib/workers/repository/init/merge.spec.ts @@ -610,7 +610,7 @@ describe('workers/repository/init/merge', () => { }, }, { - name: 'it should merge a static repo config into the repo config by appending it', + name: 'it should merge both configs and and repo config is higher priority', currentConfig: {}, repoFileConfig: { extends: ['group:socketio'], @@ -638,13 +638,53 @@ describe('workers/repository/init/merge', () => { groupName: 'socket.io packages', matchPackageNames: ['socket.io**'], }, + { + groupName: 'my-custom-socketio-override', + matchPackageNames: ['socket.io**'], + }, { groupName: 'high merge confidence', matchConfidence: ['high', 'very high'], }, + ], + renovateJsonPresent: true, + warnings: [], + }, + }, + { + name: 'it should merge extends from both a repo config and static repo config by appending it', + currentConfig: {}, + repoFileConfig: { + extends: ['group:springAndroid'], + }, + staticConfig: { + dependencyDashboard: true, + extends: ['group:springAmqp'], + packageRules: [ + { + groupName: 'some-package-rule', + matchPackageNames: ['anything**'], + }, + ], + }, + wantConfig: { + dependencyDashboard: true, + description: [ + 'Group Java Spring AMQP packages.', + 'Group Java Spring Android packages.', + ], + packageRules: [ { - groupName: 'my-custom-socketio-override', - matchPackageNames: ['socket.io**'], + groupName: 'spring amqp', + matchPackageNames: ['org.springframework.amqp:**'], + }, + { + groupName: 'spring android', + matchPackageNames: ['org.springframework.android:**'], + }, + { + groupName: 'some-package-rule', + matchPackageNames: ['anything**'], }, ], renovateJsonPresent: true, diff --git a/lib/workers/repository/init/merge.ts b/lib/workers/repository/init/merge.ts index 4d601ffdba3..66ae5936368 100644 --- a/lib/workers/repository/init/merge.ts +++ b/lib/workers/repository/init/merge.ts @@ -344,5 +344,11 @@ export async function mergeStaticRepoEnvConfig( return config; } - return mergeChildConfig(config, repoEnvConfig); + // merge extends + if (is.nonEmptyArray(repoEnvConfig.extends)) { + config.extends = [...repoEnvConfig.extends, ...(config.extends ?? [])]; + delete repoEnvConfig.extends; + } + // renovate repo config overrides RENOVATE_STATIC_REPO_CONFIG + return mergeChildConfig(repoEnvConfig, config); } diff --git a/lib/workers/repository/onboarding/branch/index.spec.ts b/lib/workers/repository/onboarding/branch/index.spec.ts index 635a48226f4..06ed49ed941 100644 --- a/lib/workers/repository/onboarding/branch/index.spec.ts +++ b/lib/workers/repository/onboarding/branch/index.spec.ts @@ -91,6 +91,14 @@ describe('workers/repository/onboarding/branch/index', () => { '}\n', ); scm.getFileList.mockResolvedValue(['package.json']); + fs.findLocalSiblingOrParent.mockImplementation( + (packageFile, configFile): Promise => { + if (packageFile === 'package.json' && configFile === '.npmrc') { + return Promise.resolve('.npmrc'); + } + return Promise.resolve(null); + }, + ); fs.readLocalFile.mockResolvedValue('{}'); await checkOnboardingBranch(config); const file = scm.commitAndPush.mock.calls[0][0] @@ -116,6 +124,14 @@ describe('workers/repository/onboarding/branch/index', () => { '}\n', ); scm.getFileList.mockResolvedValue(['package.json']); + fs.findLocalSiblingOrParent.mockImplementation( + (packageFile, configFile): Promise => { + if (packageFile === 'package.json' && configFile === '.npmrc') { + return Promise.resolve('.npmrc'); + } + return Promise.resolve(null); + }, + ); fs.readLocalFile.mockResolvedValue('{}'); await checkOnboardingBranch(config); const expectConfig = { diff --git a/lib/workers/repository/package-files.ts b/lib/workers/repository/package-files.ts index 73614ef881e..861312fe9b7 100644 --- a/lib/workers/repository/package-files.ts +++ b/lib/workers/repository/package-files.ts @@ -109,8 +109,15 @@ export class PackageFiles { for (const dep of packageFile.deps) { const ver = dep.currentValue; const digest = dep.currentDigest; - const version = - ver && digest ? `${ver}@${digest}` : `${digest ?? ver!}`; + const lock = dep.lockedVersion; + let version; + if (ver || digest) { + version = ver && digest ? `${ver}@${digest}` : `${digest ?? ver}`; + } else if (lock) { + version = `lock file @ ${lock}`; + } else { + version = 'unknown version'; + } // TODO: types (#22198) deps += ` - \`${dep.depName!} ${version}\`\n`; } diff --git a/lib/workers/repository/process/index.ts b/lib/workers/repository/process/index.ts index 0c5143466ae..e44a5cc51df 100644 --- a/lib/workers/repository/process/index.ts +++ b/lib/workers/repository/process/index.ts @@ -131,6 +131,10 @@ export async function extractDependencies( const extracted: Record> = {}; for (const baseBranch of config.baseBranches) { addMeta({ baseBranch }); + + if (scm.syncForkWithUpstream) { + await scm.syncForkWithUpstream(baseBranch); + } if (await scm.branchExists(baseBranch)) { const baseBranchConfig = await getBaseBranchConfig(baseBranch, config); extracted[baseBranch] = await extract(baseBranchConfig, overwriteCache); diff --git a/lib/workers/repository/process/lookup/index.spec.ts b/lib/workers/repository/process/lookup/index.spec.ts index e093b609d7d..653986cbb14 100644 --- a/lib/workers/repository/process/lookup/index.spec.ts +++ b/lib/workers/repository/process/lookup/index.spec.ts @@ -3685,6 +3685,23 @@ describe('workers/repository/process/lookup/index', () => { }); }); + it('prefers lockedVersion', async () => { + // Contrived test to check that lockedVersion is preferred over currentValue + config.currentValue = '1.3.0'; + config.lockedVersion = '1.4.1'; + config.rangeStrategy = 'update-lockfile'; + config.packageName = 'q'; + config.datasource = NpmDatasource.id; + httpMock.scope('https://registry.npmjs.org').get('/q').reply(200, qJson); + + const res = await Result.wrap( + lookup.lookupUpdates(config), + ).unwrapOrThrow(); + + expect(res.currentVersion).toEqual('1.4.1'); + expect(res.updates).toHaveLength(0); + }); + it('ignores deprecated when it is not the latest', async () => { config.currentValue = '1.3.0'; config.packageName = 'q2'; diff --git a/lib/workers/repository/process/lookup/index.ts b/lib/workers/repository/process/lookup/index.ts index e31fe442b16..e7d17a5af05 100644 --- a/lib/workers/repository/process/lookup/index.ts +++ b/lib/workers/repository/process/lookup/index.ts @@ -298,8 +298,7 @@ export async function lookupUpdates( let currentVersion: string; if (rangeStrategy === 'update-lockfile') { currentVersion = config.lockedVersion!; - } - if (allVersions.find((v) => v.version === compareValue)) { + } else if (allVersions.find((v) => v.version === compareValue)) { currentVersion = compareValue!; } // TODO #22198 diff --git a/lib/workers/repository/update/branch/auto-replace.spec.ts b/lib/workers/repository/update/branch/auto-replace.spec.ts index 4a14b871a9c..c64a48d538f 100644 --- a/lib/workers/repository/update/branch/auto-replace.spec.ts +++ b/lib/workers/repository/update/branch/auto-replace.spec.ts @@ -757,6 +757,33 @@ describe('workers/repository/update/branch/auto-replace', () => { ); }); + it('updates with helm value image/repository replacement with digest', async () => { + const yml = codeBlock` + parser: + image: + repository: docker.io/securecodebox/parser-nmap + tag: 3.14.3@q1w2e3r4t5z6u7i8o9p0 + `; + upgrade.manager = 'helm-values'; + upgrade.depName = 'docker.io/securecodebox/parser-nmap'; + upgrade.replaceString = '3.14.3'; + upgrade.currentValue = '3.14.3'; + upgrade.currentDigest = 'q1w2e3r4t5z6u7i8o9p0'; + upgrade.depIndex = 0; + upgrade.updateType = 'replacement'; + upgrade.newName = 'iteratec/juice-balancer'; + upgrade.newValue = 'v5.1.0'; + upgrade.newDigest = 'p0o9i8u7z6t5r4e3w2q1'; + upgrade.packageFile = 'values.yml'; + const res = await doAutoReplace(upgrade, yml, reuseExistingBranch); + expect(res).toBe( + yml + .replace(upgrade.depName, upgrade.newName) + .replace(upgrade.currentValue, upgrade.newValue) + .replace(upgrade.currentDigest, upgrade.newDigest), + ); + }); + it('updates with helm value image/repository wrong version', async () => { const yml = codeBlock` parser: @@ -1153,6 +1180,32 @@ describe('workers/repository/update/branch/auto-replace', () => { ); }); + it('updates with multiple same digest replacement without replaceString', async () => { + const dockerfile = codeBlock` + FROM notUbuntu:18.04@q1w2e3r4t5z6u7i8o9p0 + FROM alsoNotUbuntu:18.05@q1w2e3r4t5z6u7i8o9p0 + FROM ubuntu:18.04@q1w2e3r4t5z6u7i8o9p0 + `; + upgrade.manager = 'dockerfile'; + upgrade.depName = 'ubuntu'; + upgrade.currentValue = '18.04'; + upgrade.currentDigest = 'q1w2e3r4t5z6u7i8o9p0'; + upgrade.depIndex = 2; + upgrade.updateType = 'replacement'; + upgrade.newName = 'alpine'; + upgrade.newValue = '3.16'; + upgrade.newDigest = 'p0o9i8u7z6t5r4e3w2q1'; + upgrade.packageFile = 'Dockerfile'; + const res = await doAutoReplace(upgrade, dockerfile, reuseExistingBranch); + expect(res).toBe( + codeBlock` + FROM notUbuntu:18.04@q1w2e3r4t5z6u7i8o9p0 + FROM alsoNotUbuntu:18.05@q1w2e3r4t5z6u7i8o9p0 + FROM alpine:3.16@p0o9i8u7z6t5r4e3w2q1 + `, + ); + }); + it('docker: updates with pinDigest enabled but no currentDigest value', async () => { const dockerfile = codeBlock` FROM ubuntu:18.04 diff --git a/lib/workers/repository/update/branch/auto-replace.ts b/lib/workers/repository/update/branch/auto-replace.ts index af70427c4a7..ec0ad8254f4 100644 --- a/lib/workers/repository/update/branch/auto-replace.ts +++ b/lib/workers/repository/update/branch/auto-replace.ts @@ -318,6 +318,7 @@ export async function doAutoReplace( let newContent = existingContent; let nameReplaced = !newName; let valueReplaced = !newValue; + let digestReplaced = !newDigest; let startIndex = searchIndex; // Iterate through the rest of the file for (; searchIndex < newContent.length; searchIndex += 1) { @@ -339,8 +340,9 @@ export async function doAutoReplace( searchIndex = startIndex - 1; await writeLocalFile(upgrade.packageFile!, existingContent); newContent = existingContent; - nameReplaced = false; - valueReplaced = false; + nameReplaced = !newName; + valueReplaced = !newValue; + digestReplaced = !newDigest; continue; } // replace with newName @@ -366,8 +368,9 @@ export async function doAutoReplace( searchIndex = startIndex - 1; await writeLocalFile(upgrade.packageFile!, existingContent); newContent = existingContent; - nameReplaced = false; - valueReplaced = false; + nameReplaced = !newName; + valueReplaced = !newValue; + digestReplaced = !newDigest; continue; } // Now test if the result matches @@ -380,8 +383,41 @@ export async function doAutoReplace( await writeLocalFile(upgrade.packageFile!, newContent); valueReplaced = true; searchIndex += newValue.length - 1; + } else if ( + newDigest && + matchAt(newContent, searchIndex, currentDigest!) + ) { + logger.debug( + { packageFile, currentDigest }, + `Found currentDigest at index ${searchIndex}`, + ); + if (digestReplaced) { + startIndex = firstIndexOf( + existingContent, + depName!, + currentValue!, + startIndex + 1, + ); + searchIndex = startIndex - 1; + await writeLocalFile(upgrade.packageFile!, existingContent); + newContent = existingContent; + nameReplaced = !newName; + valueReplaced = !newValue; + digestReplaced = !newDigest; + continue; + } + // Now test if the result matches + newContent = replaceAt( + newContent, + searchIndex, + currentDigest!, + newDigest, + ); + await writeLocalFile(upgrade.packageFile!, newContent); + digestReplaced = true; + searchIndex += newDigest.length - 1; } - if (nameReplaced && valueReplaced) { + if (nameReplaced && valueReplaced && digestReplaced) { if (await confirmIfDepUpdated(upgrade, newContent)) { return newContent; } @@ -394,8 +430,9 @@ export async function doAutoReplace( searchIndex = startIndex - 1; await writeLocalFile(upgrade.packageFile!, existingContent); newContent = existingContent; - nameReplaced = false; - valueReplaced = false; + nameReplaced = !newName; + valueReplaced = !newValue; + digestReplaced = !newDigest; } } else if (matchAt(newContent, searchIndex, replaceString!)) { logger.debug( diff --git a/lib/workers/repository/update/branch/bump-versions.spec.ts b/lib/workers/repository/update/branch/bump-versions.spec.ts index 76252b12b8c..1d43e50c2fc 100644 --- a/lib/workers/repository/update/branch/bump-versions.spec.ts +++ b/lib/workers/repository/update/branch/bump-versions.spec.ts @@ -30,7 +30,6 @@ describe('workers/repository/update/branch/bump-versions', () => { const config = partial({ bumpVersions: [ { - name: null, filePatterns: ['\\.release-version'], bumpType: 'minor', matchStrings: ['^(?.+)$'], @@ -54,7 +53,6 @@ describe('workers/repository/update/branch/bump-versions', () => { const config = partial({ bumpVersions: [ { - name: null, filePatterns: ['\\^'], bumpType: 'minor', matchStrings: ['^(?.+)$'], @@ -131,7 +129,6 @@ describe('workers/repository/update/branch/bump-versions', () => { const config = partial({ bumpVersions: [ { - name: null, filePatterns: ['foo'], bumpType: 'minor', matchStrings: ['^(?.+)$'], @@ -164,7 +161,6 @@ describe('workers/repository/update/branch/bump-versions', () => { const config = partial({ bumpVersions: [ { - name: null, filePatterns: ['\\.release-version'], bumpType: 'minor', matchStrings: ['^(?.+)$'], @@ -193,11 +189,41 @@ describe('workers/repository/update/branch/bump-versions', () => { }); }); + it('should bump version with patch by default', async () => { + const config = partial({ + bumpVersions: [ + { + filePatterns: ['\\.release-version'], + matchStrings: ['^(?.+)$'], + }, + ], + updatedPackageFiles: [ + { + type: 'addition', + path: 'foo', + contents: 'bar', + }, + ], + }); + scm.getFileList.mockResolvedValueOnce(['foo', '.release-version']); + fs.readLocalFile.mockResolvedValueOnce('1.0.0'); + await bumpVersions(config); + + expect(config).toMatchObject({ + updatedArtifacts: [ + { + type: 'addition', + path: '.release-version', + contents: '1.0.1', + }, + ], + }); + }); + it('should bump version in an already changed packageFiles', async () => { const config = partial({ bumpVersions: [ { - name: null, filePatterns: ['foo'], bumpType: 'minor', matchStrings: ['\\s*version:\\s+(?[^\\s]+)'], @@ -243,7 +269,6 @@ describe('workers/repository/update/branch/bump-versions', () => { const config = partial({ bumpVersions: [ { - name: null, filePatterns: ['foo'], bumpType: 'minor', matchStrings: ['\\s*version:\\s+(?[^\\s]+)'], @@ -289,7 +314,6 @@ describe('workers/repository/update/branch/bump-versions', () => { const config = partial({ bumpVersions: [ { - name: null, filePatterns: ['foo'], bumpType: 'minor', matchStrings: ['\\s*version:\\s+(?[^\\s]+)'], @@ -343,7 +367,6 @@ describe('workers/repository/update/branch/bump-versions', () => { const config = partial({ bumpVersions: [ { - name: null, filePatterns: ['foo'], bumpType: 'minor', matchStrings: ['\\s*version:\\s+(?[^\\s]+)'], @@ -417,7 +440,6 @@ describe('workers/repository/update/branch/bump-versions', () => { const config = partial({ bumpVersions: [ { - name: null, filePatterns: ['foo'], bumpType: 'minor', matchStrings: [ diff --git a/lib/workers/repository/update/branch/bump-versions.ts b/lib/workers/repository/update/branch/bump-versions.ts index 4d3b8afe59d..12d04b14081 100644 --- a/lib/workers/repository/update/branch/bump-versions.ts +++ b/lib/workers/repository/update/branch/bump-versions.ts @@ -55,6 +55,8 @@ async function bumpVersion( packageFiles: Record, artifactFiles: Record, ): Promise { + const rawBumpType = config.bumpType ?? 'patch'; + const bumpVersionsDescr = config.name ? `bumpVersions(${config.name})` : 'bumpVersions'; @@ -113,7 +115,7 @@ async function bumpVersion( // getting new version let newVersion: string | null = null; try { - const bumpType = compile(config.bumpType, branchConfig); + const bumpType = compile(rawBumpType, branchConfig); newVersion = inc(version, bumpType as ReleaseType); } catch (e) { addArtifactError( diff --git a/lib/workers/repository/update/branch/execute-post-upgrade-commands.spec.ts b/lib/workers/repository/update/branch/execute-post-upgrade-commands.spec.ts index 0d03a758b08..52712c953d2 100644 --- a/lib/workers/repository/update/branch/execute-post-upgrade-commands.spec.ts +++ b/lib/workers/repository/update/branch/execute-post-upgrade-commands.spec.ts @@ -214,5 +214,92 @@ describe('workers/repository/update/branch/execute-post-upgrade-commands', () => expect(res.updatedArtifacts).toHaveLength(0); }); + it('retains previously deleted files too', async () => { + const commands = partial([ + { + manager: 'some-manager', + branchName: 'main', + postUpgradeTasks: { + executionMode: 'branch', + commands: ['command'], + fileFilters: ['*.txt'], + }, + }, + ]); + const config: BranchConfig = { + manager: 'some-manager', + updatedPackageFiles: [ + { + type: 'addition', + path: 'dependencies/Chart.yaml', + contents: '[content]', + }, + ], + updatedArtifacts: [ + { + type: 'addition', + path: 'dependencies/Chart.lock', + contents: '[content]', + }, + { + type: 'addition', + path: 'dependencies/charts/ingress-nginx-4.12.2.tgz', + contents: '[content]', + }, + { + type: 'deletion', + path: 'dependencies/charts/ingress-nginx-4.12.0.tgz', + }, + ], + upgrades: [], + branchName: 'main', + baseBranch: 'base', + }; + git.getRepoStatus.mockResolvedValueOnce( + partial({ + not_added: ['dependencies/charts/ingress-nginx-4.12.2.tgz'], + conflicted: [], + created: [], + deleted: ['dependencies/charts/ingress-nginx-4.12.0.tgz'], + modified: [ + 'dependencies/Chart.lock', + 'dependencies/Chart.yaml', + 'resources/helmfile.yaml', + ], + }), + ); + GlobalConfig.set({ + localDir: __dirname, + allowedCommands: ['some-command'], + }); + fs.localPathIsFile + .mockResolvedValueOnce(true) + .mockResolvedValueOnce(false); + fs.localPathExists + .mockResolvedValueOnce(true) + .mockResolvedValueOnce(true); + + const res = await postUpgradeCommands.postUpgradeCommandsExecutor( + commands, + config, + ); + + expect(res.updatedArtifacts).toMatchObject([ + { + type: 'addition', + path: 'dependencies/Chart.lock', + contents: '[content]', + }, + { + type: 'addition', + path: 'dependencies/charts/ingress-nginx-4.12.2.tgz', + contents: '[content]', + }, + { + type: 'deletion', + path: 'dependencies/charts/ingress-nginx-4.12.0.tgz', + }, + ]); + }); }); }); diff --git a/lib/workers/repository/update/branch/execute-post-upgrade-commands.ts b/lib/workers/repository/update/branch/execute-post-upgrade-commands.ts index 346d0daea9a..1c4ce0dee9b 100644 --- a/lib/workers/repository/update/branch/execute-post-upgrade-commands.ts +++ b/lib/workers/repository/update/branch/execute-post-upgrade-commands.ts @@ -122,18 +122,17 @@ export async function postUpgradeCommandsExecutor( ...coerceArray(status.not_added), ...coerceArray(status.modified), ]; - - logger.trace({ addedOrModifiedFiles }, 'Added or modified files'); - logger.debug( - `Checking ${addedOrModifiedFiles.length} added or modified files for post-upgrade changes`, - ); + const changedFiles = [ + ...addedOrModifiedFiles, + ...coerceArray(status.deleted), + ]; // Check for files which were previously deleted but have been re-added without modification const previouslyDeletedFiles = updatedArtifacts.filter( (ua) => ua.type === 'deletion', ); for (const previouslyDeletedFile of previouslyDeletedFiles) { - if (!addedOrModifiedFiles.includes(previouslyDeletedFile.path)) { + if (!changedFiles.includes(previouslyDeletedFile.path)) { logger.debug( { file: previouslyDeletedFile.path }, 'Previously deleted file has been restored without modification', @@ -147,6 +146,11 @@ export async function postUpgradeCommandsExecutor( } } + logger.trace({ addedOrModifiedFiles }, 'Added or modified files'); + logger.debug( + `Checking ${addedOrModifiedFiles.length} added or modified files for post-upgrade changes`, + ); + for (const relativePath of addedOrModifiedFiles) { let fileMatched = false; for (const pattern of fileFilters) { @@ -186,14 +190,20 @@ export async function postUpgradeCommandsExecutor( for (const relativePath of coerceArray(status.deleted)) { for (const pattern of fileFilters) { if (minimatch(pattern, { dot: true }).match(relativePath)) { - logger.debug( - { file: relativePath, pattern }, - 'Post-upgrade file removed', - ); - updatedArtifacts.push({ - type: 'deletion', - path: relativePath, - }); + if ( + !updatedArtifacts.some( + (ua) => ua.path === relativePath && ua.type === 'deletion', + ) + ) { + logger.debug( + { file: relativePath, pattern }, + 'Post-upgrade file removed', + ); + updatedArtifacts.push({ + type: 'deletion', + path: relativePath, + }); + } // If the file is created or modified by a previous post-update command, remove the modification from updatedArtifacts updatedArtifacts = updatedArtifacts.filter( (ua) => !(ua.type === 'addition' && ua.path === relativePath), diff --git a/lib/workers/repository/update/pr/changelog/release-notes.ts b/lib/workers/repository/update/pr/changelog/release-notes.ts index 584aa276af5..b2c04394fd4 100644 --- a/lib/workers/repository/update/pr/changelog/release-notes.ts +++ b/lib/workers/repository/update/pr/changelog/release-notes.ts @@ -366,33 +366,24 @@ export async function getReleaseNotesMd( .replace(regEx(/^\s*#*\s*/), '') .split(' ') .filter(Boolean); - let body = section.replace(regEx(/.*?\n(-{3,}\n)?/), '').trim(); + const body = section.replace(regEx(/.*?\n(-{3,}\n)?/), '').trim(); + const notesSourceUrl = getNotesSourceUrl( + baseUrl, + repository, + project, + changelogFile, + ); + const mdHeadingLink = title + .filter((word) => !isHttpUrl(word)) + .join('-') + .replace(regEx(/[^A-Za-z0-9-]/g), ''); + const url = `${notesSourceUrl}#${mdHeadingLink}`; + // Look for version in title for (const word of title) { if (word.includes(version) && !isHttpUrl(word)) { logger.trace({ body }, 'Found release notes for v' + version); - const notesSourceUrl = getNotesSourceUrl( - baseUrl, - repository, - project, - changelogFile, - ); - const mdHeadingLink = title - .filter((word) => !isHttpUrl(word)) - .join('-') - .replace(regEx(/[^A-Za-z0-9-]/g), ''); - const url = `${notesSourceUrl}#${mdHeadingLink}`; - body = massageBody(body, baseUrl); - if (body?.length) { - try { - body = await linkify(body, { - repository: `${baseUrl}${repository}`, - }); - } catch (err) /* istanbul ignore next */ { - logger.warn({ body, err }, 'linkify error'); - } - } return { - body, + body: await linkifyBody(project, body), url, notesSourceUrl, }; @@ -524,3 +515,20 @@ function getNotesSourceUrl( changelogFile, ); } + +async function linkifyBody( + { baseUrl, repository }: ChangeLogProject, + bodyStr: string, +): Promise { + const body = massageBody(bodyStr, baseUrl); + if (body?.length) { + try { + return await linkify(body, { + repository: `${baseUrl}${repository}`, + }); + } catch (err) /* istanbul ignore next */ { + logger.warn({ body, err }, 'linkify error'); + } + } + return body; +} diff --git a/lib/workers/repository/update/pr/code-owners.spec.ts b/lib/workers/repository/update/pr/code-owners.spec.ts index 3588e0ad35a..1ac5d4a10e1 100644 --- a/lib/workers/repository/update/pr/code-owners.spec.ts +++ b/lib/workers/repository/update/pr/code-owners.spec.ts @@ -1,12 +1,20 @@ import { codeBlock } from 'common-tags'; import { mock } from 'vitest-mock-extended'; import type { Pr } from '../../../../modules/platform'; +import * as gitlab from '../../../../modules/platform/gitlab'; import { codeOwnersForPr } from './code-owners'; -import { fs, git } from '~test/util'; +import { fs, git, platform } from '~test/util'; vi.mock('../../../../util/fs'); describe('workers/repository/update/pr/code-owners', () => { + beforeAll(() => { + Object.defineProperty(platform, 'extractRulesFromCodeOwnersLines', { + value: undefined, + writable: true, + }); + }); + describe('codeOwnersForPr', () => { let pr: Pr; @@ -169,6 +177,125 @@ describe('workers/repository/update/pr/code-owners', () => { }); }); + describe('supports Gitlab sections', () => { + beforeAll(() => { + Object.defineProperty(platform, 'extractRulesFromCodeOwnersLines', { + value: gitlab.extractRulesFromCodeOwnersLines, + writable: true, + }); + }); + + it('returns section code owner', async () => { + fs.readLocalFile.mockResolvedValueOnce( + ['[team] @jimmy', '*'].join('\n'), + ); + git.getBranchFiles.mockResolvedValueOnce(['README.md']); + + const codeOwners = await codeOwnersForPr(pr); + + expect(codeOwners).toEqual(['@jimmy']); + }); + + const codeOwnerFileWithDefaultApproval = codeBlock` + # Required for all files + * @general-approvers + + [Documentation] @docs-team + docs/ + README.md + *.txt + + # Invalid section + Something before [Tests] @tests-team + tests/ + + # Optional section + ^[Optional] @optional-team + optional/ + + [Database] @database-team + model/db/ + config/db/database-setup.md @docs-team + `; + + it('returns code owners of multiple sections', async () => { + fs.readLocalFile.mockResolvedValueOnce( + codeOwnerFileWithDefaultApproval, + ); + git.getBranchFiles.mockResolvedValueOnce([ + 'config/db/database-setup.md', + ]); + + const codeOwners = await codeOwnersForPr(pr); + + expect(codeOwners).toEqual(['@docs-team', '@general-approvers']); + }); + + it('returns default owners when none is explicitly set', async () => { + fs.readLocalFile.mockResolvedValueOnce( + codeOwnerFileWithDefaultApproval, + ); + git.getBranchFiles.mockResolvedValueOnce(['model/db/CHANGELOG.txt']); + + const codeOwners = await codeOwnersForPr(pr); + + expect(codeOwners).toEqual([ + '@database-team', + '@docs-team', + '@general-approvers', + ]); + }); + + it('parses only sections that start at the beginning of a line', async () => { + fs.readLocalFile.mockResolvedValueOnce( + codeOwnerFileWithDefaultApproval, + ); + git.getBranchFiles.mockResolvedValueOnce(['tests/setup.ts']); + + const codeOwners = await codeOwnersForPr(pr); + + expect(codeOwners).not.toInclude('@tests-team'); + }); + + it('returns code owners for optional sections', async () => { + fs.readLocalFile.mockResolvedValueOnce( + codeOwnerFileWithDefaultApproval, + ); + git.getBranchFiles.mockResolvedValueOnce([ + 'optional/optional-file.txt', + ]); + + const codeOwners = await codeOwnersForPr(pr); + + expect(codeOwners).toEqual([ + '@optional-team', + '@docs-team', + '@general-approvers', + ]); + }); + }); + + it.fails('does not parse Gitea regex as Gitlab sections', async () => { + Object.defineProperty(platform, 'extractRulesFromCodeOwnersLines', { + value: undefined, + writable: true, + }); + fs.readLocalFile.mockResolvedValueOnce( + codeBlock` + # This is a regex, not a Gitlab section, so 002-file.md should be assigned to @reviewer-03 + [0-3].*/*.md$ @reviewer-03 + 002-file.md + + [4-9].*/*.md$ @reviewer-49 + `, + ); + git.getBranchFiles.mockResolvedValueOnce(['001-file.md', '002-file.md']); + + const codeOwners = await codeOwnersForPr(pr); + + expect(codeOwners).toEqual(['@reviewer-03']); + }); + it('does not require all files to match a single rule, regression test for #12611', async () => { fs.readLocalFile.mockResolvedValueOnce( codeBlock` diff --git a/lib/workers/repository/update/pr/code-owners.ts b/lib/workers/repository/update/pr/code-owners.ts index b350e82c540..405ff3fc2b1 100644 --- a/lib/workers/repository/update/pr/code-owners.ts +++ b/lib/workers/repository/update/pr/code-owners.ts @@ -1,16 +1,15 @@ import is from '@sindresorhus/is'; import ignore from 'ignore'; import { logger } from '../../../../logger'; -import type { Pr } from '../../../../modules/platform'; +import type { FileOwnerRule, Pr } from '../../../../modules/platform'; +import { platform } from '../../../../modules/platform'; import { readLocalFile } from '../../../../util/fs'; import { getBranchFiles } from '../../../../util/git'; import { newlineRegex, regEx } from '../../../../util/regex'; -interface FileOwnerRule { - usernames: string[]; - pattern: string; - score: number; - match: (path: string) => boolean; +interface FileOwnersScore { + file: string; + userScoreMap: Map; } function extractOwnersFromLine(line: string): FileOwnerRule { @@ -24,11 +23,6 @@ function extractOwnersFromLine(line: string): FileOwnerRule { }; } -interface FileOwnersScore { - file: string; - userScoreMap: Map; -} - function matchFileToOwners( file: string, rules: FileOwnerRule[], @@ -75,6 +69,18 @@ function getOwnerList(filesWithOwners: FileOwnersScore[]): OwnerFileScore[] { })); } +function parseCodeOwnersContent(codeOwnersFile: string): string[] { + return ( + codeOwnersFile + .split(newlineRegex) + // Remove comments + .map((line) => line.split('#')[0]) + // Remove empty lines + .map((line) => line.trim()) + .filter(is.nonEmptyString) + ); +} + export async function codeOwnersForPr(pr: Pr): Promise { logger.debug('Searching for CODEOWNERS file'); try { @@ -102,15 +108,11 @@ export async function codeOwnersForPr(pr: Pr): Promise { } // Convert CODEOWNERS file into list of matching rules - const fileOwnerRules = codeOwnersFile - .split(newlineRegex) - // Remove comments - .map((line) => line.split('#')[0]) - // Remove empty lines - .map((line) => line.trim()) - .filter(is.nonEmptyString) - // Extract pattern & usernames - .map(extractOwnersFromLine); + const cleanedLines = parseCodeOwnersContent(codeOwnersFile); + + const fileOwnerRules = + platform.extractRulesFromCodeOwnersLines?.(cleanedLines) ?? + cleanedLines.map(extractOwnersFromLine); logger.debug( { prFiles, fileOwnerRules }, diff --git a/package.json b/package.json index 6a4f1fc4d25..2c2aee13b77 100644 --- a/package.json +++ b/package.json @@ -50,9 +50,9 @@ "test": "run-s lint test-schema jest", "test-dirty": "git diff --exit-code", "test-e2e": "run-s 'test-e2e:*'", - "test-e2e:pack": "npm pack", - "test-e2e:install": "cd test/e2e && npm install --no-package-lock --prod", - "test-e2e:run": "cd test/e2e && npm test", + "test-e2e:pack": "pnpm pack", + "test-e2e:install": "cd test/e2e && pnpm --ignore-workspace install --no-lockfile --prod", + "test-e2e:run": "cd test/e2e && pnpm test", "test-schema": "run-s create-json-schema", "test:docs": "node --test tools/docs/test/**/*.mjs", "schedule-test-shards": "SCHEDULE_TEST_SHARDS=true tsx tools/test-shards.ts", @@ -143,33 +143,33 @@ }, "volta": { "node": "22.16.0", - "pnpm": "10.11.0" + "pnpm": "10.11.1" }, "dependencies": { - "@aws-sdk/client-codecommit": "3.799.0", - "@aws-sdk/client-ec2": "3.800.0", - "@aws-sdk/client-ecr": "3.800.0", - "@aws-sdk/client-eks": "3.799.0", - "@aws-sdk/client-rds": "3.799.0", - "@aws-sdk/client-s3": "3.800.0", - "@aws-sdk/credential-providers": "3.799.0", + "@aws-sdk/client-codecommit": "3.821.0", + "@aws-sdk/client-ec2": "3.821.0", + "@aws-sdk/client-ecr": "3.821.0", + "@aws-sdk/client-eks": "3.821.0", + "@aws-sdk/client-rds": "3.821.0", + "@aws-sdk/client-s3": "3.821.0", + "@aws-sdk/credential-providers": "3.821.0", "@baszalmstra/rattler": "0.2.1", "@breejs/later": "4.2.0", "@cdktf/hcl2json": "0.20.12", "@opentelemetry/api": "1.9.0", "@opentelemetry/context-async-hooks": "2.0.1", - "@opentelemetry/exporter-trace-otlp-http": "0.201.0", - "@opentelemetry/instrumentation": "0.201.0", - "@opentelemetry/instrumentation-bunyan": "0.47.0", - "@opentelemetry/instrumentation-http": "0.201.0", - "@opentelemetry/resource-detector-aws": "2.1.0", - "@opentelemetry/resource-detector-azure": "0.8.0", - "@opentelemetry/resource-detector-gcp": "0.35.0", + "@opentelemetry/exporter-trace-otlp-http": "0.202.0", + "@opentelemetry/instrumentation": "0.202.0", + "@opentelemetry/instrumentation-bunyan": "0.48.0", + "@opentelemetry/instrumentation-http": "0.202.0", + "@opentelemetry/resource-detector-aws": "2.2.0", + "@opentelemetry/resource-detector-azure": "0.9.0", + "@opentelemetry/resource-detector-gcp": "0.36.0", "@opentelemetry/resource-detector-github": "0.31.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1", "@opentelemetry/sdk-trace-node": "2.0.1", - "@opentelemetry/semantic-conventions": "1.33.0", + "@opentelemetry/semantic-conventions": "1.34.0", "@pnpm/parse-overrides": "1001.0.0", "@qnighy/marshal": "0.1.3", "@renovatebot/detect-tools": "1.1.0", @@ -178,27 +178,26 @@ "@renovatebot/pep440": "4.1.0", "@renovatebot/ruby-semver": "4.0.0", "@sindresorhus/is": "7.0.1", - "@yarnpkg/core": "4.4.1", + "@yarnpkg/core": "4.4.2", "@yarnpkg/parsers": "3.0.3", "agentkeepalive": "4.6.0", - "aggregate-error": "3.1.0", "async-mutex": "0.5.0", "auth-header": "1.0.0", "aws4": "1.13.2", - "azure-devops-node-api": "14.1.0", + "azure-devops-node-api": "15.1.0", "bunyan": "1.8.15", "cacache": "19.0.1", "chalk": "4.1.2", "changelog-filename-regex": "2.0.1", "clean-git-ref": "2.0.1", - "commander": "13.1.0", + "commander": "14.0.0", "conventional-commits-detector": "1.0.3", "croner": "9.0.0", "cronstrue": "2.61.0", "deepmerge": "4.3.1", "dequal": "2.0.3", "detect-indent": "7.0.1", - "diff": "7.0.0", + "diff": "8.0.2", "editorconfig": "2.0.1", "email-addresses": "5.0.0", "emoji-regex": "10.4.0", @@ -217,7 +216,7 @@ "got": "11.8.6", "graph-data-structure": "4.5.0", "handlebars": "4.7.8", - "ignore": "7.0.4", + "ignore": "7.0.5", "ini": "5.0.0", "json-dup-key-validator": "1.0.3", "json-stringify-pretty-compact": "4.0.0", @@ -234,13 +233,13 @@ "nanoid": "5.1.5", "neotraverse": "0.6.18", "node-html-parser": "7.0.1", - "p-all": "3.0.0", - "p-map": "4.0.0", - "p-queue": "6.6.2", - "p-throttle": "4.1.1", + "p-all": "5.0.0", + "p-map": "7.0.3", + "p-queue": "8.1.0", + "p-throttle": "7.0.0", "parse-link-header": "2.0.0", "prettier": "3.5.3", - "protobufjs": "7.5.2", + "protobufjs": "7.5.3", "punycode": "2.3.1", "redis": "4.7.1", "remark": "13.0.0", @@ -261,21 +260,21 @@ "vuln-vects": "1.1.0", "xmldoc": "1.3.0", "yaml": "2.8.0", - "zod": "3.24.4" + "zod": "3.25.50" }, "optionalDependencies": { "better-sqlite3": "11.10.0", "openpgp": "6.1.1", - "re2": "1.21.5" + "re2": "1.22.1" }, "devDependencies": { "@containerbase/eslint-plugin": "1.1.4", - "@eslint/js": "9.26.0", + "@eslint/js": "9.28.0", "@hyrious/marshal": "0.3.3", "@ls-lint/ls-lint": "2.3.0", "@openpgp/web-stream-tools": "0.1.3", "@semantic-release/exec": "7.1.0", - "@smithy/util-stream": "4.2.0", + "@smithy/util-stream": "4.2.2", "@types/auth-header": "1.0.6", "@types/aws4": "1.11.6", "@types/better-sqlite3": "7.6.13", @@ -287,7 +286,6 @@ "@types/clean-git-ref": "2.0.2", "@types/common-tags": "1.8.4", "@types/conventional-commits-detector": "1.0.2", - "@types/diff": "7.0.2", "@types/eslint-config-prettier": "6.11.3", "@types/fs-extra": "11.0.4", "@types/github-url-from-git": "1.5.3", @@ -296,14 +294,14 @@ "@types/js-yaml": "4.0.9", "@types/json-dup-key-validator": "1.0.2", "@types/linkify-markdown": "1.0.3", - "@types/lodash": "4.17.16", + "@types/lodash": "4.17.17", "@types/luxon": "3.6.2", "@types/markdown-it": "14.1.2", "@types/marshal": "0.5.3", "@types/mdast": "3.0.15", "@types/moo": "0.5.10", "@types/ms": "2.1.0", - "@types/node": "22.15.18", + "@types/node": "22.15.29", "@types/parse-link-header": "2.0.3", "@types/punycode": "2.1.4", "@types/semver": "7.7.0", @@ -313,46 +311,46 @@ "@types/tmp": "0.2.6", "@types/validate-npm-package-name": "4.0.2", "@types/xmldoc": "1.1.9", - "@vitest/coverage-v8": "3.1.3", - "@vitest/eslint-plugin": "1.1.44", + "@vitest/coverage-v8": "3.2.1", + "@vitest/eslint-plugin": "1.2.1", "aws-sdk-client-mock": "4.1.0", "callsite": "1.0.0", "common-tags": "1.8.2", - "conventional-changelog-conventionalcommits": "8.0.0", + "conventional-changelog-conventionalcommits": "9.0.0", "emojibase-data": "16.0.3", - "esbuild": "0.25.4", - "eslint": "9.26.0", + "esbuild": "0.25.5", + "eslint": "9.28.0", "eslint-config-prettier": "10.1.5", "eslint-formatter-gha": "1.5.2", - "eslint-import-resolver-typescript": "4.3.4", - "eslint-plugin-import": "2.31.0", + "eslint-import-resolver-typescript": "4.4.2", + "eslint-plugin-import-x": "4.15.0", "eslint-plugin-promise": "7.2.1", "expect-more-jest": "5.5.0", - "globals": "16.0.0", + "globals": "16.2.0", "graphql": "16.11.0", "husky": "9.1.7", - "jest-extended": "4.0.2", - "lint-staged": "15.5.2", - "markdownlint-cli2": "0.17.2", + "jest-extended": "5.0.3", + "lint-staged": "16.1.0", + "markdownlint-cli2": "0.18.1", "memfs": "4.17.2", - "nock": "14.0.4", - "npm-run-all2": "7.0.2", + "nock": "14.0.5", + "npm-run-all2": "8.0.4", "nyc": "17.1.0", "rimraf": "6.0.1", - "semantic-release": "24.2.3", + "semantic-release": "24.2.5", "tar": "7.4.3", "tmp-promise": "3.0.3", "tsx": "4.19.4", "type-fest": "4.41.0", "typescript": "5.8.3", - "typescript-eslint": "8.32.1", + "typescript-eslint": "8.33.1", "unified": "9.2.2", "vite": "6.3.5", "vite-tsconfig-paths": "5.1.4", - "vitest": "3.1.3", + "vitest": "3.2.1", "vitest-mock-extended": "3.1.0" }, - "packageManager": "pnpm@10.11.0", + "packageManager": "pnpm@10.11.1", "files": [ "dist", "renovate-schema.json" @@ -369,7 +367,7 @@ "re2" ], "overrides": { - "esbuild": "0.25.4" + "esbuild": "0.25.5" } } } diff --git a/pdm.lock b/pdm.lock index 605492fd9f4..c6937eecc70 100644 --- a/pdm.lock +++ b/pdm.lock @@ -111,7 +111,7 @@ files = [ [[package]] name = "click" -version = "8.2.0" +version = "8.2.1" requires_python = ">=3.10" summary = "Composable command line interface toolkit" groups = ["default"] @@ -119,8 +119,8 @@ dependencies = [ "colorama; platform_system == \"Windows\"", ] files = [ - {file = "click-8.2.0-py3-none-any.whl", hash = "sha256:6b303f0b2aa85f1cb4e5303078fadcbcd4e476f114fab9b5007005711839325c"}, - {file = "click-8.2.0.tar.gz", hash = "sha256:f5452aeddd9988eefa20f90f05ab66f17fce1ee2a36907fd30b05bbb5953814d"}, + {file = "click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b"}, + {file = "click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202"}, ] [[package]] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c6b8ff8ef3e..832cae5dfb9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,33 +5,33 @@ settings: excludeLinksFromLockfile: false overrides: - esbuild: 0.25.4 + esbuild: 0.25.5 importers: .: dependencies: '@aws-sdk/client-codecommit': - specifier: 3.799.0 - version: 3.799.0 + specifier: 3.821.0 + version: 3.821.0 '@aws-sdk/client-ec2': - specifier: 3.800.0 - version: 3.800.0 + specifier: 3.821.0 + version: 3.821.0 '@aws-sdk/client-ecr': - specifier: 3.800.0 - version: 3.800.0 + specifier: 3.821.0 + version: 3.821.0 '@aws-sdk/client-eks': - specifier: 3.799.0 - version: 3.799.0 + specifier: 3.821.0 + version: 3.821.0 '@aws-sdk/client-rds': - specifier: 3.799.0 - version: 3.799.0 + specifier: 3.821.0 + version: 3.821.0 '@aws-sdk/client-s3': - specifier: 3.800.0 - version: 3.800.0 + specifier: 3.821.0 + version: 3.821.0 '@aws-sdk/credential-providers': - specifier: 3.799.0 - version: 3.799.0 + specifier: 3.821.0 + version: 3.821.0 '@baszalmstra/rattler': specifier: 0.2.1 version: 0.2.1 @@ -48,26 +48,26 @@ importers: specifier: 2.0.1 version: 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/exporter-trace-otlp-http': - specifier: 0.201.0 - version: 0.201.0(@opentelemetry/api@1.9.0) + specifier: 0.202.0 + version: 0.202.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': - specifier: 0.201.0 - version: 0.201.0(@opentelemetry/api@1.9.0) + specifier: 0.202.0 + version: 0.202.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation-bunyan': - specifier: 0.47.0 - version: 0.47.0(@opentelemetry/api@1.9.0) + specifier: 0.48.0 + version: 0.48.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation-http': - specifier: 0.201.0 - version: 0.201.0(@opentelemetry/api@1.9.0) + specifier: 0.202.0 + version: 0.202.0(@opentelemetry/api@1.9.0) '@opentelemetry/resource-detector-aws': - specifier: 2.1.0 - version: 2.1.0(@opentelemetry/api@1.9.0) + specifier: 2.2.0 + version: 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/resource-detector-azure': - specifier: 0.8.0 - version: 0.8.0(@opentelemetry/api@1.9.0) + specifier: 0.9.0 + version: 0.9.0(@opentelemetry/api@1.9.0) '@opentelemetry/resource-detector-gcp': - specifier: 0.35.0 - version: 0.35.0(@opentelemetry/api@1.9.0)(encoding@0.1.13) + specifier: 0.36.0 + version: 0.36.0(@opentelemetry/api@1.9.0)(encoding@0.1.13) '@opentelemetry/resource-detector-github': specifier: 0.31.0 version: 0.31.0(@opentelemetry/api@1.9.0) @@ -81,8 +81,8 @@ importers: specifier: 2.0.1 version: 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': - specifier: 1.33.0 - version: 1.33.0 + specifier: 1.34.0 + version: 1.34.0 '@pnpm/parse-overrides': specifier: 1001.0.0 version: 1001.0.0 @@ -108,17 +108,14 @@ importers: specifier: 7.0.1 version: 7.0.1 '@yarnpkg/core': - specifier: 4.4.1 - version: 4.4.1(typanion@3.14.0) + specifier: 4.4.2 + version: 4.4.2(typanion@3.14.0) '@yarnpkg/parsers': specifier: 3.0.3 version: 3.0.3 agentkeepalive: specifier: 4.6.0 version: 4.6.0 - aggregate-error: - specifier: 3.1.0 - version: 3.1.0 async-mutex: specifier: 0.5.0 version: 0.5.0 @@ -129,8 +126,8 @@ importers: specifier: 1.13.2 version: 1.13.2 azure-devops-node-api: - specifier: 14.1.0 - version: 14.1.0 + specifier: 15.1.0 + version: 15.1.0 bunyan: specifier: 1.8.15 version: 1.8.15 @@ -147,8 +144,8 @@ importers: specifier: 2.0.1 version: 2.0.1 commander: - specifier: 13.1.0 - version: 13.1.0 + specifier: 14.0.0 + version: 14.0.0 conventional-commits-detector: specifier: 1.0.3 version: 1.0.3 @@ -168,8 +165,8 @@ importers: specifier: 7.0.1 version: 7.0.1 diff: - specifier: 7.0.0 - version: 7.0.0 + specifier: 8.0.2 + version: 8.0.2 editorconfig: specifier: 2.0.1 version: 2.0.1 @@ -225,8 +222,8 @@ importers: specifier: 4.7.8 version: 4.7.8 ignore: - specifier: 7.0.4 - version: 7.0.4 + specifier: 7.0.5 + version: 7.0.5 ini: specifier: 5.0.0 version: 5.0.0 @@ -276,17 +273,17 @@ importers: specifier: 7.0.1 version: 7.0.1 p-all: - specifier: 3.0.0 - version: 3.0.0 + specifier: 5.0.0 + version: 5.0.0 p-map: - specifier: 4.0.0 - version: 4.0.0 + specifier: 7.0.3 + version: 7.0.3 p-queue: - specifier: 6.6.2 - version: 6.6.2 + specifier: 8.1.0 + version: 8.1.0 p-throttle: - specifier: 4.1.1 - version: 4.1.1 + specifier: 7.0.0 + version: 7.0.0 parse-link-header: specifier: 2.0.0 version: 2.0.0 @@ -294,8 +291,8 @@ importers: specifier: 3.5.3 version: 3.5.3 protobufjs: - specifier: 7.5.2 - version: 7.5.2 + specifier: 7.5.3 + version: 7.5.3 punycode: specifier: 2.3.1 version: 2.3.1 @@ -357,15 +354,15 @@ importers: specifier: 2.8.0 version: 2.8.0 zod: - specifier: 3.24.4 - version: 3.24.4 + specifier: 3.25.50 + version: 3.25.50 devDependencies: '@containerbase/eslint-plugin': specifier: 1.1.4 - version: 1.1.4(eslint-plugin-import@2.31.0)(eslint-plugin-promise@7.2.1(eslint@9.26.0))(eslint@9.26.0) + version: 1.1.4(eslint-plugin-import@2.31.0)(eslint-plugin-promise@7.2.1(eslint@9.28.0))(eslint@9.28.0) '@eslint/js': - specifier: 9.26.0 - version: 9.26.0 + specifier: 9.28.0 + version: 9.28.0 '@hyrious/marshal': specifier: 0.3.3 version: 0.3.3 @@ -377,10 +374,10 @@ importers: version: 0.1.3(typescript@5.8.3) '@semantic-release/exec': specifier: 7.1.0 - version: 7.1.0(semantic-release@24.2.3(typescript@5.8.3)) + version: 7.1.0(semantic-release@24.2.5(typescript@5.8.3)) '@smithy/util-stream': - specifier: 4.2.0 - version: 4.2.0 + specifier: 4.2.2 + version: 4.2.2 '@types/auth-header': specifier: 1.0.6 version: 1.0.6 @@ -414,9 +411,6 @@ importers: '@types/conventional-commits-detector': specifier: 1.0.2 version: 1.0.2 - '@types/diff': - specifier: 7.0.2 - version: 7.0.2 '@types/eslint-config-prettier': specifier: 6.11.3 version: 6.11.3 @@ -442,8 +436,8 @@ importers: specifier: 1.0.3 version: 1.0.3 '@types/lodash': - specifier: 4.17.16 - version: 4.17.16 + specifier: 4.17.17 + version: 4.17.17 '@types/luxon': specifier: 3.6.2 version: 3.6.2 @@ -463,8 +457,8 @@ importers: specifier: 2.1.0 version: 2.1.0 '@types/node': - specifier: 22.15.18 - version: 22.15.18 + specifier: 22.15.29 + version: 22.15.29 '@types/parse-link-header': specifier: 2.0.3 version: 2.0.3 @@ -493,11 +487,11 @@ importers: specifier: 1.1.9 version: 1.1.9 '@vitest/coverage-v8': - specifier: 3.1.3 - version: 3.1.3(vitest@3.1.3(@types/debug@4.1.12)(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0)) + specifier: 3.2.1 + version: 3.2.1(vitest@3.2.1(@types/debug@4.1.12)(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0)) '@vitest/eslint-plugin': - specifier: 1.1.44 - version: 1.1.44(@typescript-eslint/utils@8.32.1(eslint@9.26.0)(typescript@5.8.3))(eslint@9.26.0)(typescript@5.8.3)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0)) + specifier: 1.2.1 + version: 1.2.1(eslint@9.28.0)(typescript@5.8.3)(vitest@3.2.1(@types/debug@4.1.12)(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0)) aws-sdk-client-mock: specifier: 4.1.0 version: 4.1.0 @@ -508,38 +502,38 @@ importers: specifier: 1.8.2 version: 1.8.2 conventional-changelog-conventionalcommits: - specifier: 8.0.0 - version: 8.0.0 + specifier: 9.0.0 + version: 9.0.0 emojibase-data: specifier: 16.0.3 version: 16.0.3(emojibase@16.0.0) esbuild: - specifier: 0.25.4 - version: 0.25.4 + specifier: 0.25.5 + version: 0.25.5 eslint: - specifier: 9.26.0 - version: 9.26.0 + specifier: 9.28.0 + version: 9.28.0 eslint-config-prettier: specifier: 10.1.5 - version: 10.1.5(eslint@9.26.0) + version: 10.1.5(eslint@9.28.0) eslint-formatter-gha: specifier: 1.5.2 version: 1.5.2 eslint-import-resolver-typescript: - specifier: 4.3.4 - version: 4.3.4(eslint-plugin-import@2.31.0)(eslint@9.26.0) - eslint-plugin-import: - specifier: 2.31.0 - version: 2.31.0(@typescript-eslint/parser@8.32.1(eslint@9.26.0)(typescript@5.8.3))(eslint-import-resolver-typescript@4.3.4)(eslint@9.26.0) + specifier: 4.4.2 + version: 4.4.2(eslint-plugin-import-x@4.15.0(@typescript-eslint/utils@8.33.1(eslint@9.28.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.28.0))(eslint-plugin-import@2.31.0)(eslint@9.28.0) + eslint-plugin-import-x: + specifier: 4.15.0 + version: 4.15.0(@typescript-eslint/utils@8.33.1(eslint@9.28.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.28.0) eslint-plugin-promise: specifier: 7.2.1 - version: 7.2.1(eslint@9.26.0) + version: 7.2.1(eslint@9.28.0) expect-more-jest: specifier: 5.5.0 version: 5.5.0 globals: - specifier: 16.0.0 - version: 16.0.0 + specifier: 16.2.0 + version: 16.2.0 graphql: specifier: 16.11.0 version: 16.11.0 @@ -547,23 +541,23 @@ importers: specifier: 9.1.7 version: 9.1.7 jest-extended: - specifier: 4.0.2 - version: 4.0.2 + specifier: 5.0.3 + version: 5.0.3 lint-staged: - specifier: 15.5.2 - version: 15.5.2 + specifier: 16.1.0 + version: 16.1.0 markdownlint-cli2: - specifier: 0.17.2 - version: 0.17.2 + specifier: 0.18.1 + version: 0.18.1 memfs: specifier: 4.17.2 version: 4.17.2 nock: - specifier: 14.0.4 - version: 14.0.4 + specifier: 14.0.5 + version: 14.0.5 npm-run-all2: - specifier: 7.0.2 - version: 7.0.2 + specifier: 8.0.4 + version: 8.0.4 nyc: specifier: 17.1.0 version: 17.1.0 @@ -571,8 +565,8 @@ importers: specifier: 6.0.1 version: 6.0.1 semantic-release: - specifier: 24.2.3 - version: 24.2.3(typescript@5.8.3) + specifier: 24.2.5 + version: 24.2.5(typescript@5.8.3) tar: specifier: 7.4.3 version: 7.4.3 @@ -589,23 +583,23 @@ importers: specifier: 5.8.3 version: 5.8.3 typescript-eslint: - specifier: 8.32.1 - version: 8.32.1(eslint@9.26.0)(typescript@5.8.3) + specifier: 8.33.1 + version: 8.33.1(eslint@9.28.0)(typescript@5.8.3) unified: specifier: 9.2.2 version: 9.2.2 vite: specifier: 6.3.5 - version: 6.3.5(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0) + version: 6.3.5(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0) vite-tsconfig-paths: specifier: 5.1.4 - version: 5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0)) + version: 5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0)) vitest: - specifier: 3.1.3 - version: 3.1.3(@types/debug@4.1.12)(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0) + specifier: 3.2.1 + version: 3.2.1(@types/debug@4.1.12)(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0) vitest-mock-extended: specifier: 3.1.0 - version: 3.1.0(typescript@5.8.3)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0)) + version: 3.1.0(typescript@5.8.3)(vitest@3.2.1(@types/debug@4.1.12)(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0)) optionalDependencies: better-sqlite3: specifier: 11.10.0 @@ -614,8 +608,8 @@ importers: specifier: 6.1.1 version: 6.1.1 re2: - specifier: 1.21.5 - version: 1.21.5 + specifier: 1.22.1 + version: 1.22.1 packages: @@ -649,167 +643,167 @@ packages: '@aws-crypto/util@5.2.0': resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} - '@aws-sdk/client-codecommit@3.799.0': - resolution: {integrity: sha512-8SUlnZcT2U42MczTBHwhBBwO9cQgh/0O8IohihaoFsrWpfC3TGis5JJnTiw52KULEJbMPPOCdCjkIbNOttu3kA==} + '@aws-sdk/client-codecommit@3.821.0': + resolution: {integrity: sha512-WytlzAmLH+cSABuP/7WXIw4M9ml2iAZ76N2JLwLxQbSnOF8PR9pfdJK8DqK4rF3yVQAvS/VtAJlezhx2QkKlfQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/client-cognito-identity@3.799.0': - resolution: {integrity: sha512-gg1sncxYDpYWetey3v/nw9zSkL/Vj2potpeO9sYWY2brcm8SbGh106I6IM/gX6KnY9Y2Bre8xb+JoZGz6ntcnw==} + '@aws-sdk/client-cognito-identity@3.821.0': + resolution: {integrity: sha512-c6TpvrRAb4hVcbGMCPjTWU2IRNBzfEz2qZ1v6DGViW0i8vN4+zXY/DcVOL2P3ZA9MDXjFRiiA8RdIy1/zsi3YQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/client-ec2@3.800.0': - resolution: {integrity: sha512-p9W7MkOnNgaQtV+rLGMPTP4xJ2GCHusKt9tWzG64H8ZDc6H9rTopVKUSw+4uAHKJt8Bgg1NUuKL1YR8z9gb86Q==} + '@aws-sdk/client-ec2@3.821.0': + resolution: {integrity: sha512-OW7zdoViAL9Wd28Mfu7AikiuTRUqZnWIsoAim90IcHTA6cxkiEGW5TitOatBlXoepvu8NpGhr8tDPbaNLvmgCA==} engines: {node: '>=18.0.0'} - '@aws-sdk/client-ecr@3.800.0': - resolution: {integrity: sha512-vNkoc2qWwmypRXvHX0wI6+B20ry7mwClDRsEPBILgxW6T535k4cv4uCIAWhNioVyhmZtn4NPMmmlAKAUIGEvmw==} + '@aws-sdk/client-ecr@3.821.0': + resolution: {integrity: sha512-TR5BAsiVbrA7Y9BDlyNJh6Ksbu0mRE92/yDDAcGJnkKrfsyPwI7Rhf1qGF7Ew4g6CEx22TapGB2nSCXoavdvCw==} engines: {node: '>=18.0.0'} - '@aws-sdk/client-eks@3.799.0': - resolution: {integrity: sha512-sOIEdn2/rz32bzHfYQqFHh6hQ0KpDcnlr959MtTyoGGu4ZcJd575SoHqDf4epxdUeWb0rL2mZ11AnXaQdLY7pw==} + '@aws-sdk/client-eks@3.821.0': + resolution: {integrity: sha512-brbLTlhgaygJsyCJDGKdkVm+SDpEdzKcp5mVmKsazNcbQEcHS3lcTUJ11EhmIvR3LKgrVavc+Cf7W/hMSflS1w==} engines: {node: '>=18.0.0'} - '@aws-sdk/client-rds@3.799.0': - resolution: {integrity: sha512-NtDLPt5yKqXFiv3vygguG6AKdSTIoNqfFIlpyrZKS9MvyfFCUJraa5me5FZ9wfRsWo1VD3at4MuxxFJJAMDirA==} + '@aws-sdk/client-rds@3.821.0': + resolution: {integrity: sha512-M1huTDvS6g6PrrswHDgdZYqr6nSdY9S6UVswMK6TCJUirnFaTSyLYcVOi0c3zKHjbg1iGHvAjB9MOgAf5cCKvQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/client-s3@3.800.0': - resolution: {integrity: sha512-SE33Y1kbeErd5h7KlmgWs1iJ0kKi+/t9XilI6NPIb5J5TmPKVUT5gf3ywa9ZSaq1x7LiAbICm0IPEz6k0WEBbQ==} + '@aws-sdk/client-s3@3.821.0': + resolution: {integrity: sha512-enlFiONQD+oCaV+C6hMsAJvyQRT3wZmCtXXq7qjxX8BiLgXsHQ9HHS+Nhoq08Ya6mtd1Y1qHOOYpnD8yyUzTMQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/client-sso@3.799.0': - resolution: {integrity: sha512-/i/LG7AiWPmPxKCA2jnR2zaf7B3HYSTbxaZI21ElIz9wASlNAsKr8CnLY7qb50kOyXiNfQ834S5Q3Gl8dX9o3Q==} + '@aws-sdk/client-sso@3.821.0': + resolution: {integrity: sha512-aDEBZUKUd/+Tvudi0d9KQlqt2OW2P27LATZX0jkNC8yVk4145bAPS04EYoqdKLuyUn/U33DibEOgKUpxZB12jQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/core@3.799.0': - resolution: {integrity: sha512-hkKF3Zpc6+H8GI1rlttYVRh9uEE77cqAzLmLpY3iu7sql8cZgPERRBfaFct8p1SaDyrksLNiboD1vKW58mbsYg==} + '@aws-sdk/core@3.821.0': + resolution: {integrity: sha512-8eB3wKbmfciQFmxFq7hAjy7mXdUs7vBOR5SwT0ZtQBg0Txc18Lc9tMViqqdO6/KU7OukA6ib2IAVSjIJJEN7FQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-cognito-identity@3.799.0': - resolution: {integrity: sha512-qHOqGsvt/z1bvjJRzndW8VaRfbGBhoETZpoRYNbfCbrNH2IRM98KRUlYH1EJ1wFFkT0gUDJr+oIOUCvRlgRW1Q==} + '@aws-sdk/credential-provider-cognito-identity@3.821.0': + resolution: {integrity: sha512-8ZdFwmSxvQv8QindA0DJ3YUT9FD8T9sA5hQWp3B9+Znkze29IiIadnsXY0Heo2/FOFygxh8jRXiCWEie7/YpzA==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-env@3.799.0': - resolution: {integrity: sha512-vT/SSWtbUIOW/U21qgEySmmO44SFWIA7WeQPX1OrI8WJ5n7OEI23JWLHjLvHTkYmuZK6z1rPcv7HzRgmuGRibA==} + '@aws-sdk/credential-provider-env@3.821.0': + resolution: {integrity: sha512-C+s/A72pd7CXwEsJj9+Uq9T726iIfIF18hGRY8o82xcIEfOyakiPnlisku8zZOaAu+jm0CihbbYN4NyYNQ+HZQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-http@3.799.0': - resolution: {integrity: sha512-2CjBpOWmhaPAExOgHnIB5nOkS5ef+mfRlJ1JC4nsnjAx0nrK4tk0XRE0LYz11P3+ue+a86cU8WTmBo+qjnGxPQ==} + '@aws-sdk/credential-provider-http@3.821.0': + resolution: {integrity: sha512-gIRzTLnAsRfRSNarCag7G7rhcHagz4x5nNTWRihQs5cwTOghEExDy7Tj5m4TEkv3dcTAsNn+l4tnR4nZXo6R+Q==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-ini@3.799.0': - resolution: {integrity: sha512-M9ubILFxerqw4QJwk83MnjtZyoA2eNCiea5V+PzZeHlwk2PON/EnawKqy65x9/hMHGoSvvNuby7iMAmPptu7yw==} + '@aws-sdk/credential-provider-ini@3.821.0': + resolution: {integrity: sha512-VRTrmsca8kBHtY1tTek1ce+XkK/H0fzodBKcilM/qXjTyumMHPAzVAxKZfSvGC+28/pXyQzhOEyxZfw7giCiWA==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-node@3.799.0': - resolution: {integrity: sha512-nd9fSJc0wUlgKUkIr2ldJhcIIrzJFS29AGZoyY22J3xih63nNDv61eTGVMsDZzHlV21XzMlPEljTR7axiimckg==} + '@aws-sdk/credential-provider-node@3.821.0': + resolution: {integrity: sha512-oBgbcgOXWMgknAfhIdTeHSSVIv+k2LXN9oTbxu1r++o4WWBWrEQ8mHU0Zo9dfr7Uaoqi3pezYZznsBkXnMLEOg==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-process@3.799.0': - resolution: {integrity: sha512-g8jmNs2k98WNHMYcea1YKA+7ao2Ma4w0P42Dz4YpcI155pQHxHx25RwbOG+rsAKuo3bKwkW53HVE/ZTKhcWFgw==} + '@aws-sdk/credential-provider-process@3.821.0': + resolution: {integrity: sha512-e18ucfqKB3ICNj5RP/FEdvUfhVK6E9MALOsl8pKP13mwegug46p/1BsZWACD5n+Zf9ViiiHxIO7td03zQixfwA==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-sso@3.799.0': - resolution: {integrity: sha512-lQv27QkNU9FJFZqEf5DIEN3uXEN409Iaym9WJzhOouGtxvTIAWiD23OYh1u8PvBdrordJGS2YddfQvhcmq9akw==} + '@aws-sdk/credential-provider-sso@3.821.0': + resolution: {integrity: sha512-Dt+pheBLom4O/egO4L75/72k9C1qtUOLl0F0h6lmqZe4Mvhz+wDtjoO/MdGC/P1q0kcIX/bBKr0NQ3cIvAH8pA==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-web-identity@3.799.0': - resolution: {integrity: sha512-8k1i9ut+BEg0QZ+I6UQMxGNR1T8paLmAOAZXU+nLQR0lcxS6lr8v+dqofgzQPuHLBkWNCr1Av1IKeL3bJjgU7g==} + '@aws-sdk/credential-provider-web-identity@3.821.0': + resolution: {integrity: sha512-FF5wnRJkxSQaCVVvWNv53K1MhTMgH8d+O+MHTbkv51gVIgVATrtfFQMKBLcEAxzXrgAliIO3LiNv+1TqqBZ+BA==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-providers@3.799.0': - resolution: {integrity: sha512-Gk10skoEri6zsCPxn34Zpu6Z1B5R3RLwqDw1krNl+B1P749gB6i7XULXZUOotqpum0T0q4euOwAB8XWuTOkKew==} + '@aws-sdk/credential-providers@3.821.0': + resolution: {integrity: sha512-ZkV7KlKD+rSW/AP5zjSgMi+0xJ5TL5J6XVaP3IG5qyqBYTREJ8DbB/9YVUpYt2qtzpWUh/K43nmDEyfLd2YJog==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-bucket-endpoint@3.775.0': - resolution: {integrity: sha512-qogMIpVChDYr4xiUNC19/RDSw/sKoHkAhouS6Skxiy6s27HBhow1L3Z1qVYXuBmOZGSWPU0xiyZCvOyWrv9s+Q==} + '@aws-sdk/middleware-bucket-endpoint@3.821.0': + resolution: {integrity: sha512-cebgeytKlWOgGczLo3BPvNY9XlzAzGZQANSysgJ2/8PSldmUpXRIF+GKPXDVhXeInWYHIfB8zZi3RqrPoXcNYQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-expect-continue@3.775.0': - resolution: {integrity: sha512-Apd3owkIeUW5dnk3au9np2IdW2N0zc9NjTjHiH+Mx3zqwSrc+m+ANgJVgk9mnQjMzU/vb7VuxJ0eqdEbp5gYsg==} + '@aws-sdk/middleware-expect-continue@3.821.0': + resolution: {integrity: sha512-zAOoSZKe1njOrtynvK6ZORU57YGv5I7KP4+rwOvUN3ZhJbQ7QPf8gKtFUCYAPRMegaXCKF/ADPtDZBAmM+zZ9g==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-flexible-checksums@3.799.0': - resolution: {integrity: sha512-vBIAdDl2neaFiUMxyr7dAtX7m9Iw5c0bz7OirD0JGW0nYn0mBcqKpFZEU75ewA5p2+Cm7RQDdt6099ne3gj0WA==} + '@aws-sdk/middleware-flexible-checksums@3.821.0': + resolution: {integrity: sha512-C56sBHXq1fEsLfIAup+w/7SKtb6d8Mb3YBec94r2ludVn1s3ypYWRovFE/6VhUzvwUbTQaxfrA2ewy5GQ1/DJQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-host-header@3.775.0': - resolution: {integrity: sha512-tkSegM0Z6WMXpLB8oPys/d+umYIocvO298mGvcMCncpRl77L9XkvSLJIFzaHes+o7djAgIduYw8wKIMStFss2w==} + '@aws-sdk/middleware-host-header@3.821.0': + resolution: {integrity: sha512-xSMR+sopSeWGx5/4pAGhhfMvGBHioVBbqGvDs6pG64xfNwM5vq5s5v6D04e2i+uSTj4qGa71dLUs5I0UzAK3sw==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-location-constraint@3.775.0': - resolution: {integrity: sha512-8TMXEHZXZTFTckQLyBT5aEI8fX11HZcwZseRifvBKKpj0RZDk4F0EEYGxeNSPpUQ7n+PRWyfAEnnZNRdAj/1NQ==} + '@aws-sdk/middleware-location-constraint@3.821.0': + resolution: {integrity: sha512-sKrm80k0t3R0on8aA/WhWFoMaAl4yvdk+riotmMElLUpcMcRXAd1+600uFVrxJqZdbrKQ0mjX0PjT68DlkYXLg==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-logger@3.775.0': - resolution: {integrity: sha512-FaxO1xom4MAoUJsldmR92nT1G6uZxTdNYOFYtdHfd6N2wcNaTuxgjIvqzg5y7QIH9kn58XX/dzf1iTjgqUStZw==} + '@aws-sdk/middleware-logger@3.821.0': + resolution: {integrity: sha512-0cvI0ipf2tGx7fXYEEN5fBeZDz2RnHyb9xftSgUsEq7NBxjV0yTZfLJw6Za5rjE6snC80dRN8+bTNR1tuG89zA==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-recursion-detection@3.775.0': - resolution: {integrity: sha512-GLCzC8D0A0YDG5u3F5U03Vb9j5tcOEFhr8oc6PDk0k0vm5VwtZOE6LvK7hcCSoAB4HXyOUM0sQuXrbaAh9OwXA==} + '@aws-sdk/middleware-recursion-detection@3.821.0': + resolution: {integrity: sha512-efmaifbhBoqKG3bAoEfDdcM8hn1psF+4qa7ykWuYmfmah59JBeqHLfz5W9m9JoTwoKPkFcVLWZxnyZzAnVBOIg==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-sdk-ec2@3.798.0': - resolution: {integrity: sha512-LcpkQX8okL4kH0hoOtAG9n1ru7+DAKZf9Rp3zJKmrbTdDom13bUwnzMETgxOXnIcPBHZasEgV5cBc0PP8EookQ==} + '@aws-sdk/middleware-sdk-ec2@3.821.0': + resolution: {integrity: sha512-YTeuYr9VtwelYGLGSevesAz3+KMtTvZawXn3gM2CweDnphGuR55YYciFvO64+zJL2JeTmj766l1aGH6Ra6JKAg==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-sdk-rds@3.798.0': - resolution: {integrity: sha512-YwnIvqbR2Ip4mx371CNXQx/dD/eQNEyh6qy16fBdckVMY/6NSnnf6qyc1K/1n0hXQ+WHcmLbDPDVrMR2j0xgBQ==} + '@aws-sdk/middleware-sdk-rds@3.821.0': + resolution: {integrity: sha512-L1+vatNONHLa9dMyEGBlcYitMzhm5z6wbwlyM2FfIaajnGUafHENCKIghSc0ZRJCdVe/qfT4NhptHQeX5xPFqA==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-sdk-s3@3.799.0': - resolution: {integrity: sha512-Zwdge5NArgcJwPuGZwgfXY6XXkWEBmMS9dqu5g3DcfHmZUuSjQUqmOsDdSZlE3RFHrDAEbuGQlrFUE8zuwdKQA==} + '@aws-sdk/middleware-sdk-s3@3.821.0': + resolution: {integrity: sha512-D469De1d4NtcCTVHzUL2Q0tGvPFr7mk2j4+oCYpVyd5awSSOyl8Adkxse8qayZj9ROmuMlsoU5VhBvcc9Hoo2w==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-ssec@3.775.0': - resolution: {integrity: sha512-Iw1RHD8vfAWWPzBBIKaojO4GAvQkHOYIpKdAfis/EUSUmSa79QsnXnRqsdcE0mCB0Ylj23yi+ah4/0wh9FsekA==} + '@aws-sdk/middleware-ssec@3.821.0': + resolution: {integrity: sha512-YYi1Hhr2AYiU/24cQc8HIB+SWbQo6FBkMYojVuz/zgrtkFmALxENGF/21OPg7f/QWd+eadZJRxCjmRwh5F2Cxg==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-user-agent@3.799.0': - resolution: {integrity: sha512-TropQZanbOTxa+p+Nl4fWkzlRhgFwDfW+Wb6TR3jZN7IXHNlPpgGFpdrgvBExhW/RBhqr+94OsR8Ou58lp3hhA==} + '@aws-sdk/middleware-user-agent@3.821.0': + resolution: {integrity: sha512-rw8q3TxygMg3VrofN04QyWVCCyGwz3bVthYmBZZseENPWG3Krz1OCKcyqjkTcAxMQlEywOske+GIiOasGKnJ3w==} engines: {node: '>=18.0.0'} - '@aws-sdk/nested-clients@3.799.0': - resolution: {integrity: sha512-zILlWh7asrcQG9JYMYgnvEQBfwmWKfED0yWCf3UNAmQcfS9wkCAWCgicNy/y5KvNvEYnHidsU117STtyuUNG5g==} + '@aws-sdk/nested-clients@3.821.0': + resolution: {integrity: sha512-2IuHcUsWw44ftSEDYU4dvktTEqgyDvkOcfpoGC/UmT4Qo6TVCP3U5tWEGpNK9nN+7nLvekruxxG/jaMt5/oWVw==} engines: {node: '>=18.0.0'} - '@aws-sdk/region-config-resolver@3.775.0': - resolution: {integrity: sha512-40iH3LJjrQS3LKUJAl7Wj0bln7RFPEvUYKFxtP8a+oKFDO0F65F52xZxIJbPn6sHkxWDAnZlGgdjZXM3p2g5wQ==} + '@aws-sdk/region-config-resolver@3.821.0': + resolution: {integrity: sha512-t8og+lRCIIy5nlId0bScNpCkif8sc0LhmtaKsbm0ZPm3sCa/WhCbSZibjbZ28FNjVCV+p0D9RYZx0VDDbtWyjw==} engines: {node: '>=18.0.0'} - '@aws-sdk/signature-v4-multi-region@3.800.0': - resolution: {integrity: sha512-c71wZuiSUHNFCvcuqOv3jbqP+NquB2YKN4qX90OwYXEqUKn8F8fKJPpjjHjz1eK6qWKtECR4V/NTno2P70Yz/Q==} + '@aws-sdk/signature-v4-multi-region@3.821.0': + resolution: {integrity: sha512-UjfyVR/PB/TP9qe1x6tv7qLlD8/0eiSLDkkBUgBmddkkX0l17oy9c2SJINuV3jy1fbx6KORZ6gyvRZ2nb8dtMw==} engines: {node: '>=18.0.0'} - '@aws-sdk/token-providers@3.799.0': - resolution: {integrity: sha512-/8iDjnsJs/D8AhGbDAmdF5oSHzE4jsDsM2RIIxmBAKTZXkaaclQBNX9CmAqLKQmO3IUMZsDH2KENHLVAk/N/mw==} + '@aws-sdk/token-providers@3.821.0': + resolution: {integrity: sha512-qJ7wgKhdxGbPg718zWXbCYKDuSWZNU3TSw64hPRW6FtbZrIyZxObpiTKC6DKwfsVoZZhHEoP/imGykN1OdOTJA==} engines: {node: '>=18.0.0'} - '@aws-sdk/types@3.775.0': - resolution: {integrity: sha512-ZoGKwa4C9fC9Av6bdfqcW6Ix5ot05F/S4VxWR2nHuMv7hzfmAjTOcUiWT7UR4hM/U0whf84VhDtXN/DWAk52KA==} + '@aws-sdk/types@3.821.0': + resolution: {integrity: sha512-Znroqdai1a90TlxGaJ+FK1lwC0fHpo97Xjsp5UKGR5JODYm7f9+/fF17ebO1KdoBr/Rm0UIFiF5VmI8ts9F1eA==} engines: {node: '>=18.0.0'} - '@aws-sdk/util-arn-parser@3.723.0': - resolution: {integrity: sha512-ZhEfvUwNliOQROcAk34WJWVYTlTa4694kSVhDSjW6lE1bMataPnIN8A0ycukEzBXmd8ZSoBcQLn6lKGl7XIJ5w==} + '@aws-sdk/util-arn-parser@3.804.0': + resolution: {integrity: sha512-wmBJqn1DRXnZu3b4EkE6CWnoWMo1ZMvlfkqU5zPz67xx1GMaXlDCchFvKAXMjk4jn/L1O3tKnoFDNsoLV1kgNQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/util-endpoints@3.787.0': - resolution: {integrity: sha512-fd3zkiOkwnbdbN0Xp9TsP5SWrmv0SpT70YEdbb8wAj2DWQwiCmFszaSs+YCvhoCdmlR3Wl9Spu0pGpSAGKeYvQ==} + '@aws-sdk/util-endpoints@3.821.0': + resolution: {integrity: sha512-Uknt/zUZnLE76zaAAPEayOeF5/4IZ2puTFXvcSCWHsi9m3tqbb9UozlnlVqvCZLCRWfQryZQoG2W4XSS3qgk5A==} engines: {node: '>=18.0.0'} - '@aws-sdk/util-format-url@3.775.0': - resolution: {integrity: sha512-Nw4nBeyCbWixoGh8NcVpa/i8McMA6RXJIjQFyloJLaPr7CPquz7ZbSl0MUWMFVwP/VHaJ7B+lNN3Qz1iFCEP/Q==} + '@aws-sdk/util-format-url@3.821.0': + resolution: {integrity: sha512-h+xqmPToxDrZ0a7rxE1a8Oh4zpWfZe9oiQUphGtfiGFA6j75UiURH5J3MmGHa/G4t15I3iLLbYtUXxvb1i7evg==} engines: {node: '>=18.0.0'} '@aws-sdk/util-locate-window@3.804.0': resolution: {integrity: sha512-zVoRfpmBVPodYlnMjgVjfGoEZagyRF5IPn3Uo6ZvOZp24chnW/FRstH7ESDHDDRga4z3V+ElUQHKpFDXWyBW5A==} engines: {node: '>=18.0.0'} - '@aws-sdk/util-user-agent-browser@3.775.0': - resolution: {integrity: sha512-txw2wkiJmZKVdDbscK7VBK+u+TJnRtlUjRTLei+elZg2ADhpQxfVAQl436FUeIv6AhB/oRHW6/K/EAGXUSWi0A==} + '@aws-sdk/util-user-agent-browser@3.821.0': + resolution: {integrity: sha512-irWZHyM0Jr1xhC+38OuZ7JB6OXMLPZlj48thElpsO1ZSLRkLZx5+I7VV6k3sp2yZ7BYbKz/G2ojSv4wdm7XTLw==} - '@aws-sdk/util-user-agent-node@3.799.0': - resolution: {integrity: sha512-iXBk38RbIWPF5Nq9O4AnktORAzXovSVqWYClvS1qbE7ILsnTLJbagU9HlU25O2iV5COVh1qZkwuP5NHQ2yTEyw==} + '@aws-sdk/util-user-agent-node@3.821.0': + resolution: {integrity: sha512-YwMXc9EvuzJgnLBTyiQly2juPujXwDgcMHB0iSN92tHe7Dd1jJ1feBmTgdClaaqCeHFUaFpw+3JU/ZUJ6LjR+A==} engines: {node: '>=18.0.0'} peerDependencies: aws-crt: '>=1.0.0' @@ -817,24 +811,24 @@ packages: aws-crt: optional: true - '@aws-sdk/xml-builder@3.775.0': - resolution: {integrity: sha512-b9NGO6FKJeLGYnV7Z1yvcP1TNU4dkD5jNsLWOF1/sygZoASaQhNOlaiJ/1OH331YQ1R1oWk38nBb0frsYkDsOQ==} + '@aws-sdk/xml-builder@3.821.0': + resolution: {integrity: sha512-DIIotRnefVL6DiaHtO6/21DhJ4JZnnIwdNbpwiAhdt/AVbttcE4yw925gsjur0OGv5BTYXQXU3YnANBYnZjuQA==} engines: {node: '>=18.0.0'} '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.27.2': - resolution: {integrity: sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==} + '@babel/compat-data@7.27.5': + resolution: {integrity: sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==} engines: {node: '>=6.9.0'} - '@babel/core@7.27.1': - resolution: {integrity: sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==} + '@babel/core@7.27.4': + resolution: {integrity: sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==} engines: {node: '>=6.9.0'} - '@babel/generator@7.27.1': - resolution: {integrity: sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==} + '@babel/generator@7.27.5': + resolution: {integrity: sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==} engines: {node: '>=6.9.0'} '@babel/helper-compilation-targets@7.27.2': @@ -845,8 +839,8 @@ packages: resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.27.1': - resolution: {integrity: sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==} + '@babel/helper-module-transforms@7.27.3': + resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -863,29 +857,29 @@ packages: resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.27.1': - resolution: {integrity: sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==} + '@babel/helpers@7.27.6': + resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==} engines: {node: '>=6.9.0'} - '@babel/parser@7.27.2': - resolution: {integrity: sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==} + '@babel/parser@7.27.5': + resolution: {integrity: sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/runtime-corejs3@7.27.1': - resolution: {integrity: sha512-909rVuj3phpjW6y0MCXAZ5iNeORePa6ldJvp2baWGcTjwqbBDDz6xoS5JHJ7lS88NlwLYj07ImL/8IUMtDZzTA==} + '@babel/runtime-corejs3@7.27.6': + resolution: {integrity: sha512-vDVrlmRAY8z9Ul/HxT+8ceAru95LQgkSKiXkSYZvqtbkPSfhZJgpRp45Cldbh1GJ1kxzQkI70AqyrTI58KpaWQ==} engines: {node: '>=6.9.0'} '@babel/template@7.27.2': resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.27.1': - resolution: {integrity: sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==} + '@babel/traverse@7.27.4': + resolution: {integrity: sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==} engines: {node: '>=6.9.0'} - '@babel/types@7.27.1': - resolution: {integrity: sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==} + '@babel/types@7.27.6': + resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==} engines: {node: '>=6.9.0'} '@baszalmstra/rattler@0.2.1': @@ -923,152 +917,152 @@ packages: '@emnapi/wasi-threads@1.0.2': resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==} - '@esbuild/aix-ppc64@0.25.4': - resolution: {integrity: sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==} + '@esbuild/aix-ppc64@0.25.5': + resolution: {integrity: sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.25.4': - resolution: {integrity: sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==} + '@esbuild/android-arm64@0.25.5': + resolution: {integrity: sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.25.4': - resolution: {integrity: sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==} + '@esbuild/android-arm@0.25.5': + resolution: {integrity: sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.25.4': - resolution: {integrity: sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==} + '@esbuild/android-x64@0.25.5': + resolution: {integrity: sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.25.4': - resolution: {integrity: sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==} + '@esbuild/darwin-arm64@0.25.5': + resolution: {integrity: sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.25.4': - resolution: {integrity: sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==} + '@esbuild/darwin-x64@0.25.5': + resolution: {integrity: sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.25.4': - resolution: {integrity: sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==} + '@esbuild/freebsd-arm64@0.25.5': + resolution: {integrity: sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.4': - resolution: {integrity: sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==} + '@esbuild/freebsd-x64@0.25.5': + resolution: {integrity: sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.25.4': - resolution: {integrity: sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==} + '@esbuild/linux-arm64@0.25.5': + resolution: {integrity: sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.25.4': - resolution: {integrity: sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==} + '@esbuild/linux-arm@0.25.5': + resolution: {integrity: sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.25.4': - resolution: {integrity: sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==} + '@esbuild/linux-ia32@0.25.5': + resolution: {integrity: sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.25.4': - resolution: {integrity: sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==} + '@esbuild/linux-loong64@0.25.5': + resolution: {integrity: sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.25.4': - resolution: {integrity: sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==} + '@esbuild/linux-mips64el@0.25.5': + resolution: {integrity: sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.25.4': - resolution: {integrity: sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==} + '@esbuild/linux-ppc64@0.25.5': + resolution: {integrity: sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.25.4': - resolution: {integrity: sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==} + '@esbuild/linux-riscv64@0.25.5': + resolution: {integrity: sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.25.4': - resolution: {integrity: sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==} + '@esbuild/linux-s390x@0.25.5': + resolution: {integrity: sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.25.4': - resolution: {integrity: sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==} + '@esbuild/linux-x64@0.25.5': + resolution: {integrity: sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.4': - resolution: {integrity: sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==} + '@esbuild/netbsd-arm64@0.25.5': + resolution: {integrity: sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.4': - resolution: {integrity: sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==} + '@esbuild/netbsd-x64@0.25.5': + resolution: {integrity: sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.4': - resolution: {integrity: sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==} + '@esbuild/openbsd-arm64@0.25.5': + resolution: {integrity: sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.4': - resolution: {integrity: sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==} + '@esbuild/openbsd-x64@0.25.5': + resolution: {integrity: sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/sunos-x64@0.25.4': - resolution: {integrity: sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==} + '@esbuild/sunos-x64@0.25.5': + resolution: {integrity: sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.25.4': - resolution: {integrity: sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==} + '@esbuild/win32-arm64@0.25.5': + resolution: {integrity: sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.25.4': - resolution: {integrity: sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==} + '@esbuild/win32-ia32@0.25.5': + resolution: {integrity: sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.25.4': - resolution: {integrity: sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==} + '@esbuild/win32-x64@0.25.5': + resolution: {integrity: sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -1091,24 +1085,24 @@ packages: resolution: {integrity: sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@0.13.0': - resolution: {integrity: sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==} + '@eslint/core@0.14.0': + resolution: {integrity: sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/eslintrc@3.3.1': resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.26.0': - resolution: {integrity: sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ==} + '@eslint/js@9.28.0': + resolution: {integrity: sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.6': resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.2.8': - resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==} + '@eslint/plugin-kit@0.3.1': + resolution: {integrity: sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@gwhitney/detect-indent@7.0.1': @@ -1211,16 +1205,12 @@ packages: os: [darwin, linux, win32] hasBin: true - '@modelcontextprotocol/sdk@1.11.4': - resolution: {integrity: sha512-OTbhe5slIjiOtLxXhKalkKGhIQrwvhgCDs/C2r8kcBTy5HR/g43aDQU0l7r8O0VGbJPTNJvDc7ZdQMdQDJXmbw==} - engines: {node: '>=18'} - - '@mswjs/interceptors@0.38.6': - resolution: {integrity: sha512-qFlpmObPqeUs4u3oFYv/OM/xyX+pNa5TRAjqjvMhbGYlyMhzSrE5UfncL2rUcEeVfD9Gebgff73hPwqcOwJQNA==} + '@mswjs/interceptors@0.38.7': + resolution: {integrity: sha512-Jkb27iSn7JPdkqlTqKfhncFfnEZsIJVYxsFbUSWEkxdIPdsyngrhoDBk0/BGD2FQcRH99vlRrkHpNTyKqI+0/w==} engines: {node: '>=18'} - '@napi-rs/wasm-runtime@0.2.10': - resolution: {integrity: sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ==} + '@napi-rs/wasm-runtime@0.2.11': + resolution: {integrity: sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==} '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -1242,53 +1232,53 @@ packages: resolution: {integrity: sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==} engines: {node: ^18.17.0 || >=20.5.0} - '@octokit/auth-token@5.1.2': - resolution: {integrity: sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==} - engines: {node: '>= 18'} + '@octokit/auth-token@6.0.0': + resolution: {integrity: sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==} + engines: {node: '>= 20'} - '@octokit/core@6.1.5': - resolution: {integrity: sha512-vvmsN0r7rguA+FySiCsbaTTobSftpIDIpPW81trAmsv9TGxg3YCujAxRYp/Uy8xmDgYCzzgulG62H7KYUFmeIg==} - engines: {node: '>= 18'} + '@octokit/core@7.0.2': + resolution: {integrity: sha512-ODsoD39Lq6vR6aBgvjTnA3nZGliknKboc9Gtxr7E4WDNqY24MxANKcuDQSF0jzapvGb3KWOEDrKfve4HoWGK+g==} + engines: {node: '>= 20'} - '@octokit/endpoint@10.1.4': - resolution: {integrity: sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA==} - engines: {node: '>= 18'} + '@octokit/endpoint@11.0.0': + resolution: {integrity: sha512-hoYicJZaqISMAI3JfaDr1qMNi48OctWuOih1m80bkYow/ayPw6Jj52tqWJ6GEoFTk1gBqfanSoI1iY99Z5+ekQ==} + engines: {node: '>= 20'} - '@octokit/graphql@8.2.2': - resolution: {integrity: sha512-Yi8hcoqsrXGdt0yObxbebHXFOiUA+2v3n53epuOg1QUgOB6c4XzvisBNVXJSl8RYA5KrDuSL2yq9Qmqe5N0ryA==} - engines: {node: '>= 18'} + '@octokit/graphql@9.0.1': + resolution: {integrity: sha512-j1nQNU1ZxNFx2ZtKmL4sMrs4egy5h65OMDmSbVyuCzjOcwsHq6EaYjOTGXPQxgfiN8dJ4CriYHk6zF050WEULg==} + engines: {node: '>= 20'} - '@octokit/openapi-types@25.0.0': - resolution: {integrity: sha512-FZvktFu7HfOIJf2BScLKIEYjDsw6RKc7rBJCdvCTfKsVnx2GEB/Nbzjr29DUdb7vQhlzS/j8qDzdditP0OC6aw==} + '@octokit/openapi-types@25.1.0': + resolution: {integrity: sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==} - '@octokit/plugin-paginate-rest@12.0.0': - resolution: {integrity: sha512-MPd6WK1VtZ52lFrgZ0R2FlaoiWllzgqFHaSZxvp72NmoDeZ0m8GeJdg4oB6ctqMTYyrnDYp592Xma21mrgiyDA==} - engines: {node: '>= 18'} + '@octokit/plugin-paginate-rest@13.0.1': + resolution: {integrity: sha512-m1KvHlueScy4mQJWvFDCxFBTIdXS0K1SgFGLmqHyX90mZdCIv6gWBbKRhatxRjhGlONuTK/hztYdaqrTXcFZdQ==} + engines: {node: '>= 20'} peerDependencies: '@octokit/core': '>=6' - '@octokit/plugin-retry@7.2.1': - resolution: {integrity: sha512-wUc3gv0D6vNHpGxSaR3FlqJpTXGWgqmk607N9L3LvPL4QjaxDgX/1nY2mGpT37Khn+nlIXdljczkRnNdTTV3/A==} - engines: {node: '>= 18'} + '@octokit/plugin-retry@8.0.1': + resolution: {integrity: sha512-KUoYR77BjF5O3zcwDQHRRZsUvJwepobeqiSSdCJ8lWt27FZExzb0GgVxrhhfuyF6z2B2zpO0hN5pteni1sqWiw==} + engines: {node: '>= 20'} peerDependencies: - '@octokit/core': '>=6' + '@octokit/core': '>=7' - '@octokit/plugin-throttling@10.0.0': - resolution: {integrity: sha512-Kuq5/qs0DVYTHZuBAzCZStCzo2nKvVRo/TDNhCcpC2TKiOGz/DisXMCvjt3/b5kr6SCI1Y8eeeJTHBxxpFvZEg==} - engines: {node: '>= 18'} + '@octokit/plugin-throttling@11.0.1': + resolution: {integrity: sha512-S+EVhy52D/272L7up58dr3FNSMXWuNZolkL4zMJBNIfIxyZuUcczsQAU4b5w6dewJXnKYVgSHSV5wxitMSW1kw==} + engines: {node: '>= 20'} peerDependencies: - '@octokit/core': ^6.1.3 + '@octokit/core': ^7.0.0 - '@octokit/request-error@6.1.8': - resolution: {integrity: sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ==} - engines: {node: '>= 18'} + '@octokit/request-error@7.0.0': + resolution: {integrity: sha512-KRA7VTGdVyJlh0cP5Tf94hTiYVVqmt2f3I6mnimmaVz4UG3gQV/k4mDJlJv3X67iX6rmN7gSHCF8ssqeMnmhZg==} + engines: {node: '>= 20'} - '@octokit/request@9.2.3': - resolution: {integrity: sha512-Ma+pZU8PXLOEYzsWf0cn/gY+ME57Wq8f49WTXA8FMHp2Ps9djKw//xYJ1je8Hm0pR2lU9FUGeJRWOtxq6olt4w==} - engines: {node: '>= 18'} + '@octokit/request@10.0.2': + resolution: {integrity: sha512-iYj4SJG/2bbhh+iIpFmG5u49DtJ4lipQ+aPakjL9OKpsGY93wM8w06gvFbEQxcMsZcCvk5th5KkIm2m8o14aWA==} + engines: {node: '>= 20'} - '@octokit/types@14.0.0': - resolution: {integrity: sha512-VVmZP0lEhbo2O1pdq63gZFiGCKkm8PPp8AUOijlwPO6hojEVjspA0MWKP7E4hbvGxzFKNqKr6p0IYtOH/Wf/zA==} + '@octokit/types@14.1.0': + resolution: {integrity: sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==} '@one-ini/wasm@0.2.0': resolution: {integrity: sha512-n+L/BvrwKUn7q5O3wHGo+CJZAqfewh38+37sk+eBzv/39lM9pPgPRd4sOZRvSRzo0ukLxzyXso4WlGj2oKZ5hA==} @@ -1311,8 +1301,8 @@ packages: typescript: optional: true - '@opentelemetry/api-logs@0.201.0': - resolution: {integrity: sha512-WIDdWiz+Bz4coqpVg1jUmyMZJzvyy77qaMypaS8y2MwBbpVfXcunImZNJZPWbhOiGBm6PSrf2i3KU45QLtblmA==} + '@opentelemetry/api-logs@0.202.0': + resolution: {integrity: sha512-fTBjMqKCfotFWfLzaKyhjLvyEyq5vDKTTFfBmx21btv3gvy8Lq6N5Dh2OzqeuN4DjtpSvNT1uNVfg08eD2Rfxw==} engines: {node: '>=8.0.0'} '@opentelemetry/api@1.9.0': @@ -1331,56 +1321,56 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' - '@opentelemetry/exporter-trace-otlp-http@0.201.0': - resolution: {integrity: sha512-JupP7vOuYzlf1Jz5W4SyoZFizolZBAbeIB4kW4Yr3eNjtFlYWLgvpoxwBtYfu9/nDsPAZfavDoFWGIwUaThrzg==} + '@opentelemetry/exporter-trace-otlp-http@0.202.0': + resolution: {integrity: sha512-/hKE8DaFCJuaQqE1IxpgkcjOolUIwgi3TgHElPVKGdGRBSmJMTmN/cr6vWa55pCJIXPyhKvcMrbrya7DZ3VmzA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-bunyan@0.47.0': - resolution: {integrity: sha512-Sux5us8fkBLO/z+H8P2fSu+fRIm1xTeUHlwtM/E4CNZS9W/sAYrc8djZVa2JrwNXj/tE6U5vRJVObGekIkULow==} + '@opentelemetry/instrumentation-bunyan@0.48.0': + resolution: {integrity: sha512-Q6ay5CXIKuyejadPoLboz+jKumB3Zuxyk35ycFh9vfIeww3+mNRyMVj6KxHRS0Imbv9zhNbP3uyrUpvEMMyHuw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-http@0.201.0': - resolution: {integrity: sha512-ENCPm3xX/EB3egCvcAZnbhCG8tWTviPDl/hb5kAUvUHGs4s+lEZgJCZQPvwuFUyeOE2nJVyHIku3jJ8QrTv7PA==} + '@opentelemetry/instrumentation-http@0.202.0': + resolution: {integrity: sha512-oX+jyY2KBg4/nVH3vZhSWDbhywkHgE0fq3YinhUBx0jv+YUWC2UKA7qLkxr/CSzfKsFi/Km0NKV+llH17yYGKw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation@0.201.0': - resolution: {integrity: sha512-j6uDiEMClmhYlg4Q1MRh17h9mHYzigMYhyp+lUTuDb4XSDOJ21fdKPvy1WSUnmb8r0TioR/OnwYkzXpyWE+xcg==} + '@opentelemetry/instrumentation@0.202.0': + resolution: {integrity: sha512-Uz3BxZWPgDwgHM2+vCKEQRh0R8WKrd/q6Tus1vThRClhlPO39Dyz7mDrOr6KuqGXAlBQ1e5Tnymzri4RMZNaWA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/otlp-exporter-base@0.201.0': - resolution: {integrity: sha512-B1A6mb/jNZ8PMmeo8V6Z5KfiqeGipDsLcM4lOOQMBEc1tLtEefy8XPzdjJ2YsK/sPZPcVuNuZQZsiUKi5tBWBQ==} + '@opentelemetry/otlp-exporter-base@0.202.0': + resolution: {integrity: sha512-nMEOzel+pUFYuBJg2znGmHJWbmvMbdX5/RhoKNKowguMbURhz0fwik5tUKplLcUtl8wKPL1y9zPnPxeBn65N0Q==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/otlp-transformer@0.201.0': - resolution: {integrity: sha512-/AWcIXP/JRc8Bgd4xuYFEsIr7HTWIehUOfu3/kzilF060r2MxP09YmTaNCttO3EFdBKa2LjMoqsFnSdmVmZqRg==} + '@opentelemetry/otlp-transformer@0.202.0': + resolution: {integrity: sha512-5XO77QFzs9WkexvJQL9ksxL8oVFb/dfi9NWQSq7Sv0Efr9x3N+nb1iklP1TeVgxqJ7m1xWiC/Uv3wupiQGevMw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/resource-detector-aws@2.1.0': - resolution: {integrity: sha512-7QG5wQXMiHseKIyU69m8vfZgLhrxFx48DdyaQEYj6GXjE/Xrv1nS3bUwhICjb6+4NorB9+1pFCvJ/4S01CCCjQ==} + '@opentelemetry/resource-detector-aws@2.2.0': + resolution: {integrity: sha512-6k7//RWAv4U1PeZhv0Too0Sv7sp7/A6s6g9h5ZYauPcroh2t4gOmkQSspSLYCynn34YZwn3FGbuaMwTDjHEJig==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.0.0 - '@opentelemetry/resource-detector-azure@0.8.0': - resolution: {integrity: sha512-YBsJQrt0NGT66BgdVhhTkv7/oe/rTflX/rKteptVK6HNo7z8wbeAbB4SnSNJFfF+v3XrP/ruiTxKnNzoh/ampw==} + '@opentelemetry/resource-detector-azure@0.9.0': + resolution: {integrity: sha512-5wJwAAW2vhbqIhgaRisU1y0F5mUco59F/dKgmnnnT6YNbxjrbdUZYxKF5Wl7deJoACVdL5wi/3N97GCXPEwwCQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.0.0 - '@opentelemetry/resource-detector-gcp@0.35.0': - resolution: {integrity: sha512-JYkyOUc7TZAyHy37N2aPAwFvRdET0+E5qIRjmQLPop9LQi4+N0sKf65g4xCwuY/0M721T/424G3zneJjxyiooA==} + '@opentelemetry/resource-detector-gcp@0.36.0': + resolution: {integrity: sha512-mWnEcg4tA+IDPrkETWo42psEsDN20dzYZSm4ZH8m8uiQALnNksVmf5C3An0GUEj5zrrxMasjSuv4zEH1gI40XQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.0.0 @@ -1397,8 +1387,8 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.3.0 <1.10.0' - '@opentelemetry/sdk-logs@0.201.0': - resolution: {integrity: sha512-e97dyxQRKKwD7dh3qMcjJmAE1SuoXHjoRZCBf9tG1c50s++HTjalavwnmooqBj83zNk7Mz9Z8ZMQU7JlzaHJEA==} + '@opentelemetry/sdk-logs@0.202.0': + resolution: {integrity: sha512-pv8QiQLQzk4X909YKm0lnW4hpuQg4zHwJ4XBd5bZiXcd9urvrJNoNVKnxGHPiDVX/GiLFvr5DMYsDBQbZCypRQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.4.0 <1.10.0' @@ -1421,8 +1411,8 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' - '@opentelemetry/semantic-conventions@1.33.0': - resolution: {integrity: sha512-TIpZvE8fiEILFfTlfPnltpBaD3d9/+uQHVCyC3vfdh6WfCXKhNFzoP5RyDDIndfvZC5GrA4pyEDNyjPloJud+w==} + '@opentelemetry/semantic-conventions@1.34.0': + resolution: {integrity: sha512-aKcOkyrorBGlajjRdVoJWHTxfxO1vCNHLJVlSDaRHDIdjU+pX8IYQPvPDkYiujKLbRnWU+1TBwEt0QRgSm4SGA==} engines: {node: '>=14'} '@pkgjs/parseargs@0.11.0': @@ -1586,103 +1576,103 @@ packages: resolution: {integrity: sha512-vuLfebLvwYWwQYJeZiHHs5NmydjO6cdhwS1dUHJbXMi0WD8kBa/+f7gz4WcuNJPRR+enLFQUHs89OCjfl6Os0g==} engines: {node: ^20.9.0 || ^22.11.0, pnpm: ^9.0.0} - '@rollup/rollup-android-arm-eabi@4.41.0': - resolution: {integrity: sha512-KxN+zCjOYHGwCl4UCtSfZ6jrq/qi88JDUtiEFk8LELEHq2Egfc/FgW+jItZiOLRuQfb/3xJSgFuNPC9jzggX+A==} + '@rollup/rollup-android-arm-eabi@4.42.0': + resolution: {integrity: sha512-gldmAyS9hpj+H6LpRNlcjQWbuKUtb94lodB9uCz71Jm+7BxK1VIOo7y62tZZwxhA7j1ylv/yQz080L5WkS+LoQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.41.0': - resolution: {integrity: sha512-yDvqx3lWlcugozax3DItKJI5j05B0d4Kvnjx+5mwiUpWramVvmAByYigMplaoAQ3pvdprGCTCE03eduqE/8mPQ==} + '@rollup/rollup-android-arm64@4.42.0': + resolution: {integrity: sha512-bpRipfTgmGFdCZDFLRvIkSNO1/3RGS74aWkJJTFJBH7h3MRV4UijkaEUeOMbi9wxtxYmtAbVcnMtHTPBhLEkaw==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.41.0': - resolution: {integrity: sha512-2KOU574vD3gzcPSjxO0eyR5iWlnxxtmW1F5CkNOHmMlueKNCQkxR6+ekgWyVnz6zaZihpUNkGxjsYrkTJKhkaw==} + '@rollup/rollup-darwin-arm64@4.42.0': + resolution: {integrity: sha512-JxHtA081izPBVCHLKnl6GEA0w3920mlJPLh89NojpU2GsBSB6ypu4erFg/Wx1qbpUbepn0jY4dVWMGZM8gplgA==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.41.0': - resolution: {integrity: sha512-gE5ACNSxHcEZyP2BA9TuTakfZvULEW4YAOtxl/A/YDbIir/wPKukde0BNPlnBiP88ecaN4BJI2TtAd+HKuZPQQ==} + '@rollup/rollup-darwin-x64@4.42.0': + resolution: {integrity: sha512-rv5UZaWVIJTDMyQ3dCEK+m0SAn6G7H3PRc2AZmExvbDvtaDc+qXkei0knQWcI3+c9tEs7iL/4I4pTQoPbNL2SA==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.41.0': - resolution: {integrity: sha512-GSxU6r5HnWij7FoSo7cZg3l5GPg4HFLkzsFFh0N/b16q5buW1NAWuCJ+HMtIdUEi6XF0qH+hN0TEd78laRp7Dg==} + '@rollup/rollup-freebsd-arm64@4.42.0': + resolution: {integrity: sha512-fJcN4uSGPWdpVmvLuMtALUFwCHgb2XiQjuECkHT3lWLZhSQ3MBQ9pq+WoWeJq2PrNxr9rPM1Qx+IjyGj8/c6zQ==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.41.0': - resolution: {integrity: sha512-KGiGKGDg8qLRyOWmk6IeiHJzsN/OYxO6nSbT0Vj4MwjS2XQy/5emsmtoqLAabqrohbgLWJ5GV3s/ljdrIr8Qjg==} + '@rollup/rollup-freebsd-x64@4.42.0': + resolution: {integrity: sha512-CziHfyzpp8hJpCVE/ZdTizw58gr+m7Y2Xq5VOuCSrZR++th2xWAz4Nqk52MoIIrV3JHtVBhbBsJcAxs6NammOQ==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.41.0': - resolution: {integrity: sha512-46OzWeqEVQyX3N2/QdiU/CMXYDH/lSHpgfBkuhl3igpZiaB3ZIfSjKuOnybFVBQzjsLwkus2mjaESy8H41SzvA==} + '@rollup/rollup-linux-arm-gnueabihf@4.42.0': + resolution: {integrity: sha512-UsQD5fyLWm2Fe5CDM7VPYAo+UC7+2Px4Y+N3AcPh/LdZu23YcuGPegQly++XEVaC8XUTFVPscl5y5Cl1twEI4A==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.41.0': - resolution: {integrity: sha512-lfgW3KtQP4YauqdPpcUZHPcqQXmTmH4nYU0cplNeW583CMkAGjtImw4PKli09NFi2iQgChk4e9erkwlfYem6Lg==} + '@rollup/rollup-linux-arm-musleabihf@4.42.0': + resolution: {integrity: sha512-/i8NIrlgc/+4n1lnoWl1zgH7Uo0XK5xK3EDqVTf38KvyYgCU/Rm04+o1VvvzJZnVS5/cWSd07owkzcVasgfIkQ==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.41.0': - resolution: {integrity: sha512-nn8mEyzMbdEJzT7cwxgObuwviMx6kPRxzYiOl6o/o+ChQq23gfdlZcUNnt89lPhhz3BYsZ72rp0rxNqBSfqlqw==} + '@rollup/rollup-linux-arm64-gnu@4.42.0': + resolution: {integrity: sha512-eoujJFOvoIBjZEi9hJnXAbWg+Vo1Ov8n/0IKZZcPZ7JhBzxh2A+2NFyeMZIRkY9iwBvSjloKgcvnjTbGKHE44Q==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.41.0': - resolution: {integrity: sha512-l+QK99je2zUKGd31Gh+45c4pGDAqZSuWQiuRFCdHYC2CSiO47qUWsCcenrI6p22hvHZrDje9QjwSMAFL3iwXwQ==} + '@rollup/rollup-linux-arm64-musl@4.42.0': + resolution: {integrity: sha512-/3NrcOWFSR7RQUQIuZQChLND36aTU9IYE4j+TB40VU78S+RA0IiqHR30oSh6P1S9f9/wVOenHQnacs/Byb824g==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loongarch64-gnu@4.41.0': - resolution: {integrity: sha512-WbnJaxPv1gPIm6S8O/Wg+wfE/OzGSXlBMbOe4ie+zMyykMOeqmgD1BhPxZQuDqwUN+0T/xOFtL2RUWBspnZj3w==} + '@rollup/rollup-linux-loongarch64-gnu@4.42.0': + resolution: {integrity: sha512-O8AplvIeavK5ABmZlKBq9/STdZlnQo7Sle0LLhVA7QT+CiGpNVe197/t8Aph9bhJqbDVGCHpY2i7QyfEDDStDg==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.41.0': - resolution: {integrity: sha512-eRDWR5t67/b2g8Q/S8XPi0YdbKcCs4WQ8vklNnUYLaSWF+Cbv2axZsp4jni6/j7eKvMLYCYdcsv8dcU+a6QNFg==} + '@rollup/rollup-linux-powerpc64le-gnu@4.42.0': + resolution: {integrity: sha512-6Qb66tbKVN7VyQrekhEzbHRxXXFFD8QKiFAwX5v9Xt6FiJ3BnCVBuyBxa2fkFGqxOCSGGYNejxd8ht+q5SnmtA==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.41.0': - resolution: {integrity: sha512-TWrZb6GF5jsEKG7T1IHwlLMDRy2f3DPqYldmIhnA2DVqvvhY2Ai184vZGgahRrg8k9UBWoSlHv+suRfTN7Ua4A==} + '@rollup/rollup-linux-riscv64-gnu@4.42.0': + resolution: {integrity: sha512-KQETDSEBamQFvg/d8jajtRwLNBlGc3aKpaGiP/LvEbnmVUKlFta1vqJqTrvPtsYsfbE/DLg5CC9zyXRX3fnBiA==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.41.0': - resolution: {integrity: sha512-ieQljaZKuJpmWvd8gW87ZmSFwid6AxMDk5bhONJ57U8zT77zpZ/TPKkU9HpnnFrM4zsgr4kiGuzbIbZTGi7u9A==} + '@rollup/rollup-linux-riscv64-musl@4.42.0': + resolution: {integrity: sha512-qMvnyjcU37sCo/tuC+JqeDKSuukGAd+pVlRl/oyDbkvPJ3awk6G6ua7tyum02O3lI+fio+eM5wsVd66X0jQtxw==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.41.0': - resolution: {integrity: sha512-/L3pW48SxrWAlVsKCN0dGLB2bi8Nv8pr5S5ocSM+S0XCn5RCVCXqi8GVtHFsOBBCSeR+u9brV2zno5+mg3S4Aw==} + '@rollup/rollup-linux-s390x-gnu@4.42.0': + resolution: {integrity: sha512-I2Y1ZUgTgU2RLddUHXTIgyrdOwljjkmcZ/VilvaEumtS3Fkuhbw4p4hgHc39Ypwvo2o7sBFNl2MquNvGCa55Iw==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.41.0': - resolution: {integrity: sha512-XMLeKjyH8NsEDCRptf6LO8lJk23o9wvB+dJwcXMaH6ZQbbkHu2dbGIUindbMtRN6ux1xKi16iXWu6q9mu7gDhQ==} + '@rollup/rollup-linux-x64-gnu@4.42.0': + resolution: {integrity: sha512-Gfm6cV6mj3hCUY8TqWa63DB8Mx3NADoFwiJrMpoZ1uESbK8FQV3LXkhfry+8bOniq9pqY1OdsjFWNsSbfjPugw==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.41.0': - resolution: {integrity: sha512-m/P7LycHZTvSQeXhFmgmdqEiTqSV80zn6xHaQ1JSqwCtD1YGtwEK515Qmy9DcB2HK4dOUVypQxvhVSy06cJPEg==} + '@rollup/rollup-linux-x64-musl@4.42.0': + resolution: {integrity: sha512-g86PF8YZ9GRqkdi0VoGlcDUb4rYtQKyTD1IVtxxN4Hpe7YqLBShA7oHMKU6oKTCi3uxwW4VkIGnOaH/El8de3w==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.41.0': - resolution: {integrity: sha512-4yodtcOrFHpbomJGVEqZ8fzD4kfBeCbpsUy5Pqk4RluXOdsWdjLnjhiKy2w3qzcASWd04fp52Xz7JKarVJ5BTg==} + '@rollup/rollup-win32-arm64-msvc@4.42.0': + resolution: {integrity: sha512-+axkdyDGSp6hjyzQ5m1pgcvQScfHnMCcsXkx8pTgy/6qBmWVhtRVlgxjWwDp67wEXXUr0x+vD6tp5W4x6V7u1A==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.41.0': - resolution: {integrity: sha512-tmazCrAsKzdkXssEc65zIE1oC6xPHwfy9d5Ta25SRCDOZS+I6RypVVShWALNuU9bxIfGA0aqrmzlzoM5wO5SPQ==} + '@rollup/rollup-win32-ia32-msvc@4.42.0': + resolution: {integrity: sha512-F+5J9pelstXKwRSDq92J0TEBXn2nfUrQGg+HK1+Tk7VOL09e0gBqUHugZv7SW4MGrYj41oNCUe3IKCDGVlis2g==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.41.0': - resolution: {integrity: sha512-h1J+Yzjo/X+0EAvR2kIXJDuTuyT7drc+t2ALY0nIcGPbTatNOf0VWdhEA2Z4AAjv6X1NJV7SYo5oCTYRJhSlVA==} + '@rollup/rollup-win32-x64-msvc@4.42.0': + resolution: {integrity: sha512-LpHiJRwkaVz/LqjHjK8LCi8osq7elmpwujwbXKNW88bM8eeGxavJIKKjkjpMHAh/2xfnrt1ZSnhTv41WYUHYmA==} cpu: [x64] os: [win32] @@ -1714,8 +1704,8 @@ packages: peerDependencies: semantic-release: '>=24.1.0' - '@semantic-release/github@11.0.2': - resolution: {integrity: sha512-EhHimj3/eOSPu0OflgDzwgrawoGJIn8XLOkNS6WzwuTr8ebxyX976Y4mCqJ8MlkdQpV5+8T+49sy8xXlcm6uCg==} + '@semantic-release/github@11.0.3': + resolution: {integrity: sha512-T2fKUyFkHHkUNa5XNmcsEcDPuG23hwBKptfUVcFXDVG2cSjXXZYDOfVYwfouqbWo/8UefotLaoGfQeK+k3ep6A==} engines: {node: '>=20.8.1'} peerDependencies: semantic-release: '>=24.1.0' @@ -1766,8 +1756,8 @@ packages: '@sinonjs/text-encoding@0.7.3': resolution: {integrity: sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==} - '@smithy/abort-controller@4.0.2': - resolution: {integrity: sha512-Sl/78VDtgqKxN2+1qduaVE140XF+Xg+TafkncspwM4jFP/LHr76ZHmIY/y3V1M0mMLNk+Je6IGbzxy23RSToMw==} + '@smithy/abort-controller@4.0.4': + resolution: {integrity: sha512-gJnEjZMvigPDQWHrW3oPrFhQtkrgqBkyjj3pCIdF3A5M6vsZODG93KNlfJprv6bp4245bdT32fsHK4kkH3KYDA==} engines: {node: '>=18.0.0'} '@smithy/chunked-blob-reader-native@4.0.0': @@ -1778,56 +1768,56 @@ packages: resolution: {integrity: sha512-+sKqDBQqb036hh4NPaUiEkYFkTUGYzRsn3EuFhyfQfMy6oGHEUJDurLP9Ufb5dasr/XiAmPNMr6wa9afjQB+Gw==} engines: {node: '>=18.0.0'} - '@smithy/config-resolver@4.1.2': - resolution: {integrity: sha512-7r6mZGwb5LmLJ+zPtkLoznf2EtwEuSWdtid10pjGl/7HefCE4mueOkrfki8JCUm99W6UfP47/r3tbxx9CfBN5A==} + '@smithy/config-resolver@4.1.4': + resolution: {integrity: sha512-prmU+rDddxHOH0oNcwemL+SwnzcG65sBF2yXRO7aeXIn/xTlq2pX7JLVbkBnVLowHLg4/OL4+jBmv9hVrVGS+w==} engines: {node: '>=18.0.0'} - '@smithy/core@3.3.3': - resolution: {integrity: sha512-CiJNc0b/WdnttAfQ6uMkxPQ3Z8hG/ba8wF89x9KtBBLDdZk6CX52K4F8hbe94uNbc8LDUuZFtbqfdhM3T21naw==} + '@smithy/core@3.5.3': + resolution: {integrity: sha512-xa5byV9fEguZNofCclv6v9ra0FYh5FATQW/da7FQUVTic94DfrN/NvmKZjrMyzbpqfot9ZjBaO8U1UeTbmSLuA==} engines: {node: '>=18.0.0'} - '@smithy/credential-provider-imds@4.0.4': - resolution: {integrity: sha512-jN6M6zaGVyB8FmNGG+xOPQB4N89M1x97MMdMnm1ESjljLS3Qju/IegQizKujaNcy2vXAvrz0en8bobe6E55FEA==} + '@smithy/credential-provider-imds@4.0.6': + resolution: {integrity: sha512-hKMWcANhUiNbCJouYkZ9V3+/Qf9pteR1dnwgdyzR09R4ODEYx8BbUysHwRSyex4rZ9zapddZhLFTnT4ZijR4pw==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-codec@4.0.2': - resolution: {integrity: sha512-p+f2kLSK7ZrXVfskU/f5dzksKTewZk8pJLPvER3aFHPt76C2MxD9vNatSfLzzQSQB4FNO96RK4PSXfhD1TTeMQ==} + '@smithy/eventstream-codec@4.0.4': + resolution: {integrity: sha512-7XoWfZqWb/QoR/rAU4VSi0mWnO2vu9/ltS6JZ5ZSZv0eovLVfDfu0/AX4ub33RsJTOth3TiFWSHS5YdztvFnig==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-serde-browser@4.0.2': - resolution: {integrity: sha512-CepZCDs2xgVUtH7ZZ7oDdZFH8e6Y2zOv8iiX6RhndH69nlojCALSKK+OXwZUgOtUZEUaZ5e1hULVCHYbCn7pug==} + '@smithy/eventstream-serde-browser@4.0.4': + resolution: {integrity: sha512-3fb/9SYaYqbpy/z/H3yIi0bYKyAa89y6xPmIqwr2vQiUT2St+avRt8UKwsWt9fEdEasc5d/V+QjrviRaX1JRFA==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-serde-config-resolver@4.1.0': - resolution: {integrity: sha512-1PI+WPZ5TWXrfj3CIoKyUycYynYJgZjuQo8U+sphneOtjsgrttYybdqESFReQrdWJ+LKt6NEdbYzmmfDBmjX2A==} + '@smithy/eventstream-serde-config-resolver@4.1.2': + resolution: {integrity: sha512-JGtambizrWP50xHgbzZI04IWU7LdI0nh/wGbqH3sJesYToMi2j/DcoElqyOcqEIG/D4tNyxgRuaqBXWE3zOFhQ==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-serde-node@4.0.2': - resolution: {integrity: sha512-C5bJ/C6x9ENPMx2cFOirspnF9ZsBVnBMtP6BdPl/qYSuUawdGQ34Lq0dMcf42QTjUZgWGbUIZnz6+zLxJlb9aw==} + '@smithy/eventstream-serde-node@4.0.4': + resolution: {integrity: sha512-RD6UwNZ5zISpOWPuhVgRz60GkSIp0dy1fuZmj4RYmqLVRtejFqQ16WmfYDdoSoAjlp1LX+FnZo+/hkdmyyGZ1w==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-serde-universal@4.0.2': - resolution: {integrity: sha512-St8h9JqzvnbB52FtckiHPN4U/cnXcarMniXRXTKn0r4b4XesZOGiAyUdj1aXbqqn1icSqBlzzUsCl6nPB018ng==} + '@smithy/eventstream-serde-universal@4.0.4': + resolution: {integrity: sha512-UeJpOmLGhq1SLox79QWw/0n2PFX+oPRE1ZyRMxPIaFEfCqWaqpB7BU9C8kpPOGEhLF7AwEqfFbtwNxGy4ReENA==} engines: {node: '>=18.0.0'} - '@smithy/fetch-http-handler@5.0.2': - resolution: {integrity: sha512-+9Dz8sakS9pe7f2cBocpJXdeVjMopUDLgZs1yWeu7h++WqSbjUYv/JAJwKwXw1HV6gq1jyWjxuyn24E2GhoEcQ==} + '@smithy/fetch-http-handler@5.0.4': + resolution: {integrity: sha512-AMtBR5pHppYMVD7z7G+OlHHAcgAN7v0kVKEpHuTO4Gb199Gowh0taYi9oDStFeUhetkeP55JLSVlTW1n9rFtUw==} engines: {node: '>=18.0.0'} - '@smithy/hash-blob-browser@4.0.2': - resolution: {integrity: sha512-3g188Z3DyhtzfBRxpZjU8R9PpOQuYsbNnyStc/ZVS+9nVX1f6XeNOa9IrAh35HwwIZg+XWk8bFVtNINVscBP+g==} + '@smithy/hash-blob-browser@4.0.4': + resolution: {integrity: sha512-WszRiACJiQV3QG6XMV44i5YWlkrlsM5Yxgz4jvsksuu7LDXA6wAtypfPajtNTadzpJy3KyJPoWehYpmZGKUFIQ==} engines: {node: '>=18.0.0'} - '@smithy/hash-node@4.0.2': - resolution: {integrity: sha512-VnTpYPnRUE7yVhWozFdlxcYknv9UN7CeOqSrMH+V877v4oqtVYuoqhIhtSjmGPvYrYnAkaM61sLMKHvxL138yg==} + '@smithy/hash-node@4.0.4': + resolution: {integrity: sha512-qnbTPUhCVnCgBp4z4BUJUhOEkVwxiEi1cyFM+Zj6o+aY8OFGxUQleKWq8ltgp3dujuhXojIvJWdoqpm6dVO3lQ==} engines: {node: '>=18.0.0'} - '@smithy/hash-stream-node@4.0.2': - resolution: {integrity: sha512-POWDuTznzbIwlEXEvvXoPMS10y0WKXK790soe57tFRfvf4zBHyzE529HpZMqmDdwG9MfFflnyzndUQ8j78ZdSg==} + '@smithy/hash-stream-node@4.0.4': + resolution: {integrity: sha512-wHo0d8GXyVmpmMh/qOR0R7Y46/G1y6OR8U+bSTB4ppEzRxd1xVAQ9xOE9hOc0bSjhz0ujCPAbfNLkLrpa6cevg==} engines: {node: '>=18.0.0'} - '@smithy/invalid-dependency@4.0.2': - resolution: {integrity: sha512-GatB4+2DTpgWPday+mnUkoumP54u/MDM/5u44KF9hIu8jF0uafZtQLcdfIKkIcUNuF/fBojpLEHZS/56JqPeXQ==} + '@smithy/invalid-dependency@4.0.4': + resolution: {integrity: sha512-bNYMi7WKTJHu0gn26wg8OscncTt1t2b8KcsZxvOv56XA6cyXtOAAAaNP7+m45xfppXfOatXF3Sb1MNsLUgVLTw==} engines: {node: '>=18.0.0'} '@smithy/is-array-buffer@2.2.0': @@ -1838,76 +1828,76 @@ packages: resolution: {integrity: sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==} engines: {node: '>=18.0.0'} - '@smithy/md5-js@4.0.2': - resolution: {integrity: sha512-Hc0R8EiuVunUewCse2syVgA2AfSRco3LyAv07B/zCOMa+jpXI9ll+Q21Nc6FAlYPcpNcAXqBzMhNs1CD/pP2bA==} + '@smithy/md5-js@4.0.4': + resolution: {integrity: sha512-uGLBVqcOwrLvGh/v/jw423yWHq/ofUGK1W31M2TNspLQbUV1Va0F5kTxtirkoHawODAZcjXTSGi7JwbnPcDPJg==} engines: {node: '>=18.0.0'} - '@smithy/middleware-content-length@4.0.2': - resolution: {integrity: sha512-hAfEXm1zU+ELvucxqQ7I8SszwQ4znWMbNv6PLMndN83JJN41EPuS93AIyh2N+gJ6x8QFhzSO6b7q2e6oClDI8A==} + '@smithy/middleware-content-length@4.0.4': + resolution: {integrity: sha512-F7gDyfI2BB1Kc+4M6rpuOLne5LOcEknH1n6UQB69qv+HucXBR1rkzXBnQTB2q46sFy1PM/zuSJOB532yc8bg3w==} engines: {node: '>=18.0.0'} - '@smithy/middleware-endpoint@4.1.6': - resolution: {integrity: sha512-Zdieg07c3ua3ap5ungdcyNnY1OsxmsXXtKDTk28+/YbwIPju0Z1ZX9X5AnkjmDE3+AbqgvhtC/ZuCMSr6VSfPw==} + '@smithy/middleware-endpoint@4.1.11': + resolution: {integrity: sha512-zDogwtRLzKl58lVS8wPcARevFZNBOOqnmzWWxVe9XiaXU2CADFjvJ9XfNibgkOWs08sxLuSr81NrpY4mgp9OwQ==} engines: {node: '>=18.0.0'} - '@smithy/middleware-retry@4.1.7': - resolution: {integrity: sha512-lFIFUJ0E/4I0UaIDY5usNUzNKAghhxO0lDH4TZktXMmE+e4ActD9F154Si0Unc01aCPzcwd+NcOwQw6AfXXRRQ==} + '@smithy/middleware-retry@4.1.12': + resolution: {integrity: sha512-wvIH70c4e91NtRxdaLZF+mbLZ/HcC6yg7ySKUiufL6ESp6zJUSnJucZ309AvG9nqCFHSRB5I6T3Ez1Q9wCh0Ww==} engines: {node: '>=18.0.0'} - '@smithy/middleware-serde@4.0.5': - resolution: {integrity: sha512-yREC3q/HXqQigq29xX3hiy6tFi+kjPKXoYUQmwQdgPORLbQ0n6V2Z/Iw9Nnlu66da9fM/WhDtGvYvqwecrCljQ==} + '@smithy/middleware-serde@4.0.8': + resolution: {integrity: sha512-iSSl7HJoJaGyMIoNn2B7czghOVwJ9nD7TMvLhMWeSB5vt0TnEYyRRqPJu/TqW76WScaNvYYB8nRoiBHR9S1Ddw==} engines: {node: '>=18.0.0'} - '@smithy/middleware-stack@4.0.2': - resolution: {integrity: sha512-eSPVcuJJGVYrFYu2hEq8g8WWdJav3sdrI4o2c6z/rjnYDd3xH9j9E7deZQCzFn4QvGPouLngH3dQ+QVTxv5bOQ==} + '@smithy/middleware-stack@4.0.4': + resolution: {integrity: sha512-kagK5ggDrBUCCzI93ft6DjteNSfY8Ulr83UtySog/h09lTIOAJ/xUSObutanlPT0nhoHAkpmW9V5K8oPyLh+QA==} engines: {node: '>=18.0.0'} - '@smithy/node-config-provider@4.1.1': - resolution: {integrity: sha512-1slS5jf5icHETwl5hxEVBj+mh6B+LbVW4yRINsGtUKH+nxM5Pw2H59+qf+JqYFCHp9jssG4vX81f5WKnjMN3Vw==} + '@smithy/node-config-provider@4.1.3': + resolution: {integrity: sha512-HGHQr2s59qaU1lrVH6MbLlmOBxadtzTsoO4c+bF5asdgVik3I8o7JIOzoeqWc5MjVa+vD36/LWE0iXKpNqooRw==} engines: {node: '>=18.0.0'} - '@smithy/node-http-handler@4.0.4': - resolution: {integrity: sha512-/mdqabuAT3o/ihBGjL94PUbTSPSRJ0eeVTdgADzow0wRJ0rN4A27EOrtlK56MYiO1fDvlO3jVTCxQtQmK9dZ1g==} + '@smithy/node-http-handler@4.0.6': + resolution: {integrity: sha512-NqbmSz7AW2rvw4kXhKGrYTiJVDHnMsFnX4i+/FzcZAfbOBauPYs2ekuECkSbtqaxETLLTu9Rl/ex6+I2BKErPA==} engines: {node: '>=18.0.0'} - '@smithy/property-provider@4.0.2': - resolution: {integrity: sha512-wNRoQC1uISOuNc2s4hkOYwYllmiyrvVXWMtq+TysNRVQaHm4yoafYQyjN/goYZS+QbYlPIbb/QRjaUZMuzwQ7A==} + '@smithy/property-provider@4.0.4': + resolution: {integrity: sha512-qHJ2sSgu4FqF4U/5UUp4DhXNmdTrgmoAai6oQiM+c5RZ/sbDwJ12qxB1M6FnP+Tn/ggkPZf9ccn4jqKSINaquw==} engines: {node: '>=18.0.0'} - '@smithy/protocol-http@5.1.0': - resolution: {integrity: sha512-KxAOL1nUNw2JTYrtviRRjEnykIDhxc84qMBzxvu1MUfQfHTuBlCG7PA6EdVwqpJjH7glw7FqQoFxUJSyBQgu7g==} + '@smithy/protocol-http@5.1.2': + resolution: {integrity: sha512-rOG5cNLBXovxIrICSBm95dLqzfvxjEmuZx4KK3hWwPFHGdW3lxY0fZNXfv2zebfRO7sJZ5pKJYHScsqopeIWtQ==} engines: {node: '>=18.0.0'} - '@smithy/querystring-builder@4.0.2': - resolution: {integrity: sha512-NTOs0FwHw1vimmQM4ebh+wFQvOwkEf/kQL6bSM1Lock+Bv4I89B3hGYoUEPkmvYPkDKyp5UdXJYu+PoTQ3T31Q==} + '@smithy/querystring-builder@4.0.4': + resolution: {integrity: sha512-SwREZcDnEYoh9tLNgMbpop+UTGq44Hl9tdj3rf+yeLcfH7+J8OXEBaMc2kDxtyRHu8BhSg9ADEx0gFHvpJgU8w==} engines: {node: '>=18.0.0'} - '@smithy/querystring-parser@4.0.2': - resolution: {integrity: sha512-v6w8wnmZcVXjfVLjxw8qF7OwESD9wnpjp0Dqry/Pod0/5vcEA3qxCr+BhbOHlxS8O+29eLpT3aagxXGwIoEk7Q==} + '@smithy/querystring-parser@4.0.4': + resolution: {integrity: sha512-6yZf53i/qB8gRHH/l2ZwUG5xgkPgQF15/KxH0DdXMDHjesA9MeZje/853ifkSY0x4m5S+dfDZ+c4x439PF0M2w==} engines: {node: '>=18.0.0'} - '@smithy/service-error-classification@4.0.3': - resolution: {integrity: sha512-FTbcajmltovWMjj3tksDQdD23b2w6gH+A0DYA1Yz3iSpjDj8fmkwy62UnXcWMy4d5YoMoSyLFHMfkEVEzbiN8Q==} + '@smithy/service-error-classification@4.0.5': + resolution: {integrity: sha512-LvcfhrnCBvCmTee81pRlh1F39yTS/+kYleVeLCwNtkY8wtGg8V/ca9rbZZvYIl8OjlMtL6KIjaiL/lgVqHD2nA==} engines: {node: '>=18.0.0'} - '@smithy/shared-ini-file-loader@4.0.2': - resolution: {integrity: sha512-J9/gTWBGVuFZ01oVA6vdb4DAjf1XbDhK6sLsu3OS9qmLrS6KB5ygpeHiM3miIbj1qgSJ96GYszXFWv6ErJ8QEw==} + '@smithy/shared-ini-file-loader@4.0.4': + resolution: {integrity: sha512-63X0260LoFBjrHifPDs+nM9tV0VMkOTl4JRMYNuKh/f5PauSjowTfvF3LogfkWdcPoxsA9UjqEOgjeYIbhb7Nw==} engines: {node: '>=18.0.0'} - '@smithy/signature-v4@5.1.0': - resolution: {integrity: sha512-4t5WX60sL3zGJF/CtZsUQTs3UrZEDO2P7pEaElrekbLqkWPYkgqNW1oeiNYC6xXifBnT9dVBOnNQRvOE9riU9w==} + '@smithy/signature-v4@5.1.2': + resolution: {integrity: sha512-d3+U/VpX7a60seHziWnVZOHuEgJlclufjkS6zhXvxcJgkJq4UWdH5eOBLzHRMx6gXjsdT9h6lfpmLzbrdupHgQ==} engines: {node: '>=18.0.0'} - '@smithy/smithy-client@4.2.6': - resolution: {integrity: sha512-WEqP0wQ1N/lVS4pwNK1Vk+0i6QIr66cq/xbu1dVy1tM0A0qYwAYyz0JhbquzM5pMa8s89lyDBtoGKxo7iG74GA==} + '@smithy/smithy-client@4.4.3': + resolution: {integrity: sha512-xxzNYgA0HD6ETCe5QJubsxP0hQH3QK3kbpJz3QrosBCuIWyEXLR/CO5hFb2OeawEKUxMNhz3a1nuJNN2np2RMA==} engines: {node: '>=18.0.0'} - '@smithy/types@4.2.0': - resolution: {integrity: sha512-7eMk09zQKCO+E/ivsjQv+fDlOupcFUCSC/L2YUPgwhvowVGWbPQHjEFcmjt7QQ4ra5lyowS92SV53Zc6XD4+fg==} + '@smithy/types@4.3.1': + resolution: {integrity: sha512-UqKOQBL2x6+HWl3P+3QqFD4ncKq0I8Nuz9QItGv5WuKuMHuuwlhvqcZCoXGfc+P1QmfJE7VieykoYYmrOoFJxA==} engines: {node: '>=18.0.0'} - '@smithy/url-parser@4.0.2': - resolution: {integrity: sha512-Bm8n3j2ScqnT+kJaClSVCMeiSenK6jVAzZCNewsYWuZtnBehEz4r2qP0riZySZVfzB+03XZHJeqfmJDkeeSLiQ==} + '@smithy/url-parser@4.0.4': + resolution: {integrity: sha512-eMkc144MuN7B0TDA4U2fKs+BqczVbk3W+qIvcoCY6D1JY3hnAdCuhCZODC+GAeaxj0p6Jroz4+XMUn3PCxQQeQ==} engines: {node: '>=18.0.0'} '@smithy/util-base64@4.0.0': @@ -1934,32 +1924,32 @@ packages: resolution: {integrity: sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==} engines: {node: '>=18.0.0'} - '@smithy/util-defaults-mode-browser@4.0.14': - resolution: {integrity: sha512-l7QnMX8VcDOH6n/fBRu4zqguSlOBZxFzWqp58dXFSARFBjNlmEDk5G/z4T7BMGr+rI0Pg8MkhmMUfEtHFgpy2g==} + '@smithy/util-defaults-mode-browser@4.0.19': + resolution: {integrity: sha512-mvLMh87xSmQrV5XqnUYEPoiFFeEGYeAKIDDKdhE2ahqitm8OHM3aSvhqL6rrK6wm1brIk90JhxDf5lf2hbrLbQ==} engines: {node: '>=18.0.0'} - '@smithy/util-defaults-mode-node@4.0.14': - resolution: {integrity: sha512-Ujs1gsWDo3m/T63VWBTBmHLTD2UlU6J6FEokLCEp7OZQv45jcjLHoxTwgWsi8ULpsYozvH4MTWkRP+bhwr0vDg==} + '@smithy/util-defaults-mode-node@4.0.19': + resolution: {integrity: sha512-8tYnx+LUfj6m+zkUUIrIQJxPM1xVxfRBvoGHua7R/i6qAxOMjqR6CpEpDwKoIs1o0+hOjGvkKE23CafKL0vJ9w==} engines: {node: '>=18.0.0'} - '@smithy/util-endpoints@3.0.4': - resolution: {integrity: sha512-VfFATC1bmZLV2858B/O1NpMcL32wYo8DPPhHxYxDCodDl3f3mSZ5oJheW1IF91A0EeAADz2WsakM/hGGPGNKLg==} + '@smithy/util-endpoints@3.0.6': + resolution: {integrity: sha512-YARl3tFL3WgPuLzljRUnrS2ngLiUtkwhQtj8PAL13XZSyUiNLQxwG3fBBq3QXFqGFUXepIN73pINp3y8c2nBmA==} engines: {node: '>=18.0.0'} '@smithy/util-hex-encoding@4.0.0': resolution: {integrity: sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==} engines: {node: '>=18.0.0'} - '@smithy/util-middleware@4.0.2': - resolution: {integrity: sha512-6GDamTGLuBQVAEuQ4yDQ+ti/YINf/MEmIegrEeg7DdB/sld8BX1lqt9RRuIcABOhAGTA50bRbPzErez7SlDtDQ==} + '@smithy/util-middleware@4.0.4': + resolution: {integrity: sha512-9MLKmkBmf4PRb0ONJikCbCwORACcil6gUWojwARCClT7RmLzF04hUR4WdRprIXal7XVyrddadYNfp2eF3nrvtQ==} engines: {node: '>=18.0.0'} - '@smithy/util-retry@4.0.3': - resolution: {integrity: sha512-DPuYjZQDXmKr/sNvy9Spu8R/ESa2e22wXZzSAY6NkjOLj6spbIje/Aq8rT97iUMdDj0qHMRIe+bTxvlU74d9Ng==} + '@smithy/util-retry@4.0.5': + resolution: {integrity: sha512-V7MSjVDTlEt/plmOFBn1762Dyu5uqMrV2Pl2X0dYk4XvWfdWJNe9Bs5Bzb56wkCuiWjSfClVMGcsuKrGj7S/yg==} engines: {node: '>=18.0.0'} - '@smithy/util-stream@4.2.0': - resolution: {integrity: sha512-Vj1TtwWnuWqdgQI6YTUF5hQ/0jmFiOYsc51CSMgj7QfyO+RF4EnT2HNjoviNlOOmgzgvf3f5yno+EiC4vrnaWQ==} + '@smithy/util-stream@4.2.2': + resolution: {integrity: sha512-aI+GLi7MJoVxg24/3J1ipwLoYzgkB4kUfogZfnslcYlynj3xsQ0e7vk4TnTro9hhsS5PvX1mwmkRqqHQjwcU7w==} engines: {node: '>=18.0.0'} '@smithy/util-uri-escape@4.0.0': @@ -1974,8 +1964,8 @@ packages: resolution: {integrity: sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==} engines: {node: '>=18.0.0'} - '@smithy/util-waiter@4.0.3': - resolution: {integrity: sha512-JtaY3FxmD+te+KSI2FJuEcfNC9T/DGGVf551babM7fAaXhjJUt7oSYurH1Devxd2+BOSUACCgt3buinx4UnmEA==} + '@smithy/util-waiter@4.0.5': + resolution: {integrity: sha512-4QvC49HTteI1gfemu0I1syWovJgPvGn7CVUoN9ZFkdvr/cCFkrEL7qNCdx/2eICqDWEGnnr68oMdSIPCLAriSQ==} engines: {node: '>=18.0.0'} '@szmarczak/http-timer@4.0.6': @@ -2036,6 +2026,9 @@ packages: '@types/callsite@1.0.34': resolution: {integrity: sha512-eglitkkbqiQiijtKsUvOcQm+E6qLMPcggjDJXeqNBnLxdzffRGop2+2QDN/8pHh396/jN5cmIwweNKUqKJ50mQ==} + '@types/chai@5.2.2': + resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} + '@types/changelog-filename-regex@2.0.2': resolution: {integrity: sha512-H9iuCn3Ata8075f1Nyg/WScyicJ3eXr7AklsOrPeME3sa8izDlpBhbWurtdZJfuo4Vc5+J7wNoD9Yo1d66sj+A==} @@ -2051,8 +2044,8 @@ packages: '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} - '@types/diff@7.0.2': - resolution: {integrity: sha512-JSWRMozjFKsGlEjiiKajUjIJVKuKdE3oVy2DNtK+fUo8q82nhFZ2CPQwicAIkXrofahDXrWJ7mjelvZphMS98Q==} + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} '@types/emscripten@1.40.1': resolution: {integrity: sha512-sr53lnYkQNhjHNN0oJDdUm5564biioI5DuOpycufDVK7D3y+GR3oUswe2rlwY1nPNyusHbrJ9WoTyIHl4/Bpwg==} @@ -2063,6 +2056,9 @@ packages: '@types/estree@1.0.7': resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/fs-extra@11.0.4': resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} @@ -2105,8 +2101,8 @@ packages: '@types/linkify-markdown@1.0.3': resolution: {integrity: sha512-BnuGqDmpzmXCDMXHzgle/vMRUnbFcWclts0+n7Or421exav3XG6efl9gsxamLET6QPhX+pMnxcsHgnAO/daj9w==} - '@types/lodash@4.17.16': - resolution: {integrity: sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==} + '@types/lodash@4.17.17': + resolution: {integrity: sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==} '@types/luxon@3.6.2': resolution: {integrity: sha512-R/BdP7OxEMc44l2Ex5lSXHoIXTB2JLNa3y2QISIbr58U/YcsffyQrYW//hZSdrfxrjRZj3GcUoxMPGdO8gSYuw==} @@ -2135,8 +2131,8 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - '@types/node@22.15.18': - resolution: {integrity: sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg==} + '@types/node@22.15.29': + resolution: {integrity: sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -2163,9 +2159,6 @@ packages: '@types/semver@7.7.0': resolution: {integrity: sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==} - '@types/shimmer@1.2.0': - resolution: {integrity: sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==} - '@types/sinon@17.0.4': resolution: {integrity: sha512-RHnIrhfPO3+tJT0s7cFaXGZvsL4bbR3/k7z3P312qMS4JaS2Tk+KiwiLx1S0rQ56ERj00u1/BtdyVd0FY+Pdew==} @@ -2196,151 +2189,162 @@ packages: '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@typescript-eslint/eslint-plugin@8.32.1': - resolution: {integrity: sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==} + '@typescript-eslint/eslint-plugin@8.33.1': + resolution: {integrity: sha512-TDCXj+YxLgtvxvFlAvpoRv9MAncDLBV2oT9Bd7YBGC/b/sEURoOYuIwLI99rjWOfY3QtDzO+mk0n4AmdFExW8A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + '@typescript-eslint/parser': ^8.33.1 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/parser@8.32.1': - resolution: {integrity: sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==} + '@typescript-eslint/parser@8.33.1': + resolution: {integrity: sha512-qwxv6dq682yVvgKKp2qWwLgRbscDAYktPptK4JPojCwwi3R9cwrvIxS4lvBpzmcqzR4bdn54Z0IG1uHFskW4dA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/scope-manager@8.32.1': - resolution: {integrity: sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==} + '@typescript-eslint/project-service@8.33.1': + resolution: {integrity: sha512-DZR0efeNklDIHHGRpMpR5gJITQpu6tLr9lDJnKdONTC7vvzOlLAG/wcfxcdxEWrbiZApcoBCzXqU/Z458Za5Iw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/type-utils@8.32.1': - resolution: {integrity: sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==} + '@typescript-eslint/scope-manager@8.33.1': + resolution: {integrity: sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.33.1': + resolution: {integrity: sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/type-utils@8.33.1': + resolution: {integrity: sha512-1cG37d9xOkhlykom55WVwG2QRNC7YXlxMaMzqw2uPeJixBFfKWZgaP/hjAObqMN/u3fr5BrTwTnc31/L9jQ2ww==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/types@8.32.1': - resolution: {integrity: sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==} + '@typescript-eslint/types@8.33.1': + resolution: {integrity: sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.32.1': - resolution: {integrity: sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==} + '@typescript-eslint/typescript-estree@8.33.1': + resolution: {integrity: sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/utils@8.32.1': - resolution: {integrity: sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==} + '@typescript-eslint/utils@8.33.1': + resolution: {integrity: sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/visitor-keys@8.32.1': - resolution: {integrity: sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==} + '@typescript-eslint/visitor-keys@8.33.1': + resolution: {integrity: sha512-3i8NrFcZeeDHJ+7ZUuDkGT+UHq+XoFGsymNK2jZCOHcfEzRQ0BdpRtdpSx/Iyf3MHLWIcLS0COuOPibKQboIiQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@unrs/resolver-binding-darwin-arm64@1.7.2': - resolution: {integrity: sha512-vxtBno4xvowwNmO/ASL0Y45TpHqmNkAaDtz4Jqb+clmcVSSl8XCG/PNFFkGsXXXS6AMjP+ja/TtNCFFa1QwLRg==} + '@unrs/resolver-binding-darwin-arm64@1.7.11': + resolution: {integrity: sha512-i3/wlWjQJXMh1uiGtiv7k1EYvrrS3L1hdwmWJJiz1D8jWy726YFYPIxQWbEIVPVAgrfRR0XNlLrTQwq17cuCGw==} cpu: [arm64] os: [darwin] - '@unrs/resolver-binding-darwin-x64@1.7.2': - resolution: {integrity: sha512-qhVa8ozu92C23Hsmv0BF4+5Dyyd5STT1FolV4whNgbY6mj3kA0qsrGPe35zNR3wAN7eFict3s4Rc2dDTPBTuFQ==} + '@unrs/resolver-binding-darwin-x64@1.7.11': + resolution: {integrity: sha512-8XXyFvc6w6kmMmi6VYchZhjd5CDcp+Lv6Cn1YmUme0ypsZ/0Kzd+9ESrWtDrWibKPTgSteDTxp75cvBOY64FQQ==} cpu: [x64] os: [darwin] - '@unrs/resolver-binding-freebsd-x64@1.7.2': - resolution: {integrity: sha512-zKKdm2uMXqLFX6Ac7K5ElnnG5VIXbDlFWzg4WJ8CGUedJryM5A3cTgHuGMw1+P5ziV8CRhnSEgOnurTI4vpHpg==} + '@unrs/resolver-binding-freebsd-x64@1.7.11': + resolution: {integrity: sha512-0qJBYzP8Qk24CZ05RSWDQUjdiQUeIJGfqMMzbtXgCKl/a5xa6thfC0MQkGIr55LCLd6YmMyO640ifYUa53lybQ==} cpu: [x64] os: [freebsd] - '@unrs/resolver-binding-linux-arm-gnueabihf@1.7.2': - resolution: {integrity: sha512-8N1z1TbPnHH+iDS/42GJ0bMPLiGK+cUqOhNbMKtWJ4oFGzqSJk/zoXFzcQkgtI63qMcUI7wW1tq2usZQSb2jxw==} + '@unrs/resolver-binding-linux-arm-gnueabihf@1.7.11': + resolution: {integrity: sha512-1sGwpgvx+WZf0GFT6vkkOm6UJ+mlsVnjw+Yv9esK71idWeRAG3bbpkf3AoY8KIqKqmnzJExi0uKxXpakQ5Pcbg==} cpu: [arm] os: [linux] - '@unrs/resolver-binding-linux-arm-musleabihf@1.7.2': - resolution: {integrity: sha512-tjYzI9LcAXR9MYd9rO45m1s0B/6bJNuZ6jeOxo1pq1K6OBuRMMmfyvJYval3s9FPPGmrldYA3mi4gWDlWuTFGA==} + '@unrs/resolver-binding-linux-arm-musleabihf@1.7.11': + resolution: {integrity: sha512-D/1F/2lTe+XAl3ohkYj51NjniVly8sIqkA/n1aOND3ZMO418nl2JNU95iVa1/RtpzaKcWEsNTtHRogykrUflJg==} cpu: [arm] os: [linux] - '@unrs/resolver-binding-linux-arm64-gnu@1.7.2': - resolution: {integrity: sha512-jon9M7DKRLGZ9VYSkFMflvNqu9hDtOCEnO2QAryFWgT6o6AXU8du56V7YqnaLKr6rAbZBWYsYpikF226v423QA==} + '@unrs/resolver-binding-linux-arm64-gnu@1.7.11': + resolution: {integrity: sha512-7vFWHLCCNFLEQlmwKQfVy066ohLLArZl+AV/AdmrD1/pD1FlmqM+FKbtnONnIwbHtgetFUCV/SRi1q4D49aTlw==} cpu: [arm64] os: [linux] - '@unrs/resolver-binding-linux-arm64-musl@1.7.2': - resolution: {integrity: sha512-c8Cg4/h+kQ63pL43wBNaVMmOjXI/X62wQmru51qjfTvI7kmCy5uHTJvK/9LrF0G8Jdx8r34d019P1DVJmhXQpA==} + '@unrs/resolver-binding-linux-arm64-musl@1.7.11': + resolution: {integrity: sha512-tYkGIx8hjWPh4zcn17jLEHU8YMmdP2obRTGkdaB3BguGHh31VCS3ywqC4QjTODjmhhNyZYkj/1Dz/+0kKvg9YA==} cpu: [arm64] os: [linux] - '@unrs/resolver-binding-linux-ppc64-gnu@1.7.2': - resolution: {integrity: sha512-A+lcwRFyrjeJmv3JJvhz5NbcCkLQL6Mk16kHTNm6/aGNc4FwPHPE4DR9DwuCvCnVHvF5IAd9U4VIs/VvVir5lg==} + '@unrs/resolver-binding-linux-ppc64-gnu@1.7.11': + resolution: {integrity: sha512-6F328QIUev29vcZeRX6v6oqKxfUoGwIIAhWGD8wSysnBYFY0nivp25jdWmAb1GildbCCaQvOKEhCok7YfWkj4Q==} cpu: [ppc64] os: [linux] - '@unrs/resolver-binding-linux-riscv64-gnu@1.7.2': - resolution: {integrity: sha512-hQQ4TJQrSQW8JlPm7tRpXN8OCNP9ez7PajJNjRD1ZTHQAy685OYqPrKjfaMw/8LiHCt8AZ74rfUVHP9vn0N69Q==} + '@unrs/resolver-binding-linux-riscv64-gnu@1.7.11': + resolution: {integrity: sha512-NqhWmiGJGdzbZbeucPZIG9Iav4lyYLCarEnxAceguMx9qlpeEF7ENqYKOwB8Zqk7/CeuYMEcLYMaW2li6HyDzQ==} cpu: [riscv64] os: [linux] - '@unrs/resolver-binding-linux-riscv64-musl@1.7.2': - resolution: {integrity: sha512-NoAGbiqrxtY8kVooZ24i70CjLDlUFI7nDj3I9y54U94p+3kPxwd2L692YsdLa+cqQ0VoqMWoehDFp21PKRUoIQ==} + '@unrs/resolver-binding-linux-riscv64-musl@1.7.11': + resolution: {integrity: sha512-J2RPIFKMdTrLtBdfR1cUMKl8Gcy05nlQ+bEs/6al7EdWLk9cs3tnDREHZ7mV9uGbeghpjo4i8neNZNx3PYUY9w==} cpu: [riscv64] os: [linux] - '@unrs/resolver-binding-linux-s390x-gnu@1.7.2': - resolution: {integrity: sha512-KaZByo8xuQZbUhhreBTW+yUnOIHUsv04P8lKjQ5otiGoSJ17ISGYArc+4vKdLEpGaLbemGzr4ZeUbYQQsLWFjA==} + '@unrs/resolver-binding-linux-s390x-gnu@1.7.11': + resolution: {integrity: sha512-bDpGRerHvvHdhun7MmFUNDpMiYcJSqWckwAVVRTJf8F+RyqYJOp/mx04PDc7DhpNPeWdnTMu91oZRMV+gGaVcQ==} cpu: [s390x] os: [linux] - '@unrs/resolver-binding-linux-x64-gnu@1.7.2': - resolution: {integrity: sha512-dEidzJDubxxhUCBJ/SHSMJD/9q7JkyfBMT77Px1npl4xpg9t0POLvnWywSk66BgZS/b2Hy9Y1yFaoMTFJUe9yg==} + '@unrs/resolver-binding-linux-x64-gnu@1.7.11': + resolution: {integrity: sha512-G9U7bVmylzRLma3cK39RBm3guoD1HOvY4o0NS4JNm37AD0lS7/xyMt7kn0JejYyc0Im8J+rH69/dXGM9DAJcSQ==} cpu: [x64] os: [linux] - '@unrs/resolver-binding-linux-x64-musl@1.7.2': - resolution: {integrity: sha512-RvP+Ux3wDjmnZDT4XWFfNBRVG0fMsc+yVzNFUqOflnDfZ9OYujv6nkh+GOr+watwrW4wdp6ASfG/e7bkDradsw==} + '@unrs/resolver-binding-linux-x64-musl@1.7.11': + resolution: {integrity: sha512-7qL20SBKomekSunm7M9Fe5L93bFbn+FbHiGJbfTlp0RKhPVoJDP73vOxf1QrmJHyDPECsGWPFnKa/f8fO2FsHw==} cpu: [x64] os: [linux] - '@unrs/resolver-binding-wasm32-wasi@1.7.2': - resolution: {integrity: sha512-y797JBmO9IsvXVRCKDXOxjyAE4+CcZpla2GSoBQ33TVb3ILXuFnMrbR/QQZoauBYeOFuu4w3ifWLw52sdHGz6g==} + '@unrs/resolver-binding-wasm32-wasi@1.7.11': + resolution: {integrity: sha512-jisvIva8MidjI+B1lFRZZMfCPaCISePgTyR60wNT1MeQvIh5Ksa0G3gvI+Iqyj3jqYbvOHByenpa5eDGcSdoSg==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@unrs/resolver-binding-win32-arm64-msvc@1.7.2': - resolution: {integrity: sha512-gtYTh4/VREVSLA+gHrfbWxaMO/00y+34htY7XpioBTy56YN2eBjkPrY1ML1Zys89X3RJDKVaogzwxlM1qU7egg==} + '@unrs/resolver-binding-win32-arm64-msvc@1.7.11': + resolution: {integrity: sha512-G+H5nQZ8sRZ8ebMY6mRGBBvTEzMYEcgVauLsNHpvTUavZoCCRVP1zWkCZgOju2dW3O22+8seTHniTdl1/uLz3g==} cpu: [arm64] os: [win32] - '@unrs/resolver-binding-win32-ia32-msvc@1.7.2': - resolution: {integrity: sha512-Ywv20XHvHTDRQs12jd3MY8X5C8KLjDbg/jyaal/QLKx3fAShhJyD4blEANInsjxW3P7isHx1Blt56iUDDJO3jg==} + '@unrs/resolver-binding-win32-ia32-msvc@1.7.11': + resolution: {integrity: sha512-Hfy46DBfFzyv0wgR0MMOwFFib2W2+Btc8oE5h4XlPhpelnSyA6nFxkVIyTgIXYGTdFaLoZFNn62fmqx3rjEg3A==} cpu: [ia32] os: [win32] - '@unrs/resolver-binding-win32-x64-msvc@1.7.2': - resolution: {integrity: sha512-friS8NEQfHaDbkThxopGk+LuE5v3iY0StruifjQEt7SLbA46OnfgMO15sOTkbpJkol6RB+1l1TYPXh0sCddpvA==} + '@unrs/resolver-binding-win32-x64-msvc@1.7.11': + resolution: {integrity: sha512-7L8NdsQlCJ8T106Gbz/AjzM4QKWVsoQbKpB9bMBGcIZswUuAnJMHpvbqGW3RBqLHCIwX4XZ5fxSBHEFcK2h9wA==} cpu: [x64] os: [win32] - '@vitest/coverage-v8@3.1.3': - resolution: {integrity: sha512-cj76U5gXCl3g88KSnf80kof6+6w+K4BjOflCl7t6yRJPDuCrHtVu0SgNYOUARJOL5TI8RScDbm5x4s1/P9bvpw==} + '@vitest/coverage-v8@3.2.1': + resolution: {integrity: sha512-6dy0uF/0BE3jpUW9bFzg0V2S4F7XVaZHL/7qma1XANvHPQGoJuc3wtx911zSoAgUnpfvcLVK1vancNJ95d+uxQ==} peerDependencies: - '@vitest/browser': 3.1.3 - vitest: 3.1.3 + '@vitest/browser': 3.2.1 + vitest: 3.2.1 peerDependenciesMeta: '@vitest/browser': optional: true - '@vitest/eslint-plugin@1.1.44': - resolution: {integrity: sha512-m4XeohMT+Dj2RZfxnbiFR+Cv5dEC0H7C6TlxRQT7GK2556solm99kxgzJp/trKrZvanZcOFyw7aABykUTfWyrg==} + '@vitest/eslint-plugin@1.2.1': + resolution: {integrity: sha512-JQr1jdVcrsoS7Sdzn83h9sq4DvREf9Q/onTZbJCqTVlv/76qb+TZrLv/9VhjnjSMHweQH5FdpMDeCR6aDe2fgw==} peerDependencies: - '@typescript-eslint/utils': '>= 8.24.0' eslint: '>= 8.57.0' typescript: '>= 5.0.0' vitest: '*' @@ -2350,37 +2354,40 @@ packages: vitest: optional: true - '@vitest/expect@3.1.3': - resolution: {integrity: sha512-7FTQQuuLKmN1Ig/h+h/GO+44Q1IlglPlR2es4ab7Yvfx+Uk5xsv+Ykk+MEt/M2Yn/xGmzaLKxGw2lgy2bwuYqg==} + '@vitest/expect@3.2.1': + resolution: {integrity: sha512-FqS/BnDOzV6+IpxrTg5GQRyLOCtcJqkwMwcS8qGCI2IyRVDwPAtutztaf1CjtPHlZlWtl1yUPCd7HM0cNiDOYw==} - '@vitest/mocker@3.1.3': - resolution: {integrity: sha512-PJbLjonJK82uCWHjzgBJZuR7zmAOrSvKk1QBxrennDIgtH4uK0TB1PvYmc0XBCigxxtiAVPfWtAdy4lpz8SQGQ==} + '@vitest/mocker@3.2.1': + resolution: {integrity: sha512-OXxMJnx1lkB+Vl65Re5BrsZEHc90s5NMjD23ZQ9NlU7f7nZiETGoX4NeKZSmsKjseuMq2uOYXdLOeoM0pJU+qw==} peerDependencies: msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 peerDependenciesMeta: msw: optional: true vite: optional: true - '@vitest/pretty-format@3.1.3': - resolution: {integrity: sha512-i6FDiBeJUGLDKADw2Gb01UtUNb12yyXAqC/mmRWuYl+m/U9GS7s8us5ONmGkGpUUo7/iAYzI2ePVfOZTYvUifA==} + '@vitest/pretty-format@3.2.1': + resolution: {integrity: sha512-xBh1X2GPlOGBupp6E1RcUQWIxw0w/hRLd3XyBS6H+dMdKTAqHDNsIR2AnJwPA3yYe9DFy3VUKTe3VRTrAiQ01g==} + + '@vitest/pretty-format@3.2.2': + resolution: {integrity: sha512-FY4o4U1UDhO9KMd2Wee5vumwcaHw7Vg4V7yR4Oq6uK34nhEJOmdRYrk3ClburPRUA09lXD/oXWZ8y/Sdma0aUQ==} - '@vitest/runner@3.1.3': - resolution: {integrity: sha512-Tae+ogtlNfFei5DggOsSUvkIaSuVywujMj6HzR97AHK6XK8i3BuVyIifWAm/sE3a15lF5RH9yQIrbXYuo0IFyA==} + '@vitest/runner@3.2.1': + resolution: {integrity: sha512-kygXhNTu/wkMYbwYpS3z/9tBe0O8qpdBuC3dD/AW9sWa0LE/DAZEjnHtWA9sIad7lpD4nFW1yQ+zN7mEKNH3yA==} - '@vitest/snapshot@3.1.3': - resolution: {integrity: sha512-XVa5OPNTYUsyqG9skuUkFzAeFnEzDp8hQu7kZ0N25B1+6KjGm4hWLtURyBbsIAOekfWQ7Wuz/N/XXzgYO3deWQ==} + '@vitest/snapshot@3.2.1': + resolution: {integrity: sha512-5xko/ZpW2Yc65NVK9Gpfg2y4BFvcF+At7yRT5AHUpTg9JvZ4xZoyuRY4ASlmNcBZjMslV08VRLDrBOmUe2YX3g==} - '@vitest/spy@3.1.3': - resolution: {integrity: sha512-x6w+ctOEmEXdWaa6TO4ilb7l9DxPR5bwEb6hILKuxfU1NqWT2mpJD9NJN7t3OTfxmVlOMrvtoFJGdgyzZ605lQ==} + '@vitest/spy@3.2.1': + resolution: {integrity: sha512-Nbfib34Z2rfcJGSetMxjDCznn4pCYPZOtQYox2kzebIJcgH75yheIKd5QYSFmR8DIZf2M8fwOm66qSDIfRFFfQ==} - '@vitest/utils@3.1.3': - resolution: {integrity: sha512-2Ltrpht4OmHO9+c/nmHtF09HWiyWdworqnHIwjfvDyWjuwKbdkcS9AnhsDn+8E2RM4x++foD1/tNuLPVvWG1Rg==} + '@vitest/utils@3.2.1': + resolution: {integrity: sha512-KkHlGhePEKZSub5ViknBcN5KEF+u7dSUr9NW8QsVICusUojrgrOnnY3DEWWO877ax2Pyopuk2qHmt+gkNKnBVw==} - '@yarnpkg/core@4.4.1': - resolution: {integrity: sha512-iWCcc7BVN2SPZahM55FoOL36NvfOnw8j90G5PqOyjBwfCJngj7jTeT16cj27fFfHYlq+gwuu4I/tkHYzZ2mplQ==} + '@yarnpkg/core@4.4.2': + resolution: {integrity: sha512-Gf2p9WUygkcT8GobVjrQpFGE7A/GWXPXjDSIFTnZKTiq/W8giN3jqhWpIrpVa2XfPMguXzdEvb2brNYeW3IwdQ==} engines: {node: '>=18.12.0'} '@yarnpkg/fslib@3.1.2': @@ -2397,8 +2404,8 @@ packages: resolution: {integrity: sha512-mQZgUSgFurUtA07ceMjxrWkYz8QtDuYkvPlu0ZqncgjopQ0t6CNEo/OSealkmnagSUx8ZD5ewvezUwUuMqutQg==} engines: {node: '>=18.12.0'} - '@yarnpkg/shell@4.1.2': - resolution: {integrity: sha512-1ET4cNNd7//2tXHnLiHGzBbry5mlEmoKL8f32E5EKnn8Ke/gAcILeFdbX2G9C9w/7uBmFyWeSs530ib0SofVPQ==} + '@yarnpkg/shell@4.1.3': + resolution: {integrity: sha512-5igwsHbPtSAlLdmMdKqU3atXjwhtLFQXsYAG0sn1XcPb3yF8WxxtWxN6fycBoUvFyIHFz1G0KeRefnAy8n6gdw==} engines: {node: '>=18.12.0'} hasBin: true @@ -2406,10 +2413,6 @@ packages: resolution: {integrity: sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==} engines: {node: ^18.17.0 || >=20.5.0} - accepts@2.0.0: - resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} - engines: {node: '>= 0.6'} - acorn-import-attributes@1.9.5: resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} peerDependencies: @@ -2420,8 +2423,8 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.14.1: - resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} engines: {node: '>=0.4.0'} hasBin: true @@ -2448,9 +2451,6 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - ajv@8.17.1: - resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} - ansi-escapes@7.0.0: resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} engines: {node: '>=18'} @@ -2505,8 +2505,8 @@ packages: array-ify@1.0.0: resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} - array-includes@3.1.8: - resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} + array-includes@3.1.9: + resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==} engines: {node: '>= 0.4'} array.prototype.findlastindex@1.2.6: @@ -2533,6 +2533,9 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + ast-v8-to-istanbul@0.3.3: + resolution: {integrity: sha512-MuXMrSLVVoA6sYN/6Hke18vMzrT4TZNbZIj/hvh0fnYFpO+/kFXcLIaiPwXXWaQUPg4yJD8fj+lfJ7/1EBconw==} + async-function@1.0.0: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} @@ -2553,8 +2556,8 @@ packages: aws4@1.13.2: resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==} - azure-devops-node-api@14.1.0: - resolution: {integrity: sha512-QhpgjH1LQ+vgDJ7oBwcmsZ3+o4ZpjLVilw0D3oJQpYpRzN+L39lk5jZDLJ464hLUgsDzWn/Ksv7zLLMKLfoBzA==} + azure-devops-node-api@15.1.0: + resolution: {integrity: sha512-zlZ387CISkSKK1vjBv53kzR5fnzA60SxYrejypZawefZWvrjC28zyM/iKSP5b+iYl+Z7OOlm+Rgl6YsMecK6fg==} engines: {node: '>= 16.0.0'} backslash@0.2.0: @@ -2569,8 +2572,8 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - before-after-hook@3.0.2: - resolution: {integrity: sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==} + before-after-hook@4.0.0: + resolution: {integrity: sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==} better-sqlite3@11.10.0: resolution: {integrity: sha512-EwhOpyXiOEL/lKzHz9AW1msWFNzGc/z+LzeB3/jnFJpxu+th2yqvzsSWas1v9jgs9+xiXJcD5A8CJxAG2TaghQ==} @@ -2587,10 +2590,6 @@ packages: bn@1.0.5: resolution: {integrity: sha512-7TvGbqbZb6lDzsBtNz1VkdXXV0BVmZKPPViPmo2IpvwaryF7P+QKYKACyVkwo2mZPr2CpFiz7EtgPEcc3o/JFQ==} - body-parser@2.2.0: - resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==} - engines: {node: '>=18'} - boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -2614,8 +2613,8 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.24.5: - resolution: {integrity: sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==} + browserslist@4.25.0: + resolution: {integrity: sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -2639,10 +2638,6 @@ packages: engines: {'0': node >=0.10.0} hasBin: true - bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - bzip-deflate@1.0.0: resolution: {integrity: sha512-9RMnpiJqMYMJcLdr4pxwowZ8Zh3P+tVswE/bnX6tZ14UGKNcdV5WVK2P+lGp2As+RCjl+i3SFJ117HyCaaHNDA==} @@ -2693,8 +2688,8 @@ packages: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} - caniuse-lite@1.0.30001718: - resolution: {integrity: sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==} + caniuse-lite@1.0.30001721: + resolution: {integrity: sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==} chai@5.2.0: resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} @@ -2704,10 +2699,6 @@ packages: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} - chalk@3.0.0: - resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} - engines: {node: '>=8'} - chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -2833,10 +2824,18 @@ packages: resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} engines: {node: '>=18'} + commander@14.0.0: + resolution: {integrity: sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==} + engines: {node: '>=20'} + commander@8.3.0: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} + comment-parser@1.4.1: + resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} + engines: {node: '>= 12.0.0'} + common-tags@1.8.2: resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} engines: {node: '>=4.0.0'} @@ -2853,24 +2852,16 @@ packages: config-chain@1.1.13: resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} - content-disposition@1.0.0: - resolution: {integrity: sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==} - engines: {node: '>= 0.6'} - - content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} - conventional-changelog-angular@8.0.0: resolution: {integrity: sha512-CLf+zr6St0wIxos4bmaKHRXWAcsCXrJU6F4VdNDrGRK3B8LDLKoX3zuMV5GhtbGkVR/LohZ6MT6im43vZLSjmA==} engines: {node: '>=18'} - conventional-changelog-conventionalcommits@8.0.0: - resolution: {integrity: sha512-eOvlTO6OcySPyyyk8pKz2dP4jjElYunj9hn9/s0OB+gapTO8zwS9UQWrZ1pmF2hFs3vw1xhonOLGcGjy/zgsuA==} + conventional-changelog-conventionalcommits@9.0.0: + resolution: {integrity: sha512-5e48V0+DsWvQBEnnbBFhYQwYDzFPXVrakGPP1uSxekDkr5d7YWrmaWsgJpKFR0SkXmxK6qQr9O42uuLb9wpKxA==} engines: {node: '>=18'} - conventional-changelog-writer@8.0.1: - resolution: {integrity: sha512-hlqcy3xHred2gyYg/zXSMXraY2mjAYYo0msUCpK+BGyaVJMFCKWVXPIHiaacGO2GGp13kvHWXFhYmxT4QQqW3Q==} + conventional-changelog-writer@8.1.0: + resolution: {integrity: sha512-dpC440QnORNCO81XYuRRFOLCsjKj4W7tMkUIn3lR6F/FAaJcWLi7iCj6IcEvSQY2zw6VUgwUKd5DEHKEWrpmEQ==} engines: {node: '>=18'} hasBin: true @@ -2898,24 +2889,12 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - cookie-signature@1.2.2: - resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} - engines: {node: '>=6.6.0'} - - cookie@0.7.2: - resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} - engines: {node: '>= 0.6'} - core-js-pure@3.42.0: resolution: {integrity: sha512-007bM04u91fF4kMgwom2I5cQxAFIy8jVulgr9eozILl/SZE53QOqnW/+vviC+wQWLv+AunBG+8Q0TLoeSsSxRQ==} core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - cors@2.8.5: - resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} - engines: {node: '>= 0.10'} - cosmiconfig@9.0.0: resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} engines: {node: '>=14'} @@ -3027,10 +3006,6 @@ packages: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} - depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -3060,8 +3035,8 @@ packages: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} - diff@7.0.0: - resolution: {integrity: sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==} + diff@8.0.2: + resolution: {integrity: sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==} engines: {node: '>=0.3.1'} dir-glob@3.0.1: @@ -3111,11 +3086,8 @@ packages: engines: {node: '>=18'} hasBin: true - ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - - electron-to-chromium@1.5.155: - resolution: {integrity: sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng==} + electron-to-chromium@1.5.165: + resolution: {integrity: sha512-naiMx1Z6Nb2TxPU6fiFrUrDTjyPMLdTtaOd2oLmG8zVSg2hCWGkhPyxwk+qRmZ1ytwVqUv0u7ZcDA5+ALhaUtw==} email-addresses@5.0.0: resolution: {integrity: sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==} @@ -3144,10 +3116,6 @@ packages: emojilib@2.4.0: resolution: {integrity: sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==} - encodeurl@2.0.0: - resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} - engines: {node: '>= 0.8'} - encoding@0.1.13: resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} @@ -3158,8 +3126,8 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} - env-ci@11.1.0: - resolution: {integrity: sha512-Z8dnwSDbV1XYM9SBF2J0GcNVvmfmfh3a49qddGIROhBoVro6MZVTji15z/sJbQ2ko2ei8n988EU1wzoLU/tF+g==} + env-ci@11.1.1: + resolution: {integrity: sha512-mT3ks8F0kwpo7SYNds6nWj0PaRh+qJxIeBVBXAKTN9hphAzZv7s0QAZQbqnB1fAv/r4pJUGE15BV9UrS31FP2w==} engines: {node: ^18.17 || >=20.6.1} env-paths@2.2.1: @@ -3176,8 +3144,8 @@ packages: error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - es-abstract@1.23.9: - resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} + es-abstract@1.24.0: + resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==} engines: {node: '>= 0.4'} es-define-property@1.0.1: @@ -3210,8 +3178,8 @@ packages: es6-error@4.1.1: resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} - esbuild@0.25.4: - resolution: {integrity: sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==} + esbuild@0.25.5: + resolution: {integrity: sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==} engines: {node: '>=18'} hasBin: true @@ -3219,9 +3187,6 @@ packages: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} - escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} @@ -3251,11 +3216,20 @@ packages: resolution: {integrity: sha512-blbD5ZSQnjNEUaG38VCO4WG9nfDQWE8/IOmt8DFRHXUIfZikaIXmsQTdWNFk0/e0j7RgIVRza86MpsJ+aHgFLg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-import-context@0.1.8: + resolution: {integrity: sha512-bq+F7nyc65sKpZGT09dY0S0QrOnQtuDVIfyTGQ8uuvtMIF7oHp6CEP3mouN0rrnYF3Jqo6Ke0BfU/5wASZue1w==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + peerDependencies: + unrs-resolver: ^1.0.0 + peerDependenciesMeta: + unrs-resolver: + optional: true + eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - eslint-import-resolver-typescript@4.3.4: - resolution: {integrity: sha512-buzw5z5VtiQMysYLH9iW9BV04YyZebsw+gPi+c4FCjfS9i6COYOrEWw9t3m3wA9PFBfqcBCqWf32qrXLbwafDw==} + eslint-import-resolver-typescript@4.4.2: + resolution: {integrity: sha512-GdSOy0PwLYpQCrmnEQujvA+X0NKrdnVCICEbZq1zlmjjD12NHOHCN9MYyrGFR9ydCs4wJwHEV9tts44ajSlGeA==} engines: {node: ^16.17.0 || >=18.6.0} peerDependencies: eslint: '*' @@ -3288,6 +3262,19 @@ packages: eslint-import-resolver-webpack: optional: true + eslint-plugin-import-x@4.15.0: + resolution: {integrity: sha512-oqCESQlM8r0iRioPHmDqrblH69u11NuglErCnMIY2FcY0UfCCs7qlEuiuqkYKT0puJSQq+fXpDD0MvMTQsAhoQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/utils': ^8.0.0 + eslint: ^8.57.0 || ^9.0.0 + eslint-import-resolver-node: '*' + peerDependenciesMeta: + '@typescript-eslint/utils': + optional: true + eslint-import-resolver-node: + optional: true + eslint-plugin-import@2.31.0: resolution: {integrity: sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==} engines: {node: '>=4'} @@ -3316,8 +3303,8 @@ packages: resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.26.0: - resolution: {integrity: sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ==} + eslint@9.28.0: + resolution: {integrity: sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -3354,30 +3341,15 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - - eventemitter3@4.0.7: - resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} - eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - eventsource-parser@3.0.2: - resolution: {integrity: sha512-6RxOBZ/cYgd8usLwsEl+EC09Au/9BcmCKYF2/xbml6DNczf7nv0MQb+7BA2F+li6//I+28VNlQR37XfQtcAJuA==} - engines: {node: '>=18.0.0'} - - eventsource@3.0.7: - resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} - engines: {node: '>=18.0.0'} - execa@8.0.1: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} - execa@9.5.3: - resolution: {integrity: sha512-QFNnTvU3UjgWFy8Ef9iDHvIdcgZ344ebkwYx4/KLbR+CKQA4xBaHzv+iRpp86QfMHP8faFQLh8iOc57215y4Rg==} + execa@9.6.0: + resolution: {integrity: sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw==} engines: {node: ^18.19.0 || >=20.5.0} expand-template@2.0.3: @@ -3397,16 +3369,6 @@ packages: exponential-backoff@3.1.2: resolution: {integrity: sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==} - express-rate-limit@7.5.0: - resolution: {integrity: sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==} - engines: {node: '>= 16'} - peerDependencies: - express: ^4.11 || 5 || ^5.0.0-beta.1 - - express@5.1.0: - resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==} - engines: {node: '>= 18'} - extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -3415,8 +3377,8 @@ packages: engines: {node: '>= 10.17.0'} hasBin: true - fast-content-type-parse@2.0.1: - resolution: {integrity: sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==} + fast-content-type-parse@3.0.0: + resolution: {integrity: sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==} fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -3431,9 +3393,6 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fast-uri@3.0.6: - resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} - fast-xml-parser@4.4.1: resolution: {integrity: sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==} hasBin: true @@ -3444,8 +3403,8 @@ packages: fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} - fdir@6.4.4: - resolution: {integrity: sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==} + fdir@6.4.5: + resolution: {integrity: sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==} peerDependencies: picomatch: ^3 || ^4 peerDependenciesMeta: @@ -3471,10 +3430,6 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} - finalhandler@2.1.0: - resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==} - engines: {node: '>= 0.8'} - find-cache-dir@3.3.2: resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} engines: {node: '>=8'} @@ -3529,14 +3484,6 @@ packages: forwarded-parse@2.1.2: resolution: {integrity: sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==} - forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - - fresh@2.0.0: - resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} - engines: {node: '>= 0.8'} - from2@2.3.0: resolution: {integrity: sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==} @@ -3640,8 +3587,8 @@ packages: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} - get-tsconfig@4.10.0: - resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} + get-tsconfig@4.10.1: + resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} git-log-parser@1.2.1: resolution: {integrity: sha512-PI+sPDvHXNPl5WNOErAK05s3j0lgwUzMN6o8cyQrDaKfT3qd7TmNJKeXX+SknI5I0QhG5fVPAEwSY4tRGDtYoQ==} @@ -3696,18 +3643,14 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} - globals@16.0.0: - resolution: {integrity: sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A==} + globals@16.2.0: + resolution: {integrity: sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==} engines: {node: '>=18'} globalthis@1.0.4: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} - globby@14.0.2: - resolution: {integrity: sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==} - engines: {node: '>=18'} - globby@14.1.0: resolution: {integrity: sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==} engines: {node: '>=18'} @@ -3828,16 +3771,16 @@ packages: resolution: {integrity: sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==} engines: {node: ^18.17.0 || >=20.5.0} + hpagent@1.2.0: + resolution: {integrity: sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==} + engines: {node: '>=14'} + html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} http-cache-semantics@4.2.0: resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} - http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} @@ -3896,8 +3839,8 @@ packages: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} - ignore@7.0.4: - resolution: {integrity: sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==} + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} engines: {node: '>= 4'} immediate@3.0.6: @@ -3911,8 +3854,8 @@ packages: resolution: {integrity: sha512-YVt14UZCgsX1vZQ3gKjkWVdBdHQ6eu3MPU1TBgL1H5orXe2+jWD006WCPPtOuwlQm10NuzOW5WawiF1Q9veW8g==} engines: {node: '>=18.20'} - import-in-the-middle@1.13.2: - resolution: {integrity: sha512-Yjp9X7s2eHSXvZYQ0aye6UvwYPrVB5C2k47fuXjFKnYinAByaDZjh4t9MT2wEga9775n6WaIqyHnQhBxYtX2mg==} + import-in-the-middle@1.14.0: + resolution: {integrity: sha512-g5zLT0HaztRJWysayWYiUq/7E5H825QIiecMD2pI5QO7Wzr847l6GDvPvmZaDIdrDtS2w7qRczywxiK6SL5vRw==} import-meta-resolve@4.1.0: resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} @@ -3963,10 +3906,6 @@ packages: resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} engines: {node: '>= 12'} - ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - is-alphabetical@1.0.4: resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} @@ -4069,6 +4008,10 @@ packages: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + is-node-process@1.2.0: resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==} @@ -4096,9 +4039,6 @@ packages: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} - is-promise@4.0.0: - resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} - is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} @@ -4213,8 +4153,8 @@ packages: jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - jackspeak@4.1.0: - resolution: {integrity: sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==} + jackspeak@4.1.1: + resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==} engines: {node: 20 || >=22} java-properties@1.0.2: @@ -4225,9 +4165,9 @@ packages: resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-extended@4.0.2: - resolution: {integrity: sha512-FH7aaPgtGYHc9mRjriS0ZEHYM5/W69tLrFTIdzm+yJgeoCmmrSB/luSfMSqWP9O29QWHPEmJ4qmU6EwsZideog==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-extended@5.0.3: + resolution: {integrity: sha512-sxrNxTvHd5S0qFSchkYdr7WhLQb55qhr5sHcllPaPXXGhv0kXy/0VTtFbrFUPOLHyZRDpNoEmhzcPRT7b90MZA==} + engines: {node: ^18.12.0 || ^20.9.0 || ^22.11.0 || >=23.0.0} peerDependencies: jest: '>=27.2.5' peerDependenciesMeta: @@ -4248,6 +4188,9 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + js-yaml@3.14.1: resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} hasBin: true @@ -4286,9 +4229,6 @@ packages: json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -4364,9 +4304,9 @@ packages: linkify-it@5.0.0: resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} - lint-staged@15.5.2: - resolution: {integrity: sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==} - engines: {node: '>=18.12.0'} + lint-staged@16.1.0: + resolution: {integrity: sha512-HkpQh69XHxgCjObjejBT3s2ILwNjFx8M3nw+tJ/ssBauDlIpkx2RpqWSi1fBgkXLSSXnbR3iEq1NkVtpvV+FLQ==} + engines: {node: '>=20.17'} hasBin: true listr2@8.3.3: @@ -4500,14 +4440,14 @@ packages: peerDependencies: markdownlint-cli2: '>=0.0.4' - markdownlint-cli2@0.17.2: - resolution: {integrity: sha512-XH06ZOi8wCrtOSSj3p8y3yJzwgzYOSa7lglNyS3fP05JPRzRGyjauBb5UvlLUSCGysMmULS1moxdRHHudV+g/Q==} - engines: {node: '>=18'} + markdownlint-cli2@0.18.1: + resolution: {integrity: sha512-/4Osri9QFGCZOCTkfA8qJF+XGjKYERSHkXzxSyS1hd3ZERJGjvsUao2h4wdnvpHp6Tu2Jh/bPHM0FE9JJza6ng==} + engines: {node: '>=20'} hasBin: true - markdownlint@0.37.4: - resolution: {integrity: sha512-u00joA/syf3VhWh6/ybVFkib5Zpj2e5KB/cfCei8fkSRuums6nyisTWGqjTWIOFoFwuXoTBQQiqlB4qFKp8ncQ==} - engines: {node: '>=18'} + markdownlint@0.38.0: + resolution: {integrity: sha512-xaSxkaU7wY/0852zGApM8LdlIfGCW8ETZ0Rr62IQtAnUMlMuifsg09vWJcNYeL4f0anvr8Vo4ZQar8jGpV0btQ==} + engines: {node: '>=20'} marked-terminal@7.3.0: resolution: {integrity: sha512-t4rBvPsHc57uE/2nJOLmMbZCQ4tgAccAED3ngXQqW6g+TxA488JzJ+FK3lQkzBQOI1mRV/r/Kq+1ZlJ4D0owQw==} @@ -4515,8 +4455,8 @@ packages: peerDependencies: marked: '>=1 <16' - marked@12.0.2: - resolution: {integrity: sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==} + marked@15.0.12: + resolution: {integrity: sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==} engines: {node: '>= 18'} hasBin: true @@ -4546,10 +4486,6 @@ packages: mdurl@2.0.0: resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} - media-typer@1.1.0: - resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} - engines: {node: '>= 0.8'} - memfs@4.17.2: resolution: {integrity: sha512-NgYhCOWgovOXSzvYgUW0LQ7Qy72rWQMGGFJDoWg4G30RHd3z77VbYdtJ4fembJXBy8pMIUA31XNAupobOQlwdg==} engines: {node: '>= 4.0.0'} @@ -4570,10 +4506,6 @@ packages: resolution: {integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==} engines: {node: '>=10'} - merge-descriptors@2.0.0: - resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} - engines: {node: '>=18'} - merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -4581,11 +4513,11 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - micromark-core-commonmark@2.0.2: - resolution: {integrity: sha512-FKjQKbxd1cibWMM1P9N+H8TwlgGgSkWZMmfuVucLCHaYqeSvJ0hFeHsIa65pA2nYbes0f8LDHPMrd9X7Ujxg9w==} + micromark-core-commonmark@2.0.3: + resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} - micromark-extension-directive@3.0.2: - resolution: {integrity: sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==} + micromark-extension-directive@4.0.0: + resolution: {integrity: sha512-/C2nqVmXXmiseSSuCdItCMho7ybwwop6RrrRPk0KbOHW21JKoCldC+8rFOaundDoRBUWBnJJcxeA/Kvi34WQXg==} micromark-extension-gfm-autolink-literal@2.1.0: resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==} @@ -4593,8 +4525,8 @@ packages: micromark-extension-gfm-footnote@2.1.0: resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==} - micromark-extension-gfm-table@2.1.0: - resolution: {integrity: sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==} + micromark-extension-gfm-table@2.1.1: + resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==} micromark-extension-math@3.1.0: resolution: {integrity: sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==} @@ -4650,27 +4582,19 @@ packages: micromark-util-symbol@2.0.1: resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} - micromark-util-types@2.0.1: - resolution: {integrity: sha512-534m2WhVTddrcKVepwmVEVnUAmtrx9bfIjNoQHRqfnvdaHQiFytEhJoTgpWJvDEXCO5gLTQh3wYC1PgOJA4NSQ==} + micromark-util-types@2.0.2: + resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} micromark@2.11.4: resolution: {integrity: sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==} - micromark@4.0.1: - resolution: {integrity: sha512-eBPdkcoCNvYcxQOAKAlceo5SNdzZWfF+FcSupREAzdAh9rRmE239CEQAiTwIgblwnoM8zzj35sZ5ZwvSEOF6Kw==} + micromark@4.0.2: + resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} - mime-db@1.54.0: - resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} - engines: {node: '>= 0.6'} - - mime-types@3.0.1: - resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==} - engines: {node: '>= 0.6'} - mime@4.0.7: resolution: {integrity: sha512-2OfDPL+e03E0LrXaGYOtTFIYhiuzep94NSsuhrNULq+stylcJedcHdzHtz0atMUuGwJfFYs0YL5xeC/Ca2x0eQ==} engines: {node: '>=16'} @@ -4792,6 +4716,10 @@ packages: nan@2.22.2: resolution: {integrity: sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==} + nano-spawn@1.0.2: + resolution: {integrity: sha512-21t+ozMQDAL/UGgQVBbZ/xXvNO10++ZPuTmKRO8k9V3AClVRht49ahtDjfY8l1q6nSHOrE5ASfthzH3ol6R/hg==} + engines: {node: '>=20.17'} + nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -4830,8 +4758,8 @@ packages: nise@6.1.1: resolution: {integrity: sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==} - nock@14.0.4: - resolution: {integrity: sha512-86fh+gIKH8H02+y0/HKAOZZXn6OwgzXvl6JYwfjvKkoKxUWz54wIIDU/+w24xzMvk/R8pNVXOrvTubyl+Ml6cg==} + nock@14.0.5: + resolution: {integrity: sha512-R49fALR9caB6vxuSWUIaK2eBYeTloZQUFBZ4rHO+TbhMGQHtwnhdqKLYki+o+8qMgLvoBYWrp/2KzGPhxL4S6w==} engines: {node: '>=18.20.0 <20 || >=20.12.1'} node-abi@3.75.0: @@ -4894,9 +4822,9 @@ packages: resolution: {integrity: sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==} engines: {node: ^18.17.0 || >=20.5.0} - npm-run-all2@7.0.2: - resolution: {integrity: sha512-7tXR+r9hzRNOPNTvXegM+QzCuMjzUIIq66VDunL6j60O4RrExx32XUhlrS7UK4VcdGw5/Wxzb3kfNcFix9JKDA==} - engines: {node: ^18.17.0 || >=20.5.0, npm: '>= 9'} + npm-run-all2@8.0.4: + resolution: {integrity: sha512-wdbB5My48XKp2ZfJUlhnLVihzeuA1hgBnqB2J9ahV77wLS+/YAJAlN8I+X3DIFIPZ3m5L7nplmlbhNiFDmXRDA==} + engines: {node: ^20.5.0 || >=22.0.0, npm: '>= 10'} hasBin: true npm-run-path@5.3.0: @@ -5017,10 +4945,6 @@ packages: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} - on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -5047,9 +4971,9 @@ packages: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} - p-all@3.0.0: - resolution: {integrity: sha512-qUZbvbBFVXm6uJ7U/WDiO0fv6waBMbjlCm4E66oZdRR+egswICarIdHyVSZZHudH8T5SF8x/JG0q0duFzPnlBw==} - engines: {node: '>=10'} + p-all@5.0.0: + resolution: {integrity: sha512-pofqu/1FhCVa+78xNAptCGc9V45exFz2pvBRyIvgXkNM0Rh18Py7j8pQuSjA+zpabI46v9hRjNWmL9EAFcEbpw==} + engines: {node: '>=16'} p-cancelable@2.1.1: resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} @@ -5067,10 +4991,6 @@ packages: resolution: {integrity: sha512-37/tPdZ3oJwHaS3gNJdenCDB3Tz26i9sjhnguBtvN0vYlRIiDNnvTWkuh+0hETV9rLPdJ3rlL3yVOYPIAnM8rw==} engines: {node: '>=18'} - p-finally@1.0.0: - resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} - engines: {node: '>=4'} - p-is-promise@3.0.0: resolution: {integrity: sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==} engines: {node: '>=8'} @@ -5115,29 +5035,29 @@ packages: resolution: {integrity: sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==} engines: {node: '>=8'} - p-map@4.0.0: - resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} - engines: {node: '>=10'} + p-map@6.0.0: + resolution: {integrity: sha512-T8BatKGY+k5rU+Q/GTYgrEf2r4xRMevAN5mtXc2aPc4rS1j3s+vWTaO2Wag94neXuCAUAs8cxBL9EeB5EA6diw==} + engines: {node: '>=16'} p-map@7.0.3: resolution: {integrity: sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==} engines: {node: '>=18'} - p-queue@6.6.2: - resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} - engines: {node: '>=8'} + p-queue@8.1.0: + resolution: {integrity: sha512-mxLDbbGIBEXTJL0zEx8JIylaj3xQ7Z/7eEVjcF9fJX4DBiH9oqe+oahYnlKKxm0Ci9TlWTyhSHgygxMxjIB2jw==} + engines: {node: '>=18'} p-reduce@3.0.0: resolution: {integrity: sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q==} engines: {node: '>=12'} - p-throttle@4.1.1: - resolution: {integrity: sha512-TuU8Ato+pRTPJoDzYD4s7ocJYcNSEZRvlxoq3hcPI2kZDZ49IQ1Wkj7/gDJc3X7XiEAAvRGtDzdXJI0tC3IL1g==} - engines: {node: '>=10'} + p-throttle@7.0.0: + resolution: {integrity: sha512-aio0v+S0QVkH1O+9x4dHtD4dgCExACcL+3EtNaGqC01GBudS9ijMuUsmN8OVScyV4OOp0jqdLShZFuSlbL/AsA==} + engines: {node: '>=18'} - p-timeout@3.2.0: - resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} - engines: {node: '>=8'} + p-timeout@6.1.4: + resolution: {integrity: sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==} + engines: {node: '>=14.16'} p-try@1.0.0: resolution: {integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==} @@ -5199,10 +5119,6 @@ packages: parse5@6.0.1: resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} - parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - path-exists@3.0.0: resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} engines: {node: '>=4'} @@ -5246,10 +5162,6 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - path-type@5.0.0: - resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==} - engines: {node: '>=12'} - path-type@6.0.0: resolution: {integrity: sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==} engines: {node: '>=18'} @@ -5287,10 +5199,6 @@ packages: resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} engines: {node: '>=4'} - pkce-challenge@5.0.0: - resolution: {integrity: sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==} - engines: {node: '>=16.20.0'} - pkg-conf@2.1.0: resolution: {integrity: sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==} engines: {node: '>=4'} @@ -5303,8 +5211,8 @@ packages: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} - postcss@8.5.3: - resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + postcss@8.5.4: + resolution: {integrity: sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==} engines: {node: ^10 || ^12 || >=14} prebuild-install@7.1.3: @@ -5355,17 +5263,13 @@ packages: proto-list@1.2.4: resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} - protobufjs@7.5.2: - resolution: {integrity: sha512-f2ls6rpO6G153Cy+o2XQ+Y0sARLOZ17+OGVLHrc3VUKcLHYKEKWbkSujdBWQXM7gKn5NTfp0XnRPZn1MIu8n9w==} + protobufjs@7.5.3: + resolution: {integrity: sha512-sildjKwVqOI2kmFDiXQ6aEB0fjYTafpEvIBs8tOR8qI4spuL9OPROLVu2qZqi/xgCfsHIwVqlaF8JBjWFHnKbw==} engines: {node: '>=12.0.0'} protocols@2.0.2: resolution: {integrity: sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==} - proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} - pump@3.0.2: resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} @@ -5396,20 +5300,12 @@ packages: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} - range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - - raw-body@3.0.0: - resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==} - engines: {node: '>= 0.8'} - rc@1.2.8: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true - re2@1.21.5: - resolution: {integrity: sha512-ud7gX1bO6K4+l2YVUxZjOPCiyCBZvmi7XUnGArSk3rGIvsZW35jX3pjGs8zQiTumOpgbxHCZI1ivB1VO7i4MFw==} + re2@1.22.1: + resolution: {integrity: sha512-E4J0EtgyNLdIr0wTg0dQPefuiqNY29KaLacytiUAYYRzxCG+zOkWoUygt1rI+TA1LrhN49/njrfSO1DHtVC5Vw==} react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} @@ -5488,10 +5384,6 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} - require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - require-in-the-middle@7.5.2: resolution: {integrity: sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==} engines: {node: '>=8.6.0'} @@ -5550,15 +5442,11 @@ packages: resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==} engines: {node: '>=8.0'} - rollup@4.41.0: - resolution: {integrity: sha512-HqMFpUbWlf/tvcxBFNKnJyzc7Lk+XO3FGc3pbNBLqEbOz0gPLRgcrlS3UF4MfUrVlstOaP/q0kM6GVvi+LrLRg==} + rollup@4.42.0: + resolution: {integrity: sha512-LW+Vse3BJPyGJGAJt1j8pWDKPd73QM8cRXYK1IxOBgL2AGLu7Xd2YOW0M2sLUBCkF5MshXXtMApyEAEzMVMsnw==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - router@2.2.0: - resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} - engines: {node: '>= 18'} - run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -5590,8 +5478,8 @@ packages: sax@1.4.1: resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} - semantic-release@24.2.3: - resolution: {integrity: sha512-KRhQG9cUazPavJiJEFIJ3XAMjgfd0fcK3B+T26qOl8L0UG5aZUjeRfREO0KM5InGtYwxqiiytkJrbcYoLDEv0A==} + semantic-release@24.2.5: + resolution: {integrity: sha512-9xV49HNY8C0/WmPWxTlaNleiXhWb//qfMzG2c5X8/k7tuWcu8RssbuS+sujb/h7PiWSXv53mrQvV9hrO9b7vuQ==} engines: {node: '>=20.8.1'} hasBin: true @@ -5626,18 +5514,10 @@ packages: engines: {node: '>=10'} hasBin: true - send@1.2.0: - resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==} - engines: {node: '>= 18'} - serialize-error@7.0.1: resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==} engines: {node: '>=10'} - serve-static@2.2.0: - resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==} - engines: {node: '>= 18'} - set-blocking@2.0.0: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} @@ -5653,9 +5533,6 @@ packages: resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} engines: {node: '>= 0.4'} - setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -5664,13 +5541,10 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - shell-quote@1.8.2: - resolution: {integrity: sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==} + shell-quote@1.8.3: + resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==} engines: {node: '>= 0.4'} - shimmer@1.2.1: - resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==} - shlex@2.1.2: resolution: {integrity: sha512-Nz6gtibMVgYeMEhUjp2KuwAgqaJA1K155dU/HuDaEJUGgnmYfVtVZah+uerVWdH8UGnyahhDCgABbYTbs254+w==} @@ -5798,19 +5672,23 @@ packages: resolution: {integrity: sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==} engines: {node: ^18.17.0 || >=20.5.0} + stable-hash-x@0.1.1: + resolution: {integrity: sha512-l0x1D6vhnsNUGPFVDx45eif0y6eedVC8nm5uACTrVFJFtl2mLRW17aWtVyxFCpn5t94VUPkjU8vSLwIuwwqtJQ==} + engines: {node: '>=12.0.0'} + stable-hash@0.0.5: resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==} stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - std-env@3.9.0: resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} + stream-combiner2@1.1.1: resolution: {integrity: sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==} @@ -5913,8 +5791,8 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - tar-fs@2.1.2: - resolution: {integrity: sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==} + tar-fs@2.1.3: + resolution: {integrity: sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==} tar-stream@2.2.0: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} @@ -5979,23 +5857,23 @@ packages: tinyexec@0.3.2: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - tinyglobby@0.2.13: - resolution: {integrity: sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==} + tinyglobby@0.2.14: + resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} engines: {node: '>=12.0.0'} tinylogic@2.0.0: resolution: {integrity: sha512-dljTkiLLITtsjqBvTA1MRZQK/sGP4kI3UJKc3yA9fMzYbMF2RhcN04SeROVqJBIYYOoJMM8u0WDnhFwMSFQotw==} - tinypool@1.0.2: - resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} + tinypool@1.1.0: + resolution: {integrity: sha512-7CotroY9a8DKsKprEy/a14aCCm8jYVmR7aFy4fpkZM8sdpNJbKkixuNjgM50yCmip2ezc8z4N7k3oe2+rfRJCQ==} engines: {node: ^18.0.0 || >=20.0.0} tinyrainbow@2.0.0: resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} engines: {node: '>=14.0.0'} - tinyspy@3.0.2: - resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + tinyspy@4.0.3: + resolution: {integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==} engines: {node: '>=14.0.0'} tmp-promise@3.0.3: @@ -6009,10 +5887,6 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - toml-eslint-parser@0.10.0: resolution: {integrity: sha512-khrZo4buq4qVmsGzS5yQjKe/WsFvV8fGfOjDQN0q4iy9FjRfPWRgTFrU8u1R2iu/SfWLhY9WnCi4Jhdrcbtg+g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -6024,8 +5898,8 @@ packages: resolution: {integrity: sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==} engines: {node: '>= 0.4'} - tree-dump@1.0.2: - resolution: {integrity: sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==} + tree-dump@1.0.3: + resolution: {integrity: sha512-il+Cv80yVHFBwokQSfd4bldvr1Md951DpgAGfmhydt04L+YzHgubm2tQ7zueWDcGENKHq0ZvGFR/hjvNXilHEg==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' @@ -6050,16 +5924,16 @@ packages: peerDependencies: typescript: '>=4.8.4' - ts-essentials@10.0.4: - resolution: {integrity: sha512-lwYdz28+S4nicm+jFi6V58LaAIpxzhg9rLdgNC1VsdP/xiFBseGhF1M/shwCk6zMmwahBZdXcl34LVHrEang3A==} + ts-essentials@10.1.0: + resolution: {integrity: sha512-LirrVzbhIpFQ9BdGfqLnM9r7aP9rnyfeoxbP5ZEkdr531IaY21+KdebRSsbvqu28VDJtcDDn+AlGn95t0c52zQ==} peerDependencies: typescript: '>=4.5.0' peerDependenciesMeta: typescript: optional: true - tsconfck@3.1.5: - resolution: {integrity: sha512-CLDfGgUp7XPswWnezWwsCRxNmgQjhYq3VXHM0/XIRxhVrKw0M1if9agzryh1QS3nxjCROvV+xWxoJO1YctzzWg==} + tsconfck@3.1.6: + resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==} engines: {node: ^18 || >=20} hasBin: true peerDependencies: @@ -6135,10 +6009,6 @@ packages: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} - type-is@2.0.1: - resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} - engines: {node: '>= 0.6'} - typed-array-buffer@1.0.3: resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} @@ -6162,8 +6032,8 @@ packages: typedarray-to-buffer@3.1.5: resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} - typescript-eslint@8.32.1: - resolution: {integrity: sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg==} + typescript-eslint@8.33.1: + resolution: {integrity: sha512-AgRnV4sKkWOiZ0Kjbnf5ytTJXMUZQ0qhSVdQtDNYLPLnjsATEYhaO94GlRQwi4t4gO8FfjM6NnikHeKjUm8D7A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -6241,12 +6111,8 @@ packages: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} - unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - - unrs-resolver@1.7.2: - resolution: {integrity: sha512-BBKpaylOW8KbHsu378Zky/dGh4ckT/4NW/0SHRABdqRLcQJ2dAOjDo9g97p04sWflm0kqPqpUatxReNV/dqI5A==} + unrs-resolver@1.7.11: + resolution: {integrity: sha512-OhuAzBImFPjKNgZ2JwHMfGFUA6NSbRegd1+BPjC1Y0E6X9Y/vJ4zKeGmIMqmlYboj6cMNEwKI+xQisrg4J0HaQ==} upath@2.0.1: resolution: {integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==} @@ -6290,18 +6156,14 @@ packages: resolution: {integrity: sha512-d7KLgL1LD3U3fgnvWEY1cQXoO/q6EQ1BSz48Sa149V/5zVTAbgmZIpyI8TRi6U9/JNyeYLlTKsEMPtLC27RFUg==} engines: {node: ^18.17.0 || >=20.5.0} - vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - vfile-message@2.0.4: resolution: {integrity: sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==} vfile@4.2.1: resolution: {integrity: sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==} - vite-node@3.1.3: - resolution: {integrity: sha512-uHV4plJ2IxCl4u1up1FQRrqclylKAogbtBfOTwcuJ28xFi+89PZ57BRh+naIRvH70HPwxy5QHYzg1OrEaC7AbA==} + vite-node@3.2.1: + resolution: {integrity: sha512-V4EyKQPxquurNJPtQJRZo8hKOoKNBRIhxcDbQFPFig0JdoWcUhwRgK8yoCXXrfYVPKS6XwirGHPszLnR8FbjCA==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true @@ -6359,16 +6221,16 @@ packages: typescript: 3.x || 4.x || 5.x vitest: '>=3.0.0' - vitest@3.1.3: - resolution: {integrity: sha512-188iM4hAHQ0km23TN/adso1q5hhwKqUpv+Sd6p5sOuh6FhQnRNW3IsiIpvxqahtBabsJ2SLZgmGSpcYK4wQYJw==} + vitest@3.2.1: + resolution: {integrity: sha512-VZ40MBnlE1/V5uTgdqY3DmjUgZtIzsYq758JGlyQrv5syIsaYcabkfPkEuWML49Ph0D/SoqpVFd0dyVTr551oA==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/debug': ^4.1.12 '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.1.3 - '@vitest/ui': 3.1.3 + '@vitest/browser': 3.2.1 + '@vitest/ui': 3.2.1 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -6535,13 +6397,8 @@ packages: resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==} engines: {node: '>=18'} - zod-to-json-schema@3.24.5: - resolution: {integrity: sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==} - peerDependencies: - zod: ^3.24.1 - - zod@3.24.4: - resolution: {integrity: sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==} + zod@3.25.50: + resolution: {integrity: sha512-VstOnRxf4tlSq0raIwbn0n+LA34SxVoZ8r3pkwSUM0jqNiA/HCMQEVjTuS5FZmHsge+9MDGTiAuHyml5T0um6A==} zwitch@1.0.5: resolution: {integrity: sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==} @@ -6566,20 +6423,20 @@ snapshots: '@aws-crypto/crc32@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.775.0 + '@aws-sdk/types': 3.821.0 tslib: 2.8.1 '@aws-crypto/crc32c@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.775.0 + '@aws-sdk/types': 3.821.0 tslib: 2.8.1 '@aws-crypto/sha1-browser@5.2.0': dependencies: '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.775.0 + '@aws-sdk/types': 3.821.0 '@aws-sdk/util-locate-window': 3.804.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 @@ -6589,7 +6446,7 @@ snapshots: '@aws-crypto/sha256-js': 5.2.0 '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.775.0 + '@aws-sdk/types': 3.821.0 '@aws-sdk/util-locate-window': 3.804.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 @@ -6597,7 +6454,7 @@ snapshots: '@aws-crypto/sha256-js@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.775.0 + '@aws-sdk/types': 3.821.0 tslib: 2.8.1 '@aws-crypto/supports-web-crypto@5.2.0': @@ -6606,49 +6463,49 @@ snapshots: '@aws-crypto/util@5.2.0': dependencies: - '@aws-sdk/types': 3.775.0 + '@aws-sdk/types': 3.821.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 - '@aws-sdk/client-codecommit@3.799.0': + '@aws-sdk/client-codecommit@3.821.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.799.0 - '@aws-sdk/credential-provider-node': 3.799.0 - '@aws-sdk/middleware-host-header': 3.775.0 - '@aws-sdk/middleware-logger': 3.775.0 - '@aws-sdk/middleware-recursion-detection': 3.775.0 - '@aws-sdk/middleware-user-agent': 3.799.0 - '@aws-sdk/region-config-resolver': 3.775.0 - '@aws-sdk/types': 3.775.0 - '@aws-sdk/util-endpoints': 3.787.0 - '@aws-sdk/util-user-agent-browser': 3.775.0 - '@aws-sdk/util-user-agent-node': 3.799.0 - '@smithy/config-resolver': 4.1.2 - '@smithy/core': 3.3.3 - '@smithy/fetch-http-handler': 5.0.2 - '@smithy/hash-node': 4.0.2 - '@smithy/invalid-dependency': 4.0.2 - '@smithy/middleware-content-length': 4.0.2 - '@smithy/middleware-endpoint': 4.1.6 - '@smithy/middleware-retry': 4.1.7 - '@smithy/middleware-serde': 4.0.5 - '@smithy/middleware-stack': 4.0.2 - '@smithy/node-config-provider': 4.1.1 - '@smithy/node-http-handler': 4.0.4 - '@smithy/protocol-http': 5.1.0 - '@smithy/smithy-client': 4.2.6 - '@smithy/types': 4.2.0 - '@smithy/url-parser': 4.0.2 + '@aws-sdk/core': 3.821.0 + '@aws-sdk/credential-provider-node': 3.821.0 + '@aws-sdk/middleware-host-header': 3.821.0 + '@aws-sdk/middleware-logger': 3.821.0 + '@aws-sdk/middleware-recursion-detection': 3.821.0 + '@aws-sdk/middleware-user-agent': 3.821.0 + '@aws-sdk/region-config-resolver': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@aws-sdk/util-endpoints': 3.821.0 + '@aws-sdk/util-user-agent-browser': 3.821.0 + '@aws-sdk/util-user-agent-node': 3.821.0 + '@smithy/config-resolver': 4.1.4 + '@smithy/core': 3.5.3 + '@smithy/fetch-http-handler': 5.0.4 + '@smithy/hash-node': 4.0.4 + '@smithy/invalid-dependency': 4.0.4 + '@smithy/middleware-content-length': 4.0.4 + '@smithy/middleware-endpoint': 4.1.11 + '@smithy/middleware-retry': 4.1.12 + '@smithy/middleware-serde': 4.0.8 + '@smithy/middleware-stack': 4.0.4 + '@smithy/node-config-provider': 4.1.3 + '@smithy/node-http-handler': 4.0.6 + '@smithy/protocol-http': 5.1.2 + '@smithy/smithy-client': 4.4.3 + '@smithy/types': 4.3.1 + '@smithy/url-parser': 4.0.4 '@smithy/util-base64': 4.0.0 '@smithy/util-body-length-browser': 4.0.0 '@smithy/util-body-length-node': 4.0.0 - '@smithy/util-defaults-mode-browser': 4.0.14 - '@smithy/util-defaults-mode-node': 4.0.14 - '@smithy/util-endpoints': 3.0.4 - '@smithy/util-middleware': 4.0.2 - '@smithy/util-retry': 4.0.3 + '@smithy/util-defaults-mode-browser': 4.0.19 + '@smithy/util-defaults-mode-node': 4.0.19 + '@smithy/util-endpoints': 3.0.6 + '@smithy/util-middleware': 4.0.4 + '@smithy/util-retry': 4.0.5 '@smithy/util-utf8': 4.0.0 '@types/uuid': 9.0.8 tslib: 2.8.1 @@ -6656,707 +6513,708 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/client-cognito-identity@3.799.0': + '@aws-sdk/client-cognito-identity@3.821.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.799.0 - '@aws-sdk/credential-provider-node': 3.799.0 - '@aws-sdk/middleware-host-header': 3.775.0 - '@aws-sdk/middleware-logger': 3.775.0 - '@aws-sdk/middleware-recursion-detection': 3.775.0 - '@aws-sdk/middleware-user-agent': 3.799.0 - '@aws-sdk/region-config-resolver': 3.775.0 - '@aws-sdk/types': 3.775.0 - '@aws-sdk/util-endpoints': 3.787.0 - '@aws-sdk/util-user-agent-browser': 3.775.0 - '@aws-sdk/util-user-agent-node': 3.799.0 - '@smithy/config-resolver': 4.1.2 - '@smithy/core': 3.3.3 - '@smithy/fetch-http-handler': 5.0.2 - '@smithy/hash-node': 4.0.2 - '@smithy/invalid-dependency': 4.0.2 - '@smithy/middleware-content-length': 4.0.2 - '@smithy/middleware-endpoint': 4.1.6 - '@smithy/middleware-retry': 4.1.7 - '@smithy/middleware-serde': 4.0.5 - '@smithy/middleware-stack': 4.0.2 - '@smithy/node-config-provider': 4.1.1 - '@smithy/node-http-handler': 4.0.4 - '@smithy/protocol-http': 5.1.0 - '@smithy/smithy-client': 4.2.6 - '@smithy/types': 4.2.0 - '@smithy/url-parser': 4.0.2 + '@aws-sdk/core': 3.821.0 + '@aws-sdk/credential-provider-node': 3.821.0 + '@aws-sdk/middleware-host-header': 3.821.0 + '@aws-sdk/middleware-logger': 3.821.0 + '@aws-sdk/middleware-recursion-detection': 3.821.0 + '@aws-sdk/middleware-user-agent': 3.821.0 + '@aws-sdk/region-config-resolver': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@aws-sdk/util-endpoints': 3.821.0 + '@aws-sdk/util-user-agent-browser': 3.821.0 + '@aws-sdk/util-user-agent-node': 3.821.0 + '@smithy/config-resolver': 4.1.4 + '@smithy/core': 3.5.3 + '@smithy/fetch-http-handler': 5.0.4 + '@smithy/hash-node': 4.0.4 + '@smithy/invalid-dependency': 4.0.4 + '@smithy/middleware-content-length': 4.0.4 + '@smithy/middleware-endpoint': 4.1.11 + '@smithy/middleware-retry': 4.1.12 + '@smithy/middleware-serde': 4.0.8 + '@smithy/middleware-stack': 4.0.4 + '@smithy/node-config-provider': 4.1.3 + '@smithy/node-http-handler': 4.0.6 + '@smithy/protocol-http': 5.1.2 + '@smithy/smithy-client': 4.4.3 + '@smithy/types': 4.3.1 + '@smithy/url-parser': 4.0.4 '@smithy/util-base64': 4.0.0 '@smithy/util-body-length-browser': 4.0.0 '@smithy/util-body-length-node': 4.0.0 - '@smithy/util-defaults-mode-browser': 4.0.14 - '@smithy/util-defaults-mode-node': 4.0.14 - '@smithy/util-endpoints': 3.0.4 - '@smithy/util-middleware': 4.0.2 - '@smithy/util-retry': 4.0.3 + '@smithy/util-defaults-mode-browser': 4.0.19 + '@smithy/util-defaults-mode-node': 4.0.19 + '@smithy/util-endpoints': 3.0.6 + '@smithy/util-middleware': 4.0.4 + '@smithy/util-retry': 4.0.5 '@smithy/util-utf8': 4.0.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/client-ec2@3.800.0': + '@aws-sdk/client-ec2@3.821.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.799.0 - '@aws-sdk/credential-provider-node': 3.799.0 - '@aws-sdk/middleware-host-header': 3.775.0 - '@aws-sdk/middleware-logger': 3.775.0 - '@aws-sdk/middleware-recursion-detection': 3.775.0 - '@aws-sdk/middleware-sdk-ec2': 3.798.0 - '@aws-sdk/middleware-user-agent': 3.799.0 - '@aws-sdk/region-config-resolver': 3.775.0 - '@aws-sdk/types': 3.775.0 - '@aws-sdk/util-endpoints': 3.787.0 - '@aws-sdk/util-user-agent-browser': 3.775.0 - '@aws-sdk/util-user-agent-node': 3.799.0 - '@smithy/config-resolver': 4.1.2 - '@smithy/core': 3.3.3 - '@smithy/fetch-http-handler': 5.0.2 - '@smithy/hash-node': 4.0.2 - '@smithy/invalid-dependency': 4.0.2 - '@smithy/middleware-content-length': 4.0.2 - '@smithy/middleware-endpoint': 4.1.6 - '@smithy/middleware-retry': 4.1.7 - '@smithy/middleware-serde': 4.0.5 - '@smithy/middleware-stack': 4.0.2 - '@smithy/node-config-provider': 4.1.1 - '@smithy/node-http-handler': 4.0.4 - '@smithy/protocol-http': 5.1.0 - '@smithy/smithy-client': 4.2.6 - '@smithy/types': 4.2.0 - '@smithy/url-parser': 4.0.2 + '@aws-sdk/core': 3.821.0 + '@aws-sdk/credential-provider-node': 3.821.0 + '@aws-sdk/middleware-host-header': 3.821.0 + '@aws-sdk/middleware-logger': 3.821.0 + '@aws-sdk/middleware-recursion-detection': 3.821.0 + '@aws-sdk/middleware-sdk-ec2': 3.821.0 + '@aws-sdk/middleware-user-agent': 3.821.0 + '@aws-sdk/region-config-resolver': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@aws-sdk/util-endpoints': 3.821.0 + '@aws-sdk/util-user-agent-browser': 3.821.0 + '@aws-sdk/util-user-agent-node': 3.821.0 + '@smithy/config-resolver': 4.1.4 + '@smithy/core': 3.5.3 + '@smithy/fetch-http-handler': 5.0.4 + '@smithy/hash-node': 4.0.4 + '@smithy/invalid-dependency': 4.0.4 + '@smithy/middleware-content-length': 4.0.4 + '@smithy/middleware-endpoint': 4.1.11 + '@smithy/middleware-retry': 4.1.12 + '@smithy/middleware-serde': 4.0.8 + '@smithy/middleware-stack': 4.0.4 + '@smithy/node-config-provider': 4.1.3 + '@smithy/node-http-handler': 4.0.6 + '@smithy/protocol-http': 5.1.2 + '@smithy/smithy-client': 4.4.3 + '@smithy/types': 4.3.1 + '@smithy/url-parser': 4.0.4 '@smithy/util-base64': 4.0.0 '@smithy/util-body-length-browser': 4.0.0 '@smithy/util-body-length-node': 4.0.0 - '@smithy/util-defaults-mode-browser': 4.0.14 - '@smithy/util-defaults-mode-node': 4.0.14 - '@smithy/util-endpoints': 3.0.4 - '@smithy/util-middleware': 4.0.2 - '@smithy/util-retry': 4.0.3 + '@smithy/util-defaults-mode-browser': 4.0.19 + '@smithy/util-defaults-mode-node': 4.0.19 + '@smithy/util-endpoints': 3.0.6 + '@smithy/util-middleware': 4.0.4 + '@smithy/util-retry': 4.0.5 '@smithy/util-utf8': 4.0.0 - '@smithy/util-waiter': 4.0.3 + '@smithy/util-waiter': 4.0.5 '@types/uuid': 9.0.8 tslib: 2.8.1 uuid: 9.0.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/client-ecr@3.800.0': + '@aws-sdk/client-ecr@3.821.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.799.0 - '@aws-sdk/credential-provider-node': 3.799.0 - '@aws-sdk/middleware-host-header': 3.775.0 - '@aws-sdk/middleware-logger': 3.775.0 - '@aws-sdk/middleware-recursion-detection': 3.775.0 - '@aws-sdk/middleware-user-agent': 3.799.0 - '@aws-sdk/region-config-resolver': 3.775.0 - '@aws-sdk/types': 3.775.0 - '@aws-sdk/util-endpoints': 3.787.0 - '@aws-sdk/util-user-agent-browser': 3.775.0 - '@aws-sdk/util-user-agent-node': 3.799.0 - '@smithy/config-resolver': 4.1.2 - '@smithy/core': 3.3.3 - '@smithy/fetch-http-handler': 5.0.2 - '@smithy/hash-node': 4.0.2 - '@smithy/invalid-dependency': 4.0.2 - '@smithy/middleware-content-length': 4.0.2 - '@smithy/middleware-endpoint': 4.1.6 - '@smithy/middleware-retry': 4.1.7 - '@smithy/middleware-serde': 4.0.5 - '@smithy/middleware-stack': 4.0.2 - '@smithy/node-config-provider': 4.1.1 - '@smithy/node-http-handler': 4.0.4 - '@smithy/protocol-http': 5.1.0 - '@smithy/smithy-client': 4.2.6 - '@smithy/types': 4.2.0 - '@smithy/url-parser': 4.0.2 + '@aws-sdk/core': 3.821.0 + '@aws-sdk/credential-provider-node': 3.821.0 + '@aws-sdk/middleware-host-header': 3.821.0 + '@aws-sdk/middleware-logger': 3.821.0 + '@aws-sdk/middleware-recursion-detection': 3.821.0 + '@aws-sdk/middleware-user-agent': 3.821.0 + '@aws-sdk/region-config-resolver': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@aws-sdk/util-endpoints': 3.821.0 + '@aws-sdk/util-user-agent-browser': 3.821.0 + '@aws-sdk/util-user-agent-node': 3.821.0 + '@smithy/config-resolver': 4.1.4 + '@smithy/core': 3.5.3 + '@smithy/fetch-http-handler': 5.0.4 + '@smithy/hash-node': 4.0.4 + '@smithy/invalid-dependency': 4.0.4 + '@smithy/middleware-content-length': 4.0.4 + '@smithy/middleware-endpoint': 4.1.11 + '@smithy/middleware-retry': 4.1.12 + '@smithy/middleware-serde': 4.0.8 + '@smithy/middleware-stack': 4.0.4 + '@smithy/node-config-provider': 4.1.3 + '@smithy/node-http-handler': 4.0.6 + '@smithy/protocol-http': 5.1.2 + '@smithy/smithy-client': 4.4.3 + '@smithy/types': 4.3.1 + '@smithy/url-parser': 4.0.4 '@smithy/util-base64': 4.0.0 '@smithy/util-body-length-browser': 4.0.0 '@smithy/util-body-length-node': 4.0.0 - '@smithy/util-defaults-mode-browser': 4.0.14 - '@smithy/util-defaults-mode-node': 4.0.14 - '@smithy/util-endpoints': 3.0.4 - '@smithy/util-middleware': 4.0.2 - '@smithy/util-retry': 4.0.3 + '@smithy/util-defaults-mode-browser': 4.0.19 + '@smithy/util-defaults-mode-node': 4.0.19 + '@smithy/util-endpoints': 3.0.6 + '@smithy/util-middleware': 4.0.4 + '@smithy/util-retry': 4.0.5 '@smithy/util-utf8': 4.0.0 - '@smithy/util-waiter': 4.0.3 + '@smithy/util-waiter': 4.0.5 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/client-eks@3.799.0': + '@aws-sdk/client-eks@3.821.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.799.0 - '@aws-sdk/credential-provider-node': 3.799.0 - '@aws-sdk/middleware-host-header': 3.775.0 - '@aws-sdk/middleware-logger': 3.775.0 - '@aws-sdk/middleware-recursion-detection': 3.775.0 - '@aws-sdk/middleware-user-agent': 3.799.0 - '@aws-sdk/region-config-resolver': 3.775.0 - '@aws-sdk/types': 3.775.0 - '@aws-sdk/util-endpoints': 3.787.0 - '@aws-sdk/util-user-agent-browser': 3.775.0 - '@aws-sdk/util-user-agent-node': 3.799.0 - '@smithy/config-resolver': 4.1.2 - '@smithy/core': 3.3.3 - '@smithy/fetch-http-handler': 5.0.2 - '@smithy/hash-node': 4.0.2 - '@smithy/invalid-dependency': 4.0.2 - '@smithy/middleware-content-length': 4.0.2 - '@smithy/middleware-endpoint': 4.1.6 - '@smithy/middleware-retry': 4.1.7 - '@smithy/middleware-serde': 4.0.5 - '@smithy/middleware-stack': 4.0.2 - '@smithy/node-config-provider': 4.1.1 - '@smithy/node-http-handler': 4.0.4 - '@smithy/protocol-http': 5.1.0 - '@smithy/smithy-client': 4.2.6 - '@smithy/types': 4.2.0 - '@smithy/url-parser': 4.0.2 + '@aws-sdk/core': 3.821.0 + '@aws-sdk/credential-provider-node': 3.821.0 + '@aws-sdk/middleware-host-header': 3.821.0 + '@aws-sdk/middleware-logger': 3.821.0 + '@aws-sdk/middleware-recursion-detection': 3.821.0 + '@aws-sdk/middleware-user-agent': 3.821.0 + '@aws-sdk/region-config-resolver': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@aws-sdk/util-endpoints': 3.821.0 + '@aws-sdk/util-user-agent-browser': 3.821.0 + '@aws-sdk/util-user-agent-node': 3.821.0 + '@smithy/config-resolver': 4.1.4 + '@smithy/core': 3.5.3 + '@smithy/fetch-http-handler': 5.0.4 + '@smithy/hash-node': 4.0.4 + '@smithy/invalid-dependency': 4.0.4 + '@smithy/middleware-content-length': 4.0.4 + '@smithy/middleware-endpoint': 4.1.11 + '@smithy/middleware-retry': 4.1.12 + '@smithy/middleware-serde': 4.0.8 + '@smithy/middleware-stack': 4.0.4 + '@smithy/node-config-provider': 4.1.3 + '@smithy/node-http-handler': 4.0.6 + '@smithy/protocol-http': 5.1.2 + '@smithy/smithy-client': 4.4.3 + '@smithy/types': 4.3.1 + '@smithy/url-parser': 4.0.4 '@smithy/util-base64': 4.0.0 '@smithy/util-body-length-browser': 4.0.0 '@smithy/util-body-length-node': 4.0.0 - '@smithy/util-defaults-mode-browser': 4.0.14 - '@smithy/util-defaults-mode-node': 4.0.14 - '@smithy/util-endpoints': 3.0.4 - '@smithy/util-middleware': 4.0.2 - '@smithy/util-retry': 4.0.3 + '@smithy/util-defaults-mode-browser': 4.0.19 + '@smithy/util-defaults-mode-node': 4.0.19 + '@smithy/util-endpoints': 3.0.6 + '@smithy/util-middleware': 4.0.4 + '@smithy/util-retry': 4.0.5 '@smithy/util-utf8': 4.0.0 - '@smithy/util-waiter': 4.0.3 + '@smithy/util-waiter': 4.0.5 '@types/uuid': 9.0.8 tslib: 2.8.1 uuid: 9.0.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/client-rds@3.799.0': + '@aws-sdk/client-rds@3.821.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.799.0 - '@aws-sdk/credential-provider-node': 3.799.0 - '@aws-sdk/middleware-host-header': 3.775.0 - '@aws-sdk/middleware-logger': 3.775.0 - '@aws-sdk/middleware-recursion-detection': 3.775.0 - '@aws-sdk/middleware-sdk-rds': 3.798.0 - '@aws-sdk/middleware-user-agent': 3.799.0 - '@aws-sdk/region-config-resolver': 3.775.0 - '@aws-sdk/types': 3.775.0 - '@aws-sdk/util-endpoints': 3.787.0 - '@aws-sdk/util-user-agent-browser': 3.775.0 - '@aws-sdk/util-user-agent-node': 3.799.0 - '@smithy/config-resolver': 4.1.2 - '@smithy/core': 3.3.3 - '@smithy/fetch-http-handler': 5.0.2 - '@smithy/hash-node': 4.0.2 - '@smithy/invalid-dependency': 4.0.2 - '@smithy/middleware-content-length': 4.0.2 - '@smithy/middleware-endpoint': 4.1.6 - '@smithy/middleware-retry': 4.1.7 - '@smithy/middleware-serde': 4.0.5 - '@smithy/middleware-stack': 4.0.2 - '@smithy/node-config-provider': 4.1.1 - '@smithy/node-http-handler': 4.0.4 - '@smithy/protocol-http': 5.1.0 - '@smithy/smithy-client': 4.2.6 - '@smithy/types': 4.2.0 - '@smithy/url-parser': 4.0.2 + '@aws-sdk/core': 3.821.0 + '@aws-sdk/credential-provider-node': 3.821.0 + '@aws-sdk/middleware-host-header': 3.821.0 + '@aws-sdk/middleware-logger': 3.821.0 + '@aws-sdk/middleware-recursion-detection': 3.821.0 + '@aws-sdk/middleware-sdk-rds': 3.821.0 + '@aws-sdk/middleware-user-agent': 3.821.0 + '@aws-sdk/region-config-resolver': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@aws-sdk/util-endpoints': 3.821.0 + '@aws-sdk/util-user-agent-browser': 3.821.0 + '@aws-sdk/util-user-agent-node': 3.821.0 + '@smithy/config-resolver': 4.1.4 + '@smithy/core': 3.5.3 + '@smithy/fetch-http-handler': 5.0.4 + '@smithy/hash-node': 4.0.4 + '@smithy/invalid-dependency': 4.0.4 + '@smithy/middleware-content-length': 4.0.4 + '@smithy/middleware-endpoint': 4.1.11 + '@smithy/middleware-retry': 4.1.12 + '@smithy/middleware-serde': 4.0.8 + '@smithy/middleware-stack': 4.0.4 + '@smithy/node-config-provider': 4.1.3 + '@smithy/node-http-handler': 4.0.6 + '@smithy/protocol-http': 5.1.2 + '@smithy/smithy-client': 4.4.3 + '@smithy/types': 4.3.1 + '@smithy/url-parser': 4.0.4 '@smithy/util-base64': 4.0.0 '@smithy/util-body-length-browser': 4.0.0 '@smithy/util-body-length-node': 4.0.0 - '@smithy/util-defaults-mode-browser': 4.0.14 - '@smithy/util-defaults-mode-node': 4.0.14 - '@smithy/util-endpoints': 3.0.4 - '@smithy/util-middleware': 4.0.2 - '@smithy/util-retry': 4.0.3 + '@smithy/util-defaults-mode-browser': 4.0.19 + '@smithy/util-defaults-mode-node': 4.0.19 + '@smithy/util-endpoints': 3.0.6 + '@smithy/util-middleware': 4.0.4 + '@smithy/util-retry': 4.0.5 '@smithy/util-utf8': 4.0.0 - '@smithy/util-waiter': 4.0.3 + '@smithy/util-waiter': 4.0.5 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/client-s3@3.800.0': + '@aws-sdk/client-s3@3.821.0': dependencies: '@aws-crypto/sha1-browser': 5.2.0 '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.799.0 - '@aws-sdk/credential-provider-node': 3.799.0 - '@aws-sdk/middleware-bucket-endpoint': 3.775.0 - '@aws-sdk/middleware-expect-continue': 3.775.0 - '@aws-sdk/middleware-flexible-checksums': 3.799.0 - '@aws-sdk/middleware-host-header': 3.775.0 - '@aws-sdk/middleware-location-constraint': 3.775.0 - '@aws-sdk/middleware-logger': 3.775.0 - '@aws-sdk/middleware-recursion-detection': 3.775.0 - '@aws-sdk/middleware-sdk-s3': 3.799.0 - '@aws-sdk/middleware-ssec': 3.775.0 - '@aws-sdk/middleware-user-agent': 3.799.0 - '@aws-sdk/region-config-resolver': 3.775.0 - '@aws-sdk/signature-v4-multi-region': 3.800.0 - '@aws-sdk/types': 3.775.0 - '@aws-sdk/util-endpoints': 3.787.0 - '@aws-sdk/util-user-agent-browser': 3.775.0 - '@aws-sdk/util-user-agent-node': 3.799.0 - '@aws-sdk/xml-builder': 3.775.0 - '@smithy/config-resolver': 4.1.2 - '@smithy/core': 3.3.3 - '@smithy/eventstream-serde-browser': 4.0.2 - '@smithy/eventstream-serde-config-resolver': 4.1.0 - '@smithy/eventstream-serde-node': 4.0.2 - '@smithy/fetch-http-handler': 5.0.2 - '@smithy/hash-blob-browser': 4.0.2 - '@smithy/hash-node': 4.0.2 - '@smithy/hash-stream-node': 4.0.2 - '@smithy/invalid-dependency': 4.0.2 - '@smithy/md5-js': 4.0.2 - '@smithy/middleware-content-length': 4.0.2 - '@smithy/middleware-endpoint': 4.1.6 - '@smithy/middleware-retry': 4.1.7 - '@smithy/middleware-serde': 4.0.5 - '@smithy/middleware-stack': 4.0.2 - '@smithy/node-config-provider': 4.1.1 - '@smithy/node-http-handler': 4.0.4 - '@smithy/protocol-http': 5.1.0 - '@smithy/smithy-client': 4.2.6 - '@smithy/types': 4.2.0 - '@smithy/url-parser': 4.0.2 + '@aws-sdk/core': 3.821.0 + '@aws-sdk/credential-provider-node': 3.821.0 + '@aws-sdk/middleware-bucket-endpoint': 3.821.0 + '@aws-sdk/middleware-expect-continue': 3.821.0 + '@aws-sdk/middleware-flexible-checksums': 3.821.0 + '@aws-sdk/middleware-host-header': 3.821.0 + '@aws-sdk/middleware-location-constraint': 3.821.0 + '@aws-sdk/middleware-logger': 3.821.0 + '@aws-sdk/middleware-recursion-detection': 3.821.0 + '@aws-sdk/middleware-sdk-s3': 3.821.0 + '@aws-sdk/middleware-ssec': 3.821.0 + '@aws-sdk/middleware-user-agent': 3.821.0 + '@aws-sdk/region-config-resolver': 3.821.0 + '@aws-sdk/signature-v4-multi-region': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@aws-sdk/util-endpoints': 3.821.0 + '@aws-sdk/util-user-agent-browser': 3.821.0 + '@aws-sdk/util-user-agent-node': 3.821.0 + '@aws-sdk/xml-builder': 3.821.0 + '@smithy/config-resolver': 4.1.4 + '@smithy/core': 3.5.3 + '@smithy/eventstream-serde-browser': 4.0.4 + '@smithy/eventstream-serde-config-resolver': 4.1.2 + '@smithy/eventstream-serde-node': 4.0.4 + '@smithy/fetch-http-handler': 5.0.4 + '@smithy/hash-blob-browser': 4.0.4 + '@smithy/hash-node': 4.0.4 + '@smithy/hash-stream-node': 4.0.4 + '@smithy/invalid-dependency': 4.0.4 + '@smithy/md5-js': 4.0.4 + '@smithy/middleware-content-length': 4.0.4 + '@smithy/middleware-endpoint': 4.1.11 + '@smithy/middleware-retry': 4.1.12 + '@smithy/middleware-serde': 4.0.8 + '@smithy/middleware-stack': 4.0.4 + '@smithy/node-config-provider': 4.1.3 + '@smithy/node-http-handler': 4.0.6 + '@smithy/protocol-http': 5.1.2 + '@smithy/smithy-client': 4.4.3 + '@smithy/types': 4.3.1 + '@smithy/url-parser': 4.0.4 '@smithy/util-base64': 4.0.0 '@smithy/util-body-length-browser': 4.0.0 '@smithy/util-body-length-node': 4.0.0 - '@smithy/util-defaults-mode-browser': 4.0.14 - '@smithy/util-defaults-mode-node': 4.0.14 - '@smithy/util-endpoints': 3.0.4 - '@smithy/util-middleware': 4.0.2 - '@smithy/util-retry': 4.0.3 - '@smithy/util-stream': 4.2.0 + '@smithy/util-defaults-mode-browser': 4.0.19 + '@smithy/util-defaults-mode-node': 4.0.19 + '@smithy/util-endpoints': 3.0.6 + '@smithy/util-middleware': 4.0.4 + '@smithy/util-retry': 4.0.5 + '@smithy/util-stream': 4.2.2 '@smithy/util-utf8': 4.0.0 - '@smithy/util-waiter': 4.0.3 + '@smithy/util-waiter': 4.0.5 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/client-sso@3.799.0': + '@aws-sdk/client-sso@3.821.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.799.0 - '@aws-sdk/middleware-host-header': 3.775.0 - '@aws-sdk/middleware-logger': 3.775.0 - '@aws-sdk/middleware-recursion-detection': 3.775.0 - '@aws-sdk/middleware-user-agent': 3.799.0 - '@aws-sdk/region-config-resolver': 3.775.0 - '@aws-sdk/types': 3.775.0 - '@aws-sdk/util-endpoints': 3.787.0 - '@aws-sdk/util-user-agent-browser': 3.775.0 - '@aws-sdk/util-user-agent-node': 3.799.0 - '@smithy/config-resolver': 4.1.2 - '@smithy/core': 3.3.3 - '@smithy/fetch-http-handler': 5.0.2 - '@smithy/hash-node': 4.0.2 - '@smithy/invalid-dependency': 4.0.2 - '@smithy/middleware-content-length': 4.0.2 - '@smithy/middleware-endpoint': 4.1.6 - '@smithy/middleware-retry': 4.1.7 - '@smithy/middleware-serde': 4.0.5 - '@smithy/middleware-stack': 4.0.2 - '@smithy/node-config-provider': 4.1.1 - '@smithy/node-http-handler': 4.0.4 - '@smithy/protocol-http': 5.1.0 - '@smithy/smithy-client': 4.2.6 - '@smithy/types': 4.2.0 - '@smithy/url-parser': 4.0.2 + '@aws-sdk/core': 3.821.0 + '@aws-sdk/middleware-host-header': 3.821.0 + '@aws-sdk/middleware-logger': 3.821.0 + '@aws-sdk/middleware-recursion-detection': 3.821.0 + '@aws-sdk/middleware-user-agent': 3.821.0 + '@aws-sdk/region-config-resolver': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@aws-sdk/util-endpoints': 3.821.0 + '@aws-sdk/util-user-agent-browser': 3.821.0 + '@aws-sdk/util-user-agent-node': 3.821.0 + '@smithy/config-resolver': 4.1.4 + '@smithy/core': 3.5.3 + '@smithy/fetch-http-handler': 5.0.4 + '@smithy/hash-node': 4.0.4 + '@smithy/invalid-dependency': 4.0.4 + '@smithy/middleware-content-length': 4.0.4 + '@smithy/middleware-endpoint': 4.1.11 + '@smithy/middleware-retry': 4.1.12 + '@smithy/middleware-serde': 4.0.8 + '@smithy/middleware-stack': 4.0.4 + '@smithy/node-config-provider': 4.1.3 + '@smithy/node-http-handler': 4.0.6 + '@smithy/protocol-http': 5.1.2 + '@smithy/smithy-client': 4.4.3 + '@smithy/types': 4.3.1 + '@smithy/url-parser': 4.0.4 '@smithy/util-base64': 4.0.0 '@smithy/util-body-length-browser': 4.0.0 '@smithy/util-body-length-node': 4.0.0 - '@smithy/util-defaults-mode-browser': 4.0.14 - '@smithy/util-defaults-mode-node': 4.0.14 - '@smithy/util-endpoints': 3.0.4 - '@smithy/util-middleware': 4.0.2 - '@smithy/util-retry': 4.0.3 + '@smithy/util-defaults-mode-browser': 4.0.19 + '@smithy/util-defaults-mode-node': 4.0.19 + '@smithy/util-endpoints': 3.0.6 + '@smithy/util-middleware': 4.0.4 + '@smithy/util-retry': 4.0.5 '@smithy/util-utf8': 4.0.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/core@3.799.0': - dependencies: - '@aws-sdk/types': 3.775.0 - '@smithy/core': 3.3.3 - '@smithy/node-config-provider': 4.1.1 - '@smithy/property-provider': 4.0.2 - '@smithy/protocol-http': 5.1.0 - '@smithy/signature-v4': 5.1.0 - '@smithy/smithy-client': 4.2.6 - '@smithy/types': 4.2.0 - '@smithy/util-middleware': 4.0.2 + '@aws-sdk/core@3.821.0': + dependencies: + '@aws-sdk/types': 3.821.0 + '@smithy/core': 3.5.3 + '@smithy/node-config-provider': 4.1.3 + '@smithy/property-provider': 4.0.4 + '@smithy/protocol-http': 5.1.2 + '@smithy/signature-v4': 5.1.2 + '@smithy/smithy-client': 4.4.3 + '@smithy/types': 4.3.1 + '@smithy/util-middleware': 4.0.4 fast-xml-parser: 4.4.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-cognito-identity@3.799.0': + '@aws-sdk/credential-provider-cognito-identity@3.821.0': dependencies: - '@aws-sdk/client-cognito-identity': 3.799.0 - '@aws-sdk/types': 3.775.0 - '@smithy/property-provider': 4.0.2 - '@smithy/types': 4.2.0 + '@aws-sdk/client-cognito-identity': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@smithy/property-provider': 4.0.4 + '@smithy/types': 4.3.1 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-env@3.799.0': + '@aws-sdk/credential-provider-env@3.821.0': dependencies: - '@aws-sdk/core': 3.799.0 - '@aws-sdk/types': 3.775.0 - '@smithy/property-provider': 4.0.2 - '@smithy/types': 4.2.0 + '@aws-sdk/core': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@smithy/property-provider': 4.0.4 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-http@3.799.0': - dependencies: - '@aws-sdk/core': 3.799.0 - '@aws-sdk/types': 3.775.0 - '@smithy/fetch-http-handler': 5.0.2 - '@smithy/node-http-handler': 4.0.4 - '@smithy/property-provider': 4.0.2 - '@smithy/protocol-http': 5.1.0 - '@smithy/smithy-client': 4.2.6 - '@smithy/types': 4.2.0 - '@smithy/util-stream': 4.2.0 + '@aws-sdk/credential-provider-http@3.821.0': + dependencies: + '@aws-sdk/core': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@smithy/fetch-http-handler': 5.0.4 + '@smithy/node-http-handler': 4.0.6 + '@smithy/property-provider': 4.0.4 + '@smithy/protocol-http': 5.1.2 + '@smithy/smithy-client': 4.4.3 + '@smithy/types': 4.3.1 + '@smithy/util-stream': 4.2.2 tslib: 2.8.1 - '@aws-sdk/credential-provider-ini@3.799.0': - dependencies: - '@aws-sdk/core': 3.799.0 - '@aws-sdk/credential-provider-env': 3.799.0 - '@aws-sdk/credential-provider-http': 3.799.0 - '@aws-sdk/credential-provider-process': 3.799.0 - '@aws-sdk/credential-provider-sso': 3.799.0 - '@aws-sdk/credential-provider-web-identity': 3.799.0 - '@aws-sdk/nested-clients': 3.799.0 - '@aws-sdk/types': 3.775.0 - '@smithy/credential-provider-imds': 4.0.4 - '@smithy/property-provider': 4.0.2 - '@smithy/shared-ini-file-loader': 4.0.2 - '@smithy/types': 4.2.0 + '@aws-sdk/credential-provider-ini@3.821.0': + dependencies: + '@aws-sdk/core': 3.821.0 + '@aws-sdk/credential-provider-env': 3.821.0 + '@aws-sdk/credential-provider-http': 3.821.0 + '@aws-sdk/credential-provider-process': 3.821.0 + '@aws-sdk/credential-provider-sso': 3.821.0 + '@aws-sdk/credential-provider-web-identity': 3.821.0 + '@aws-sdk/nested-clients': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@smithy/credential-provider-imds': 4.0.6 + '@smithy/property-provider': 4.0.4 + '@smithy/shared-ini-file-loader': 4.0.4 + '@smithy/types': 4.3.1 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-node@3.799.0': - dependencies: - '@aws-sdk/credential-provider-env': 3.799.0 - '@aws-sdk/credential-provider-http': 3.799.0 - '@aws-sdk/credential-provider-ini': 3.799.0 - '@aws-sdk/credential-provider-process': 3.799.0 - '@aws-sdk/credential-provider-sso': 3.799.0 - '@aws-sdk/credential-provider-web-identity': 3.799.0 - '@aws-sdk/types': 3.775.0 - '@smithy/credential-provider-imds': 4.0.4 - '@smithy/property-provider': 4.0.2 - '@smithy/shared-ini-file-loader': 4.0.2 - '@smithy/types': 4.2.0 + '@aws-sdk/credential-provider-node@3.821.0': + dependencies: + '@aws-sdk/credential-provider-env': 3.821.0 + '@aws-sdk/credential-provider-http': 3.821.0 + '@aws-sdk/credential-provider-ini': 3.821.0 + '@aws-sdk/credential-provider-process': 3.821.0 + '@aws-sdk/credential-provider-sso': 3.821.0 + '@aws-sdk/credential-provider-web-identity': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@smithy/credential-provider-imds': 4.0.6 + '@smithy/property-provider': 4.0.4 + '@smithy/shared-ini-file-loader': 4.0.4 + '@smithy/types': 4.3.1 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-process@3.799.0': + '@aws-sdk/credential-provider-process@3.821.0': dependencies: - '@aws-sdk/core': 3.799.0 - '@aws-sdk/types': 3.775.0 - '@smithy/property-provider': 4.0.2 - '@smithy/shared-ini-file-loader': 4.0.2 - '@smithy/types': 4.2.0 + '@aws-sdk/core': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@smithy/property-provider': 4.0.4 + '@smithy/shared-ini-file-loader': 4.0.4 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-sso@3.799.0': + '@aws-sdk/credential-provider-sso@3.821.0': dependencies: - '@aws-sdk/client-sso': 3.799.0 - '@aws-sdk/core': 3.799.0 - '@aws-sdk/token-providers': 3.799.0 - '@aws-sdk/types': 3.775.0 - '@smithy/property-provider': 4.0.2 - '@smithy/shared-ini-file-loader': 4.0.2 - '@smithy/types': 4.2.0 + '@aws-sdk/client-sso': 3.821.0 + '@aws-sdk/core': 3.821.0 + '@aws-sdk/token-providers': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@smithy/property-provider': 4.0.4 + '@smithy/shared-ini-file-loader': 4.0.4 + '@smithy/types': 4.3.1 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-web-identity@3.799.0': + '@aws-sdk/credential-provider-web-identity@3.821.0': dependencies: - '@aws-sdk/core': 3.799.0 - '@aws-sdk/nested-clients': 3.799.0 - '@aws-sdk/types': 3.775.0 - '@smithy/property-provider': 4.0.2 - '@smithy/types': 4.2.0 + '@aws-sdk/core': 3.821.0 + '@aws-sdk/nested-clients': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@smithy/property-provider': 4.0.4 + '@smithy/types': 4.3.1 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-providers@3.799.0': - dependencies: - '@aws-sdk/client-cognito-identity': 3.799.0 - '@aws-sdk/core': 3.799.0 - '@aws-sdk/credential-provider-cognito-identity': 3.799.0 - '@aws-sdk/credential-provider-env': 3.799.0 - '@aws-sdk/credential-provider-http': 3.799.0 - '@aws-sdk/credential-provider-ini': 3.799.0 - '@aws-sdk/credential-provider-node': 3.799.0 - '@aws-sdk/credential-provider-process': 3.799.0 - '@aws-sdk/credential-provider-sso': 3.799.0 - '@aws-sdk/credential-provider-web-identity': 3.799.0 - '@aws-sdk/nested-clients': 3.799.0 - '@aws-sdk/types': 3.775.0 - '@smithy/config-resolver': 4.1.2 - '@smithy/core': 3.3.3 - '@smithy/credential-provider-imds': 4.0.4 - '@smithy/node-config-provider': 4.1.1 - '@smithy/property-provider': 4.0.2 - '@smithy/types': 4.2.0 + '@aws-sdk/credential-providers@3.821.0': + dependencies: + '@aws-sdk/client-cognito-identity': 3.821.0 + '@aws-sdk/core': 3.821.0 + '@aws-sdk/credential-provider-cognito-identity': 3.821.0 + '@aws-sdk/credential-provider-env': 3.821.0 + '@aws-sdk/credential-provider-http': 3.821.0 + '@aws-sdk/credential-provider-ini': 3.821.0 + '@aws-sdk/credential-provider-node': 3.821.0 + '@aws-sdk/credential-provider-process': 3.821.0 + '@aws-sdk/credential-provider-sso': 3.821.0 + '@aws-sdk/credential-provider-web-identity': 3.821.0 + '@aws-sdk/nested-clients': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@smithy/config-resolver': 4.1.4 + '@smithy/core': 3.5.3 + '@smithy/credential-provider-imds': 4.0.6 + '@smithy/node-config-provider': 4.1.3 + '@smithy/property-provider': 4.0.4 + '@smithy/types': 4.3.1 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/middleware-bucket-endpoint@3.775.0': + '@aws-sdk/middleware-bucket-endpoint@3.821.0': dependencies: - '@aws-sdk/types': 3.775.0 - '@aws-sdk/util-arn-parser': 3.723.0 - '@smithy/node-config-provider': 4.1.1 - '@smithy/protocol-http': 5.1.0 - '@smithy/types': 4.2.0 + '@aws-sdk/types': 3.821.0 + '@aws-sdk/util-arn-parser': 3.804.0 + '@smithy/node-config-provider': 4.1.3 + '@smithy/protocol-http': 5.1.2 + '@smithy/types': 4.3.1 '@smithy/util-config-provider': 4.0.0 tslib: 2.8.1 - '@aws-sdk/middleware-expect-continue@3.775.0': + '@aws-sdk/middleware-expect-continue@3.821.0': dependencies: - '@aws-sdk/types': 3.775.0 - '@smithy/protocol-http': 5.1.0 - '@smithy/types': 4.2.0 + '@aws-sdk/types': 3.821.0 + '@smithy/protocol-http': 5.1.2 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@aws-sdk/middleware-flexible-checksums@3.799.0': + '@aws-sdk/middleware-flexible-checksums@3.821.0': dependencies: '@aws-crypto/crc32': 5.2.0 '@aws-crypto/crc32c': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/core': 3.799.0 - '@aws-sdk/types': 3.775.0 + '@aws-sdk/core': 3.821.0 + '@aws-sdk/types': 3.821.0 '@smithy/is-array-buffer': 4.0.0 - '@smithy/node-config-provider': 4.1.1 - '@smithy/protocol-http': 5.1.0 - '@smithy/types': 4.2.0 - '@smithy/util-middleware': 4.0.2 - '@smithy/util-stream': 4.2.0 + '@smithy/node-config-provider': 4.1.3 + '@smithy/protocol-http': 5.1.2 + '@smithy/types': 4.3.1 + '@smithy/util-middleware': 4.0.4 + '@smithy/util-stream': 4.2.2 '@smithy/util-utf8': 4.0.0 tslib: 2.8.1 - '@aws-sdk/middleware-host-header@3.775.0': + '@aws-sdk/middleware-host-header@3.821.0': dependencies: - '@aws-sdk/types': 3.775.0 - '@smithy/protocol-http': 5.1.0 - '@smithy/types': 4.2.0 + '@aws-sdk/types': 3.821.0 + '@smithy/protocol-http': 5.1.2 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@aws-sdk/middleware-location-constraint@3.775.0': + '@aws-sdk/middleware-location-constraint@3.821.0': dependencies: - '@aws-sdk/types': 3.775.0 - '@smithy/types': 4.2.0 + '@aws-sdk/types': 3.821.0 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@aws-sdk/middleware-logger@3.775.0': + '@aws-sdk/middleware-logger@3.821.0': dependencies: - '@aws-sdk/types': 3.775.0 - '@smithy/types': 4.2.0 + '@aws-sdk/types': 3.821.0 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@aws-sdk/middleware-recursion-detection@3.775.0': + '@aws-sdk/middleware-recursion-detection@3.821.0': dependencies: - '@aws-sdk/types': 3.775.0 - '@smithy/protocol-http': 5.1.0 - '@smithy/types': 4.2.0 + '@aws-sdk/types': 3.821.0 + '@smithy/protocol-http': 5.1.2 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-ec2@3.798.0': + '@aws-sdk/middleware-sdk-ec2@3.821.0': dependencies: - '@aws-sdk/types': 3.775.0 - '@aws-sdk/util-format-url': 3.775.0 - '@smithy/middleware-endpoint': 4.1.6 - '@smithy/protocol-http': 5.1.0 - '@smithy/signature-v4': 5.1.0 - '@smithy/smithy-client': 4.2.6 - '@smithy/types': 4.2.0 + '@aws-sdk/types': 3.821.0 + '@aws-sdk/util-format-url': 3.821.0 + '@smithy/middleware-endpoint': 4.1.11 + '@smithy/protocol-http': 5.1.2 + '@smithy/signature-v4': 5.1.2 + '@smithy/smithy-client': 4.4.3 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-rds@3.798.0': + '@aws-sdk/middleware-sdk-rds@3.821.0': dependencies: - '@aws-sdk/types': 3.775.0 - '@aws-sdk/util-format-url': 3.775.0 - '@smithy/middleware-endpoint': 4.1.6 - '@smithy/protocol-http': 5.1.0 - '@smithy/signature-v4': 5.1.0 - '@smithy/types': 4.2.0 + '@aws-sdk/types': 3.821.0 + '@aws-sdk/util-format-url': 3.821.0 + '@smithy/middleware-endpoint': 4.1.11 + '@smithy/protocol-http': 5.1.2 + '@smithy/signature-v4': 5.1.2 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-s3@3.799.0': - dependencies: - '@aws-sdk/core': 3.799.0 - '@aws-sdk/types': 3.775.0 - '@aws-sdk/util-arn-parser': 3.723.0 - '@smithy/core': 3.3.3 - '@smithy/node-config-provider': 4.1.1 - '@smithy/protocol-http': 5.1.0 - '@smithy/signature-v4': 5.1.0 - '@smithy/smithy-client': 4.2.6 - '@smithy/types': 4.2.0 + '@aws-sdk/middleware-sdk-s3@3.821.0': + dependencies: + '@aws-sdk/core': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@aws-sdk/util-arn-parser': 3.804.0 + '@smithy/core': 3.5.3 + '@smithy/node-config-provider': 4.1.3 + '@smithy/protocol-http': 5.1.2 + '@smithy/signature-v4': 5.1.2 + '@smithy/smithy-client': 4.4.3 + '@smithy/types': 4.3.1 '@smithy/util-config-provider': 4.0.0 - '@smithy/util-middleware': 4.0.2 - '@smithy/util-stream': 4.2.0 + '@smithy/util-middleware': 4.0.4 + '@smithy/util-stream': 4.2.2 '@smithy/util-utf8': 4.0.0 tslib: 2.8.1 - '@aws-sdk/middleware-ssec@3.775.0': + '@aws-sdk/middleware-ssec@3.821.0': dependencies: - '@aws-sdk/types': 3.775.0 - '@smithy/types': 4.2.0 + '@aws-sdk/types': 3.821.0 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@aws-sdk/middleware-user-agent@3.799.0': + '@aws-sdk/middleware-user-agent@3.821.0': dependencies: - '@aws-sdk/core': 3.799.0 - '@aws-sdk/types': 3.775.0 - '@aws-sdk/util-endpoints': 3.787.0 - '@smithy/core': 3.3.3 - '@smithy/protocol-http': 5.1.0 - '@smithy/types': 4.2.0 + '@aws-sdk/core': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@aws-sdk/util-endpoints': 3.821.0 + '@smithy/core': 3.5.3 + '@smithy/protocol-http': 5.1.2 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@aws-sdk/nested-clients@3.799.0': + '@aws-sdk/nested-clients@3.821.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.799.0 - '@aws-sdk/middleware-host-header': 3.775.0 - '@aws-sdk/middleware-logger': 3.775.0 - '@aws-sdk/middleware-recursion-detection': 3.775.0 - '@aws-sdk/middleware-user-agent': 3.799.0 - '@aws-sdk/region-config-resolver': 3.775.0 - '@aws-sdk/types': 3.775.0 - '@aws-sdk/util-endpoints': 3.787.0 - '@aws-sdk/util-user-agent-browser': 3.775.0 - '@aws-sdk/util-user-agent-node': 3.799.0 - '@smithy/config-resolver': 4.1.2 - '@smithy/core': 3.3.3 - '@smithy/fetch-http-handler': 5.0.2 - '@smithy/hash-node': 4.0.2 - '@smithy/invalid-dependency': 4.0.2 - '@smithy/middleware-content-length': 4.0.2 - '@smithy/middleware-endpoint': 4.1.6 - '@smithy/middleware-retry': 4.1.7 - '@smithy/middleware-serde': 4.0.5 - '@smithy/middleware-stack': 4.0.2 - '@smithy/node-config-provider': 4.1.1 - '@smithy/node-http-handler': 4.0.4 - '@smithy/protocol-http': 5.1.0 - '@smithy/smithy-client': 4.2.6 - '@smithy/types': 4.2.0 - '@smithy/url-parser': 4.0.2 + '@aws-sdk/core': 3.821.0 + '@aws-sdk/middleware-host-header': 3.821.0 + '@aws-sdk/middleware-logger': 3.821.0 + '@aws-sdk/middleware-recursion-detection': 3.821.0 + '@aws-sdk/middleware-user-agent': 3.821.0 + '@aws-sdk/region-config-resolver': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@aws-sdk/util-endpoints': 3.821.0 + '@aws-sdk/util-user-agent-browser': 3.821.0 + '@aws-sdk/util-user-agent-node': 3.821.0 + '@smithy/config-resolver': 4.1.4 + '@smithy/core': 3.5.3 + '@smithy/fetch-http-handler': 5.0.4 + '@smithy/hash-node': 4.0.4 + '@smithy/invalid-dependency': 4.0.4 + '@smithy/middleware-content-length': 4.0.4 + '@smithy/middleware-endpoint': 4.1.11 + '@smithy/middleware-retry': 4.1.12 + '@smithy/middleware-serde': 4.0.8 + '@smithy/middleware-stack': 4.0.4 + '@smithy/node-config-provider': 4.1.3 + '@smithy/node-http-handler': 4.0.6 + '@smithy/protocol-http': 5.1.2 + '@smithy/smithy-client': 4.4.3 + '@smithy/types': 4.3.1 + '@smithy/url-parser': 4.0.4 '@smithy/util-base64': 4.0.0 '@smithy/util-body-length-browser': 4.0.0 '@smithy/util-body-length-node': 4.0.0 - '@smithy/util-defaults-mode-browser': 4.0.14 - '@smithy/util-defaults-mode-node': 4.0.14 - '@smithy/util-endpoints': 3.0.4 - '@smithy/util-middleware': 4.0.2 - '@smithy/util-retry': 4.0.3 + '@smithy/util-defaults-mode-browser': 4.0.19 + '@smithy/util-defaults-mode-node': 4.0.19 + '@smithy/util-endpoints': 3.0.6 + '@smithy/util-middleware': 4.0.4 + '@smithy/util-retry': 4.0.5 '@smithy/util-utf8': 4.0.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/region-config-resolver@3.775.0': + '@aws-sdk/region-config-resolver@3.821.0': dependencies: - '@aws-sdk/types': 3.775.0 - '@smithy/node-config-provider': 4.1.1 - '@smithy/types': 4.2.0 + '@aws-sdk/types': 3.821.0 + '@smithy/node-config-provider': 4.1.3 + '@smithy/types': 4.3.1 '@smithy/util-config-provider': 4.0.0 - '@smithy/util-middleware': 4.0.2 + '@smithy/util-middleware': 4.0.4 tslib: 2.8.1 - '@aws-sdk/signature-v4-multi-region@3.800.0': + '@aws-sdk/signature-v4-multi-region@3.821.0': dependencies: - '@aws-sdk/middleware-sdk-s3': 3.799.0 - '@aws-sdk/types': 3.775.0 - '@smithy/protocol-http': 5.1.0 - '@smithy/signature-v4': 5.1.0 - '@smithy/types': 4.2.0 + '@aws-sdk/middleware-sdk-s3': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@smithy/protocol-http': 5.1.2 + '@smithy/signature-v4': 5.1.2 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@aws-sdk/token-providers@3.799.0': + '@aws-sdk/token-providers@3.821.0': dependencies: - '@aws-sdk/nested-clients': 3.799.0 - '@aws-sdk/types': 3.775.0 - '@smithy/property-provider': 4.0.2 - '@smithy/shared-ini-file-loader': 4.0.2 - '@smithy/types': 4.2.0 + '@aws-sdk/core': 3.821.0 + '@aws-sdk/nested-clients': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@smithy/property-provider': 4.0.4 + '@smithy/shared-ini-file-loader': 4.0.4 + '@smithy/types': 4.3.1 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/types@3.775.0': + '@aws-sdk/types@3.821.0': dependencies: - '@smithy/types': 4.2.0 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@aws-sdk/util-arn-parser@3.723.0': + '@aws-sdk/util-arn-parser@3.804.0': dependencies: tslib: 2.8.1 - '@aws-sdk/util-endpoints@3.787.0': + '@aws-sdk/util-endpoints@3.821.0': dependencies: - '@aws-sdk/types': 3.775.0 - '@smithy/types': 4.2.0 - '@smithy/util-endpoints': 3.0.4 + '@aws-sdk/types': 3.821.0 + '@smithy/types': 4.3.1 + '@smithy/util-endpoints': 3.0.6 tslib: 2.8.1 - '@aws-sdk/util-format-url@3.775.0': + '@aws-sdk/util-format-url@3.821.0': dependencies: - '@aws-sdk/types': 3.775.0 - '@smithy/querystring-builder': 4.0.2 - '@smithy/types': 4.2.0 + '@aws-sdk/types': 3.821.0 + '@smithy/querystring-builder': 4.0.4 + '@smithy/types': 4.3.1 tslib: 2.8.1 '@aws-sdk/util-locate-window@3.804.0': dependencies: tslib: 2.8.1 - '@aws-sdk/util-user-agent-browser@3.775.0': + '@aws-sdk/util-user-agent-browser@3.821.0': dependencies: - '@aws-sdk/types': 3.775.0 - '@smithy/types': 4.2.0 + '@aws-sdk/types': 3.821.0 + '@smithy/types': 4.3.1 bowser: 2.11.0 tslib: 2.8.1 - '@aws-sdk/util-user-agent-node@3.799.0': + '@aws-sdk/util-user-agent-node@3.821.0': dependencies: - '@aws-sdk/middleware-user-agent': 3.799.0 - '@aws-sdk/types': 3.775.0 - '@smithy/node-config-provider': 4.1.1 - '@smithy/types': 4.2.0 + '@aws-sdk/middleware-user-agent': 3.821.0 + '@aws-sdk/types': 3.821.0 + '@smithy/node-config-provider': 4.1.3 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@aws-sdk/xml-builder@3.775.0': + '@aws-sdk/xml-builder@3.821.0': dependencies: - '@smithy/types': 4.2.0 + '@smithy/types': 4.3.1 tslib: 2.8.1 '@babel/code-frame@7.27.1': @@ -7365,20 +7223,20 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.27.2': {} + '@babel/compat-data@7.27.5': {} - '@babel/core@7.27.1': + '@babel/core@7.27.4': dependencies: '@ampproject/remapping': 2.3.0 '@babel/code-frame': 7.27.1 - '@babel/generator': 7.27.1 + '@babel/generator': 7.27.5 '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.27.1(@babel/core@7.27.1) - '@babel/helpers': 7.27.1 - '@babel/parser': 7.27.2 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.4) + '@babel/helpers': 7.27.6 + '@babel/parser': 7.27.5 '@babel/template': 7.27.2 - '@babel/traverse': 7.27.1 - '@babel/types': 7.27.1 + '@babel/traverse': 7.27.4 + '@babel/types': 7.27.6 convert-source-map: 2.0.0 debug: 4.4.1 gensync: 1.0.0-beta.2 @@ -7387,35 +7245,35 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.27.1': + '@babel/generator@7.27.5': dependencies: - '@babel/parser': 7.27.2 - '@babel/types': 7.27.1 + '@babel/parser': 7.27.5 + '@babel/types': 7.27.6 '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.1.0 '@babel/helper-compilation-targets@7.27.2': dependencies: - '@babel/compat-data': 7.27.2 + '@babel/compat-data': 7.27.5 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.24.5 + browserslist: 4.25.0 lru-cache: 5.1.1 semver: 6.3.1 '@babel/helper-module-imports@7.27.1': dependencies: - '@babel/traverse': 7.27.1 - '@babel/types': 7.27.1 + '@babel/traverse': 7.27.4 + '@babel/types': 7.27.6 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.27.1(@babel/core@7.27.1)': + '@babel/helper-module-transforms@7.27.3(@babel/core@7.27.4)': dependencies: - '@babel/core': 7.27.1 + '@babel/core': 7.27.4 '@babel/helper-module-imports': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.27.1 + '@babel/traverse': 7.27.4 transitivePeerDependencies: - supports-color @@ -7425,38 +7283,38 @@ snapshots: '@babel/helper-validator-option@7.27.1': {} - '@babel/helpers@7.27.1': + '@babel/helpers@7.27.6': dependencies: '@babel/template': 7.27.2 - '@babel/types': 7.27.1 + '@babel/types': 7.27.6 - '@babel/parser@7.27.2': + '@babel/parser@7.27.5': dependencies: - '@babel/types': 7.27.1 + '@babel/types': 7.27.6 - '@babel/runtime-corejs3@7.27.1': + '@babel/runtime-corejs3@7.27.6': dependencies: core-js-pure: 3.42.0 '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 - '@babel/parser': 7.27.2 - '@babel/types': 7.27.1 + '@babel/parser': 7.27.5 + '@babel/types': 7.27.6 - '@babel/traverse@7.27.1': + '@babel/traverse@7.27.4': dependencies: '@babel/code-frame': 7.27.1 - '@babel/generator': 7.27.1 - '@babel/parser': 7.27.2 + '@babel/generator': 7.27.5 + '@babel/parser': 7.27.5 '@babel/template': 7.27.2 - '@babel/types': 7.27.1 + '@babel/types': 7.27.6 debug: 4.4.1 globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/types@7.27.1': + '@babel/types@7.27.6': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 @@ -7474,11 +7332,11 @@ snapshots: '@colors/colors@1.5.0': optional: true - '@containerbase/eslint-plugin@1.1.4(eslint-plugin-import@2.31.0)(eslint-plugin-promise@7.2.1(eslint@9.26.0))(eslint@9.26.0)': + '@containerbase/eslint-plugin@1.1.4(eslint-plugin-import@2.31.0)(eslint-plugin-promise@7.2.1(eslint@9.28.0))(eslint@9.28.0)': dependencies: - eslint: 9.26.0 - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.32.1(eslint@9.26.0)(typescript@5.8.3))(eslint-import-resolver-typescript@4.3.4)(eslint@9.26.0) - eslint-plugin-promise: 7.2.1(eslint@9.26.0) + eslint: 9.28.0 + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.33.1(eslint@9.28.0)(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.2)(eslint@9.28.0) + eslint-plugin-promise: 7.2.1(eslint@9.28.0) '@emnapi/core@1.4.3': dependencies: @@ -7496,84 +7354,84 @@ snapshots: tslib: 2.8.1 optional: true - '@esbuild/aix-ppc64@0.25.4': + '@esbuild/aix-ppc64@0.25.5': optional: true - '@esbuild/android-arm64@0.25.4': + '@esbuild/android-arm64@0.25.5': optional: true - '@esbuild/android-arm@0.25.4': + '@esbuild/android-arm@0.25.5': optional: true - '@esbuild/android-x64@0.25.4': + '@esbuild/android-x64@0.25.5': optional: true - '@esbuild/darwin-arm64@0.25.4': + '@esbuild/darwin-arm64@0.25.5': optional: true - '@esbuild/darwin-x64@0.25.4': + '@esbuild/darwin-x64@0.25.5': optional: true - '@esbuild/freebsd-arm64@0.25.4': + '@esbuild/freebsd-arm64@0.25.5': optional: true - '@esbuild/freebsd-x64@0.25.4': + '@esbuild/freebsd-x64@0.25.5': optional: true - '@esbuild/linux-arm64@0.25.4': + '@esbuild/linux-arm64@0.25.5': optional: true - '@esbuild/linux-arm@0.25.4': + '@esbuild/linux-arm@0.25.5': optional: true - '@esbuild/linux-ia32@0.25.4': + '@esbuild/linux-ia32@0.25.5': optional: true - '@esbuild/linux-loong64@0.25.4': + '@esbuild/linux-loong64@0.25.5': optional: true - '@esbuild/linux-mips64el@0.25.4': + '@esbuild/linux-mips64el@0.25.5': optional: true - '@esbuild/linux-ppc64@0.25.4': + '@esbuild/linux-ppc64@0.25.5': optional: true - '@esbuild/linux-riscv64@0.25.4': + '@esbuild/linux-riscv64@0.25.5': optional: true - '@esbuild/linux-s390x@0.25.4': + '@esbuild/linux-s390x@0.25.5': optional: true - '@esbuild/linux-x64@0.25.4': + '@esbuild/linux-x64@0.25.5': optional: true - '@esbuild/netbsd-arm64@0.25.4': + '@esbuild/netbsd-arm64@0.25.5': optional: true - '@esbuild/netbsd-x64@0.25.4': + '@esbuild/netbsd-x64@0.25.5': optional: true - '@esbuild/openbsd-arm64@0.25.4': + '@esbuild/openbsd-arm64@0.25.5': optional: true - '@esbuild/openbsd-x64@0.25.4': + '@esbuild/openbsd-x64@0.25.5': optional: true - '@esbuild/sunos-x64@0.25.4': + '@esbuild/sunos-x64@0.25.5': optional: true - '@esbuild/win32-arm64@0.25.4': + '@esbuild/win32-arm64@0.25.5': optional: true - '@esbuild/win32-ia32@0.25.4': + '@esbuild/win32-ia32@0.25.5': optional: true - '@esbuild/win32-x64@0.25.4': + '@esbuild/win32-x64@0.25.5': optional: true - '@eslint-community/eslint-utils@4.7.0(eslint@9.26.0)': + '@eslint-community/eslint-utils@4.7.0(eslint@9.28.0)': dependencies: - eslint: 9.26.0 + eslint: 9.28.0 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} @@ -7588,7 +7446,7 @@ snapshots: '@eslint/config-helpers@0.2.2': {} - '@eslint/core@0.13.0': + '@eslint/core@0.14.0': dependencies: '@types/json-schema': 7.0.15 @@ -7606,13 +7464,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.26.0': {} + '@eslint/js@9.28.0': {} '@eslint/object-schema@2.1.6': {} - '@eslint/plugin-kit@0.2.8': + '@eslint/plugin-kit@0.3.1': dependencies: - '@eslint/core': 0.13.0 + '@eslint/core': 0.14.0 levn: 0.4.1 '@gwhitney/detect-indent@7.0.1': {} @@ -7706,23 +7564,7 @@ snapshots: '@ls-lint/ls-lint@2.3.0': {} - '@modelcontextprotocol/sdk@1.11.4': - dependencies: - ajv: 8.17.1 - content-type: 1.0.5 - cors: 2.8.5 - cross-spawn: 7.0.6 - eventsource: 3.0.7 - express: 5.1.0 - express-rate-limit: 7.5.0(express@5.1.0) - pkce-challenge: 5.0.0 - raw-body: 3.0.0 - zod: 3.24.4 - zod-to-json-schema: 3.24.5(zod@3.24.4) - transitivePeerDependencies: - - supports-color - - '@mswjs/interceptors@0.38.6': + '@mswjs/interceptors@0.38.7': dependencies: '@open-draft/deferred-promise': 2.2.0 '@open-draft/logger': 0.3.0 @@ -7731,7 +7573,7 @@ snapshots: outvariant: 1.4.3 strict-event-emitter: 0.5.1 - '@napi-rs/wasm-runtime@0.2.10': + '@napi-rs/wasm-runtime@0.2.11': dependencies: '@emnapi/core': 1.4.3 '@emnapi/runtime': 1.4.3 @@ -7765,64 +7607,64 @@ snapshots: dependencies: semver: 7.7.2 - '@octokit/auth-token@5.1.2': {} + '@octokit/auth-token@6.0.0': {} - '@octokit/core@6.1.5': + '@octokit/core@7.0.2': dependencies: - '@octokit/auth-token': 5.1.2 - '@octokit/graphql': 8.2.2 - '@octokit/request': 9.2.3 - '@octokit/request-error': 6.1.8 - '@octokit/types': 14.0.0 - before-after-hook: 3.0.2 + '@octokit/auth-token': 6.0.0 + '@octokit/graphql': 9.0.1 + '@octokit/request': 10.0.2 + '@octokit/request-error': 7.0.0 + '@octokit/types': 14.1.0 + before-after-hook: 4.0.0 universal-user-agent: 7.0.3 - '@octokit/endpoint@10.1.4': + '@octokit/endpoint@11.0.0': dependencies: - '@octokit/types': 14.0.0 + '@octokit/types': 14.1.0 universal-user-agent: 7.0.3 - '@octokit/graphql@8.2.2': + '@octokit/graphql@9.0.1': dependencies: - '@octokit/request': 9.2.3 - '@octokit/types': 14.0.0 + '@octokit/request': 10.0.2 + '@octokit/types': 14.1.0 universal-user-agent: 7.0.3 - '@octokit/openapi-types@25.0.0': {} + '@octokit/openapi-types@25.1.0': {} - '@octokit/plugin-paginate-rest@12.0.0(@octokit/core@6.1.5)': + '@octokit/plugin-paginate-rest@13.0.1(@octokit/core@7.0.2)': dependencies: - '@octokit/core': 6.1.5 - '@octokit/types': 14.0.0 + '@octokit/core': 7.0.2 + '@octokit/types': 14.1.0 - '@octokit/plugin-retry@7.2.1(@octokit/core@6.1.5)': + '@octokit/plugin-retry@8.0.1(@octokit/core@7.0.2)': dependencies: - '@octokit/core': 6.1.5 - '@octokit/request-error': 6.1.8 - '@octokit/types': 14.0.0 + '@octokit/core': 7.0.2 + '@octokit/request-error': 7.0.0 + '@octokit/types': 14.1.0 bottleneck: 2.19.5 - '@octokit/plugin-throttling@10.0.0(@octokit/core@6.1.5)': + '@octokit/plugin-throttling@11.0.1(@octokit/core@7.0.2)': dependencies: - '@octokit/core': 6.1.5 - '@octokit/types': 14.0.0 + '@octokit/core': 7.0.2 + '@octokit/types': 14.1.0 bottleneck: 2.19.5 - '@octokit/request-error@6.1.8': + '@octokit/request-error@7.0.0': dependencies: - '@octokit/types': 14.0.0 + '@octokit/types': 14.1.0 - '@octokit/request@9.2.3': + '@octokit/request@10.0.2': dependencies: - '@octokit/endpoint': 10.1.4 - '@octokit/request-error': 6.1.8 - '@octokit/types': 14.0.0 - fast-content-type-parse: 2.0.1 + '@octokit/endpoint': 11.0.0 + '@octokit/request-error': 7.0.0 + '@octokit/types': 14.1.0 + fast-content-type-parse: 3.0.0 universal-user-agent: 7.0.3 - '@octokit/types@14.0.0': + '@octokit/types@14.1.0': dependencies: - '@octokit/openapi-types': 25.0.0 + '@octokit/openapi-types': 25.1.0 '@one-ini/wasm@0.2.0': {} @@ -7839,7 +7681,7 @@ snapshots: optionalDependencies: typescript: 5.8.3 - '@opentelemetry/api-logs@0.201.0': + '@opentelemetry/api-logs@0.202.0': dependencies: '@opentelemetry/api': 1.9.0 @@ -7852,84 +7694,82 @@ snapshots: '@opentelemetry/core@2.0.1(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/semantic-conventions': 1.33.0 + '@opentelemetry/semantic-conventions': 1.34.0 - '@opentelemetry/exporter-trace-otlp-http@0.201.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-trace-otlp-http@0.202.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.201.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.201.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.202.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.202.0(@opentelemetry/api@1.9.0) '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-bunyan@0.47.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-bunyan@0.48.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs': 0.201.0 - '@opentelemetry/instrumentation': 0.201.0(@opentelemetry/api@1.9.0) + '@opentelemetry/api-logs': 0.202.0 + '@opentelemetry/instrumentation': 0.202.0(@opentelemetry/api@1.9.0) '@types/bunyan': 1.8.11 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-http@0.201.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-http@0.202.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.201.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.33.0 + '@opentelemetry/instrumentation': 0.202.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.34.0 forwarded-parse: 2.1.2 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation@0.201.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation@0.202.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs': 0.201.0 - '@types/shimmer': 1.2.0 - import-in-the-middle: 1.13.2 + '@opentelemetry/api-logs': 0.202.0 + import-in-the-middle: 1.14.0 require-in-the-middle: 7.5.2 - shimmer: 1.2.1 transitivePeerDependencies: - supports-color - '@opentelemetry/otlp-exporter-base@0.201.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/otlp-exporter-base@0.202.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.201.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.202.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer@0.201.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/otlp-transformer@0.202.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs': 0.201.0 + '@opentelemetry/api-logs': 0.202.0 '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-logs': 0.201.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.202.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) - protobufjs: 7.5.2 + protobufjs: 7.5.3 - '@opentelemetry/resource-detector-aws@2.1.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/resource-detector-aws@2.2.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.33.0 + '@opentelemetry/semantic-conventions': 1.34.0 - '@opentelemetry/resource-detector-azure@0.8.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/resource-detector-azure@0.9.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.33.0 + '@opentelemetry/semantic-conventions': 1.34.0 - '@opentelemetry/resource-detector-gcp@0.35.0(@opentelemetry/api@1.9.0)(encoding@0.1.13)': + '@opentelemetry/resource-detector-gcp@0.36.0(@opentelemetry/api@1.9.0)(encoding@0.1.13)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.33.0 + '@opentelemetry/semantic-conventions': 1.34.0 gcp-metadata: 6.1.1(encoding@0.1.13) transitivePeerDependencies: - encoding @@ -7944,12 +7784,12 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.33.0 + '@opentelemetry/semantic-conventions': 1.34.0 - '@opentelemetry/sdk-logs@0.201.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/sdk-logs@0.202.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs': 0.201.0 + '@opentelemetry/api-logs': 0.202.0 '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) @@ -7964,7 +7804,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.33.0 + '@opentelemetry/semantic-conventions': 1.34.0 '@opentelemetry/sdk-trace-node@2.0.1(@opentelemetry/api@1.9.0)': dependencies: @@ -7973,7 +7813,7 @@ snapshots: '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions@1.33.0': {} + '@opentelemetry/semantic-conventions@1.34.0': {} '@pkgjs/parseargs@0.11.0': optional: true @@ -8083,7 +7923,7 @@ snapshots: '@qnighy/marshal@0.1.3': dependencies: - '@babel/runtime-corejs3': 7.27.1 + '@babel/runtime-corejs3': 7.27.6 '@redis/bloom@1.2.0(@redis/client@1.6.1)': dependencies: @@ -8116,7 +7956,7 @@ snapshots: fs-extra: 11.3.0 toml-eslint-parser: 0.10.0 upath: 2.0.1 - zod: 3.24.4 + zod: 3.25.50 '@renovatebot/kbpgp@4.0.1': dependencies: @@ -8149,64 +7989,64 @@ snapshots: '@renovatebot/ruby-semver@4.0.0': {} - '@rollup/rollup-android-arm-eabi@4.41.0': + '@rollup/rollup-android-arm-eabi@4.42.0': optional: true - '@rollup/rollup-android-arm64@4.41.0': + '@rollup/rollup-android-arm64@4.42.0': optional: true - '@rollup/rollup-darwin-arm64@4.41.0': + '@rollup/rollup-darwin-arm64@4.42.0': optional: true - '@rollup/rollup-darwin-x64@4.41.0': + '@rollup/rollup-darwin-x64@4.42.0': optional: true - '@rollup/rollup-freebsd-arm64@4.41.0': + '@rollup/rollup-freebsd-arm64@4.42.0': optional: true - '@rollup/rollup-freebsd-x64@4.41.0': + '@rollup/rollup-freebsd-x64@4.42.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.41.0': + '@rollup/rollup-linux-arm-gnueabihf@4.42.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.41.0': + '@rollup/rollup-linux-arm-musleabihf@4.42.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.41.0': + '@rollup/rollup-linux-arm64-gnu@4.42.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.41.0': + '@rollup/rollup-linux-arm64-musl@4.42.0': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.41.0': + '@rollup/rollup-linux-loongarch64-gnu@4.42.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.41.0': + '@rollup/rollup-linux-powerpc64le-gnu@4.42.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.41.0': + '@rollup/rollup-linux-riscv64-gnu@4.42.0': optional: true - '@rollup/rollup-linux-riscv64-musl@4.41.0': + '@rollup/rollup-linux-riscv64-musl@4.42.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.41.0': + '@rollup/rollup-linux-s390x-gnu@4.42.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.41.0': + '@rollup/rollup-linux-x64-gnu@4.42.0': optional: true - '@rollup/rollup-linux-x64-musl@4.41.0': + '@rollup/rollup-linux-x64-musl@4.42.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.41.0': + '@rollup/rollup-win32-arm64-msvc@4.42.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.41.0': + '@rollup/rollup-win32-ia32-msvc@4.42.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.41.0': + '@rollup/rollup-win32-x64-msvc@4.42.0': optional: true '@rtsao/scc@1.1.0': {} @@ -8221,40 +8061,40 @@ snapshots: '@sec-ant/readable-stream@0.4.1': {} - '@semantic-release/commit-analyzer@13.0.1(semantic-release@24.2.3(typescript@5.8.3))': + '@semantic-release/commit-analyzer@13.0.1(semantic-release@24.2.5(typescript@5.8.3))': dependencies: conventional-changelog-angular: 8.0.0 - conventional-changelog-writer: 8.0.1 + conventional-changelog-writer: 8.1.0 conventional-commits-filter: 5.0.0 conventional-commits-parser: 6.1.0 debug: 4.4.1 import-from-esm: 2.0.0 lodash-es: 4.17.21 micromatch: 4.0.8 - semantic-release: 24.2.3(typescript@5.8.3) + semantic-release: 24.2.5(typescript@5.8.3) transitivePeerDependencies: - supports-color '@semantic-release/error@4.0.0': {} - '@semantic-release/exec@7.1.0(semantic-release@24.2.3(typescript@5.8.3))': + '@semantic-release/exec@7.1.0(semantic-release@24.2.5(typescript@5.8.3))': dependencies: '@semantic-release/error': 4.0.0 aggregate-error: 3.1.0 debug: 4.4.1 - execa: 9.5.3 + execa: 9.6.0 lodash-es: 4.17.21 parse-json: 8.3.0 - semantic-release: 24.2.3(typescript@5.8.3) + semantic-release: 24.2.5(typescript@5.8.3) transitivePeerDependencies: - supports-color - '@semantic-release/github@11.0.2(semantic-release@24.2.3(typescript@5.8.3))': + '@semantic-release/github@11.0.3(semantic-release@24.2.5(typescript@5.8.3))': dependencies: - '@octokit/core': 6.1.5 - '@octokit/plugin-paginate-rest': 12.0.0(@octokit/core@6.1.5) - '@octokit/plugin-retry': 7.2.1(@octokit/core@6.1.5) - '@octokit/plugin-throttling': 10.0.0(@octokit/core@6.1.5) + '@octokit/core': 7.0.2 + '@octokit/plugin-paginate-rest': 13.0.1(@octokit/core@7.0.2) + '@octokit/plugin-retry': 8.0.1(@octokit/core@7.0.2) + '@octokit/plugin-throttling': 11.0.1(@octokit/core@7.0.2) '@semantic-release/error': 4.0.0 aggregate-error: 5.0.0 debug: 4.4.1 @@ -8266,16 +8106,16 @@ snapshots: lodash-es: 4.17.21 mime: 4.0.7 p-filter: 4.1.0 - semantic-release: 24.2.3(typescript@5.8.3) + semantic-release: 24.2.5(typescript@5.8.3) url-join: 5.0.0 transitivePeerDependencies: - supports-color - '@semantic-release/npm@12.0.1(semantic-release@24.2.3(typescript@5.8.3))': + '@semantic-release/npm@12.0.1(semantic-release@24.2.5(typescript@5.8.3))': dependencies: '@semantic-release/error': 4.0.0 aggregate-error: 5.0.0 - execa: 9.5.3 + execa: 9.6.0 fs-extra: 11.3.0 lodash-es: 4.17.21 nerf-dart: 1.0.0 @@ -8284,14 +8124,14 @@ snapshots: rc: 1.2.8 read-pkg: 9.0.1 registry-auth-token: 5.1.0 - semantic-release: 24.2.3(typescript@5.8.3) + semantic-release: 24.2.5(typescript@5.8.3) semver: 7.7.2 tempy: 3.1.0 - '@semantic-release/release-notes-generator@14.0.3(semantic-release@24.2.3(typescript@5.8.3))': + '@semantic-release/release-notes-generator@14.0.3(semantic-release@24.2.5(typescript@5.8.3))': dependencies: conventional-changelog-angular: 8.0.0 - conventional-changelog-writer: 8.0.1 + conventional-changelog-writer: 8.1.0 conventional-commits-filter: 5.0.0 conventional-commits-parser: 6.1.0 debug: 4.4.1 @@ -8300,7 +8140,7 @@ snapshots: into-stream: 7.0.0 lodash-es: 4.17.21 read-package-up: 11.0.0 - semantic-release: 24.2.3(typescript@5.8.3) + semantic-release: 24.2.5(typescript@5.8.3) transitivePeerDependencies: - supports-color @@ -8334,9 +8174,9 @@ snapshots: '@sinonjs/text-encoding@0.7.3': {} - '@smithy/abort-controller@4.0.2': + '@smithy/abort-controller@4.0.4': dependencies: - '@smithy/types': 4.2.0 + '@smithy/types': 4.3.1 tslib: 2.8.1 '@smithy/chunked-blob-reader-native@4.0.0': @@ -8348,94 +8188,95 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/config-resolver@4.1.2': + '@smithy/config-resolver@4.1.4': dependencies: - '@smithy/node-config-provider': 4.1.1 - '@smithy/types': 4.2.0 + '@smithy/node-config-provider': 4.1.3 + '@smithy/types': 4.3.1 '@smithy/util-config-provider': 4.0.0 - '@smithy/util-middleware': 4.0.2 + '@smithy/util-middleware': 4.0.4 tslib: 2.8.1 - '@smithy/core@3.3.3': + '@smithy/core@3.5.3': dependencies: - '@smithy/middleware-serde': 4.0.5 - '@smithy/protocol-http': 5.1.0 - '@smithy/types': 4.2.0 + '@smithy/middleware-serde': 4.0.8 + '@smithy/protocol-http': 5.1.2 + '@smithy/types': 4.3.1 + '@smithy/util-base64': 4.0.0 '@smithy/util-body-length-browser': 4.0.0 - '@smithy/util-middleware': 4.0.2 - '@smithy/util-stream': 4.2.0 + '@smithy/util-middleware': 4.0.4 + '@smithy/util-stream': 4.2.2 '@smithy/util-utf8': 4.0.0 tslib: 2.8.1 - '@smithy/credential-provider-imds@4.0.4': + '@smithy/credential-provider-imds@4.0.6': dependencies: - '@smithy/node-config-provider': 4.1.1 - '@smithy/property-provider': 4.0.2 - '@smithy/types': 4.2.0 - '@smithy/url-parser': 4.0.2 + '@smithy/node-config-provider': 4.1.3 + '@smithy/property-provider': 4.0.4 + '@smithy/types': 4.3.1 + '@smithy/url-parser': 4.0.4 tslib: 2.8.1 - '@smithy/eventstream-codec@4.0.2': + '@smithy/eventstream-codec@4.0.4': dependencies: '@aws-crypto/crc32': 5.2.0 - '@smithy/types': 4.2.0 + '@smithy/types': 4.3.1 '@smithy/util-hex-encoding': 4.0.0 tslib: 2.8.1 - '@smithy/eventstream-serde-browser@4.0.2': + '@smithy/eventstream-serde-browser@4.0.4': dependencies: - '@smithy/eventstream-serde-universal': 4.0.2 - '@smithy/types': 4.2.0 + '@smithy/eventstream-serde-universal': 4.0.4 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@smithy/eventstream-serde-config-resolver@4.1.0': + '@smithy/eventstream-serde-config-resolver@4.1.2': dependencies: - '@smithy/types': 4.2.0 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@smithy/eventstream-serde-node@4.0.2': + '@smithy/eventstream-serde-node@4.0.4': dependencies: - '@smithy/eventstream-serde-universal': 4.0.2 - '@smithy/types': 4.2.0 + '@smithy/eventstream-serde-universal': 4.0.4 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@smithy/eventstream-serde-universal@4.0.2': + '@smithy/eventstream-serde-universal@4.0.4': dependencies: - '@smithy/eventstream-codec': 4.0.2 - '@smithy/types': 4.2.0 + '@smithy/eventstream-codec': 4.0.4 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@smithy/fetch-http-handler@5.0.2': + '@smithy/fetch-http-handler@5.0.4': dependencies: - '@smithy/protocol-http': 5.1.0 - '@smithy/querystring-builder': 4.0.2 - '@smithy/types': 4.2.0 + '@smithy/protocol-http': 5.1.2 + '@smithy/querystring-builder': 4.0.4 + '@smithy/types': 4.3.1 '@smithy/util-base64': 4.0.0 tslib: 2.8.1 - '@smithy/hash-blob-browser@4.0.2': + '@smithy/hash-blob-browser@4.0.4': dependencies: '@smithy/chunked-blob-reader': 5.0.0 '@smithy/chunked-blob-reader-native': 4.0.0 - '@smithy/types': 4.2.0 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@smithy/hash-node@4.0.2': + '@smithy/hash-node@4.0.4': dependencies: - '@smithy/types': 4.2.0 + '@smithy/types': 4.3.1 '@smithy/util-buffer-from': 4.0.0 '@smithy/util-utf8': 4.0.0 tslib: 2.8.1 - '@smithy/hash-stream-node@4.0.2': + '@smithy/hash-stream-node@4.0.4': dependencies: - '@smithy/types': 4.2.0 + '@smithy/types': 4.3.1 '@smithy/util-utf8': 4.0.0 tslib: 2.8.1 - '@smithy/invalid-dependency@4.0.2': + '@smithy/invalid-dependency@4.0.4': dependencies: - '@smithy/types': 4.2.0 + '@smithy/types': 4.3.1 tslib: 2.8.1 '@smithy/is-array-buffer@2.2.0': @@ -8446,126 +8287,126 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/md5-js@4.0.2': + '@smithy/md5-js@4.0.4': dependencies: - '@smithy/types': 4.2.0 + '@smithy/types': 4.3.1 '@smithy/util-utf8': 4.0.0 tslib: 2.8.1 - '@smithy/middleware-content-length@4.0.2': + '@smithy/middleware-content-length@4.0.4': dependencies: - '@smithy/protocol-http': 5.1.0 - '@smithy/types': 4.2.0 + '@smithy/protocol-http': 5.1.2 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@smithy/middleware-endpoint@4.1.6': + '@smithy/middleware-endpoint@4.1.11': dependencies: - '@smithy/core': 3.3.3 - '@smithy/middleware-serde': 4.0.5 - '@smithy/node-config-provider': 4.1.1 - '@smithy/shared-ini-file-loader': 4.0.2 - '@smithy/types': 4.2.0 - '@smithy/url-parser': 4.0.2 - '@smithy/util-middleware': 4.0.2 + '@smithy/core': 3.5.3 + '@smithy/middleware-serde': 4.0.8 + '@smithy/node-config-provider': 4.1.3 + '@smithy/shared-ini-file-loader': 4.0.4 + '@smithy/types': 4.3.1 + '@smithy/url-parser': 4.0.4 + '@smithy/util-middleware': 4.0.4 tslib: 2.8.1 - '@smithy/middleware-retry@4.1.7': + '@smithy/middleware-retry@4.1.12': dependencies: - '@smithy/node-config-provider': 4.1.1 - '@smithy/protocol-http': 5.1.0 - '@smithy/service-error-classification': 4.0.3 - '@smithy/smithy-client': 4.2.6 - '@smithy/types': 4.2.0 - '@smithy/util-middleware': 4.0.2 - '@smithy/util-retry': 4.0.3 + '@smithy/node-config-provider': 4.1.3 + '@smithy/protocol-http': 5.1.2 + '@smithy/service-error-classification': 4.0.5 + '@smithy/smithy-client': 4.4.3 + '@smithy/types': 4.3.1 + '@smithy/util-middleware': 4.0.4 + '@smithy/util-retry': 4.0.5 tslib: 2.8.1 uuid: 9.0.1 - '@smithy/middleware-serde@4.0.5': + '@smithy/middleware-serde@4.0.8': dependencies: - '@smithy/protocol-http': 5.1.0 - '@smithy/types': 4.2.0 + '@smithy/protocol-http': 5.1.2 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@smithy/middleware-stack@4.0.2': + '@smithy/middleware-stack@4.0.4': dependencies: - '@smithy/types': 4.2.0 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@smithy/node-config-provider@4.1.1': + '@smithy/node-config-provider@4.1.3': dependencies: - '@smithy/property-provider': 4.0.2 - '@smithy/shared-ini-file-loader': 4.0.2 - '@smithy/types': 4.2.0 + '@smithy/property-provider': 4.0.4 + '@smithy/shared-ini-file-loader': 4.0.4 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@smithy/node-http-handler@4.0.4': + '@smithy/node-http-handler@4.0.6': dependencies: - '@smithy/abort-controller': 4.0.2 - '@smithy/protocol-http': 5.1.0 - '@smithy/querystring-builder': 4.0.2 - '@smithy/types': 4.2.0 + '@smithy/abort-controller': 4.0.4 + '@smithy/protocol-http': 5.1.2 + '@smithy/querystring-builder': 4.0.4 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@smithy/property-provider@4.0.2': + '@smithy/property-provider@4.0.4': dependencies: - '@smithy/types': 4.2.0 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@smithy/protocol-http@5.1.0': + '@smithy/protocol-http@5.1.2': dependencies: - '@smithy/types': 4.2.0 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@smithy/querystring-builder@4.0.2': + '@smithy/querystring-builder@4.0.4': dependencies: - '@smithy/types': 4.2.0 + '@smithy/types': 4.3.1 '@smithy/util-uri-escape': 4.0.0 tslib: 2.8.1 - '@smithy/querystring-parser@4.0.2': + '@smithy/querystring-parser@4.0.4': dependencies: - '@smithy/types': 4.2.0 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@smithy/service-error-classification@4.0.3': + '@smithy/service-error-classification@4.0.5': dependencies: - '@smithy/types': 4.2.0 + '@smithy/types': 4.3.1 - '@smithy/shared-ini-file-loader@4.0.2': + '@smithy/shared-ini-file-loader@4.0.4': dependencies: - '@smithy/types': 4.2.0 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@smithy/signature-v4@5.1.0': + '@smithy/signature-v4@5.1.2': dependencies: '@smithy/is-array-buffer': 4.0.0 - '@smithy/protocol-http': 5.1.0 - '@smithy/types': 4.2.0 + '@smithy/protocol-http': 5.1.2 + '@smithy/types': 4.3.1 '@smithy/util-hex-encoding': 4.0.0 - '@smithy/util-middleware': 4.0.2 + '@smithy/util-middleware': 4.0.4 '@smithy/util-uri-escape': 4.0.0 '@smithy/util-utf8': 4.0.0 tslib: 2.8.1 - '@smithy/smithy-client@4.2.6': + '@smithy/smithy-client@4.4.3': dependencies: - '@smithy/core': 3.3.3 - '@smithy/middleware-endpoint': 4.1.6 - '@smithy/middleware-stack': 4.0.2 - '@smithy/protocol-http': 5.1.0 - '@smithy/types': 4.2.0 - '@smithy/util-stream': 4.2.0 + '@smithy/core': 3.5.3 + '@smithy/middleware-endpoint': 4.1.11 + '@smithy/middleware-stack': 4.0.4 + '@smithy/protocol-http': 5.1.2 + '@smithy/types': 4.3.1 + '@smithy/util-stream': 4.2.2 tslib: 2.8.1 - '@smithy/types@4.2.0': + '@smithy/types@4.3.1': dependencies: tslib: 2.8.1 - '@smithy/url-parser@4.0.2': + '@smithy/url-parser@4.0.4': dependencies: - '@smithy/querystring-parser': 4.0.2 - '@smithy/types': 4.2.0 + '@smithy/querystring-parser': 4.0.4 + '@smithy/types': 4.3.1 tslib: 2.8.1 '@smithy/util-base64@4.0.0': @@ -8596,50 +8437,50 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/util-defaults-mode-browser@4.0.14': + '@smithy/util-defaults-mode-browser@4.0.19': dependencies: - '@smithy/property-provider': 4.0.2 - '@smithy/smithy-client': 4.2.6 - '@smithy/types': 4.2.0 + '@smithy/property-provider': 4.0.4 + '@smithy/smithy-client': 4.4.3 + '@smithy/types': 4.3.1 bowser: 2.11.0 tslib: 2.8.1 - '@smithy/util-defaults-mode-node@4.0.14': + '@smithy/util-defaults-mode-node@4.0.19': dependencies: - '@smithy/config-resolver': 4.1.2 - '@smithy/credential-provider-imds': 4.0.4 - '@smithy/node-config-provider': 4.1.1 - '@smithy/property-provider': 4.0.2 - '@smithy/smithy-client': 4.2.6 - '@smithy/types': 4.2.0 + '@smithy/config-resolver': 4.1.4 + '@smithy/credential-provider-imds': 4.0.6 + '@smithy/node-config-provider': 4.1.3 + '@smithy/property-provider': 4.0.4 + '@smithy/smithy-client': 4.4.3 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@smithy/util-endpoints@3.0.4': + '@smithy/util-endpoints@3.0.6': dependencies: - '@smithy/node-config-provider': 4.1.1 - '@smithy/types': 4.2.0 + '@smithy/node-config-provider': 4.1.3 + '@smithy/types': 4.3.1 tslib: 2.8.1 '@smithy/util-hex-encoding@4.0.0': dependencies: tslib: 2.8.1 - '@smithy/util-middleware@4.0.2': + '@smithy/util-middleware@4.0.4': dependencies: - '@smithy/types': 4.2.0 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@smithy/util-retry@4.0.3': + '@smithy/util-retry@4.0.5': dependencies: - '@smithy/service-error-classification': 4.0.3 - '@smithy/types': 4.2.0 + '@smithy/service-error-classification': 4.0.5 + '@smithy/types': 4.3.1 tslib: 2.8.1 - '@smithy/util-stream@4.2.0': + '@smithy/util-stream@4.2.2': dependencies: - '@smithy/fetch-http-handler': 5.0.2 - '@smithy/node-http-handler': 4.0.4 - '@smithy/types': 4.2.0 + '@smithy/fetch-http-handler': 5.0.4 + '@smithy/node-http-handler': 4.0.6 + '@smithy/types': 4.3.1 '@smithy/util-base64': 4.0.0 '@smithy/util-buffer-from': 4.0.0 '@smithy/util-hex-encoding': 4.0.0 @@ -8660,10 +8501,10 @@ snapshots: '@smithy/util-buffer-from': 4.0.0 tslib: 2.8.1 - '@smithy/util-waiter@4.0.3': + '@smithy/util-waiter@4.0.5': dependencies: - '@smithy/abort-controller': 4.0.2 - '@smithy/types': 4.2.0 + '@smithy/abort-controller': 4.0.4 + '@smithy/types': 4.3.1 tslib: 2.8.1 '@szmarczak/http-timer@4.0.6': @@ -8716,31 +8557,35 @@ snapshots: '@types/aws4@1.11.6': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.15.29 '@types/better-sqlite3@7.6.13': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.15.29 '@types/breejs__later@4.1.5': {} '@types/bunyan@1.8.11': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.15.29 '@types/cacache@17.0.2': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.15.29 '@types/cacheable-request@6.0.3': dependencies: '@types/http-cache-semantics': 4.0.4 '@types/keyv': 3.1.4 - '@types/node': 22.15.18 + '@types/node': 22.15.29 '@types/responselike': 1.0.3 '@types/callsite@1.0.34': {} + '@types/chai@5.2.2': + dependencies: + '@types/deep-eql': 4.0.2 + '@types/changelog-filename-regex@2.0.2': {} '@types/clean-git-ref@2.0.2': {} @@ -8753,7 +8598,7 @@ snapshots: dependencies: '@types/ms': 2.1.0 - '@types/diff@7.0.2': {} + '@types/deep-eql@4.0.2': {} '@types/emscripten@1.40.1': {} @@ -8761,10 +8606,12 @@ snapshots: '@types/estree@1.0.7': {} + '@types/estree@1.0.8': {} + '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 - '@types/node': 22.15.18 + '@types/node': 22.15.29 '@types/github-url-from-git@1.5.3': {} @@ -8784,19 +8631,19 @@ snapshots: '@types/jsonfile@6.1.4': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.15.29 '@types/katex@0.16.7': {} '@types/keyv@3.1.4': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.15.29 '@types/linkify-it@5.0.0': {} '@types/linkify-markdown@1.0.3': {} - '@types/lodash@4.17.16': {} + '@types/lodash@4.17.17': {} '@types/luxon@3.6.2': {} @@ -8807,7 +8654,7 @@ snapshots: '@types/marshal@0.5.3': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.15.29 '@types/mdast@3.0.15': dependencies: @@ -8823,7 +8670,7 @@ snapshots: '@types/ms@2.1.0': {} - '@types/node@22.15.18': + '@types/node@22.15.29': dependencies: undici-types: 6.21.0 @@ -8839,7 +8686,7 @@ snapshots: '@types/responselike@1.0.3': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.15.29 '@types/semver-stable@3.0.2': {} @@ -8847,8 +8694,6 @@ snapshots: '@types/semver@7.7.0': {} - '@types/shimmer@1.2.0': {} - '@types/sinon@17.0.4': dependencies: '@types/sinonjs__fake-timers': 8.1.5 @@ -8857,7 +8702,7 @@ snapshots: '@types/tar@6.1.13': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.15.29 minipass: 4.2.8 '@types/tmp@0.2.6': {} @@ -8874,60 +8719,75 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.15.29 optional: true - '@typescript-eslint/eslint-plugin@8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.26.0)(typescript@5.8.3))(eslint@9.26.0)(typescript@5.8.3)': + '@typescript-eslint/eslint-plugin@8.33.1(@typescript-eslint/parser@8.33.1(eslint@9.28.0)(typescript@5.8.3))(eslint@9.28.0)(typescript@5.8.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.32.1(eslint@9.26.0)(typescript@5.8.3) - '@typescript-eslint/scope-manager': 8.32.1 - '@typescript-eslint/type-utils': 8.32.1(eslint@9.26.0)(typescript@5.8.3) - '@typescript-eslint/utils': 8.32.1(eslint@9.26.0)(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.32.1 - eslint: 9.26.0 + '@typescript-eslint/parser': 8.33.1(eslint@9.28.0)(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.33.1 + '@typescript-eslint/type-utils': 8.33.1(eslint@9.28.0)(typescript@5.8.3) + '@typescript-eslint/utils': 8.33.1(eslint@9.28.0)(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.33.1 + eslint: 9.28.0 graphemer: 1.4.0 - ignore: 7.0.4 + ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.32.1(eslint@9.26.0)(typescript@5.8.3)': + '@typescript-eslint/parser@8.33.1(eslint@9.28.0)(typescript@5.8.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.33.1 + '@typescript-eslint/types': 8.33.1 + '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.33.1 + debug: 4.4.1 + eslint: 9.28.0 + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.33.1(typescript@5.8.3)': dependencies: - '@typescript-eslint/scope-manager': 8.32.1 - '@typescript-eslint/types': 8.32.1 - '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.32.1 + '@typescript-eslint/tsconfig-utils': 8.33.1(typescript@5.8.3) + '@typescript-eslint/types': 8.33.1 debug: 4.4.1 - eslint: 9.26.0 typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.32.1': + '@typescript-eslint/scope-manager@8.33.1': + dependencies: + '@typescript-eslint/types': 8.33.1 + '@typescript-eslint/visitor-keys': 8.33.1 + + '@typescript-eslint/tsconfig-utils@8.33.1(typescript@5.8.3)': dependencies: - '@typescript-eslint/types': 8.32.1 - '@typescript-eslint/visitor-keys': 8.32.1 + typescript: 5.8.3 - '@typescript-eslint/type-utils@8.32.1(eslint@9.26.0)(typescript@5.8.3)': + '@typescript-eslint/type-utils@8.33.1(eslint@9.28.0)(typescript@5.8.3)': dependencies: - '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3) - '@typescript-eslint/utils': 8.32.1(eslint@9.26.0)(typescript@5.8.3) + '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3) + '@typescript-eslint/utils': 8.33.1(eslint@9.28.0)(typescript@5.8.3) debug: 4.4.1 - eslint: 9.26.0 + eslint: 9.28.0 ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.32.1': {} + '@typescript-eslint/types@8.33.1': {} - '@typescript-eslint/typescript-estree@8.32.1(typescript@5.8.3)': + '@typescript-eslint/typescript-estree@8.33.1(typescript@5.8.3)': dependencies: - '@typescript-eslint/types': 8.32.1 - '@typescript-eslint/visitor-keys': 8.32.1 + '@typescript-eslint/project-service': 8.33.1(typescript@5.8.3) + '@typescript-eslint/tsconfig-utils': 8.33.1(typescript@5.8.3) + '@typescript-eslint/types': 8.33.1 + '@typescript-eslint/visitor-keys': 8.33.1 debug: 4.4.1 fast-glob: 3.3.3 is-glob: 4.0.3 @@ -8938,79 +8798,80 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.32.1(eslint@9.26.0)(typescript@5.8.3)': + '@typescript-eslint/utils@8.33.1(eslint@9.28.0)(typescript@5.8.3)': dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0) - '@typescript-eslint/scope-manager': 8.32.1 - '@typescript-eslint/types': 8.32.1 - '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3) - eslint: 9.26.0 + '@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0) + '@typescript-eslint/scope-manager': 8.33.1 + '@typescript-eslint/types': 8.33.1 + '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3) + eslint: 9.28.0 typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.32.1': + '@typescript-eslint/visitor-keys@8.33.1': dependencies: - '@typescript-eslint/types': 8.32.1 + '@typescript-eslint/types': 8.33.1 eslint-visitor-keys: 4.2.0 - '@unrs/resolver-binding-darwin-arm64@1.7.2': + '@unrs/resolver-binding-darwin-arm64@1.7.11': optional: true - '@unrs/resolver-binding-darwin-x64@1.7.2': + '@unrs/resolver-binding-darwin-x64@1.7.11': optional: true - '@unrs/resolver-binding-freebsd-x64@1.7.2': + '@unrs/resolver-binding-freebsd-x64@1.7.11': optional: true - '@unrs/resolver-binding-linux-arm-gnueabihf@1.7.2': + '@unrs/resolver-binding-linux-arm-gnueabihf@1.7.11': optional: true - '@unrs/resolver-binding-linux-arm-musleabihf@1.7.2': + '@unrs/resolver-binding-linux-arm-musleabihf@1.7.11': optional: true - '@unrs/resolver-binding-linux-arm64-gnu@1.7.2': + '@unrs/resolver-binding-linux-arm64-gnu@1.7.11': optional: true - '@unrs/resolver-binding-linux-arm64-musl@1.7.2': + '@unrs/resolver-binding-linux-arm64-musl@1.7.11': optional: true - '@unrs/resolver-binding-linux-ppc64-gnu@1.7.2': + '@unrs/resolver-binding-linux-ppc64-gnu@1.7.11': optional: true - '@unrs/resolver-binding-linux-riscv64-gnu@1.7.2': + '@unrs/resolver-binding-linux-riscv64-gnu@1.7.11': optional: true - '@unrs/resolver-binding-linux-riscv64-musl@1.7.2': + '@unrs/resolver-binding-linux-riscv64-musl@1.7.11': optional: true - '@unrs/resolver-binding-linux-s390x-gnu@1.7.2': + '@unrs/resolver-binding-linux-s390x-gnu@1.7.11': optional: true - '@unrs/resolver-binding-linux-x64-gnu@1.7.2': + '@unrs/resolver-binding-linux-x64-gnu@1.7.11': optional: true - '@unrs/resolver-binding-linux-x64-musl@1.7.2': + '@unrs/resolver-binding-linux-x64-musl@1.7.11': optional: true - '@unrs/resolver-binding-wasm32-wasi@1.7.2': + '@unrs/resolver-binding-wasm32-wasi@1.7.11': dependencies: - '@napi-rs/wasm-runtime': 0.2.10 + '@napi-rs/wasm-runtime': 0.2.11 optional: true - '@unrs/resolver-binding-win32-arm64-msvc@1.7.2': + '@unrs/resolver-binding-win32-arm64-msvc@1.7.11': optional: true - '@unrs/resolver-binding-win32-ia32-msvc@1.7.2': + '@unrs/resolver-binding-win32-ia32-msvc@1.7.11': optional: true - '@unrs/resolver-binding-win32-x64-msvc@1.7.2': + '@unrs/resolver-binding-win32-x64-msvc@1.7.11': optional: true - '@vitest/coverage-v8@3.1.3(vitest@3.1.3(@types/debug@4.1.12)(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0))': + '@vitest/coverage-v8@3.2.1(vitest@3.2.1(@types/debug@4.1.12)(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 + ast-v8-to-istanbul: 0.3.3 debug: 4.4.1 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 @@ -9021,59 +8882,66 @@ snapshots: std-env: 3.9.0 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 3.1.3(@types/debug@4.1.12)(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0) + vitest: 3.2.1(@types/debug@4.1.12)(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0) transitivePeerDependencies: - supports-color - '@vitest/eslint-plugin@1.1.44(@typescript-eslint/utils@8.32.1(eslint@9.26.0)(typescript@5.8.3))(eslint@9.26.0)(typescript@5.8.3)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0))': + '@vitest/eslint-plugin@1.2.1(eslint@9.28.0)(typescript@5.8.3)(vitest@3.2.1(@types/debug@4.1.12)(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0))': dependencies: - '@typescript-eslint/utils': 8.32.1(eslint@9.26.0)(typescript@5.8.3) - eslint: 9.26.0 + '@typescript-eslint/utils': 8.33.1(eslint@9.28.0)(typescript@5.8.3) + eslint: 9.28.0 optionalDependencies: typescript: 5.8.3 - vitest: 3.1.3(@types/debug@4.1.12)(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0) + vitest: 3.2.1(@types/debug@4.1.12)(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0) + transitivePeerDependencies: + - supports-color - '@vitest/expect@3.1.3': + '@vitest/expect@3.2.1': dependencies: - '@vitest/spy': 3.1.3 - '@vitest/utils': 3.1.3 + '@types/chai': 5.2.2 + '@vitest/spy': 3.2.1 + '@vitest/utils': 3.2.1 chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.1.3(vite@6.3.5(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0))': + '@vitest/mocker@3.2.1(vite@6.3.5(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0))': dependencies: - '@vitest/spy': 3.1.3 + '@vitest/spy': 3.2.1 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 6.3.5(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0) + vite: 6.3.5(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0) - '@vitest/pretty-format@3.1.3': + '@vitest/pretty-format@3.2.1': dependencies: tinyrainbow: 2.0.0 - '@vitest/runner@3.1.3': + '@vitest/pretty-format@3.2.2': dependencies: - '@vitest/utils': 3.1.3 + tinyrainbow: 2.0.0 + + '@vitest/runner@3.2.1': + dependencies: + '@vitest/utils': 3.2.1 pathe: 2.0.3 - '@vitest/snapshot@3.1.3': + '@vitest/snapshot@3.2.1': dependencies: - '@vitest/pretty-format': 3.1.3 + '@vitest/pretty-format': 3.2.1 magic-string: 0.30.17 pathe: 2.0.3 - '@vitest/spy@3.1.3': + '@vitest/spy@3.2.1': dependencies: - tinyspy: 3.0.2 + tinyspy: 4.0.3 - '@vitest/utils@3.1.3': + '@vitest/utils@3.2.1': dependencies: - '@vitest/pretty-format': 3.1.3 + '@vitest/pretty-format': 3.2.1 loupe: 3.1.3 tinyrainbow: 2.0.0 - '@yarnpkg/core@4.4.1(typanion@3.14.0)': + '@yarnpkg/core@4.4.2(typanion@3.14.0)': dependencies: '@arcanis/slice-ansi': 1.1.1 '@types/semver': 7.7.0 @@ -9081,9 +8949,9 @@ snapshots: '@yarnpkg/fslib': 3.1.2 '@yarnpkg/libzip': 3.2.1(@yarnpkg/fslib@3.1.2) '@yarnpkg/parsers': 3.0.3 - '@yarnpkg/shell': 4.1.2(typanion@3.14.0) + '@yarnpkg/shell': 4.1.3(typanion@3.14.0) camelcase: 5.3.1 - chalk: 3.0.0 + chalk: 4.1.2 ci-info: 4.2.0 clipanion: 4.0.0-rc.4(typanion@3.14.0) cross-spawn: 7.0.6 @@ -9091,6 +8959,7 @@ snapshots: dotenv: 16.5.0 fast-glob: 3.3.3 got: 11.8.6 + hpagent: 1.2.0 lodash: 4.17.21 micromatch: 4.0.8 p-limit: 2.3.0 @@ -9100,7 +8969,6 @@ snapshots: tinylogic: 2.0.0 treeify: 1.1.0 tslib: 2.8.1 - tunnel: 0.0.6 transitivePeerDependencies: - typanion @@ -9119,11 +8987,11 @@ snapshots: js-yaml: 3.14.1 tslib: 2.8.1 - '@yarnpkg/shell@4.1.2(typanion@3.14.0)': + '@yarnpkg/shell@4.1.3(typanion@3.14.0)': dependencies: '@yarnpkg/fslib': 3.1.2 '@yarnpkg/parsers': 3.0.3 - chalk: 3.0.0 + chalk: 4.1.2 clipanion: 4.0.0-rc.4(typanion@3.14.0) cross-spawn: 7.0.6 fast-glob: 3.3.3 @@ -9135,20 +9003,15 @@ snapshots: abbrev@3.0.1: optional: true - accepts@2.0.0: + acorn-import-attributes@1.9.5(acorn@8.15.0): dependencies: - mime-types: 3.0.1 - negotiator: 1.0.0 - - acorn-import-attributes@1.9.5(acorn@8.14.1): - dependencies: - acorn: 8.14.1 + acorn: 8.15.0 - acorn-jsx@5.3.2(acorn@8.14.1): + acorn-jsx@5.3.2(acorn@8.15.0): dependencies: - acorn: 8.14.1 + acorn: 8.15.0 - acorn@8.14.1: {} + acorn@8.15.0: {} adm-zip@0.5.16: {} @@ -9175,13 +9038,6 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ajv@8.17.1: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.0.6 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - ansi-escapes@7.0.0: dependencies: environment: 1.1.0 @@ -9225,21 +9081,23 @@ snapshots: array-ify@1.0.0: {} - array-includes@3.1.8: + array-includes@3.1.9: dependencies: call-bind: 1.0.8 + call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-object-atoms: 1.1.1 get-intrinsic: 1.3.0 is-string: 1.1.1 + math-intrinsics: 1.1.0 array.prototype.findlastindex@1.2.6: dependencies: call-bind: 1.0.8 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-errors: 1.3.0 es-object-atoms: 1.1.1 es-shim-unscopables: 1.1.0 @@ -9248,14 +9106,14 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-shim-unscopables: 1.1.0 array.prototype.flatmap@1.3.3: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-shim-unscopables: 1.1.0 arraybuffer.prototype.slice@1.0.4: @@ -9263,7 +9121,7 @@ snapshots: array-buffer-byte-length: 1.0.2 call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-errors: 1.3.0 get-intrinsic: 1.3.0 is-array-buffer: 3.0.5 @@ -9272,6 +9130,12 @@ snapshots: assertion-error@2.0.1: {} + ast-v8-to-istanbul@0.3.3: + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + estree-walker: 3.0.3 + js-tokens: 9.0.1 + async-function@1.0.0: {} async-mutex@0.5.0: @@ -9292,7 +9156,7 @@ snapshots: aws4@1.13.2: {} - azure-devops-node-api@14.1.0: + azure-devops-node-api@15.1.0: dependencies: tunnel: 0.0.6 typed-rest-client: 2.1.0 @@ -9305,7 +9169,7 @@ snapshots: base64-js@1.5.1: {} - before-after-hook@3.0.2: {} + before-after-hook@4.0.0: {} better-sqlite3@11.10.0: dependencies: @@ -9329,20 +9193,6 @@ snapshots: bn@1.0.5: {} - body-parser@2.2.0: - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 4.4.1 - http-errors: 2.0.0 - iconv-lite: 0.6.3 - on-finished: 2.4.1 - qs: 6.14.0 - raw-body: 3.0.0 - type-is: 2.0.1 - transitivePeerDependencies: - - supports-color - boolbase@1.0.0: {} boolean@3.2.0: {} @@ -9364,12 +9214,12 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.24.5: + browserslist@4.25.0: dependencies: - caniuse-lite: 1.0.30001718 - electron-to-chromium: 1.5.155 + caniuse-lite: 1.0.30001721 + electron-to-chromium: 1.5.165 node-releases: 2.0.19 - update-browserslist-db: 1.1.3(browserslist@4.24.5) + update-browserslist-db: 1.1.3(browserslist@4.25.0) buffer-crc32@0.2.13: {} @@ -9389,8 +9239,6 @@ snapshots: bunyan@1.8.15: {} - bytes@3.1.2: {} - bzip-deflate@1.0.0: {} cac@6.7.14: {} @@ -9458,7 +9306,7 @@ snapshots: camelcase@5.3.1: {} - caniuse-lite@1.0.30001718: {} + caniuse-lite@1.0.30001721: {} chai@5.2.0: dependencies: @@ -9474,11 +9322,6 @@ snapshots: escape-string-regexp: 1.0.5 supports-color: 5.5.0 - chalk@3.0.0: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -9591,8 +9434,12 @@ snapshots: commander@13.1.0: {} + commander@14.0.0: {} + commander@8.3.0: {} + comment-parser@1.4.1: {} + common-tags@1.8.2: {} commondir@1.0.1: {} @@ -9609,21 +9456,15 @@ snapshots: ini: 1.3.8 proto-list: 1.2.4 - content-disposition@1.0.0: - dependencies: - safe-buffer: 5.2.1 - - content-type@1.0.5: {} - conventional-changelog-angular@8.0.0: dependencies: compare-func: 2.0.0 - conventional-changelog-conventionalcommits@8.0.0: + conventional-changelog-conventionalcommits@9.0.0: dependencies: compare-func: 2.0.0 - conventional-changelog-writer@8.0.1: + conventional-changelog-writer@8.1.0: dependencies: conventional-commits-filter: 5.0.0 handlebars: 4.7.8 @@ -9649,19 +9490,10 @@ snapshots: convert-source-map@2.0.0: {} - cookie-signature@1.2.2: {} - - cookie@0.7.2: {} - core-js-pure@3.42.0: {} core-util-is@1.0.3: {} - cors@2.8.5: - dependencies: - object-assign: 4.1.1 - vary: 1.1.2 - cosmiconfig@9.0.0(typescript@5.8.3): dependencies: env-paths: 2.2.1 @@ -9764,8 +9596,6 @@ snapshots: has-property-descriptors: 1.0.2 object-keys: 1.1.1 - depd@2.0.0: {} - dequal@2.0.3: {} des.js@1.1.0: @@ -9788,7 +9618,7 @@ snapshots: diff@5.2.0: {} - diff@7.0.0: {} + diff@8.0.2: {} dir-glob@3.0.1: dependencies: @@ -9845,9 +9675,7 @@ snapshots: minimatch: 10.0.1 semver: 7.7.2 - ee-first@1.1.1: {} - - electron-to-chromium@1.5.155: {} + electron-to-chromium@1.5.165: {} email-addresses@5.0.0: {} @@ -9867,8 +9695,6 @@ snapshots: emojilib@2.4.0: {} - encodeurl@2.0.0: {} - encoding@0.1.13: dependencies: iconv-lite: 0.6.3 @@ -9880,7 +9706,7 @@ snapshots: entities@4.5.0: {} - env-ci@11.1.0: + env-ci@11.1.1: dependencies: execa: 8.0.1 java-properties: 1.0.2 @@ -9896,7 +9722,7 @@ snapshots: dependencies: is-arrayish: 0.2.1 - es-abstract@1.23.9: + es-abstract@1.24.0: dependencies: array-buffer-byte-length: 1.0.2 arraybuffer.prototype.slice: 1.0.4 @@ -9925,7 +9751,9 @@ snapshots: is-array-buffer: 3.0.5 is-callable: 1.2.7 is-data-view: 1.0.2 + is-negative-zero: 2.0.3 is-regex: 1.2.1 + is-set: 2.0.3 is-shared-array-buffer: 1.0.4 is-string: 1.1.1 is-typed-array: 1.1.15 @@ -9940,6 +9768,7 @@ snapshots: safe-push-apply: 1.0.0 safe-regex-test: 1.1.0 set-proto: 1.0.0 + stop-iteration-iterator: 1.1.0 string.prototype.trim: 1.2.10 string.prototype.trimend: 1.0.9 string.prototype.trimstart: 1.0.8 @@ -9979,47 +9808,45 @@ snapshots: es6-error@4.1.1: {} - esbuild@0.25.4: + esbuild@0.25.5: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.4 - '@esbuild/android-arm': 0.25.4 - '@esbuild/android-arm64': 0.25.4 - '@esbuild/android-x64': 0.25.4 - '@esbuild/darwin-arm64': 0.25.4 - '@esbuild/darwin-x64': 0.25.4 - '@esbuild/freebsd-arm64': 0.25.4 - '@esbuild/freebsd-x64': 0.25.4 - '@esbuild/linux-arm': 0.25.4 - '@esbuild/linux-arm64': 0.25.4 - '@esbuild/linux-ia32': 0.25.4 - '@esbuild/linux-loong64': 0.25.4 - '@esbuild/linux-mips64el': 0.25.4 - '@esbuild/linux-ppc64': 0.25.4 - '@esbuild/linux-riscv64': 0.25.4 - '@esbuild/linux-s390x': 0.25.4 - '@esbuild/linux-x64': 0.25.4 - '@esbuild/netbsd-arm64': 0.25.4 - '@esbuild/netbsd-x64': 0.25.4 - '@esbuild/openbsd-arm64': 0.25.4 - '@esbuild/openbsd-x64': 0.25.4 - '@esbuild/sunos-x64': 0.25.4 - '@esbuild/win32-arm64': 0.25.4 - '@esbuild/win32-ia32': 0.25.4 - '@esbuild/win32-x64': 0.25.4 + '@esbuild/aix-ppc64': 0.25.5 + '@esbuild/android-arm': 0.25.5 + '@esbuild/android-arm64': 0.25.5 + '@esbuild/android-x64': 0.25.5 + '@esbuild/darwin-arm64': 0.25.5 + '@esbuild/darwin-x64': 0.25.5 + '@esbuild/freebsd-arm64': 0.25.5 + '@esbuild/freebsd-x64': 0.25.5 + '@esbuild/linux-arm': 0.25.5 + '@esbuild/linux-arm64': 0.25.5 + '@esbuild/linux-ia32': 0.25.5 + '@esbuild/linux-loong64': 0.25.5 + '@esbuild/linux-mips64el': 0.25.5 + '@esbuild/linux-ppc64': 0.25.5 + '@esbuild/linux-riscv64': 0.25.5 + '@esbuild/linux-s390x': 0.25.5 + '@esbuild/linux-x64': 0.25.5 + '@esbuild/netbsd-arm64': 0.25.5 + '@esbuild/netbsd-x64': 0.25.5 + '@esbuild/openbsd-arm64': 0.25.5 + '@esbuild/openbsd-x64': 0.25.5 + '@esbuild/sunos-x64': 0.25.5 + '@esbuild/win32-arm64': 0.25.5 + '@esbuild/win32-ia32': 0.25.5 + '@esbuild/win32-x64': 0.25.5 escalade@3.2.0: {} - escape-html@1.0.3: {} - escape-string-regexp@1.0.5: {} escape-string-regexp@4.0.0: {} escape-string-regexp@5.0.0: {} - eslint-config-prettier@10.1.5(eslint@9.26.0): + eslint-config-prettier@10.1.5(eslint@9.28.0): dependencies: - eslint: 9.26.0 + eslint: 9.28.0 eslint-formatter-gha@1.5.2: dependencies: @@ -10034,6 +9861,13 @@ snapshots: strip-ansi: 6.0.1 text-table: 0.2.0 + eslint-import-context@0.1.8(unrs-resolver@1.7.11): + dependencies: + get-tsconfig: 4.10.1 + stable-hash-x: 0.1.1 + optionalDependencies: + unrs-resolver: 1.7.11 + eslint-import-resolver-node@0.3.9: dependencies: debug: 3.2.7 @@ -10042,43 +9876,63 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@4.3.4(eslint-plugin-import@2.31.0)(eslint@9.26.0): + eslint-import-resolver-typescript@4.4.2(eslint-plugin-import-x@4.15.0(@typescript-eslint/utils@8.33.1(eslint@9.28.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.28.0))(eslint-plugin-import@2.31.0)(eslint@9.28.0): dependencies: debug: 4.4.1 - eslint: 9.26.0 - get-tsconfig: 4.10.0 + eslint: 9.28.0 + eslint-import-context: 0.1.8(unrs-resolver@1.7.11) + get-tsconfig: 4.10.1 is-bun-module: 2.0.0 stable-hash: 0.0.5 - tinyglobby: 0.2.13 - unrs-resolver: 1.7.2 + tinyglobby: 0.2.14 + unrs-resolver: 1.7.11 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.32.1(eslint@9.26.0)(typescript@5.8.3))(eslint-import-resolver-typescript@4.3.4)(eslint@9.26.0) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.33.1(eslint@9.28.0)(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.2)(eslint@9.28.0) + eslint-plugin-import-x: 4.15.0(@typescript-eslint/utils@8.33.1(eslint@9.28.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.28.0) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.32.1(eslint@9.26.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.3.4)(eslint@9.26.0): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.33.1(eslint@9.28.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.2)(eslint@9.28.0): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.32.1(eslint@9.26.0)(typescript@5.8.3) - eslint: 9.26.0 + '@typescript-eslint/parser': 8.33.1(eslint@9.28.0)(typescript@5.8.3) + eslint: 9.28.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 4.3.4(eslint-plugin-import@2.31.0)(eslint@9.26.0) + eslint-import-resolver-typescript: 4.4.2(eslint-plugin-import-x@4.15.0(@typescript-eslint/utils@8.33.1(eslint@9.28.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.28.0))(eslint-plugin-import@2.31.0)(eslint@9.28.0) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.32.1(eslint@9.26.0)(typescript@5.8.3))(eslint-import-resolver-typescript@4.3.4)(eslint@9.26.0): + eslint-plugin-import-x@4.15.0(@typescript-eslint/utils@8.33.1(eslint@9.28.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.28.0): + dependencies: + '@typescript-eslint/types': 8.33.1 + comment-parser: 1.4.1 + debug: 4.4.1 + eslint: 9.28.0 + eslint-import-context: 0.1.8(unrs-resolver@1.7.11) + is-glob: 4.0.3 + minimatch: 10.0.1 + semver: 7.7.2 + stable-hash: 0.0.5 + unrs-resolver: 1.7.11 + optionalDependencies: + '@typescript-eslint/utils': 8.33.1(eslint@9.28.0)(typescript@5.8.3) + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.33.1(eslint@9.28.0)(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.2)(eslint@9.28.0): dependencies: '@rtsao/scc': 1.1.0 - array-includes: 3.1.8 + array-includes: 3.1.9 array.prototype.findlastindex: 1.2.6 array.prototype.flat: 1.3.3 array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.26.0 + eslint: 9.28.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.32.1(eslint@9.26.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.3.4)(eslint@9.26.0) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.33.1(eslint@9.28.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.2)(eslint@9.28.0) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -10090,16 +9944,16 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.32.1(eslint@9.26.0)(typescript@5.8.3) + '@typescript-eslint/parser': 8.33.1(eslint@9.28.0)(typescript@5.8.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-promise@7.2.1(eslint@9.26.0): + eslint-plugin-promise@7.2.1(eslint@9.28.0): dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0) - eslint: 9.26.0 + '@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0) + eslint: 9.28.0 eslint-scope@8.3.0: dependencies: @@ -10110,21 +9964,20 @@ snapshots: eslint-visitor-keys@4.2.0: {} - eslint@9.26.0: + eslint@9.28.0: dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.20.0 '@eslint/config-helpers': 0.2.2 - '@eslint/core': 0.13.0 + '@eslint/core': 0.14.0 '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.26.0 - '@eslint/plugin-kit': 0.2.8 + '@eslint/js': 9.28.0 + '@eslint/plugin-kit': 0.3.1 '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 - '@modelcontextprotocol/sdk': 1.11.4 - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 '@types/json-schema': 7.0.15 ajv: 6.12.6 chalk: 4.1.2 @@ -10148,14 +10001,13 @@ snapshots: minimatch: 3.1.2 natural-compare: 1.4.0 optionator: 0.9.4 - zod: 3.24.4 transitivePeerDependencies: - supports-color espree@10.3.0: dependencies: - acorn: 8.14.1 - acorn-jsx: 5.3.2(acorn@8.14.1) + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) eslint-visitor-keys: 4.2.0 esprima@4.0.1: {} @@ -10172,22 +10024,12 @@ snapshots: estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 esutils@2.0.3: {} - etag@1.8.1: {} - - eventemitter3@4.0.7: {} - eventemitter3@5.0.1: {} - eventsource-parser@3.0.2: {} - - eventsource@3.0.7: - dependencies: - eventsource-parser: 3.0.2 - execa@8.0.1: dependencies: cross-spawn: 7.0.6 @@ -10200,7 +10042,7 @@ snapshots: signal-exit: 4.1.0 strip-final-newline: 3.0.0 - execa@9.5.3: + execa@9.6.0: dependencies: '@sindresorhus/merge-streams': 4.0.0 cross-spawn: 7.0.6 @@ -10231,42 +10073,6 @@ snapshots: exponential-backoff@3.1.2: optional: true - express-rate-limit@7.5.0(express@5.1.0): - dependencies: - express: 5.1.0 - - express@5.1.0: - dependencies: - accepts: 2.0.0 - body-parser: 2.2.0 - content-disposition: 1.0.0 - content-type: 1.0.5 - cookie: 0.7.2 - cookie-signature: 1.2.2 - debug: 4.4.1 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 2.1.0 - fresh: 2.0.0 - http-errors: 2.0.0 - merge-descriptors: 2.0.0 - mime-types: 3.0.1 - on-finished: 2.4.1 - once: 1.4.0 - parseurl: 1.3.3 - proxy-addr: 2.0.7 - qs: 6.14.0 - range-parser: 1.2.1 - router: 2.2.0 - send: 1.2.0 - serve-static: 2.2.0 - statuses: 2.0.1 - type-is: 2.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - extend@3.0.2: {} extract-zip@2.0.1: @@ -10279,7 +10085,7 @@ snapshots: transitivePeerDependencies: - supports-color - fast-content-type-parse@2.0.1: {} + fast-content-type-parse@3.0.0: {} fast-deep-equal@3.1.3: {} @@ -10295,8 +10101,6 @@ snapshots: fast-levenshtein@2.0.6: {} - fast-uri@3.0.6: {} - fast-xml-parser@4.4.1: dependencies: strnum: 1.1.2 @@ -10309,7 +10113,7 @@ snapshots: dependencies: pend: 1.2.0 - fdir@6.4.4(picomatch@4.0.2): + fdir@6.4.5(picomatch@4.0.2): optionalDependencies: picomatch: 4.0.2 @@ -10332,17 +10136,6 @@ snapshots: dependencies: to-regex-range: 5.0.1 - finalhandler@2.1.0: - dependencies: - debug: 4.4.1 - encodeurl: 2.0.0 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.1 - transitivePeerDependencies: - - supports-color - find-cache-dir@3.3.2: dependencies: commondir: 1.0.1 @@ -10407,10 +10200,6 @@ snapshots: forwarded-parse@2.1.2: {} - forwarded@0.2.0: {} - - fresh@2.0.0: {} - from2@2.3.0: dependencies: inherits: 2.0.4 @@ -10524,7 +10313,7 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.3.0 - get-tsconfig@4.10.0: + get-tsconfig@4.10.1: dependencies: resolve-pkg-maps: 1.0.0 @@ -10579,7 +10368,7 @@ snapshots: glob@11.0.2: dependencies: foreground-child: 3.3.1 - jackspeak: 4.1.0 + jackspeak: 4.1.1 minimatch: 10.0.1 minipass: 7.1.2 package-json-from-dist: 1.0.1 @@ -10607,27 +10396,18 @@ snapshots: globals@14.0.0: {} - globals@16.0.0: {} + globals@16.2.0: {} globalthis@1.0.4: dependencies: define-properties: 1.2.1 gopd: 1.2.0 - globby@14.0.2: - dependencies: - '@sindresorhus/merge-streams': 2.3.0 - fast-glob: 3.3.3 - ignore: 5.3.2 - path-type: 5.0.0 - slash: 5.1.0 - unicorn-magic: 0.1.0 - globby@14.1.0: dependencies: '@sindresorhus/merge-streams': 2.3.0 fast-glob: 3.3.3 - ignore: 7.0.4 + ignore: 7.0.5 path-type: 6.0.0 slash: 5.1.0 unicorn-magic: 0.3.0 @@ -10751,18 +10531,12 @@ snapshots: dependencies: lru-cache: 10.4.3 + hpagent@1.2.0: {} + html-escaper@2.0.2: {} http-cache-semantics@4.2.0: {} - http-errors@2.0.0: - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.3 @@ -10811,13 +10585,14 @@ snapshots: iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 + optional: true ieee754@1.2.1: optional: true ignore@5.3.2: {} - ignore@7.0.4: {} + ignore@7.0.5: {} immediate@3.0.6: {} @@ -10833,10 +10608,10 @@ snapshots: transitivePeerDependencies: - supports-color - import-in-the-middle@1.13.2: + import-in-the-middle@1.14.0: dependencies: - acorn: 8.14.1 - acorn-import-attributes: 1.9.5(acorn@8.14.1) + acorn: 8.15.0 + acorn-import-attributes: 1.9.5(acorn@8.15.0) cjs-module-lexer: 1.4.3 module-details-from-path: 1.0.4 @@ -10881,8 +10656,6 @@ snapshots: sprintf-js: 1.1.3 optional: true - ipaddr.js@1.9.1: {} - is-alphabetical@1.0.4: {} is-alphabetical@2.0.1: {} @@ -10985,6 +10758,8 @@ snapshots: is-map@2.0.3: {} + is-negative-zero@2.0.3: {} + is-node-process@1.2.0: {} is-number-object@1.1.1: @@ -11002,8 +10777,6 @@ snapshots: is-plain-obj@4.1.0: {} - is-promise@4.0.0: {} - is-regex@1.2.1: dependencies: call-bound: 1.0.4 @@ -11083,8 +10856,8 @@ snapshots: istanbul-lib-instrument@6.0.3: dependencies: - '@babel/core': 7.27.1 - '@babel/parser': 7.27.2 + '@babel/core': 7.27.4 + '@babel/parser': 7.27.5 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 7.7.2 @@ -11133,7 +10906,7 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 - jackspeak@4.1.0: + jackspeak@4.1.1: dependencies: '@isaacs/cliui': 8.0.2 @@ -11146,10 +10919,9 @@ snapshots: jest-get-type: 29.6.3 pretty-format: 29.7.0 - jest-extended@4.0.2: + jest-extended@5.0.3: dependencies: jest-diff: 29.7.0 - jest-get-type: 29.6.3 jest-get-type@29.6.3: {} @@ -11164,6 +10936,8 @@ snapshots: js-tokens@4.0.0: {} + js-tokens@9.0.1: {} + js-yaml@3.14.1: dependencies: argparse: 1.0.10 @@ -11196,8 +10970,6 @@ snapshots: json-schema-traverse@0.4.1: {} - json-schema-traverse@1.0.0: {} - json-stable-stringify-without-jsonify@1.0.1: {} json-stringify-pretty-compact@4.0.0: {} @@ -11272,15 +11044,15 @@ snapshots: dependencies: uc.micro: 2.1.0 - lint-staged@15.5.2: + lint-staged@16.1.0: dependencies: chalk: 5.4.1 - commander: 13.1.0 + commander: 14.0.0 debug: 4.4.1 - execa: 8.0.1 lilconfig: 3.1.3 listr2: 8.3.3 micromatch: 4.0.8 + nano-spawn: 1.0.2 pidtree: 0.6.0 string-argv: 0.3.2 yaml: 2.8.0 @@ -11380,8 +11152,8 @@ snapshots: magicast@0.3.5: dependencies: - '@babel/parser': 7.27.2 - '@babel/types': 7.27.1 + '@babel/parser': 7.27.5 + '@babel/types': 7.27.6 source-map-js: 1.2.1 make-dir@3.1.0: @@ -11424,47 +11196,47 @@ snapshots: markdown-table@3.0.4: {} - markdownlint-cli2-formatter-default@0.0.5(markdownlint-cli2@0.17.2): + markdownlint-cli2-formatter-default@0.0.5(markdownlint-cli2@0.18.1): dependencies: - markdownlint-cli2: 0.17.2 + markdownlint-cli2: 0.18.1 - markdownlint-cli2@0.17.2: + markdownlint-cli2@0.18.1: dependencies: - globby: 14.0.2 + globby: 14.1.0 js-yaml: 4.1.0 jsonc-parser: 3.3.1 - markdownlint: 0.37.4 - markdownlint-cli2-formatter-default: 0.0.5(markdownlint-cli2@0.17.2) + markdown-it: 14.1.0 + markdownlint: 0.38.0 + markdownlint-cli2-formatter-default: 0.0.5(markdownlint-cli2@0.18.1) micromatch: 4.0.8 transitivePeerDependencies: - supports-color - markdownlint@0.37.4: + markdownlint@0.38.0: dependencies: - markdown-it: 14.1.0 - micromark: 4.0.1 - micromark-core-commonmark: 2.0.2 - micromark-extension-directive: 3.0.2 + micromark: 4.0.2 + micromark-core-commonmark: 2.0.3 + micromark-extension-directive: 4.0.0 micromark-extension-gfm-autolink-literal: 2.1.0 micromark-extension-gfm-footnote: 2.1.0 - micromark-extension-gfm-table: 2.1.0 + micromark-extension-gfm-table: 2.1.1 micromark-extension-math: 3.1.0 - micromark-util-types: 2.0.1 + micromark-util-types: 2.0.2 transitivePeerDependencies: - supports-color - marked-terminal@7.3.0(marked@12.0.2): + marked-terminal@7.3.0(marked@15.0.12): dependencies: ansi-escapes: 7.0.0 ansi-regex: 6.1.0 chalk: 5.4.1 cli-highlight: 2.1.11 cli-table3: 0.6.5 - marked: 12.0.2 + marked: 15.0.12 node-emoji: 2.2.0 supports-hyperlinks: 3.2.0 - marked@12.0.2: {} + marked@15.0.12: {} matcher@3.0.0: dependencies: @@ -11503,13 +11275,11 @@ snapshots: mdurl@2.0.0: {} - media-typer@1.1.0: {} - memfs@4.17.2: dependencies: '@jsonjoy.com/json-pack': 1.2.0(tslib@2.8.1) '@jsonjoy.com/util': 1.6.0(tslib@2.8.1) - tree-dump: 1.0.2(tslib@2.8.1) + tree-dump: 1.0.3(tslib@2.8.1) tslib: 2.8.1 memorystream@0.3.1: {} @@ -11544,13 +11314,11 @@ snapshots: type-fest: 0.18.1 yargs-parser: 20.2.9 - merge-descriptors@2.0.0: {} - merge-stream@2.0.0: {} merge2@1.4.1: {} - micromark-core-commonmark@2.0.2: + micromark-core-commonmark@2.0.3: dependencies: decode-named-character-reference: 1.1.0 devlop: 1.1.0 @@ -11567,16 +11335,16 @@ snapshots: micromark-util-resolve-all: 2.0.1 micromark-util-subtokenize: 2.1.0 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.1 + micromark-util-types: 2.0.2 - micromark-extension-directive@3.0.2: + micromark-extension-directive@4.0.0: dependencies: devlop: 1.1.0 micromark-factory-space: 2.0.1 micromark-factory-whitespace: 2.0.1 micromark-util-character: 2.1.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.1 + micromark-util-types: 2.0.2 parse-entities: 4.0.2 micromark-extension-gfm-autolink-literal@2.1.0: @@ -11584,26 +11352,26 @@ snapshots: micromark-util-character: 2.1.1 micromark-util-sanitize-uri: 2.0.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.1 + micromark-util-types: 2.0.2 micromark-extension-gfm-footnote@2.1.0: dependencies: devlop: 1.1.0 - micromark-core-commonmark: 2.0.2 + micromark-core-commonmark: 2.0.3 micromark-factory-space: 2.0.1 micromark-util-character: 2.1.1 micromark-util-normalize-identifier: 2.0.1 micromark-util-sanitize-uri: 2.0.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.1 + micromark-util-types: 2.0.2 - micromark-extension-gfm-table@2.1.0: + micromark-extension-gfm-table@2.1.1: dependencies: devlop: 1.1.0 micromark-factory-space: 2.0.1 micromark-util-character: 2.1.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.1 + micromark-util-types: 2.0.2 micromark-extension-math@3.1.0: dependencies: @@ -11613,44 +11381,44 @@ snapshots: micromark-factory-space: 2.0.1 micromark-util-character: 2.1.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.1 + micromark-util-types: 2.0.2 micromark-factory-destination@2.0.1: dependencies: micromark-util-character: 2.1.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.1 + micromark-util-types: 2.0.2 micromark-factory-label@2.0.1: dependencies: devlop: 1.1.0 micromark-util-character: 2.1.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.1 + micromark-util-types: 2.0.2 micromark-factory-space@2.0.1: dependencies: micromark-util-character: 2.1.1 - micromark-util-types: 2.0.1 + micromark-util-types: 2.0.2 micromark-factory-title@2.0.1: dependencies: micromark-factory-space: 2.0.1 micromark-util-character: 2.1.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.1 + micromark-util-types: 2.0.2 micromark-factory-whitespace@2.0.1: dependencies: micromark-factory-space: 2.0.1 micromark-util-character: 2.1.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.1 + micromark-util-types: 2.0.2 micromark-util-character@2.1.1: dependencies: micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.1 + micromark-util-types: 2.0.2 micromark-util-chunked@2.0.1: dependencies: @@ -11660,12 +11428,12 @@ snapshots: dependencies: micromark-util-character: 2.1.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.1 + micromark-util-types: 2.0.2 micromark-util-combine-extensions@2.0.1: dependencies: micromark-util-chunked: 2.0.1 - micromark-util-types: 2.0.1 + micromark-util-types: 2.0.2 micromark-util-decode-numeric-character-reference@2.0.2: dependencies: @@ -11681,7 +11449,7 @@ snapshots: micromark-util-resolve-all@2.0.1: dependencies: - micromark-util-types: 2.0.1 + micromark-util-types: 2.0.2 micromark-util-sanitize-uri@2.0.1: dependencies: @@ -11694,11 +11462,11 @@ snapshots: devlop: 1.1.0 micromark-util-chunked: 2.0.1 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.1 + micromark-util-types: 2.0.2 micromark-util-symbol@2.0.1: {} - micromark-util-types@2.0.1: {} + micromark-util-types@2.0.2: {} micromark@2.11.4: dependencies: @@ -11707,13 +11475,13 @@ snapshots: transitivePeerDependencies: - supports-color - micromark@4.0.1: + micromark@4.0.2: dependencies: '@types/debug': 4.1.12 debug: 4.4.1 decode-named-character-reference: 1.1.0 devlop: 1.1.0 - micromark-core-commonmark: 2.0.2 + micromark-core-commonmark: 2.0.3 micromark-factory-space: 2.0.1 micromark-util-character: 2.1.1 micromark-util-chunked: 2.0.1 @@ -11725,7 +11493,7 @@ snapshots: micromark-util-sanitize-uri: 2.0.1 micromark-util-subtokenize: 2.1.0 micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.1 + micromark-util-types: 2.0.2 transitivePeerDependencies: - supports-color @@ -11734,12 +11502,6 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 - mime-db@1.54.0: {} - - mime-types@3.0.1: - dependencies: - mime-db: 1.54.0 - mime@4.0.7: {} mimic-fn@4.0.0: {} @@ -11845,6 +11607,8 @@ snapshots: nan@2.22.2: optional: true + nano-spawn@1.0.2: {} + nanoid@3.3.11: {} nanoid@5.1.5: {} @@ -11856,7 +11620,8 @@ snapshots: natural-compare@1.4.0: {} - negotiator@1.0.0: {} + negotiator@1.0.0: + optional: true neo-async@2.6.2: {} @@ -11872,9 +11637,9 @@ snapshots: just-extend: 6.2.0 path-to-regexp: 8.2.0 - nock@14.0.4: + nock@14.0.5: dependencies: - '@mswjs/interceptors': 0.38.6 + '@mswjs/interceptors': 0.38.7 json-stringify-safe: 5.0.1 propagate: 2.0.1 @@ -11906,7 +11671,7 @@ snapshots: proc-log: 5.0.0 semver: 7.7.2 tar: 7.4.3 - tinyglobby: 0.2.13 + tinyglobby: 0.2.14 which: 5.0.0 transitivePeerDependencies: - supports-color @@ -11954,15 +11719,15 @@ snapshots: npm-normalize-package-bin@4.0.0: {} - npm-run-all2@7.0.2: + npm-run-all2@8.0.4: dependencies: ansi-styles: 6.2.1 cross-spawn: 7.0.6 memorystream: 0.3.1 - minimatch: 9.0.5 + picomatch: 4.0.2 pidtree: 0.6.0 read-package-json-fast: 4.0.0 - shell-quote: 1.8.2 + shell-quote: 1.8.3 which: 5.0.0 npm-run-path@5.3.0: @@ -12031,14 +11796,14 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-object-atoms: 1.1.1 object.groupby@1.0.3: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 object.values@1.2.1: dependencies: @@ -12047,10 +11812,6 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 - on-finished@2.4.1: - dependencies: - ee-first: 1.1.1 - once@1.4.0: dependencies: wrappy: 1.0.2 @@ -12083,9 +11844,9 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 - p-all@3.0.0: + p-all@5.0.0: dependencies: - p-map: 4.0.0 + p-map: 6.0.0 p-cancelable@2.1.1: {} @@ -12099,8 +11860,6 @@ snapshots: dependencies: p-map: 7.0.3 - p-finally@1.0.0: {} - p-is-promise@3.0.0: {} p-limit@1.3.0: @@ -12141,24 +11900,20 @@ snapshots: dependencies: aggregate-error: 3.1.0 - p-map@4.0.0: - dependencies: - aggregate-error: 3.1.0 + p-map@6.0.0: {} p-map@7.0.3: {} - p-queue@6.6.2: + p-queue@8.1.0: dependencies: - eventemitter3: 4.0.7 - p-timeout: 3.2.0 + eventemitter3: 5.0.1 + p-timeout: 6.1.4 p-reduce@3.0.0: {} - p-throttle@4.1.1: {} + p-throttle@7.0.0: {} - p-timeout@3.2.0: - dependencies: - p-finally: 1.0.0 + p-timeout@6.1.4: {} p-try@1.0.0: {} @@ -12237,8 +11992,6 @@ snapshots: parse5@6.0.1: {} - parseurl@1.3.3: {} - path-exists@3.0.0: {} path-exists@4.0.0: {} @@ -12267,8 +12020,6 @@ snapshots: path-type@4.0.0: {} - path-type@5.0.0: {} - path-type@6.0.0: {} pathe@2.0.3: {} @@ -12292,8 +12043,6 @@ snapshots: pify@3.0.0: {} - pkce-challenge@5.0.0: {} - pkg-conf@2.1.0: dependencies: find-up: 2.1.0 @@ -12305,7 +12054,7 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss@8.5.3: + postcss@8.5.4: dependencies: nanoid: 3.3.11 picocolors: 1.1.1 @@ -12323,7 +12072,7 @@ snapshots: pump: 3.0.2 rc: 1.2.8 simple-get: 4.0.1 - tar-fs: 2.1.2 + tar-fs: 2.1.3 tunnel-agent: 0.6.0 optional: true @@ -12362,7 +12111,7 @@ snapshots: proto-list@1.2.4: {} - protobufjs@7.5.2: + protobufjs@7.5.3: dependencies: '@protobufjs/aspromise': 1.1.2 '@protobufjs/base64': 1.1.2 @@ -12374,16 +12123,11 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 22.15.18 + '@types/node': 22.15.29 long: 5.3.2 protocols@2.0.2: {} - proxy-addr@2.0.7: - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - pump@3.0.2: dependencies: end-of-stream: 1.4.4 @@ -12405,15 +12149,6 @@ snapshots: quick-lru@5.1.1: {} - range-parser@1.2.1: {} - - raw-body@3.0.0: - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.6.3 - unpipe: 1.0.0 - rc@1.2.8: dependencies: deep-extend: 0.6.0 @@ -12421,7 +12156,7 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 - re2@1.21.5: + re2@1.22.1: dependencies: install-artifact-from-github: 1.4.0 nan: 2.22.2 @@ -12503,7 +12238,7 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-errors: 1.3.0 es-object-atoms: 1.1.1 get-intrinsic: 1.3.0 @@ -12555,8 +12290,6 @@ snapshots: require-directory@2.1.1: {} - require-from-string@2.0.2: {} - require-in-the-middle@7.5.2: dependencies: debug: 4.4.1 @@ -12615,42 +12348,32 @@ snapshots: semver-compare: 1.0.0 sprintf-js: 1.1.3 - rollup@4.41.0: + rollup@4.42.0: dependencies: '@types/estree': 1.0.7 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.41.0 - '@rollup/rollup-android-arm64': 4.41.0 - '@rollup/rollup-darwin-arm64': 4.41.0 - '@rollup/rollup-darwin-x64': 4.41.0 - '@rollup/rollup-freebsd-arm64': 4.41.0 - '@rollup/rollup-freebsd-x64': 4.41.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.41.0 - '@rollup/rollup-linux-arm-musleabihf': 4.41.0 - '@rollup/rollup-linux-arm64-gnu': 4.41.0 - '@rollup/rollup-linux-arm64-musl': 4.41.0 - '@rollup/rollup-linux-loongarch64-gnu': 4.41.0 - '@rollup/rollup-linux-powerpc64le-gnu': 4.41.0 - '@rollup/rollup-linux-riscv64-gnu': 4.41.0 - '@rollup/rollup-linux-riscv64-musl': 4.41.0 - '@rollup/rollup-linux-s390x-gnu': 4.41.0 - '@rollup/rollup-linux-x64-gnu': 4.41.0 - '@rollup/rollup-linux-x64-musl': 4.41.0 - '@rollup/rollup-win32-arm64-msvc': 4.41.0 - '@rollup/rollup-win32-ia32-msvc': 4.41.0 - '@rollup/rollup-win32-x64-msvc': 4.41.0 + '@rollup/rollup-android-arm-eabi': 4.42.0 + '@rollup/rollup-android-arm64': 4.42.0 + '@rollup/rollup-darwin-arm64': 4.42.0 + '@rollup/rollup-darwin-x64': 4.42.0 + '@rollup/rollup-freebsd-arm64': 4.42.0 + '@rollup/rollup-freebsd-x64': 4.42.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.42.0 + '@rollup/rollup-linux-arm-musleabihf': 4.42.0 + '@rollup/rollup-linux-arm64-gnu': 4.42.0 + '@rollup/rollup-linux-arm64-musl': 4.42.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.42.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.42.0 + '@rollup/rollup-linux-riscv64-gnu': 4.42.0 + '@rollup/rollup-linux-riscv64-musl': 4.42.0 + '@rollup/rollup-linux-s390x-gnu': 4.42.0 + '@rollup/rollup-linux-x64-gnu': 4.42.0 + '@rollup/rollup-linux-x64-musl': 4.42.0 + '@rollup/rollup-win32-arm64-msvc': 4.42.0 + '@rollup/rollup-win32-ia32-msvc': 4.42.0 + '@rollup/rollup-win32-x64-msvc': 4.42.0 fsevents: 2.3.3 - router@2.2.0: - dependencies: - debug: 4.4.1 - depd: 2.0.0 - is-promise: 4.0.0 - parseurl: 1.3.3 - path-to-regexp: 8.2.0 - transitivePeerDependencies: - - supports-color - run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -12680,22 +12403,23 @@ snapshots: safe-stable-stringify@2.5.0: {} - safer-buffer@2.1.2: {} + safer-buffer@2.1.2: + optional: true sax@1.4.1: {} - semantic-release@24.2.3(typescript@5.8.3): + semantic-release@24.2.5(typescript@5.8.3): dependencies: - '@semantic-release/commit-analyzer': 13.0.1(semantic-release@24.2.3(typescript@5.8.3)) + '@semantic-release/commit-analyzer': 13.0.1(semantic-release@24.2.5(typescript@5.8.3)) '@semantic-release/error': 4.0.0 - '@semantic-release/github': 11.0.2(semantic-release@24.2.3(typescript@5.8.3)) - '@semantic-release/npm': 12.0.1(semantic-release@24.2.3(typescript@5.8.3)) - '@semantic-release/release-notes-generator': 14.0.3(semantic-release@24.2.3(typescript@5.8.3)) + '@semantic-release/github': 11.0.3(semantic-release@24.2.5(typescript@5.8.3)) + '@semantic-release/npm': 12.0.1(semantic-release@24.2.5(typescript@5.8.3)) + '@semantic-release/release-notes-generator': 14.0.3(semantic-release@24.2.5(typescript@5.8.3)) aggregate-error: 5.0.0 cosmiconfig: 9.0.0(typescript@5.8.3) debug: 4.4.1 - env-ci: 11.1.0 - execa: 9.5.3 + env-ci: 11.1.1 + execa: 9.6.0 figures: 6.1.0 find-versions: 6.0.0 get-stream: 6.0.1 @@ -12704,8 +12428,8 @@ snapshots: hosted-git-info: 8.1.0 import-from-esm: 2.0.0 lodash-es: 4.17.21 - marked: 12.0.2 - marked-terminal: 7.3.0(marked@12.0.2) + marked: 15.0.12 + marked-terminal: 7.3.0(marked@15.0.12) micromatch: 4.0.8 p-each-series: 3.0.0 p-reduce: 3.0.0 @@ -12739,35 +12463,10 @@ snapshots: semver@7.7.2: {} - send@1.2.0: - dependencies: - debug: 4.4.1 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 2.0.0 - http-errors: 2.0.0 - mime-types: 3.0.1 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.1 - transitivePeerDependencies: - - supports-color - serialize-error@7.0.1: dependencies: type-fest: 0.13.1 - serve-static@2.2.0: - dependencies: - encodeurl: 2.0.0 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 1.2.0 - transitivePeerDependencies: - - supports-color - set-blocking@2.0.0: {} set-function-length@1.2.2: @@ -12792,17 +12491,13 @@ snapshots: es-errors: 1.3.0 es-object-atoms: 1.1.1 - setprototypeof@1.2.0: {} - shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 shebang-regex@3.0.0: {} - shell-quote@1.8.2: {} - - shimmer@1.2.1: {} + shell-quote@1.8.3: {} shlex@2.1.2: {} @@ -12963,14 +12658,19 @@ snapshots: dependencies: minipass: 7.1.2 + stable-hash-x@0.1.1: {} + stable-hash@0.0.5: {} stackback@0.0.2: {} - statuses@2.0.1: {} - std-env@3.9.0: {} + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + stream-combiner2@1.1.1: dependencies: duplexer2: 0.1.4 @@ -13004,7 +12704,7 @@ snapshots: call-bound: 1.0.4 define-data-property: 1.1.4 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-object-atoms: 1.1.1 has-property-descriptors: 1.0.2 @@ -13077,7 +12777,7 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - tar-fs@2.1.2: + tar-fs@2.1.3: dependencies: chownr: 1.1.4 mkdirp-classic: 0.5.3 @@ -13168,18 +12868,18 @@ snapshots: tinyexec@0.3.2: {} - tinyglobby@0.2.13: + tinyglobby@0.2.14: dependencies: - fdir: 6.4.4(picomatch@4.0.2) + fdir: 6.4.5(picomatch@4.0.2) picomatch: 4.0.2 tinylogic@2.0.0: {} - tinypool@1.0.2: {} + tinypool@1.1.0: {} tinyrainbow@2.0.0: {} - tinyspy@3.0.2: {} + tinyspy@4.0.3: {} tmp-promise@3.0.3: dependencies: @@ -13191,8 +12891,6 @@ snapshots: dependencies: is-number: 7.0.0 - toidentifier@1.0.1: {} - toml-eslint-parser@0.10.0: dependencies: eslint-visitor-keys: 3.4.3 @@ -13201,7 +12899,7 @@ snapshots: traverse@0.6.8: {} - tree-dump@1.0.2(tslib@2.8.1): + tree-dump@1.0.3(tslib@2.8.1): dependencies: tslib: 2.8.1 @@ -13224,11 +12922,11 @@ snapshots: dependencies: typescript: 5.8.3 - ts-essentials@10.0.4(typescript@5.8.3): + ts-essentials@10.1.0(typescript@5.8.3): optionalDependencies: typescript: 5.8.3 - tsconfck@3.1.5(typescript@5.8.3): + tsconfck@3.1.6(typescript@5.8.3): optionalDependencies: typescript: 5.8.3 @@ -13243,8 +12941,8 @@ snapshots: tsx@4.19.4: dependencies: - esbuild: 0.25.4 - get-tsconfig: 4.10.0 + esbuild: 0.25.5 + get-tsconfig: 4.10.1 optionalDependencies: fsevents: 2.3.3 @@ -13283,12 +12981,6 @@ snapshots: type-fest@4.41.0: {} - type-is@2.0.1: - dependencies: - content-type: 1.0.5 - media-typer: 1.1.0 - mime-types: 3.0.1 - typed-array-buffer@1.0.3: dependencies: call-bound: 1.0.4 @@ -13334,12 +13026,12 @@ snapshots: dependencies: is-typedarray: 1.0.0 - typescript-eslint@8.32.1(eslint@9.26.0)(typescript@5.8.3): + typescript-eslint@8.33.1(eslint@9.28.0)(typescript@5.8.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.26.0)(typescript@5.8.3))(eslint@9.26.0)(typescript@5.8.3) - '@typescript-eslint/parser': 8.32.1(eslint@9.26.0)(typescript@5.8.3) - '@typescript-eslint/utils': 8.32.1(eslint@9.26.0)(typescript@5.8.3) - eslint: 9.26.0 + '@typescript-eslint/eslint-plugin': 8.33.1(@typescript-eslint/parser@8.33.1(eslint@9.28.0)(typescript@5.8.3))(eslint@9.28.0)(typescript@5.8.3) + '@typescript-eslint/parser': 8.33.1(eslint@9.28.0)(typescript@5.8.3) + '@typescript-eslint/utils': 8.33.1(eslint@9.28.0)(typescript@5.8.3) + eslint: 9.28.0 typescript: 5.8.3 transitivePeerDependencies: - supports-color @@ -13412,35 +13104,33 @@ snapshots: universalify@2.0.1: {} - unpipe@1.0.0: {} - - unrs-resolver@1.7.2: + unrs-resolver@1.7.11: dependencies: napi-postinstall: 0.2.4 optionalDependencies: - '@unrs/resolver-binding-darwin-arm64': 1.7.2 - '@unrs/resolver-binding-darwin-x64': 1.7.2 - '@unrs/resolver-binding-freebsd-x64': 1.7.2 - '@unrs/resolver-binding-linux-arm-gnueabihf': 1.7.2 - '@unrs/resolver-binding-linux-arm-musleabihf': 1.7.2 - '@unrs/resolver-binding-linux-arm64-gnu': 1.7.2 - '@unrs/resolver-binding-linux-arm64-musl': 1.7.2 - '@unrs/resolver-binding-linux-ppc64-gnu': 1.7.2 - '@unrs/resolver-binding-linux-riscv64-gnu': 1.7.2 - '@unrs/resolver-binding-linux-riscv64-musl': 1.7.2 - '@unrs/resolver-binding-linux-s390x-gnu': 1.7.2 - '@unrs/resolver-binding-linux-x64-gnu': 1.7.2 - '@unrs/resolver-binding-linux-x64-musl': 1.7.2 - '@unrs/resolver-binding-wasm32-wasi': 1.7.2 - '@unrs/resolver-binding-win32-arm64-msvc': 1.7.2 - '@unrs/resolver-binding-win32-ia32-msvc': 1.7.2 - '@unrs/resolver-binding-win32-x64-msvc': 1.7.2 + '@unrs/resolver-binding-darwin-arm64': 1.7.11 + '@unrs/resolver-binding-darwin-x64': 1.7.11 + '@unrs/resolver-binding-freebsd-x64': 1.7.11 + '@unrs/resolver-binding-linux-arm-gnueabihf': 1.7.11 + '@unrs/resolver-binding-linux-arm-musleabihf': 1.7.11 + '@unrs/resolver-binding-linux-arm64-gnu': 1.7.11 + '@unrs/resolver-binding-linux-arm64-musl': 1.7.11 + '@unrs/resolver-binding-linux-ppc64-gnu': 1.7.11 + '@unrs/resolver-binding-linux-riscv64-gnu': 1.7.11 + '@unrs/resolver-binding-linux-riscv64-musl': 1.7.11 + '@unrs/resolver-binding-linux-s390x-gnu': 1.7.11 + '@unrs/resolver-binding-linux-x64-gnu': 1.7.11 + '@unrs/resolver-binding-linux-x64-musl': 1.7.11 + '@unrs/resolver-binding-wasm32-wasi': 1.7.11 + '@unrs/resolver-binding-win32-arm64-msvc': 1.7.11 + '@unrs/resolver-binding-win32-ia32-msvc': 1.7.11 + '@unrs/resolver-binding-win32-x64-msvc': 1.7.11 upath@2.0.1: {} - update-browserslist-db@1.1.3(browserslist@4.24.5): + update-browserslist-db@1.1.3(browserslist@4.25.0): dependencies: - browserslist: 4.24.5 + browserslist: 4.25.0 escalade: 3.2.0 picocolors: 1.1.1 @@ -13475,8 +13165,6 @@ snapshots: validate-npm-package-name@6.0.0: {} - vary@1.1.2: {} - vfile-message@2.0.4: dependencies: '@types/unist': 2.0.11 @@ -13489,13 +13177,13 @@ snapshots: unist-util-stringify-position: 2.0.3 vfile-message: 2.0.4 - vite-node@3.1.3(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0): + vite-node@3.2.1(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0): dependencies: cac: 6.7.14 debug: 4.4.1 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.3.5(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0) + vite: 6.3.5(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0) transitivePeerDependencies: - '@types/node' - jiti @@ -13510,63 +13198,65 @@ snapshots: - tsx - yaml - vite-tsconfig-paths@5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0)): + vite-tsconfig-paths@5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0)): dependencies: debug: 4.4.1 globrex: 0.1.2 - tsconfck: 3.1.5(typescript@5.8.3) + tsconfck: 3.1.6(typescript@5.8.3) optionalDependencies: - vite: 6.3.5(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0) + vite: 6.3.5(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0) transitivePeerDependencies: - supports-color - typescript - vite@6.3.5(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0): + vite@6.3.5(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0): dependencies: - esbuild: 0.25.4 - fdir: 6.4.4(picomatch@4.0.2) + esbuild: 0.25.5 + fdir: 6.4.5(picomatch@4.0.2) picomatch: 4.0.2 - postcss: 8.5.3 - rollup: 4.41.0 - tinyglobby: 0.2.13 + postcss: 8.5.4 + rollup: 4.42.0 + tinyglobby: 0.2.14 optionalDependencies: - '@types/node': 22.15.18 + '@types/node': 22.15.29 fsevents: 2.3.3 tsx: 4.19.4 yaml: 2.8.0 - vitest-mock-extended@3.1.0(typescript@5.8.3)(vitest@3.1.3(@types/debug@4.1.12)(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0)): + vitest-mock-extended@3.1.0(typescript@5.8.3)(vitest@3.2.1(@types/debug@4.1.12)(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0)): dependencies: - ts-essentials: 10.0.4(typescript@5.8.3) + ts-essentials: 10.1.0(typescript@5.8.3) typescript: 5.8.3 - vitest: 3.1.3(@types/debug@4.1.12)(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0) - - vitest@3.1.3(@types/debug@4.1.12)(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0): - dependencies: - '@vitest/expect': 3.1.3 - '@vitest/mocker': 3.1.3(vite@6.3.5(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0)) - '@vitest/pretty-format': 3.1.3 - '@vitest/runner': 3.1.3 - '@vitest/snapshot': 3.1.3 - '@vitest/spy': 3.1.3 - '@vitest/utils': 3.1.3 + vitest: 3.2.1(@types/debug@4.1.12)(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0) + + vitest@3.2.1(@types/debug@4.1.12)(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0): + dependencies: + '@types/chai': 5.2.2 + '@vitest/expect': 3.2.1 + '@vitest/mocker': 3.2.1(vite@6.3.5(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0)) + '@vitest/pretty-format': 3.2.2 + '@vitest/runner': 3.2.1 + '@vitest/snapshot': 3.2.1 + '@vitest/spy': 3.2.1 + '@vitest/utils': 3.2.1 chai: 5.2.0 debug: 4.4.1 expect-type: 1.2.1 magic-string: 0.30.17 pathe: 2.0.3 + picomatch: 4.0.2 std-env: 3.9.0 tinybench: 2.9.0 tinyexec: 0.3.2 - tinyglobby: 0.2.13 - tinypool: 1.0.2 + tinyglobby: 0.2.14 + tinypool: 1.1.0 tinyrainbow: 2.0.0 - vite: 6.3.5(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0) - vite-node: 3.1.3(@types/node@22.15.18)(tsx@4.19.4)(yaml@2.8.0) + vite: 6.3.5(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0) + vite-node: 3.2.1(@types/node@22.15.29)(tsx@4.19.4)(yaml@2.8.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 - '@types/node': 22.15.18 + '@types/node': 22.15.29 transitivePeerDependencies: - jiti - less @@ -13765,10 +13455,6 @@ snapshots: yoctocolors@2.1.1: {} - zod-to-json-schema@3.24.5(zod@3.24.4): - dependencies: - zod: 3.24.4 - - zod@3.24.4: {} + zod@3.25.50: {} zwitch@1.0.5: {} diff --git a/test/other/validate-schemas.spec.ts b/test/other/validate-schemas.spec.ts index 4cfc346bba5..cfe8d8c28a8 100644 --- a/test/other/validate-schemas.spec.ts +++ b/test/other/validate-schemas.spec.ts @@ -38,7 +38,7 @@ describe('other/validate-schemas', () => { // validate json data against schema: using parse here instead of safeParse so we throw // this leads to a better error message when the assertion fails - // eslint-disable-next-line import/namespace + // eslint-disable-next-line import-x/namespace Schemas[schemaName].parse(data); }), ); diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index a8723a474d7..ebd77e8f9cb 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -5,19 +5,19 @@ ARG BASE_IMAGE_TYPE=slim # -------------------------------------- # slim image # -------------------------------------- -FROM ghcr.io/renovatebot/base-image:9.70.3@sha256:01ad59538532d0d9eb4c072a4b3de0131dfee2e25ed802b4d7606e366e09e575 AS slim-base +FROM ghcr.io/renovatebot/base-image:9.71.13@sha256:52e335d4a0d5200aa80bd2306c839ade4bdf24c1260bf8c34bfcd7736205bc83 AS slim-base # -------------------------------------- # full image # -------------------------------------- -FROM ghcr.io/renovatebot/base-image:9.70.3-full@sha256:3c7e3c75b673e337bd8190e0c34a83493ec7dadf669cdd204db64a1d356b2e84 AS full-base +FROM ghcr.io/renovatebot/base-image:9.71.13-full@sha256:c1697d8f37b0768d5485b75f06fe0531b290738d8f2a1c9601fd8398b8170dcd AS full-base ENV RENOVATE_BINARY_SOURCE=global # -------------------------------------- # build image # -------------------------------------- -FROM --platform=$BUILDPLATFORM ghcr.io/renovatebot/base-image:9.70.3@sha256:01ad59538532d0d9eb4c072a4b3de0131dfee2e25ed802b4d7606e366e09e575 AS build +FROM --platform=$BUILDPLATFORM ghcr.io/renovatebot/base-image:9.71.13@sha256:52e335d4a0d5200aa80bd2306c839ade4bdf24c1260bf8c34bfcd7736205bc83 AS build # We want a specific node version here # renovate: datasource=github-releases packageName=containerbase/node-prebuild versioning=node @@ -25,7 +25,7 @@ RUN install-tool node 22.16.0 # corepack is too buggy 😞 # renovate: datasource=npm -RUN install-tool pnpm 10.11.0 +RUN install-tool pnpm 10.11.1 WORKDIR /usr/local/renovate diff --git a/tools/mkdocs/overrides/main.html b/tools/mkdocs/overrides/main.html index b1977fd71df..6f60b52c63b 100644 --- a/tools/mkdocs/overrides/main.html +++ b/tools/mkdocs/overrides/main.html @@ -8,7 +8,4 @@

If you use a Mend-hosted Renovate App and you have encrypted secrets in your Renovate config, then you must migrate the secrets to the Developer Portal UI. If you do not migrate the secrets, eventually Renovate will stop running on repositories that use the Mend-hosted Renovate App. Please read the announcement about the disabling of Encrypted Secrets in Mend-hosted Renovate apps to learn more.

-

- We released a new major version of Renovate. Read the Renovate 40 changelog on GitHub. -

{% endblock %} diff --git a/tsconfig.json b/tsconfig.json index 04d5a09a0a0..05ce52faeb0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -32,10 +32,14 @@ "node_modules", "./.cache", "./dist", + "./.pnpm-store/", + "./.venv/", "**/__mocks__/*", + "**/__fixtures__/*", "coverage", "config.js", "tmp", + "tools/mkdocs/docs", "tools/mkdocs/site" ], "ts-node": {