renovate 44.17.0 → 44.17.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/migrations/custom/ignore-npmrc-file-migration.js +2 -1
- package/dist/config/migrations/custom/ignore-npmrc-file-migration.js.map +1 -1
- package/dist/config/migrations/custom/stability-days-migration.js +1 -3
- package/dist/config/migrations/custom/stability-days-migration.js.map +1 -1
- package/dist/config/options/index.js +1 -1
- package/dist/config/options/index.js.map +1 -1
- package/dist/config/secrets.js +2 -1
- package/dist/config/secrets.js.map +1 -1
- package/dist/config/validation.js +1 -3
- package/dist/config/validation.js.map +1 -1
- package/dist/config-validator.js +2 -1
- package/dist/config-validator.js.map +1 -1
- package/dist/expose.js.map +1 -1
- package/dist/global-config-option-defaults.generated.js +1 -1
- package/dist/global-config-option-defaults.generated.js.map +1 -1
- package/dist/modules/datasource/artifactory/index.js +2 -1
- package/dist/modules/datasource/artifactory/index.js.map +1 -1
- package/dist/modules/datasource/aws-eks-addon/index.js +2 -1
- package/dist/modules/datasource/aws-eks-addon/index.js.map +1 -1
- package/dist/modules/datasource/aws-machine-image/index.js +3 -2
- package/dist/modules/datasource/aws-machine-image/index.js.map +1 -1
- package/dist/modules/datasource/bazel/index.js +2 -1
- package/dist/modules/datasource/bazel/index.js.map +1 -1
- package/dist/modules/datasource/bitbucket-server-tags/index.js +4 -2
- package/dist/modules/datasource/bitbucket-server-tags/index.js.map +1 -1
- package/dist/modules/datasource/bitbucket-tags/index.js +2 -1
- package/dist/modules/datasource/bitbucket-tags/index.js.map +1 -1
- package/dist/modules/datasource/bitrise/index.js +2 -1
- package/dist/modules/datasource/bitrise/index.js.map +1 -1
- package/dist/modules/datasource/common.js +4 -2
- package/dist/modules/datasource/common.js.map +1 -1
- package/dist/modules/datasource/crate/index.js +12 -5
- package/dist/modules/datasource/crate/index.js.map +1 -1
- package/dist/modules/datasource/custom/formats/toml.js +2 -1
- package/dist/modules/datasource/custom/formats/toml.js.map +1 -1
- package/dist/modules/datasource/custom/formats/yaml.js +4 -2
- package/dist/modules/datasource/custom/formats/yaml.js.map +1 -1
- package/dist/modules/datasource/deb/checksum.js +2 -1
- package/dist/modules/datasource/deb/checksum.js.map +1 -1
- package/dist/modules/datasource/deb/packages.js +3 -1
- package/dist/modules/datasource/deb/packages.js.map +1 -1
- package/dist/modules/datasource/deno/index.js +2 -1
- package/dist/modules/datasource/deno/index.js.map +1 -1
- package/dist/modules/datasource/docker/common.js +3 -2
- package/dist/modules/datasource/docker/common.js.map +1 -1
- package/dist/modules/datasource/docker/dockerhub-cache.js +1 -1
- package/dist/modules/datasource/docker/dockerhub-cache.js.map +1 -1
- package/dist/modules/datasource/docker/index.js +11 -10
- package/dist/modules/datasource/docker/index.js.map +1 -1
- package/dist/modules/datasource/forgejo-tags/index.js +4 -2
- package/dist/modules/datasource/forgejo-tags/index.js.map +1 -1
- package/dist/modules/datasource/galaxy-collection/index.js +5 -3
- package/dist/modules/datasource/galaxy-collection/index.js.map +1 -1
- package/dist/modules/datasource/git-refs/base.js +2 -1
- package/dist/modules/datasource/git-refs/base.js.map +1 -1
- package/dist/modules/datasource/git-refs/index.js +1 -1
- package/dist/modules/datasource/git-refs/index.js.map +1 -1
- package/dist/modules/datasource/gitea-tags/index.js +4 -2
- package/dist/modules/datasource/gitea-tags/index.js.map +1 -1
- package/dist/modules/datasource/github-release-attachments/index.js +3 -2
- package/dist/modules/datasource/github-release-attachments/index.js.map +1 -1
- package/dist/modules/datasource/github-tags/index.js +1 -1
- package/dist/modules/datasource/github-tags/index.js.map +1 -1
- package/dist/modules/datasource/gitlab-tags/index.js +2 -1
- package/dist/modules/datasource/gitlab-tags/index.js.map +1 -1
- package/dist/modules/datasource/gitlab-tags/util.js +2 -1
- package/dist/modules/datasource/gitlab-tags/util.js.map +1 -1
- package/dist/modules/datasource/go/releases-goproxy.js +8 -5
- package/dist/modules/datasource/go/releases-goproxy.js.map +1 -1
- package/dist/modules/datasource/jenkins-plugins/index.js +1 -1
- package/dist/modules/datasource/jenkins-plugins/index.js.map +1 -1
- package/dist/modules/datasource/jsr/index.js +2 -1
- package/dist/modules/datasource/jsr/index.js.map +1 -1
- package/dist/modules/datasource/maven/index.js +3 -2
- package/dist/modules/datasource/maven/index.js.map +1 -1
- package/dist/modules/datasource/maven/util.js +1 -1
- package/dist/modules/datasource/maven/util.js.map +1 -1
- package/dist/modules/datasource/nuget/v2.js +3 -2
- package/dist/modules/datasource/nuget/v2.js.map +1 -1
- package/dist/modules/datasource/nuget/v3.js +9 -5
- package/dist/modules/datasource/nuget/v3.js.map +1 -1
- package/dist/modules/datasource/packagist/index.js +7 -4
- package/dist/modules/datasource/packagist/index.js.map +1 -1
- package/dist/modules/datasource/rpm/providers/common.js +3 -1
- package/dist/modules/datasource/rpm/providers/common.js.map +1 -1
- package/dist/modules/datasource/rpm/repomd.js +2 -1
- package/dist/modules/datasource/rpm/repomd.js.map +1 -1
- package/dist/modules/datasource/ruby-version/index.js +2 -1
- package/dist/modules/datasource/ruby-version/index.js.map +1 -1
- package/dist/modules/datasource/rubygems/metadata-cache.js +1 -1
- package/dist/modules/datasource/rubygems/metadata-cache.js.map +1 -1
- package/dist/modules/datasource/sbt-package/index.js +8 -5
- package/dist/modules/datasource/sbt-package/index.js.map +1 -1
- package/dist/modules/datasource/sbt-package/util.js +2 -1
- package/dist/modules/datasource/sbt-package/util.js.map +1 -1
- package/dist/modules/datasource/terraform-module/index.js +4 -2
- package/dist/modules/datasource/terraform-module/index.js.map +1 -1
- package/dist/modules/datasource/terraform-module/utils.js +2 -1
- package/dist/modules/datasource/terraform-module/utils.js.map +1 -1
- package/dist/modules/datasource/terraform-provider/index.js +2 -1
- package/dist/modules/datasource/terraform-provider/index.js.map +1 -1
- package/dist/modules/datasource/typst/schema.js +4 -2
- package/dist/modules/datasource/typst/schema.js.map +1 -1
- package/dist/modules/manager/ansible-galaxy/collections.js +2 -2
- package/dist/modules/manager/ansible-galaxy/collections.js.map +1 -1
- package/dist/modules/manager/ansible-galaxy/extract.js +5 -3
- package/dist/modules/manager/ansible-galaxy/extract.js.map +1 -1
- package/dist/modules/manager/bazel/artifacts.js +1 -1
- package/dist/modules/manager/bazel/artifacts.js.map +1 -1
- package/dist/modules/manager/bazel/parser.js +1 -1
- package/dist/modules/manager/bazel/parser.js.map +1 -1
- package/dist/modules/manager/bazel/rules/index.js +7 -2
- package/dist/modules/manager/bazel/rules/index.js.map +1 -1
- package/dist/modules/manager/bazel-module/extract.js +2 -1
- package/dist/modules/manager/bazel-module/extract.js.map +1 -1
- package/dist/modules/manager/bazel-module/parser/extension-tags.js +3 -2
- package/dist/modules/manager/bazel-module/parser/extension-tags.js.map +1 -1
- package/dist/modules/manager/bazel-module/rules.js +1 -3
- package/dist/modules/manager/bazel-module/rules.js.map +1 -1
- package/dist/modules/manager/bitbucket-pipelines/extract.js +5 -3
- package/dist/modules/manager/bitbucket-pipelines/extract.js.map +1 -1
- package/dist/modules/manager/buildkite/extract.js +1 -1
- package/dist/modules/manager/buildkite/extract.js.map +1 -1
- package/dist/modules/manager/bun/extract.js +2 -1
- package/dist/modules/manager/bun/extract.js.map +1 -1
- package/dist/modules/manager/bundler/artifacts.js +3 -2
- package/dist/modules/manager/bundler/artifacts.js.map +1 -1
- package/dist/modules/manager/cargo/artifacts.js +3 -2
- package/dist/modules/manager/cargo/artifacts.js.map +1 -1
- package/dist/modules/manager/cocoapods/artifacts.js +2 -1
- package/dist/modules/manager/cocoapods/artifacts.js.map +1 -1
- package/dist/modules/manager/composer/update-locked.js +1 -1
- package/dist/modules/manager/composer/update-locked.js.map +1 -1
- package/dist/modules/manager/conan/artifacts.js +4 -2
- package/dist/modules/manager/conan/artifacts.js.map +1 -1
- package/dist/modules/manager/custom/jsonata/index.js +1 -3
- package/dist/modules/manager/custom/jsonata/index.js.map +1 -1
- package/dist/modules/manager/custom/jsonata/utils.js +1 -3
- package/dist/modules/manager/custom/jsonata/utils.js.map +1 -1
- package/dist/modules/manager/custom/regex/index.js +1 -3
- package/dist/modules/manager/custom/regex/index.js.map +1 -1
- package/dist/modules/manager/custom/regex/strategies.js +7 -6
- package/dist/modules/manager/custom/regex/strategies.js.map +1 -1
- package/dist/modules/manager/custom/regex/utils.js +1 -3
- package/dist/modules/manager/custom/regex/utils.js.map +1 -1
- package/dist/modules/manager/docker-compose/extract.js +2 -2
- package/dist/modules/manager/docker-compose/extract.js.map +1 -1
- package/dist/modules/manager/droneci/extract.js +1 -1
- package/dist/modules/manager/droneci/extract.js.map +1 -1
- package/dist/modules/manager/flux/artifacts.js +5 -3
- package/dist/modules/manager/flux/artifacts.js.map +1 -1
- package/dist/modules/manager/flux/extract.js +2 -6
- package/dist/modules/manager/flux/extract.js.map +1 -1
- package/dist/modules/manager/git-submodules/extract.js +5 -4
- package/dist/modules/manager/git-submodules/extract.js.map +1 -1
- package/dist/modules/manager/github-actions/extract.js +2 -1
- package/dist/modules/manager/github-actions/extract.js.map +1 -1
- package/dist/modules/manager/gitlabci/extract.js +1 -1
- package/dist/modules/manager/gitlabci/extract.js.map +1 -1
- package/dist/modules/manager/gitlabci/schema.js +2 -1
- package/dist/modules/manager/gitlabci/schema.js.map +1 -1
- package/dist/modules/manager/gitlabci-include/extract.js +1 -1
- package/dist/modules/manager/gitlabci-include/extract.js.map +1 -1
- package/dist/modules/manager/gleam/artifacts.js +2 -1
- package/dist/modules/manager/gleam/artifacts.js.map +1 -1
- package/dist/modules/manager/gomod/artifacts.js +2 -1
- package/dist/modules/manager/gomod/artifacts.js.map +1 -1
- package/dist/modules/manager/gradle/artifacts.js +3 -1
- package/dist/modules/manager/gradle/artifacts.js.map +1 -1
- package/dist/modules/manager/gradle/extract/catalog.js +3 -1
- package/dist/modules/manager/gradle/extract/catalog.js.map +1 -1
- package/dist/modules/manager/gradle/extract/consistent-versions-plugin.js +2 -1
- package/dist/modules/manager/gradle/extract/consistent-versions-plugin.js.map +1 -1
- package/dist/modules/manager/gradle/extract.js +4 -2
- package/dist/modules/manager/gradle/extract.js.map +1 -1
- package/dist/modules/manager/gradle/parser/handlers.js +4 -2
- package/dist/modules/manager/gradle/parser/handlers.js.map +1 -1
- package/dist/modules/manager/gradle/parser/registry-urls.js +3 -2
- package/dist/modules/manager/gradle/parser/registry-urls.js.map +1 -1
- package/dist/modules/manager/gradle-wrapper/utils.js +2 -1
- package/dist/modules/manager/gradle-wrapper/utils.js.map +1 -1
- package/dist/modules/manager/helm-values/extract.js +1 -1
- package/dist/modules/manager/helm-values/extract.js.map +1 -1
- package/dist/modules/manager/helmfile/utils.js +3 -2
- package/dist/modules/manager/helmfile/utils.js.map +1 -1
- package/dist/modules/manager/helmsman/extract.js +1 -1
- package/dist/modules/manager/helmsman/extract.js.map +1 -1
- package/dist/modules/manager/helmv3/artifacts.js +3 -2
- package/dist/modules/manager/helmv3/artifacts.js.map +1 -1
- package/dist/modules/manager/jenkins/extract.js +1 -1
- package/dist/modules/manager/jenkins/extract.js.map +1 -1
- package/dist/modules/manager/jsonnet-bundler/artifacts.js +1 -1
- package/dist/modules/manager/jsonnet-bundler/artifacts.js.map +1 -1
- package/dist/modules/manager/kustomize/artifacts.js +3 -4
- package/dist/modules/manager/kustomize/artifacts.js.map +1 -1
- package/dist/modules/manager/kustomize/extract.js +1 -1
- package/dist/modules/manager/kustomize/extract.js.map +1 -1
- package/dist/modules/manager/leiningen/extract.js +2 -1
- package/dist/modules/manager/leiningen/extract.js.map +1 -1
- package/dist/modules/manager/maven/extract.js +6 -6
- package/dist/modules/manager/maven/extract.js.map +1 -1
- package/dist/modules/manager/maven-wrapper/artifacts.js +4 -1
- package/dist/modules/manager/maven-wrapper/artifacts.js.map +1 -1
- package/dist/modules/manager/meteor/extract.js +1 -1
- package/dist/modules/manager/meteor/extract.js.map +1 -1
- package/dist/modules/manager/mix/artifacts.js +2 -1
- package/dist/modules/manager/mix/artifacts.js.map +1 -1
- package/dist/modules/manager/nix/extract.js +0 -1
- package/dist/modules/manager/nix/extract.js.map +1 -1
- package/dist/modules/manager/npm/artifacts.js +2 -1
- package/dist/modules/manager/npm/artifacts.js.map +1 -1
- package/dist/modules/manager/npm/extract/common/package-file.js +1 -1
- package/dist/modules/manager/npm/extract/common/package-file.js.map +1 -1
- package/dist/modules/manager/npm/extract/pnpm.js +2 -1
- package/dist/modules/manager/npm/extract/pnpm.js.map +1 -1
- package/dist/modules/manager/npm/extract/yarn.js +3 -2
- package/dist/modules/manager/npm/extract/yarn.js.map +1 -1
- package/dist/modules/manager/npm/post-update/index.js +9 -7
- package/dist/modules/manager/npm/post-update/index.js.map +1 -1
- package/dist/modules/manager/npm/post-update/npm.js +7 -4
- package/dist/modules/manager/npm/post-update/npm.js.map +1 -1
- package/dist/modules/manager/npm/post-update/pnpm.js +1 -1
- package/dist/modules/manager/npm/post-update/pnpm.js.map +1 -1
- package/dist/modules/manager/npm/update/dependency/index.js +2 -1
- package/dist/modules/manager/npm/update/dependency/index.js.map +1 -1
- package/dist/modules/manager/npm/update/index.js +5 -0
- package/dist/modules/manager/npm/update/index.js.map +1 -0
- package/dist/modules/manager/npm/update/locked-dependency/common/parent-version.js +1 -1
- package/dist/modules/manager/npm/update/locked-dependency/common/parent-version.js.map +1 -1
- package/dist/modules/manager/npm/update/locked-dependency/package-lock/index.js +21 -16
- package/dist/modules/manager/npm/update/locked-dependency/package-lock/index.js.map +1 -1
- package/dist/modules/manager/npm/update/locked-dependency/yarn-lock/get-locked.js +2 -2
- package/dist/modules/manager/npm/update/locked-dependency/yarn-lock/get-locked.js.map +1 -1
- package/dist/modules/manager/npm/update/locked-dependency/yarn-lock/index.js +1 -1
- package/dist/modules/manager/npm/update/locked-dependency/yarn-lock/index.js.map +1 -1
- package/dist/modules/manager/npm/utils.js +3 -3
- package/dist/modules/manager/npm/utils.js.map +1 -1
- package/dist/modules/manager/nuget/artifacts.js +2 -1
- package/dist/modules/manager/nuget/artifacts.js.map +1 -1
- package/dist/modules/manager/nuget/update.js +2 -1
- package/dist/modules/manager/nuget/update.js.map +1 -1
- package/dist/modules/manager/pep621/processors/pdm.js +2 -1
- package/dist/modules/manager/pep621/processors/pdm.js.map +1 -1
- package/dist/modules/manager/pep621/schema.js +2 -1
- package/dist/modules/manager/pep621/schema.js.map +1 -1
- package/dist/modules/manager/pip-compile/artifacts.js +2 -1
- package/dist/modules/manager/pip-compile/artifacts.js.map +1 -1
- package/dist/modules/manager/pip_requirements/artifacts.js +5 -3
- package/dist/modules/manager/pip_requirements/artifacts.js.map +1 -1
- package/dist/modules/manager/pipenv/extract.js +2 -1
- package/dist/modules/manager/pipenv/extract.js.map +1 -1
- package/dist/modules/manager/poetry/artifacts.js +3 -2
- package/dist/modules/manager/poetry/artifacts.js.map +1 -1
- package/dist/modules/manager/poetry/extract.js +2 -1
- package/dist/modules/manager/poetry/extract.js.map +1 -1
- package/dist/modules/manager/pre-commit/extract.js +5 -3
- package/dist/modules/manager/pre-commit/extract.js.map +1 -1
- package/dist/modules/manager/puppet/puppetfile-parser.js +2 -1
- package/dist/modules/manager/puppet/puppetfile-parser.js.map +1 -1
- package/dist/modules/manager/quadlet/extract.js +2 -1
- package/dist/modules/manager/quadlet/extract.js.map +1 -1
- package/dist/modules/manager/sbt/extract.js +1 -1
- package/dist/modules/manager/sbt/extract.js.map +1 -1
- package/dist/modules/manager/swift/extract.js +4 -6
- package/dist/modules/manager/swift/extract.js.map +1 -1
- package/dist/modules/manager/terraform/lockfile/index.js +4 -3
- package/dist/modules/manager/terraform/lockfile/index.js.map +1 -1
- package/dist/modules/manager/terraform/util.js +2 -1
- package/dist/modules/manager/terraform/util.js.map +1 -1
- package/dist/modules/manager/terragrunt/extract.js +3 -9
- package/dist/modules/manager/terragrunt/extract.js.map +1 -1
- package/dist/modules/manager/tflint-plugin/extract.js +1 -1
- package/dist/modules/manager/tflint-plugin/extract.js.map +1 -1
- package/dist/modules/manager/vendir/artifacts.js +3 -2
- package/dist/modules/manager/vendir/artifacts.js.map +1 -1
- package/dist/modules/platform/azure/index.js +8 -7
- package/dist/modules/platform/azure/index.js.map +1 -1
- package/dist/modules/platform/bitbucket/comments.js +2 -2
- package/dist/modules/platform/bitbucket/comments.js.map +1 -1
- package/dist/modules/platform/bitbucket/index.js +9 -8
- package/dist/modules/platform/bitbucket/index.js.map +1 -1
- package/dist/modules/platform/bitbucket-server/index.js +8 -9
- package/dist/modules/platform/bitbucket-server/index.js.map +1 -1
- package/dist/modules/platform/codecommit/codecommit-client.js +8 -5
- package/dist/modules/platform/codecommit/codecommit-client.js.map +1 -1
- package/dist/modules/platform/codecommit/index.js +5 -5
- package/dist/modules/platform/codecommit/index.js.map +1 -1
- package/dist/modules/platform/forgejo/forgejo-helper.js +5 -3
- package/dist/modules/platform/forgejo/forgejo-helper.js.map +1 -1
- package/dist/modules/platform/forgejo/index.js +15 -8
- package/dist/modules/platform/forgejo/index.js.map +1 -1
- package/dist/modules/platform/gerrit/client.js +2 -1
- package/dist/modules/platform/gerrit/client.js.map +1 -1
- package/dist/modules/platform/gerrit/index.js +4 -2
- package/dist/modules/platform/gerrit/index.js.map +1 -1
- package/dist/modules/platform/gerrit/utils.js +1 -1
- package/dist/modules/platform/gerrit/utils.js.map +1 -1
- package/dist/modules/platform/gitea/gitea-helper.js +5 -3
- package/dist/modules/platform/gitea/gitea-helper.js.map +1 -1
- package/dist/modules/platform/gitea/index.js +16 -9
- package/dist/modules/platform/gitea/index.js.map +1 -1
- package/dist/modules/platform/github/index.js +27 -24
- package/dist/modules/platform/github/index.js.map +1 -1
- package/dist/modules/platform/github/massage-markdown-links.js +1 -1
- package/dist/modules/platform/github/massage-markdown-links.js.map +1 -1
- package/dist/modules/platform/github/pr.js +1 -1
- package/dist/modules/platform/github/pr.js.map +1 -1
- package/dist/modules/platform/github/schema.js +3 -2
- package/dist/modules/platform/github/schema.js.map +1 -1
- package/dist/modules/platform/gitlab/index.js +19 -14
- package/dist/modules/platform/gitlab/index.js.map +1 -1
- package/dist/modules/platform/local/scm.js +1 -1
- package/dist/modules/platform/local/scm.js.map +1 -1
- package/dist/modules/platform/util.js +2 -1
- package/dist/modules/platform/util.js.map +1 -1
- package/dist/modules/versioning/cargo/index.js +1 -1
- package/dist/modules/versioning/cargo/index.js.map +1 -1
- package/dist/modules/versioning/conan/index.js +4 -2
- package/dist/modules/versioning/conan/index.js.map +1 -1
- package/dist/modules/versioning/nixpkgs/index.js +2 -1
- package/dist/modules/versioning/nixpkgs/index.js.map +1 -1
- package/dist/modules/versioning/nuget/index.js +4 -2
- package/dist/modules/versioning/nuget/index.js.map +1 -1
- package/dist/modules/versioning/nuget/range.js +4 -2
- package/dist/modules/versioning/nuget/range.js.map +1 -1
- package/dist/modules/versioning/pep440/range.js +1 -1
- package/dist/modules/versioning/pep440/range.js.map +1 -1
- package/dist/modules/versioning/perl/index.js +1 -1
- package/dist/modules/versioning/perl/index.js.map +1 -1
- package/dist/modules/versioning/poetry/index.js +2 -2
- package/dist/modules/versioning/poetry/index.js.map +1 -1
- package/dist/modules/versioning/rez/index.js +5 -5
- package/dist/modules/versioning/rez/index.js.map +1 -1
- package/dist/modules/versioning/ruby/strategies/bump.js +3 -2
- package/dist/modules/versioning/ruby/strategies/bump.js.map +1 -1
- package/dist/modules/versioning/ruby/strategies/replace.js +3 -2
- package/dist/modules/versioning/ruby/strategies/replace.js.map +1 -1
- package/dist/modules/versioning/ruby/strategies/widen.js +3 -2
- package/dist/modules/versioning/ruby/strategies/widen.js.map +1 -1
- package/dist/util/cache/package/index.js +3 -1
- package/dist/util/cache/package/index.js.map +1 -1
- package/dist/util/cache/package/with-cache.js +7 -4
- package/dist/util/cache/package/with-cache.js.map +1 -1
- package/dist/util/cache/repository/impl/base.js +3 -2
- package/dist/util/cache/repository/impl/base.js.map +1 -1
- package/dist/util/cache/repository/impl/local.js +2 -1
- package/dist/util/cache/repository/impl/local.js.map +1 -1
- package/dist/util/cache/repository/impl/s3.js +4 -1
- package/dist/util/cache/repository/impl/s3.js.map +1 -1
- package/dist/util/date.js +1 -1
- package/dist/util/date.js.map +1 -1
- package/dist/util/emoji.js +6 -2
- package/dist/util/emoji.js.map +1 -1
- package/dist/util/exec/common.js +1 -1
- package/dist/util/exec/common.js.map +1 -1
- package/dist/util/exec/docker/index.js +2 -1
- package/dist/util/exec/docker/index.js.map +1 -1
- package/dist/util/exec/hermit.js +2 -1
- package/dist/util/exec/hermit.js.map +1 -1
- package/dist/util/exec/index.js +1 -1
- package/dist/util/exec/index.js.map +1 -1
- package/dist/util/fs/index.js +2 -1
- package/dist/util/fs/index.js.map +1 -1
- package/dist/util/git/index.js +32 -34
- package/dist/util/git/index.js.map +1 -1
- package/dist/util/git/url.js +2 -3
- package/dist/util/git/url.js.map +1 -1
- package/dist/util/github/graphql/cache-strategies/memory-cache-strategy.js +4 -2
- package/dist/util/github/graphql/cache-strategies/memory-cache-strategy.js.map +1 -1
- package/dist/util/github/graphql/datasource-fetcher.js +3 -1
- package/dist/util/github/graphql/datasource-fetcher.js.map +1 -1
- package/dist/util/http/cache/memory-http-cache-provider.js +2 -1
- package/dist/util/http/cache/memory-http-cache-provider.js.map +1 -1
- package/dist/util/http/github.js +3 -2
- package/dist/util/http/github.js.map +1 -1
- package/dist/util/http/http.js +2 -1
- package/dist/util/http/http.js.map +1 -1
- package/dist/util/http/index.js +1 -0
- package/dist/util/http/index.js.map +1 -1
- package/dist/util/http/www-authenticate.js +1 -3
- package/dist/util/http/www-authenticate.js.map +1 -1
- package/dist/util/mutex.js +1 -1
- package/dist/util/mutex.js.map +1 -1
- package/dist/util/schema-utils/index.js +1 -1
- package/dist/util/schema-utils/index.js.map +1 -1
- package/dist/util/toml.js +2 -1
- package/dist/util/toml.js.map +1 -1
- package/dist/util/yaml.js +4 -2
- package/dist/util/yaml.js.map +1 -1
- package/dist/workers/global/config/parse/util.js.map +1 -1
- package/dist/workers/global/index.js +2 -2
- package/dist/workers/global/index.js.map +1 -1
- package/dist/workers/repository/changelog/index.js +2 -1
- package/dist/workers/repository/changelog/index.js.map +1 -1
- package/dist/workers/repository/config-migration/branch/rebase.js +2 -1
- package/dist/workers/repository/config-migration/branch/rebase.js.map +1 -1
- package/dist/workers/repository/error-config.js +1 -1
- package/dist/workers/repository/error-config.js.map +1 -1
- package/dist/workers/repository/finalize/prune.js +1 -1
- package/dist/workers/repository/finalize/prune.js.map +1 -1
- package/dist/workers/repository/finalize/repository-statistics.js +1 -4
- package/dist/workers/repository/finalize/repository-statistics.js.map +1 -1
- package/dist/workers/repository/index.js +8 -5
- package/dist/workers/repository/index.js.map +1 -1
- package/dist/workers/repository/init/vulnerability.js +1 -1
- package/dist/workers/repository/init/vulnerability.js.map +1 -1
- package/dist/workers/repository/onboarding/branch/config.js +2 -1
- package/dist/workers/repository/onboarding/branch/config.js.map +1 -1
- package/dist/workers/repository/onboarding/branch/create.js +2 -1
- package/dist/workers/repository/onboarding/branch/create.js.map +1 -1
- package/dist/workers/repository/onboarding/branch/index.js +2 -1
- package/dist/workers/repository/onboarding/branch/index.js.map +1 -1
- package/dist/workers/repository/onboarding/pr/index.js +3 -1
- package/dist/workers/repository/onboarding/pr/index.js.map +1 -1
- package/dist/workers/repository/process/lookup/filter-checks.js +2 -1
- package/dist/workers/repository/process/lookup/filter-checks.js.map +1 -1
- package/dist/workers/repository/process/lookup/filter.js +1 -1
- package/dist/workers/repository/process/lookup/filter.js.map +1 -1
- package/dist/workers/repository/process/lookup/generate.js +1 -1
- package/dist/workers/repository/process/lookup/generate.js.map +1 -1
- package/dist/workers/repository/process/lookup/index.js +6 -3
- package/dist/workers/repository/process/lookup/index.js.map +1 -1
- package/dist/workers/repository/process/lookup/rollback.js +1 -1
- package/dist/workers/repository/process/lookup/rollback.js.map +1 -1
- package/dist/workers/repository/process/vulnerabilities.js +2 -1
- package/dist/workers/repository/process/vulnerabilities.js.map +1 -1
- package/dist/workers/repository/process/write.js +8 -4
- package/dist/workers/repository/process/write.js.map +1 -1
- package/dist/workers/repository/reconfigure/validate.js +2 -1
- package/dist/workers/repository/reconfigure/validate.js.map +1 -1
- package/dist/workers/repository/update/branch/auto-replace.js +1 -1
- package/dist/workers/repository/update/branch/auto-replace.js.map +1 -1
- package/dist/workers/repository/update/branch/bump-versions.js +2 -1
- package/dist/workers/repository/update/branch/bump-versions.js.map +1 -1
- package/dist/workers/repository/update/branch/index.js +3 -1
- package/dist/workers/repository/update/branch/index.js.map +1 -1
- package/dist/workers/repository/update/pr/automerge.js +1 -1
- package/dist/workers/repository/update/pr/automerge.js.map +1 -1
- package/dist/workers/repository/update/pr/body/updates-table.js +1 -1
- package/dist/workers/repository/update/pr/body/updates-table.js.map +1 -1
- package/dist/workers/repository/update/pr/changelog/github/index.js +2 -1
- package/dist/workers/repository/update/pr/changelog/github/index.js.map +1 -1
- package/dist/workers/repository/update/pr/changelog/github/source.js +2 -1
- package/dist/workers/repository/update/pr/changelog/github/source.js.map +1 -1
- package/dist/workers/repository/update/pr/changelog/index.js +1 -1
- package/dist/workers/repository/update/pr/changelog/index.js.map +1 -1
- package/dist/workers/repository/update/pr/changelog/release-notes.js +5 -5
- package/dist/workers/repository/update/pr/changelog/release-notes.js.map +1 -1
- package/dist/workers/repository/update/pr/changelog/releases.js +1 -1
- package/dist/workers/repository/update/pr/changelog/releases.js.map +1 -1
- package/dist/workers/repository/update/pr/index.js +6 -3
- package/dist/workers/repository/update/pr/index.js.map +1 -1
- package/dist/workers/repository/update/pr/pr-reuse.js +1 -1
- package/dist/workers/repository/update/pr/pr-reuse.js.map +1 -1
- package/package.json +1 -1
- package/renovate-schema.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","names":["packageCache.get","HttpError","packageCache.set","packageCache.getCacheType"],"sources":["../../../../lib/modules/datasource/maven/util.ts"],"sourcesContent":["import { Readable } from 'node:stream';\nimport { GetObjectCommand } from '@aws-sdk/client-s3';\nimport { XmlDocument } from 'xmldoc';\nimport { HOST_DISABLED } from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport * as packageCache from '../../../util/cache/package/index.ts';\nimport { PackageHttpCacheProvider } from '../../../util/http/cache/package-http-cache-provider.ts';\nimport { type Http, HttpError } from '../../../util/http/index.ts';\nimport type { HttpOptions, HttpResponse } from '../../../util/http/types.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { Result } from '../../../util/result.ts';\nimport { getS3Client, parseS3Url } from '../../../util/s3.ts';\nimport { streamToString } from '../../../util/streams.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport { ensureTrailingSlash, isHttpUrl } from '../../../util/url.ts';\nimport { getGoogleAuthToken } from '../util.ts';\nimport { isMavenCentral } from './common.ts';\nimport { CachedMavenXml } from './schema.ts';\nimport type {\n DependencyInfo,\n MavenDependency,\n MavenFetchResult,\n MavenFetchSuccess,\n} from './types.ts';\n\nfunction isTemporaryError(err: HttpError): boolean {\n if (err.code === 'ECONNRESET') {\n return true;\n }\n\n if (err.response) {\n const status = err.response.statusCode;\n return status === 429 || (status >= 500 && status < 600);\n }\n\n return false;\n}\n\nfunction isHostError(err: HttpError): boolean {\n return err.code === 'ETIMEDOUT';\n}\n\nfunction isNotFoundError(err: HttpError): boolean {\n return err.code === 'ENOTFOUND' || err.response?.statusCode === 404;\n}\n\nfunction isPermissionsIssue(err: HttpError): boolean {\n const status = err.response?.statusCode;\n return status === 401 || status === 403;\n}\n\nfunction isConnectionError(err: HttpError): boolean {\n return (\n err.code === 'EAI_AGAIN' ||\n err.code === 'ERR_TLS_CERT_ALTNAME_INVALID' ||\n err.code === 'ECONNREFUSED'\n );\n}\n\nfunction isUnsupportedHostError(err: HttpError): boolean {\n return err.name === 'UnsupportedProtocolError';\n}\n\nconst cacheProvider = new PackageHttpCacheProvider({\n namespace: 'datasource-maven:cache-provider',\n softTtlMinutes: 15,\n checkAuthorizationHeader: true,\n checkCacheControlHeader: false, // Maven doesn't respond with `cache-control` headers\n writeSchema: CachedMavenXml,\n});\n\n// Release POMs and timestamped snapshot POMs are immutable once published, so we can cache them much longer than mutable metadata files.\nconst pomCacheProvider = new PackageHttpCacheProvider({\n namespace: 'datasource-maven:pom-cache-provider',\n softTtlMinutes: 60 * 24 * 28, // 28 days before we'll give it another check, just in case it's updated\n checkAuthorizationHeader: true,\n checkCacheControlHeader: false,\n writeSchema: CachedMavenXml,\n});\n\nfunction selectCacheProvider(url: string): PackageHttpCacheProvider {\n // Non-timestamped -SNAPSHOT.pom files are mutable; everything else ending in .pom (release POMs and timestamped snapshot POMs) is immutable.\n if (url.endsWith('.pom') && !url.endsWith('-SNAPSHOT.pom')) {\n return pomCacheProvider;\n }\n return cacheProvider;\n}\n\nconst METADATA_NOT_FOUND_NAMESPACE =\n 'datasource-maven:metadata-not-found' as const;\nconst METADATA_NOT_FOUND_TTL_MINUTES = 60 * 12; // 12 hours\n\n/** introduces jitter to make sure that a given repo's cache expiring doesn't lead to many requests leading to high traffic and/or rate limits */\nfunction getMetadataNotFoundTtl(): number {\n const jitter = Math.floor(Math.random() * 60 * 2); // 0–120 minutes\n return METADATA_NOT_FOUND_TTL_MINUTES + jitter;\n}\n\nfunction isMetadataUrl(url: string): boolean {\n return url.endsWith('/maven-metadata.xml');\n}\n\nexport async function downloadHttpProtocol(\n http: Http,\n pkgUrl: URL | string,\n opts: HttpOptions = {},\n): Promise<MavenFetchResult> {\n const url = pkgUrl.toString();\n\n if (isMetadataUrl(url)) {\n const cacheHasNotFoundResponse = await packageCache.get<true>(\n METADATA_NOT_FOUND_NAMESPACE,\n url,\n );\n if (cacheHasNotFoundResponse) {\n logger.trace(\n { url },\n 'Returning cached 404 response for the metadata-metadata URL request',\n );\n return Result.err({ type: 'not-found' });\n }\n }\n\n const fetchResult = await Result.wrap<HttpResponse>(\n http.getText(url, { ...opts, cacheProvider: selectCacheProvider(url) }),\n )\n .transform((res): MavenFetchSuccess => {\n const result: MavenFetchSuccess = { data: res.body };\n\n if (!res.authorization) {\n result.isCacheable = true;\n }\n\n const lastModified = asTimestamp(res?.headers?.['last-modified']);\n if (lastModified) {\n result.lastModified = lastModified;\n }\n\n return result;\n })\n .catch(async (err): Promise<MavenFetchResult> => {\n /* v8 ignore next: never happens, needs for type narrowing */\n if (!(err instanceof HttpError)) {\n return Result.err({ type: 'unknown', err });\n }\n\n const failedUrl = url;\n if (err.message === HOST_DISABLED) {\n logger.trace({ failedUrl }, 'Host disabled');\n return Result.err({ type: 'host-disabled' });\n }\n\n if (isNotFoundError(err)) {\n logger.trace({ failedUrl }, `Url not found`);\n if (isMetadataUrl(failedUrl)) {\n await packageCache.set(\n METADATA_NOT_FOUND_NAMESPACE,\n failedUrl,\n true,\n getMetadataNotFoundTtl(),\n );\n }\n return Result.err({ type: 'not-found' });\n }\n\n if (isHostError(err)) {\n logger.debug(`Cannot connect to host ${failedUrl}`);\n return Result.err({ type: 'host-error' });\n }\n\n if (isPermissionsIssue(err)) {\n logger.debug(\n `Dependency lookup unauthorized. Please add authentication with a hostRule for ${failedUrl}`,\n );\n return Result.err({ type: 'permission-issue' });\n }\n\n if (isTemporaryError(err)) {\n logger.debug({ failedUrl, err }, 'Temporary error');\n\n if (isMavenCentral(url)) {\n const statusCode = err?.response?.statusCode;\n if (statusCode === 429) {\n if (packageCache.getCacheType() === 'redis') {\n logger.once.warn(\n { failedUrl },\n 'Maven Central rate limiting detected despite Redis caching.',\n );\n } else {\n logger.once.warn(\n { failedUrl },\n 'Maven Central rate limiting detected. Persistent caching required.',\n );\n }\n }\n return Result.err({ type: 'maven-central-temporary-error', err });\n }\n return Result.err({ type: 'temporary-error' });\n }\n\n if (isConnectionError(err)) {\n logger.debug(`Connection refused to maven registry ${failedUrl}`);\n return Result.err({ type: 'connection-error' });\n }\n\n if (isUnsupportedHostError(err)) {\n logger.debug(`Unsupported host ${failedUrl}`);\n return Result.err({ type: 'unsupported-host' });\n }\n\n logger.info({ failedUrl, err }, 'Unknown HTTP download error');\n return Result.err({ type: 'unknown', err });\n });\n\n const { err } = fetchResult.unwrap();\n if (err?.type === 'maven-central-temporary-error') {\n throw new ExternalHostError(err.err);\n }\n\n return fetchResult;\n}\n\nexport async function downloadHttpContent(\n http: Http,\n pkgUrl: URL | string,\n opts: HttpOptions = {},\n): Promise<string | null> {\n const fetchResult = await downloadHttpProtocol(http, pkgUrl, opts);\n return fetchResult.transform(({ data }) => data).unwrapOrNull();\n}\n\nfunction isS3NotFound(err: Error): boolean {\n return err.message === 'NotFound' || err.message === 'NoSuchKey';\n}\n\nexport async function downloadS3Protocol(\n pkgUrl: URL,\n): Promise<MavenFetchResult> {\n logger.trace({ url: pkgUrl.toString() }, `Attempting to load S3 dependency`);\n\n const s3Url = parseS3Url(pkgUrl);\n if (!s3Url) {\n return Result.err({ type: 'invalid-url' });\n }\n\n return await Result.wrap(() => {\n const command = new GetObjectCommand(s3Url);\n const client = getS3Client();\n return client.send(command);\n })\n .transform(\n async ({\n Body,\n LastModified,\n DeleteMarker,\n }): Promise<MavenFetchResult> => {\n if (DeleteMarker) {\n logger.trace(\n { failedUrl: pkgUrl.toString() },\n 'Maven S3 lookup error: DeleteMarker encountered',\n );\n return Result.err({ type: 'not-found' });\n }\n\n if (!(Body instanceof Readable)) {\n logger.debug(\n { failedUrl: pkgUrl.toString() },\n 'Maven S3 lookup error: unsupported Body type',\n );\n return Result.err({ type: 'unsupported-format' });\n }\n\n const data = await streamToString(Body);\n const result: MavenFetchSuccess = { data };\n\n const lastModified = asTimestamp(LastModified);\n if (lastModified) {\n result.lastModified = lastModified;\n }\n\n return Result.ok(result);\n },\n )\n .catch((err): MavenFetchResult => {\n if (!(err instanceof Error)) {\n return Result.err(err);\n }\n\n const failedUrl = pkgUrl.toString();\n\n if (err.name === 'CredentialsProviderError') {\n logger.debug(\n { failedUrl },\n 'Maven S3 lookup error: credentials provider error, check \"AWS_ACCESS_KEY_ID\" and \"AWS_SECRET_ACCESS_KEY\" variables',\n );\n return Result.err({ type: 'credentials-error' });\n }\n\n if (err.message === 'Region is missing') {\n logger.debug(\n { failedUrl },\n 'Maven S3 lookup error: missing region, check \"AWS_REGION\" variable',\n );\n return Result.err({ type: 'missing-aws-region' });\n }\n\n if (isS3NotFound(err)) {\n logger.trace({ failedUrl }, 'Maven S3 lookup error: object not found');\n return Result.err({ type: 'not-found' });\n }\n\n logger.debug({ failedUrl, err }, 'Maven S3 lookup error: unknown error');\n return Result.err({ type: 'unknown', err });\n });\n}\n\nexport async function downloadArtifactRegistryProtocol(\n http: Http,\n pkgUrl: URL,\n): Promise<MavenFetchResult> {\n const opts: HttpOptions = {};\n const host = pkgUrl.host;\n const path = pkgUrl.pathname;\n\n logger.trace({ host, path }, `Using google auth for Maven repository`);\n const auth = await getGoogleAuthToken();\n if (auth) {\n opts.headers = { authorization: `Basic ${auth}` };\n } else {\n logger.once.debug(\n { host, path },\n 'Could not get Google access token, using no auth',\n );\n }\n\n const url = pkgUrl.toString().replace('artifactregistry:', 'https:');\n\n return downloadHttpProtocol(http, url, opts);\n}\n\nfunction containsPlaceholder(str: string): boolean {\n return regEx(/\\${.*?}/g).test(str);\n}\n\nfunction removeKnownPlaceholders(str: string): string {\n return str.replace(regEx(/\\/tree\\/\\${[^}]+}/), '');\n}\n\nexport function getMavenUrl(\n dependency: MavenDependency,\n repoUrl: string,\n path: string,\n): URL {\n return new URL(\n `${dependency.dependencyUrl}/${path}`,\n ensureTrailingSlash(repoUrl),\n );\n}\n\nexport async function downloadMaven(\n http: Http,\n url: URL,\n): Promise<MavenFetchResult> {\n const protocol = url.protocol;\n\n let result: MavenFetchResult = Result.err({ type: 'unsupported-protocol' });\n\n if (isHttpUrl(url)) {\n result = await downloadHttpProtocol(http, url);\n }\n\n if (protocol === 'artifactregistry:') {\n result = await downloadArtifactRegistryProtocol(http, url);\n }\n\n if (protocol === 's3:') {\n result = await downloadS3Protocol(url);\n }\n\n return result.onError((err) => {\n if (err.type === 'unsupported-protocol') {\n logger.debug(\n { url: url.toString() },\n `Maven lookup error: unsupported protocol (${protocol})`,\n );\n }\n });\n}\n\nexport async function downloadMavenXml(\n http: Http,\n url: URL,\n): Promise<MavenFetchResult<XmlDocument>> {\n const rawResult = await downloadMaven(http, url);\n return rawResult.transform((result): MavenFetchResult<XmlDocument> => {\n try {\n return Result.ok({\n ...result,\n data: new XmlDocument(result.data),\n });\n } catch (err) {\n return Result.err({ type: 'xml-parse-error', err });\n }\n });\n}\n\nexport function getDependencyParts(packageName: string): MavenDependency {\n const [group, name] = packageName.split(':');\n const dependencyUrl = `${group.replace(regEx(/\\./g), '/')}/${name}`;\n return {\n display: packageName,\n group,\n name,\n dependencyUrl,\n };\n}\n\nfunction extractSnapshotVersion(metadata: XmlDocument): string | null {\n // Parse the maven-metadata.xml for the snapshot version and determine\n // the fixed version of the latest deployed snapshot.\n // The metadata descriptor can be found at\n // https://maven.apache.org/ref/3.3.3/maven-repository-metadata/repository-metadata.html\n //\n // Basically, we need to replace -SNAPSHOT with the artifact timestanp & build number,\n // so for example 1.0.0-SNAPSHOT will become 1.0.0-<timestamp>-<buildNumber>\n const version = metadata\n .descendantWithPath('version')\n ?.val?.replace('-SNAPSHOT', '');\n\n const snapshot = metadata.descendantWithPath('versioning.snapshot');\n const timestamp = snapshot?.childNamed('timestamp')?.val;\n const build = snapshot?.childNamed('buildNumber')?.val;\n\n // If we weren't able to parse out the required 3 version elements,\n // return null because we can't determine the fixed version of the latest snapshot.\n if (!version || !timestamp || !build) {\n return null;\n }\n return `${version}-${timestamp}-${build}`;\n}\n\nasync function getSnapshotFullVersion(\n http: Http,\n version: string,\n dependency: MavenDependency,\n repoUrl: string,\n): Promise<string | null> {\n // To determine what actual files are available for the snapshot, first we have to fetch and parse\n // the metadata located at http://<repo>/<group>/<artifact>/<version-SNAPSHOT>/maven-metadata.xml\n const metadataUrl = getMavenUrl(\n dependency,\n repoUrl,\n `${version}/maven-metadata.xml`,\n );\n\n const metadataXmlResult = await downloadMavenXml(http, metadataUrl);\n\n return metadataXmlResult\n .transform(({ data }) =>\n Result.wrapNullable(extractSnapshotVersion(data), {\n type: 'snapshot-extract-error',\n }),\n )\n .unwrapOrNull();\n}\n\nfunction isSnapshotVersion(version: string): boolean {\n if (version.endsWith('-SNAPSHOT')) {\n return true;\n }\n return false;\n}\n\nexport async function createUrlForDependencyPom(\n http: Http,\n version: string,\n dependency: MavenDependency,\n repoUrl: string,\n): Promise<string> {\n if (isSnapshotVersion(version)) {\n // By default, Maven snapshots are deployed to the repository with fixed file names.\n // Resolve the full, actual pom file name for the version.\n const fullVersion = await getSnapshotFullVersion(\n http,\n version,\n dependency,\n repoUrl,\n );\n\n // If we were able to resolve the version, use that, otherwise fall back to using -SNAPSHOT\n if (fullVersion !== null) {\n // TODO: types (#22198)\n return `${version}/${dependency.name}-${fullVersion}.pom`;\n }\n }\n\n // TODO: types (#22198)\n return `${version}/${dependency.name}-${version}.pom`;\n}\n\nexport async function getDependencyInfo(\n http: Http,\n dependency: MavenDependency,\n repoUrl: string,\n version: string,\n recursionLimit = 5,\n): Promise<DependencyInfo> {\n const path = await createUrlForDependencyPom(\n http,\n version,\n dependency,\n repoUrl,\n );\n\n const pomUrl = getMavenUrl(dependency, repoUrl, path);\n const pomXmlResult = await downloadMavenXml(http, pomUrl);\n const dependencyInfoResult = await pomXmlResult.transform(\n async ({ data: pomContent }) => {\n const result: DependencyInfo = {};\n\n const homepage = pomContent.valueWithPath('url');\n if (homepage && !containsPlaceholder(homepage)) {\n result.homepage = homepage;\n }\n\n const sourceUrl = pomContent.valueWithPath('scm.url');\n if (\n sourceUrl &&\n !containsPlaceholder(removeKnownPlaceholders(sourceUrl))\n ) {\n result.sourceUrl = sourceUrl\n .replace(regEx(/^scm:/), '')\n .replace(regEx(/^git:/), '')\n .replace(regEx(/^git@github.com:/), 'https://github.com/')\n .replace(regEx(/^git@github.com\\//), 'https://github.com/');\n\n if (result.sourceUrl.startsWith('//')) {\n // most likely the result of us stripping scm:, git: etc\n // going with prepending https: here which should result in potential information retrival\n result.sourceUrl = `https:${result.sourceUrl}`;\n }\n }\n\n const relocation = pomContent.descendantWithPath(\n 'distributionManagement.relocation',\n );\n if (relocation) {\n const relocationGroup =\n relocation.valueWithPath('groupId') ?? dependency.group;\n const relocationName =\n relocation.valueWithPath('artifactId') ?? dependency.name;\n result.replacementName = `${relocationGroup}:${relocationName}`;\n const relocationVersion = relocation.valueWithPath('version');\n result.replacementVersion = relocationVersion ?? version;\n const relocationMessage = relocation.valueWithPath('message');\n if (relocationMessage) {\n result.deprecationMessage = relocationMessage;\n }\n }\n\n const groupId = pomContent.valueWithPath('groupId');\n if (groupId) {\n result.packageScope = groupId;\n }\n\n const parent = pomContent.childNamed('parent');\n if (\n recursionLimit > 0 &&\n parent &&\n (!result.sourceUrl || !result.homepage)\n ) {\n // if we found a parent and are missing some information\n // trying to get the scm/homepage information from it\n const [parentGroupId, parentArtifactId, parentVersion] = [\n 'groupId',\n 'artifactId',\n 'version',\n ].map((k) => parent.valueWithPath(k)?.replace(/\\s+/g, ''));\n if (parentGroupId && parentArtifactId && parentVersion) {\n const parentDisplayId = `${parentGroupId}:${parentArtifactId}`;\n const parentDependency = getDependencyParts(parentDisplayId);\n const parentInformation = await getDependencyInfo(\n http,\n parentDependency,\n repoUrl,\n parentVersion,\n recursionLimit - 1,\n );\n if (!result.sourceUrl && parentInformation.sourceUrl) {\n result.sourceUrl = parentInformation.sourceUrl;\n }\n if (!result.homepage && parentInformation.homepage) {\n result.homepage = parentInformation.homepage;\n }\n }\n }\n\n return result;\n },\n );\n\n return dependencyInfoResult.unwrapOr({});\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"util.js","names":["packageCache.get","HttpError","packageCache.set","packageCache.getCacheType"],"sources":["../../../../lib/modules/datasource/maven/util.ts"],"sourcesContent":["import { Readable } from 'node:stream';\nimport { GetObjectCommand } from '@aws-sdk/client-s3';\nimport { XmlDocument } from 'xmldoc';\nimport { HOST_DISABLED } from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport * as packageCache from '../../../util/cache/package/index.ts';\nimport { PackageHttpCacheProvider } from '../../../util/http/cache/package-http-cache-provider.ts';\nimport { type Http, HttpError } from '../../../util/http/index.ts';\nimport type { HttpOptions, HttpResponse } from '../../../util/http/types.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { Result } from '../../../util/result.ts';\nimport { getS3Client, parseS3Url } from '../../../util/s3.ts';\nimport { streamToString } from '../../../util/streams.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport { ensureTrailingSlash, isHttpUrl } from '../../../util/url.ts';\nimport { getGoogleAuthToken } from '../util.ts';\nimport { isMavenCentral } from './common.ts';\nimport { CachedMavenXml } from './schema.ts';\nimport type {\n DependencyInfo,\n MavenDependency,\n MavenFetchResult,\n MavenFetchSuccess,\n} from './types.ts';\n\nfunction isTemporaryError(err: HttpError): boolean {\n if (err.code === 'ECONNRESET') {\n return true;\n }\n\n if (err.response) {\n const status = err.response.statusCode;\n return status === 429 || (status >= 500 && status < 600);\n }\n\n return false;\n}\n\nfunction isHostError(err: HttpError): boolean {\n return err.code === 'ETIMEDOUT';\n}\n\nfunction isNotFoundError(err: HttpError): boolean {\n return err.code === 'ENOTFOUND' || err.response?.statusCode === 404;\n}\n\nfunction isPermissionsIssue(err: HttpError): boolean {\n const status = err.response?.statusCode;\n return status === 401 || status === 403;\n}\n\nfunction isConnectionError(err: HttpError): boolean {\n return (\n err.code === 'EAI_AGAIN' ||\n err.code === 'ERR_TLS_CERT_ALTNAME_INVALID' ||\n err.code === 'ECONNREFUSED'\n );\n}\n\nfunction isUnsupportedHostError(err: HttpError): boolean {\n return err.name === 'UnsupportedProtocolError';\n}\n\nconst cacheProvider = new PackageHttpCacheProvider({\n namespace: 'datasource-maven:cache-provider',\n softTtlMinutes: 15,\n checkAuthorizationHeader: true,\n checkCacheControlHeader: false, // Maven doesn't respond with `cache-control` headers\n writeSchema: CachedMavenXml,\n});\n\n// Release POMs and timestamped snapshot POMs are immutable once published, so we can cache them much longer than mutable metadata files.\nconst pomCacheProvider = new PackageHttpCacheProvider({\n namespace: 'datasource-maven:pom-cache-provider',\n softTtlMinutes: 60 * 24 * 28, // 28 days before we'll give it another check, just in case it's updated\n checkAuthorizationHeader: true,\n checkCacheControlHeader: false,\n writeSchema: CachedMavenXml,\n});\n\nfunction selectCacheProvider(url: string): PackageHttpCacheProvider {\n // Non-timestamped -SNAPSHOT.pom files are mutable; everything else ending in .pom (release POMs and timestamped snapshot POMs) is immutable.\n if (url.endsWith('.pom') && !url.endsWith('-SNAPSHOT.pom')) {\n return pomCacheProvider;\n }\n return cacheProvider;\n}\n\nconst METADATA_NOT_FOUND_NAMESPACE =\n 'datasource-maven:metadata-not-found' as const;\nconst METADATA_NOT_FOUND_TTL_MINUTES = 60 * 12; // 12 hours\n\n/** introduces jitter to make sure that a given repo's cache expiring doesn't lead to many requests leading to high traffic and/or rate limits */\nfunction getMetadataNotFoundTtl(): number {\n const jitter = Math.floor(Math.random() * 60 * 2); // 0–120 minutes\n return METADATA_NOT_FOUND_TTL_MINUTES + jitter;\n}\n\nfunction isMetadataUrl(url: string): boolean {\n return url.endsWith('/maven-metadata.xml');\n}\n\nexport async function downloadHttpProtocol(\n http: Http,\n pkgUrl: URL | string,\n opts: HttpOptions = {},\n): Promise<MavenFetchResult> {\n const url = pkgUrl.toString();\n\n if (isMetadataUrl(url)) {\n const cacheHasNotFoundResponse = await packageCache.get<true>(\n METADATA_NOT_FOUND_NAMESPACE,\n url,\n );\n if (cacheHasNotFoundResponse) {\n logger.trace(\n { url },\n 'Returning cached 404 response for the metadata-metadata URL request',\n );\n return Result.err({ type: 'not-found' });\n }\n }\n\n const fetchResult = await Result.wrap<HttpResponse>(\n http.getText(url, { ...opts, cacheProvider: selectCacheProvider(url) }),\n )\n .transform((res): MavenFetchSuccess => {\n const result: MavenFetchSuccess = { data: res.body };\n\n if (!res.authorization) {\n result.isCacheable = true;\n }\n\n const lastModified = asTimestamp(res?.headers?.['last-modified']);\n if (lastModified) {\n result.lastModified = lastModified;\n }\n\n return result;\n })\n .catch(async (err): Promise<MavenFetchResult> => {\n /* v8 ignore next: never happens, needs for type narrowing */\n if (!(err instanceof HttpError)) {\n return Result.err({ type: 'unknown', err });\n }\n\n const failedUrl = url;\n if (err.message === HOST_DISABLED) {\n logger.trace({ failedUrl }, 'Host disabled');\n return Result.err({ type: 'host-disabled' });\n }\n\n if (isNotFoundError(err)) {\n logger.trace({ failedUrl }, `Url not found`);\n if (isMetadataUrl(failedUrl)) {\n await packageCache.set(\n METADATA_NOT_FOUND_NAMESPACE,\n failedUrl,\n true,\n getMetadataNotFoundTtl(),\n );\n }\n return Result.err({ type: 'not-found' });\n }\n\n if (isHostError(err)) {\n logger.debug(`Cannot connect to host ${failedUrl}`);\n return Result.err({ type: 'host-error' });\n }\n\n if (isPermissionsIssue(err)) {\n logger.debug(\n `Dependency lookup unauthorized. Please add authentication with a hostRule for ${failedUrl}`,\n );\n return Result.err({ type: 'permission-issue' });\n }\n\n if (isTemporaryError(err)) {\n logger.debug({ failedUrl, err }, 'Temporary error');\n\n if (isMavenCentral(url)) {\n const statusCode = err?.response?.statusCode;\n if (statusCode === 429) {\n if (packageCache.getCacheType() === 'redis') {\n logger.once.warn(\n { failedUrl },\n 'Maven Central rate limiting detected despite Redis caching.',\n );\n } else {\n logger.once.warn(\n { failedUrl },\n 'Maven Central rate limiting detected. Persistent caching required.',\n );\n }\n }\n return Result.err({ type: 'maven-central-temporary-error', err });\n }\n return Result.err({ type: 'temporary-error' });\n }\n\n if (isConnectionError(err)) {\n logger.debug(`Connection refused to maven registry ${failedUrl}`);\n return Result.err({ type: 'connection-error' });\n }\n\n if (isUnsupportedHostError(err)) {\n logger.debug(`Unsupported host ${failedUrl}`);\n return Result.err({ type: 'unsupported-host' });\n }\n\n logger.info({ failedUrl, err }, 'Unknown HTTP download error');\n return Result.err({ type: 'unknown', err });\n });\n\n const { err } = fetchResult.unwrap();\n if (err?.type === 'maven-central-temporary-error') {\n throw new ExternalHostError(err.err);\n }\n\n return fetchResult;\n}\n\nexport async function downloadHttpContent(\n http: Http,\n pkgUrl: URL | string,\n opts: HttpOptions = {},\n): Promise<string | null> {\n const fetchResult = await downloadHttpProtocol(http, pkgUrl, opts);\n return fetchResult.transform(({ data }) => data).unwrapOrNull();\n}\n\nfunction isS3NotFound(err: Error): boolean {\n return err.message === 'NotFound' || err.message === 'NoSuchKey';\n}\n\nexport async function downloadS3Protocol(\n pkgUrl: URL,\n): Promise<MavenFetchResult> {\n logger.trace({ url: pkgUrl.toString() }, `Attempting to load S3 dependency`);\n\n const s3Url = parseS3Url(pkgUrl);\n if (!s3Url) {\n return Result.err({ type: 'invalid-url' });\n }\n\n return await Result.wrap(() => {\n const command = new GetObjectCommand(s3Url);\n const client = getS3Client();\n return client.send(command);\n })\n .transform(\n async ({\n Body,\n LastModified,\n DeleteMarker,\n }): Promise<MavenFetchResult> => {\n if (DeleteMarker) {\n logger.trace(\n { failedUrl: pkgUrl.toString() },\n 'Maven S3 lookup error: DeleteMarker encountered',\n );\n return Result.err({ type: 'not-found' });\n }\n\n if (!(Body instanceof Readable)) {\n logger.debug(\n { failedUrl: pkgUrl.toString() },\n 'Maven S3 lookup error: unsupported Body type',\n );\n return Result.err({ type: 'unsupported-format' });\n }\n\n const data = await streamToString(Body);\n const result: MavenFetchSuccess = { data };\n\n const lastModified = asTimestamp(LastModified);\n if (lastModified) {\n result.lastModified = lastModified;\n }\n\n return Result.ok(result);\n },\n )\n .catch((err): MavenFetchResult => {\n if (!(err instanceof Error)) {\n return Result.err(err);\n }\n\n const failedUrl = pkgUrl.toString();\n\n if (err.name === 'CredentialsProviderError') {\n logger.debug(\n { failedUrl },\n 'Maven S3 lookup error: credentials provider error, check \"AWS_ACCESS_KEY_ID\" and \"AWS_SECRET_ACCESS_KEY\" variables',\n );\n return Result.err({ type: 'credentials-error' });\n }\n\n if (err.message === 'Region is missing') {\n logger.debug(\n { failedUrl },\n 'Maven S3 lookup error: missing region, check \"AWS_REGION\" variable',\n );\n return Result.err({ type: 'missing-aws-region' });\n }\n\n if (isS3NotFound(err)) {\n logger.trace({ failedUrl }, 'Maven S3 lookup error: object not found');\n return Result.err({ type: 'not-found' });\n }\n\n logger.debug({ failedUrl, err }, 'Maven S3 lookup error: unknown error');\n return Result.err({ type: 'unknown', err });\n });\n}\n\nexport async function downloadArtifactRegistryProtocol(\n http: Http,\n pkgUrl: URL,\n): Promise<MavenFetchResult> {\n const opts: HttpOptions = {};\n const host = pkgUrl.host;\n const path = pkgUrl.pathname;\n\n logger.trace({ host, path }, `Using google auth for Maven repository`);\n const auth = await getGoogleAuthToken();\n if (auth) {\n opts.headers = { authorization: `Basic ${auth}` };\n } else {\n logger.once.debug(\n { host, path },\n 'Could not get Google access token, using no auth',\n );\n }\n\n const url = pkgUrl.toString().replace('artifactregistry:', 'https:');\n\n return downloadHttpProtocol(http, url, opts);\n}\n\nfunction containsPlaceholder(str: string): boolean {\n return regEx(/\\${.*?}/g).test(str);\n}\n\nfunction removeKnownPlaceholders(str: string): string {\n return str.replace(regEx(/\\/tree\\/\\${[^}]+}/), '');\n}\n\nexport function getMavenUrl(\n dependency: MavenDependency,\n repoUrl: string,\n path: string,\n): URL {\n return new URL(\n `${dependency.dependencyUrl}/${path}`,\n ensureTrailingSlash(repoUrl),\n );\n}\n\nexport async function downloadMaven(\n http: Http,\n url: URL,\n): Promise<MavenFetchResult> {\n const protocol = url.protocol;\n\n let result: MavenFetchResult = Result.err({ type: 'unsupported-protocol' });\n\n if (isHttpUrl(url)) {\n result = await downloadHttpProtocol(http, url);\n }\n\n if (protocol === 'artifactregistry:') {\n result = await downloadArtifactRegistryProtocol(http, url);\n }\n\n if (protocol === 's3:') {\n result = await downloadS3Protocol(url);\n }\n\n return result.onError((err) => {\n if (err.type === 'unsupported-protocol') {\n logger.debug(\n { url: url.toString() },\n `Maven lookup error: unsupported protocol (${protocol})`,\n );\n }\n });\n}\n\nexport async function downloadMavenXml(\n http: Http,\n url: URL,\n): Promise<MavenFetchResult<XmlDocument>> {\n const rawResult = await downloadMaven(http, url);\n return rawResult.transform((result): MavenFetchResult<XmlDocument> => {\n try {\n return Result.ok({\n ...result,\n data: new XmlDocument(result.data),\n });\n } catch (err) {\n return Result.err({ type: 'xml-parse-error', err });\n }\n });\n}\n\nexport function getDependencyParts(packageName: string): MavenDependency {\n const [group, name] = packageName.split(':');\n const dependencyUrl = `${group.replace(regEx(/\\./g), '/')}/${name}`;\n return {\n display: packageName,\n group,\n name,\n dependencyUrl,\n };\n}\n\nfunction extractSnapshotVersion(metadata: XmlDocument): string | null {\n // Parse the maven-metadata.xml for the snapshot version and determine\n // the fixed version of the latest deployed snapshot.\n // The metadata descriptor can be found at\n // https://maven.apache.org/ref/3.3.3/maven-repository-metadata/repository-metadata.html\n //\n // Basically, we need to replace -SNAPSHOT with the artifact timestanp & build number,\n // so for example 1.0.0-SNAPSHOT will become 1.0.0-<timestamp>-<buildNumber>\n const version = metadata\n .descendantWithPath('version')\n ?.val?.replace('-SNAPSHOT', '');\n\n const snapshot = metadata.descendantWithPath('versioning.snapshot');\n const timestamp = snapshot?.childNamed('timestamp')?.val;\n const build = snapshot?.childNamed('buildNumber')?.val;\n\n // If we weren't able to parse out the required 3 version elements,\n // return null because we can't determine the fixed version of the latest snapshot.\n if (!version || !timestamp || !build) {\n return null;\n }\n return `${version}-${timestamp}-${build}`;\n}\n\nasync function getSnapshotFullVersion(\n http: Http,\n version: string,\n dependency: MavenDependency,\n repoUrl: string,\n): Promise<string | null> {\n // To determine what actual files are available for the snapshot, first we have to fetch and parse\n // the metadata located at http://<repo>/<group>/<artifact>/<version-SNAPSHOT>/maven-metadata.xml\n const metadataUrl = getMavenUrl(\n dependency,\n repoUrl,\n `${version}/maven-metadata.xml`,\n );\n\n const metadataXmlResult = await downloadMavenXml(http, metadataUrl);\n\n return metadataXmlResult\n .transform(({ data }) =>\n Result.wrapNullable(extractSnapshotVersion(data), {\n type: 'snapshot-extract-error',\n }),\n )\n .unwrapOrNull();\n}\n\nfunction isSnapshotVersion(version: string): boolean {\n if (version.endsWith('-SNAPSHOT')) {\n return true;\n }\n return false;\n}\n\nexport async function createUrlForDependencyPom(\n http: Http,\n version: string,\n dependency: MavenDependency,\n repoUrl: string,\n): Promise<string> {\n if (isSnapshotVersion(version)) {\n // By default, Maven snapshots are deployed to the repository with fixed file names.\n // Resolve the full, actual pom file name for the version.\n const fullVersion = await getSnapshotFullVersion(\n http,\n version,\n dependency,\n repoUrl,\n );\n\n // If we were able to resolve the version, use that, otherwise fall back to using -SNAPSHOT\n if (fullVersion !== null) {\n // TODO: types (#22198)\n return `${version}/${dependency.name}-${fullVersion}.pom`;\n }\n }\n\n // TODO: types (#22198)\n return `${version}/${dependency.name}-${version}.pom`;\n}\n\nexport async function getDependencyInfo(\n http: Http,\n dependency: MavenDependency,\n repoUrl: string,\n version: string,\n recursionLimit = 5,\n): Promise<DependencyInfo> {\n const path = await createUrlForDependencyPom(\n http,\n version,\n dependency,\n repoUrl,\n );\n\n const pomUrl = getMavenUrl(dependency, repoUrl, path);\n const pomXmlResult = await downloadMavenXml(http, pomUrl);\n const dependencyInfoResult = await pomXmlResult.transform(\n async ({ data: pomContent }) => {\n const result: DependencyInfo = {};\n\n const homepage = pomContent.valueWithPath('url');\n if (homepage && !containsPlaceholder(homepage)) {\n result.homepage = homepage;\n }\n\n const sourceUrl = pomContent.valueWithPath('scm.url');\n if (\n sourceUrl &&\n !containsPlaceholder(removeKnownPlaceholders(sourceUrl))\n ) {\n result.sourceUrl = sourceUrl\n .replace(regEx(/^scm:/), '')\n .replace(regEx(/^git:/), '')\n .replace(regEx(/^git@github.com:/), 'https://github.com/')\n .replace(regEx(/^git@github.com\\//), 'https://github.com/');\n\n if (result.sourceUrl.startsWith('//')) {\n // most likely the result of us stripping scm:, git: etc\n // going with prepending https: here which should result in potential information retrival\n result.sourceUrl = `https:${result.sourceUrl}`;\n }\n }\n\n const relocation = pomContent.descendantWithPath(\n 'distributionManagement.relocation',\n );\n if (relocation) {\n const relocationGroup =\n relocation.valueWithPath('groupId') ?? dependency.group;\n const relocationName =\n relocation.valueWithPath('artifactId') ?? dependency.name;\n result.replacementName = `${relocationGroup}:${relocationName}`;\n const relocationVersion = relocation.valueWithPath('version');\n result.replacementVersion = relocationVersion ?? version;\n const relocationMessage = relocation.valueWithPath('message');\n if (relocationMessage) {\n result.deprecationMessage = relocationMessage;\n }\n }\n\n const groupId = pomContent.valueWithPath('groupId');\n if (groupId) {\n result.packageScope = groupId;\n }\n\n const parent = pomContent.childNamed('parent');\n if (\n recursionLimit > 0 &&\n parent &&\n (!result.sourceUrl || !result.homepage)\n ) {\n // if we found a parent and are missing some information\n // trying to get the scm/homepage information from it\n const [parentGroupId, parentArtifactId, parentVersion] = [\n 'groupId',\n 'artifactId',\n 'version',\n ].map((k) => parent.valueWithPath(k)?.replace(/\\s+/g, ''));\n if (parentGroupId && parentArtifactId && parentVersion) {\n const parentDisplayId = `${parentGroupId}:${parentArtifactId}`;\n const parentDependency = getDependencyParts(parentDisplayId);\n const parentInformation = await getDependencyInfo(\n http,\n parentDependency,\n repoUrl,\n parentVersion,\n recursionLimit - 1,\n );\n if (!result.sourceUrl && parentInformation.sourceUrl) {\n result.sourceUrl = parentInformation.sourceUrl;\n }\n if (!result.homepage && parentInformation.homepage) {\n result.homepage = parentInformation.homepage;\n }\n }\n }\n\n return result;\n },\n );\n\n return dependencyInfoResult.unwrapOr({});\n}\n"],"mappings":"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"}
|
|
@@ -13,7 +13,8 @@ var NugetV2Api = class {
|
|
|
13
13
|
const dep = { releases: [] };
|
|
14
14
|
let pkgUrlList = `${feedUrl.replace(regEx(/\/+$/), "")}/FindPackagesById()?id=%27${pkgName}%27&$select=Version,IsLatestVersion,ProjectUrl,Published`;
|
|
15
15
|
while (pkgUrlList !== null) {
|
|
16
|
-
const
|
|
16
|
+
const pkgVersionsListRaw = await http.getText(pkgUrlList);
|
|
17
|
+
const pkgVersionsListDoc = new XmlDocument(pkgVersionsListRaw.body);
|
|
17
18
|
const pkgInfoList = pkgVersionsListDoc.childrenNamed("entry");
|
|
18
19
|
for (const pkgInfo of pkgInfoList) {
|
|
19
20
|
const version = this.getPkgProp(pkgInfo, "Version");
|
|
@@ -28,7 +29,7 @@ var NugetV2Api = class {
|
|
|
28
29
|
const projectUrl = this.getPkgProp(pkgInfo, "ProjectUrl");
|
|
29
30
|
if (projectUrl) dep.sourceUrl = massageUrl(projectUrl);
|
|
30
31
|
}
|
|
31
|
-
} catch (err)
|
|
32
|
+
} catch (err) /* istanbul ignore next */ {
|
|
32
33
|
logger.debug({
|
|
33
34
|
err,
|
|
34
35
|
pkgName,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v2.js","names":[],"sources":["../../../../lib/modules/datasource/nuget/v2.ts"],"sourcesContent":["import type { XmlElement } from 'xmldoc';\nimport { XmlDocument } from 'xmldoc';\nimport { logger } from '../../../logger/index.ts';\nimport type { Http } from '../../../util/http/index.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport type { ReleaseResult } from '../types.ts';\nimport { resolvePaginationUrl } from '../util.ts';\nimport { massageUrl, removeBuildMeta } from './common.ts';\n\nexport class NugetV2Api {\n getPkgProp(pkgInfo: XmlElement, propName: string): string | undefined {\n return pkgInfo.childNamed('m:properties')?.childNamed(`d:${propName}`)?.val;\n }\n\n async getReleases(\n http: Http,\n feedUrl: string,\n pkgName: string,\n allowCrossOrigin: boolean,\n ): Promise<ReleaseResult | null> {\n const dep: ReleaseResult = {\n releases: [],\n };\n let pkgUrlList: string | null = `${feedUrl.replace(\n regEx(/\\/+$/),\n '',\n )}/FindPackagesById()?id=%27${pkgName}%27&$select=Version,IsLatestVersion,ProjectUrl,Published`;\n while (pkgUrlList !== null) {\n // typescript issue\n const pkgVersionsListRaw = await http.getText(pkgUrlList);\n const pkgVersionsListDoc = new XmlDocument(pkgVersionsListRaw.body);\n\n const pkgInfoList = pkgVersionsListDoc.childrenNamed('entry');\n\n for (const pkgInfo of pkgInfoList) {\n const version = this.getPkgProp(pkgInfo, 'Version');\n const releaseTimestamp = asTimestamp(\n this.getPkgProp(pkgInfo, 'Published'),\n );\n dep.releases.push({\n // TODO: types (#22198)\n version: removeBuildMeta(`${version}`),\n releaseTimestamp,\n });\n try {\n const pkgIsLatestVersion = this.getPkgProp(\n pkgInfo,\n 'IsLatestVersion',\n );\n if (pkgIsLatestVersion === 'true') {\n dep.tags = { latest: removeBuildMeta(`${version}`) };\n const projectUrl = this.getPkgProp(pkgInfo, 'ProjectUrl');\n if (projectUrl) {\n dep.sourceUrl = massageUrl(projectUrl);\n }\n }\n } catch (err) /* istanbul ignore next */ {\n logger.debug(\n { err, pkgName, feedUrl },\n `nuget registry failure: can't parse pkg info for project url`,\n );\n }\n }\n\n const nextPkgUrlListLink = pkgVersionsListDoc\n .childrenNamed('link')\n .find((node) => node.attr.rel === 'next');\n\n // Resolve the relative-or-absolute next link, but only follow it when it stays on the same origin, or if the user has opted in via `RENOVATE_X_NUGET_PAGINATION_ALLOW_CROSS_ORIGIN`\n const nextHref = nextPkgUrlListLink?.attr.href;\n const nextUrl: string | null = nextHref\n ? resolvePaginationUrl(pkgUrlList, nextHref, allowCrossOrigin)\n : null;\n if (nextHref && !nextUrl) {\n // make sure that users are aware if there are any (potentially malicious, or misconfigured) pagination links being returned\n logger.once.warn(\n { feedUrl, nextUrl: nextHref },\n 'Ignoring cross-origin or invalid NuGet feed pagination link',\n );\n }\n pkgUrlList = nextUrl;\n }\n\n // dep not found if no release, so we can try next registry\n if (dep.releases.length === 0) {\n return null;\n }\n\n return dep;\n }\n}\n"],"mappings":";;;;;;;AAUA,IAAa,aAAb,MAAwB;CACtB,WAAW,SAAqB,UAAsC;EACpE,OAAO,QAAQ,WAAW,cAAc,CAAC,EAAE,WAAW,KAAK,UAAU,CAAC,EAAE;CAC1E;CAEA,MAAM,YACJ,MACA,SACA,SACA,kBAC+B;EAC/B,MAAM,MAAqB,EACzB,UAAU,CAAC,EACb;EACA,IAAI,aAA4B,GAAG,QAAQ,QACzC,MAAM,MAAM,GACZ,EACF,EAAE,4BAA4B,QAAQ;EACtC,OAAO,eAAe,MAAM;
|
|
1
|
+
{"version":3,"file":"v2.js","names":[],"sources":["../../../../lib/modules/datasource/nuget/v2.ts"],"sourcesContent":["import type { XmlElement } from 'xmldoc';\nimport { XmlDocument } from 'xmldoc';\nimport { logger } from '../../../logger/index.ts';\nimport type { Http } from '../../../util/http/index.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport type { ReleaseResult } from '../types.ts';\nimport { resolvePaginationUrl } from '../util.ts';\nimport { massageUrl, removeBuildMeta } from './common.ts';\n\nexport class NugetV2Api {\n getPkgProp(pkgInfo: XmlElement, propName: string): string | undefined {\n return pkgInfo.childNamed('m:properties')?.childNamed(`d:${propName}`)?.val;\n }\n\n async getReleases(\n http: Http,\n feedUrl: string,\n pkgName: string,\n allowCrossOrigin: boolean,\n ): Promise<ReleaseResult | null> {\n const dep: ReleaseResult = {\n releases: [],\n };\n let pkgUrlList: string | null = `${feedUrl.replace(\n regEx(/\\/+$/),\n '',\n )}/FindPackagesById()?id=%27${pkgName}%27&$select=Version,IsLatestVersion,ProjectUrl,Published`;\n while (pkgUrlList !== null) {\n // typescript issue\n const pkgVersionsListRaw = await http.getText(pkgUrlList);\n const pkgVersionsListDoc = new XmlDocument(pkgVersionsListRaw.body);\n\n const pkgInfoList = pkgVersionsListDoc.childrenNamed('entry');\n\n for (const pkgInfo of pkgInfoList) {\n const version = this.getPkgProp(pkgInfo, 'Version');\n const releaseTimestamp = asTimestamp(\n this.getPkgProp(pkgInfo, 'Published'),\n );\n dep.releases.push({\n // TODO: types (#22198)\n version: removeBuildMeta(`${version}`),\n releaseTimestamp,\n });\n try {\n const pkgIsLatestVersion = this.getPkgProp(\n pkgInfo,\n 'IsLatestVersion',\n );\n if (pkgIsLatestVersion === 'true') {\n dep.tags = { latest: removeBuildMeta(`${version}`) };\n const projectUrl = this.getPkgProp(pkgInfo, 'ProjectUrl');\n if (projectUrl) {\n dep.sourceUrl = massageUrl(projectUrl);\n }\n }\n } catch (err) /* istanbul ignore next */ {\n logger.debug(\n { err, pkgName, feedUrl },\n `nuget registry failure: can't parse pkg info for project url`,\n );\n }\n }\n\n const nextPkgUrlListLink = pkgVersionsListDoc\n .childrenNamed('link')\n .find((node) => node.attr.rel === 'next');\n\n // Resolve the relative-or-absolute next link, but only follow it when it stays on the same origin, or if the user has opted in via `RENOVATE_X_NUGET_PAGINATION_ALLOW_CROSS_ORIGIN`\n const nextHref = nextPkgUrlListLink?.attr.href;\n const nextUrl: string | null = nextHref\n ? resolvePaginationUrl(pkgUrlList, nextHref, allowCrossOrigin)\n : null;\n if (nextHref && !nextUrl) {\n // make sure that users are aware if there are any (potentially malicious, or misconfigured) pagination links being returned\n logger.once.warn(\n { feedUrl, nextUrl: nextHref },\n 'Ignoring cross-origin or invalid NuGet feed pagination link',\n );\n }\n pkgUrlList = nextUrl;\n }\n\n // dep not found if no release, so we can try next registry\n if (dep.releases.length === 0) {\n return null;\n }\n\n return dep;\n }\n}\n"],"mappings":";;;;;;;AAUA,IAAa,aAAb,MAAwB;CACtB,WAAW,SAAqB,UAAsC;EACpE,OAAO,QAAQ,WAAW,cAAc,CAAC,EAAE,WAAW,KAAK,UAAU,CAAC,EAAE;CAC1E;CAEA,MAAM,YACJ,MACA,SACA,SACA,kBAC+B;EAC/B,MAAM,MAAqB,EACzB,UAAU,CAAC,EACb;EACA,IAAI,aAA4B,GAAG,QAAQ,QACzC,MAAM,MAAM,GACZ,EACF,EAAE,4BAA4B,QAAQ;EACtC,OAAO,eAAe,MAAM;GAE1B,MAAM,qBAAqB,MAAM,KAAK,QAAQ,UAAU;GACxD,MAAM,qBAAqB,IAAI,YAAY,mBAAmB,IAAI;GAElE,MAAM,cAAc,mBAAmB,cAAc,OAAO;GAE5D,KAAK,MAAM,WAAW,aAAa;IACjC,MAAM,UAAU,KAAK,WAAW,SAAS,SAAS;IAClD,MAAM,mBAAmB,YACvB,KAAK,WAAW,SAAS,WAAW,CACtC;IACA,IAAI,SAAS,KAAK;KAEhB,SAAS,gBAAgB,GAAG,SAAS;KACrC;IACF,CAAC;IACD,IAAI;KAKF,IAJ2B,KAAK,WAC9B,SACA,iBAEmB,MAAM,QAAQ;MACjC,IAAI,OAAO,EAAE,QAAQ,gBAAgB,GAAG,SAAS,EAAE;MACnD,MAAM,aAAa,KAAK,WAAW,SAAS,YAAY;MACxD,IAAI,YACF,IAAI,YAAY,WAAW,UAAU;KAEzC;IACF,SAAS,gCAAgC;KACvC,OAAO,MACL;MAAE;MAAK;MAAS;KAAQ,GACxB,8DACF;IACF;GACF;GAOA,MAAM,WALqB,mBACxB,cAAc,MAAM,CAAC,CACrB,MAAM,SAAS,KAAK,KAAK,QAAQ,MAGF,CAAC,EAAE,KAAK;GAC1C,MAAM,UAAyB,WAC3B,qBAAqB,YAAY,UAAU,gBAAgB,IAC3D;GACJ,IAAI,YAAY,CAAC,SAEf,OAAO,KAAK,KACV;IAAE;IAAS,SAAS;GAAS,GAC7B,6DACF;GAEF,aAAa;EACf;EAGA,IAAI,IAAI,SAAS,WAAW,GAC1B,OAAO;EAGT,OAAO;CACT;AACF"}
|
|
@@ -40,7 +40,7 @@ var NugetV3Api = class NugetV3Api {
|
|
|
40
40
|
serviceId,
|
|
41
41
|
type: t?.split("/")?.shift(),
|
|
42
42
|
version: t?.split("/")?.pop()
|
|
43
|
-
})).filter(({ type, version }) => type === resourceType && semver.valid(version)).sort((x, y) => x.version && y.version ? semver.compare(x.version, y.version) :
|
|
43
|
+
})).filter(({ type, version }) => type === resourceType && semver.valid(version)).sort((x, y) => x.version && y.version ? semver.compare(x.version, y.version) : /* istanbul ignore next: hard to test */ 0);
|
|
44
44
|
if (services.length === 0) {
|
|
45
45
|
await set(NugetV3Api.cacheNamespace, resultCacheKey, null, 60);
|
|
46
46
|
logger.debug({
|
|
@@ -80,7 +80,8 @@ var NugetV3Api = class NugetV3Api {
|
|
|
80
80
|
async getReleases(http, registryUrl, feedUrl, pkgName) {
|
|
81
81
|
const url = `${feedUrl.replace(regEx(/\/*$/), "")}/${pkgName.toLowerCase()}/index.json`;
|
|
82
82
|
const catalogPages = (await http.getJson(url, PackageRegistration)).body.items;
|
|
83
|
-
const
|
|
83
|
+
const catalogPagesQueue = catalogPages.map((page) => () => this.getCatalogEntry(http, page));
|
|
84
|
+
const catalogEntries = (await all(catalogPagesQueue)).flat().sort((a, b) => sortNugetVersions(a.version, b.version));
|
|
84
85
|
let homepage = null;
|
|
85
86
|
let latestStable = null;
|
|
86
87
|
let nupkgUrl = null;
|
|
@@ -112,7 +113,8 @@ var NugetV3Api = class NugetV3Api {
|
|
|
112
113
|
if (isNonEmptyString(packageBaseAddress)) {
|
|
113
114
|
const nuspecUrl = `${ensureTrailingSlash(packageBaseAddress)}${pkgName.toLowerCase()}/${latestStable}/${pkgName.toLowerCase()}.nuspec`;
|
|
114
115
|
try {
|
|
115
|
-
const
|
|
116
|
+
const metaresult = await http.getText(nuspecUrl, { cacheProvider: memCacheProvider });
|
|
117
|
+
const nuspec = new XmlDocument(metaresult.body);
|
|
116
118
|
const releaseNotes = nuspec.valueWithPath("metadata.releaseNotes");
|
|
117
119
|
if (releaseNotes) dep.changelogContent = releaseNotes;
|
|
118
120
|
const sourceUrl = nuspec.valueWithPath("metadata.repository@url");
|
|
@@ -168,9 +170,11 @@ var NugetV3Api = class NugetV3Api {
|
|
|
168
170
|
const nupkgContentsDir = upath.join(cacheDir, `${packageName}.${packageVersion}`);
|
|
169
171
|
const readStream = http.stream(nupkgUrl);
|
|
170
172
|
try {
|
|
171
|
-
|
|
173
|
+
const writeStream = createCacheWriteStream(nupkgFile);
|
|
174
|
+
await pipeline(readStream, writeStream);
|
|
172
175
|
new AdmZip(nupkgFile).extractAllTo(nupkgContentsDir);
|
|
173
|
-
|
|
176
|
+
const nuspecFile = upath.join(nupkgContentsDir, `${packageName}.nuspec`);
|
|
177
|
+
return new XmlDocument(await readCacheFile(nuspecFile, "utf8")).valueWithPath("metadata.repository@url") ?? null;
|
|
174
178
|
} finally {
|
|
175
179
|
await rmCache(nupkgFile);
|
|
176
180
|
await rmCache(nupkgContentsDir);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v3.js","names":["packageCache.get","packageCache.set","p.all","versioning","HttpError","fs.createCacheWriteStream","fs.pipeline","fs.readCacheFile","fs.rmCache"],"sources":["../../../../lib/modules/datasource/nuget/v3.ts"],"sourcesContent":["import { isNonEmptyString } from '@sindresorhus/is';\nimport AdmZip from 'adm-zip';\nimport semver from 'semver';\nimport upath from 'upath';\nimport { XmlDocument } from 'xmldoc';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport * as packageCache from '../../../util/cache/package/index.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport * as fs from '../../../util/fs/index.ts';\nimport { ensureCacheDir } from '../../../util/fs/index.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport type { Http } from '../../../util/http/index.ts';\nimport { HttpError } from '../../../util/http/index.ts';\nimport * as p from '../../../util/promises.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport { ensureTrailingSlash } from '../../../util/url.ts';\nimport { api as versioning } from '../../versioning/nuget/index.ts';\nimport type { Release, ReleaseResult } from '../types.ts';\nimport { massageUrl, removeBuildMeta, sortNugetVersions } from './common.ts';\nimport type { CatalogEntry } from './schema.ts';\nimport {\n CatalogPage,\n PackageRegistration,\n ServicesIndexRaw,\n} from './schema.ts';\n\nexport class NugetV3Api {\n static readonly cacheNamespace = 'datasource-nuget-v3';\n\n async getResourceUrl(\n http: Http,\n url: string,\n resourceType = 'RegistrationsBaseUrl',\n ): Promise<string | null> {\n // https://learn.microsoft.com/nuget/api/service-index\n const resultCacheKey = `${url}:${resourceType}`;\n const cachedResult = await packageCache.get<string>(\n NugetV3Api.cacheNamespace,\n resultCacheKey,\n );\n\n /* v8 ignore next 3 -- TODO: add test */\n if (cachedResult) {\n return cachedResult;\n }\n let servicesIndexRaw: ServicesIndexRaw | undefined;\n try {\n const responseCacheKey = url;\n servicesIndexRaw = await packageCache.get<ServicesIndexRaw>(\n NugetV3Api.cacheNamespace,\n responseCacheKey,\n );\n if (!servicesIndexRaw) {\n servicesIndexRaw = (\n await http.getJson(\n url,\n { cacheProvider: memCacheProvider },\n ServicesIndexRaw,\n )\n ).body;\n await packageCache.set(\n NugetV3Api.cacheNamespace,\n responseCacheKey,\n servicesIndexRaw,\n 3 * 24 * 60,\n );\n }\n\n const services = servicesIndexRaw.resources\n .map(({ '@id': serviceId, '@type': t }) => ({\n serviceId,\n type: t?.split('/')?.shift(),\n version: t?.split('/')?.pop(),\n }))\n .filter(\n ({ type, version }) => type === resourceType && semver.valid(version),\n )\n .sort((x, y) =>\n x.version && y.version\n ? semver.compare(x.version, y.version)\n : /* istanbul ignore next: hard to test */ 0,\n );\n\n if (services.length === 0) {\n await packageCache.set(\n NugetV3Api.cacheNamespace,\n resultCacheKey,\n null,\n 60,\n );\n logger.debug(\n { url, servicesIndexRaw },\n `no ${resourceType} services found`,\n );\n return null;\n }\n\n const { serviceId, version } = services.pop()!;\n\n // istanbul ignore if\n if (\n resourceType === 'RegistrationsBaseUrl' &&\n version &&\n !version.startsWith('3.0.0-') &&\n !semver.satisfies(version, '^3.0.0')\n ) {\n logger.warn(\n { url, version },\n `Nuget: Unknown version returned. Only v3 is supported`,\n );\n }\n\n await packageCache.set(\n NugetV3Api.cacheNamespace,\n resultCacheKey,\n serviceId,\n 60,\n );\n return serviceId;\n } catch (err) {\n // istanbul ignore if: not easy testable with nock\n if (err instanceof ExternalHostError) {\n throw err;\n }\n logger.debug(\n { err, url, servicesIndexRaw },\n `nuget registry failure: can't get ${resourceType}`,\n );\n return null;\n }\n }\n\n async getCatalogEntry(\n http: Http,\n catalogPage: CatalogPage,\n ): Promise<CatalogEntry[]> {\n let items = catalogPage.items;\n if (!items) {\n const url = catalogPage['@id'];\n if (!url) {\n return [];\n }\n const catalogPageFull = await http.getJson(url, CatalogPage);\n items = catalogPageFull.body.items;\n }\n return coerceArray(items).map(({ catalogEntry }) => catalogEntry);\n }\n\n async getReleases(\n http: Http,\n registryUrl: string,\n feedUrl: string,\n pkgName: string,\n ): Promise<ReleaseResult | null> {\n const baseUrl = feedUrl.replace(regEx(/\\/*$/), '');\n const url = `${baseUrl}/${pkgName.toLowerCase()}/index.json`;\n const packageRegistration = await http.getJson(url, PackageRegistration);\n const catalogPages = packageRegistration.body.items;\n const catalogPagesQueue = catalogPages.map(\n (page) => (): Promise<CatalogEntry[]> => this.getCatalogEntry(http, page),\n );\n const catalogEntries = (await p.all(catalogPagesQueue))\n .flat()\n .sort((a, b) => sortNugetVersions(a.version, b.version));\n\n let homepage: string | null = null;\n let latestStable: string | null = null;\n let nupkgUrl: string | null = null;\n const releases = catalogEntries.map(\n ({\n version,\n published,\n projectUrl,\n listed,\n packageContent,\n deprecation,\n }) => {\n const release: Release = { version: removeBuildMeta(version) };\n const releaseTimestamp = asTimestamp(published);\n if (releaseTimestamp) {\n release.releaseTimestamp = releaseTimestamp;\n }\n if (\n versioning.isValid(version) &&\n versioning.isStable(version) &&\n listed\n ) {\n latestStable = removeBuildMeta(version);\n homepage = projectUrl ? massageUrl(projectUrl) : homepage;\n nupkgUrl = massageUrl(packageContent);\n }\n\n if (listed === false || deprecation) {\n release.isDeprecated = true;\n }\n return release;\n },\n );\n\n if (!releases.length) {\n return null;\n }\n\n // istanbul ignore next: only happens when no stable version exists\n if (latestStable === null && catalogPages.length) {\n const last = catalogEntries.pop()!;\n latestStable = removeBuildMeta(last.version);\n homepage ??= last.projectUrl ?? null;\n nupkgUrl ??= massageUrl(last.packageContent);\n }\n\n const dep: ReleaseResult = {\n releases,\n };\n\n if (releases.every((release) => release.isDeprecated === true)) {\n dep.deprecationMessage = this.getDeprecationMessage(pkgName);\n }\n\n try {\n const packageBaseAddress = await this.getResourceUrl(\n http,\n registryUrl,\n 'PackageBaseAddress',\n );\n let shouldTryNupkg = false;\n if (isNonEmptyString(packageBaseAddress)) {\n const nuspecUrl = `${ensureTrailingSlash(\n packageBaseAddress,\n )}${pkgName.toLowerCase()}/${\n latestStable\n }/${pkgName.toLowerCase()}.nuspec`;\n try {\n const metaresult = await http.getText(nuspecUrl, {\n cacheProvider: memCacheProvider,\n });\n const nuspec = new XmlDocument(metaresult.body);\n const releaseNotes = nuspec.valueWithPath('metadata.releaseNotes');\n if (releaseNotes) {\n dep.changelogContent = releaseNotes;\n }\n const sourceUrl = nuspec.valueWithPath('metadata.repository@url');\n if (sourceUrl) {\n dep.sourceUrl = massageUrl(sourceUrl);\n }\n } catch (err) {\n /* v8 ignore else -- not easy testable with nock */\n if (err instanceof HttpError && err.response?.statusCode === 404) {\n shouldTryNupkg = true;\n logger.debug(\n { registryUrl, pkgName, pkgVersion: latestStable },\n `package manifest (.nuspec) not found`,\n );\n } else {\n throw err;\n }\n }\n } else {\n shouldTryNupkg = true;\n }\n\n if (!dep.sourceUrl && shouldTryNupkg && nupkgUrl) {\n const sourceUrl = await this.getSourceUrlFromNupkg(\n http,\n registryUrl,\n pkgName,\n latestStable,\n nupkgUrl,\n );\n if (sourceUrl) {\n dep.sourceUrl = massageUrl(sourceUrl);\n logger.debug(`Determined sourceUrl ${sourceUrl} from ${nupkgUrl}`);\n }\n }\n } catch (err) {\n // istanbul ignore if: not easy testable with nock\n if (err instanceof ExternalHostError) {\n throw err;\n }\n // ignore / silence 404. Seen on proget, if remote connector is used and package is not yet cached\n if (err instanceof HttpError && err.response?.statusCode === 404) {\n logger.debug(\n { registryUrl, pkgName, pkgVersion: latestStable },\n `package manifest (.nuspec) not found`,\n );\n } else {\n logger.debug(\n { err, registryUrl, pkgName, pkgVersion: latestStable },\n `Cannot obtain sourceUrl`,\n );\n }\n }\n\n if (homepage) {\n // only assign if not assigned\n dep.sourceUrl ??= homepage;\n dep.homepage ??= homepage;\n }\n\n return dep;\n }\n\n private async _getSourceUrlFromNupkg(\n http: Http,\n _registryUrl: string,\n packageName: string,\n packageVersion: string | null,\n nupkgUrl: string,\n ): Promise<string | null> {\n /* v8 ignore if -- specs enable RENOVATE_X_NUGET_DOWNLOAD_NUPKGS, so the disabled path is unexercised */\n if (!getEnv().RENOVATE_X_NUGET_DOWNLOAD_NUPKGS) {\n logger.once.debug('RENOVATE_X_NUGET_DOWNLOAD_NUPKGS is not set');\n return null;\n }\n const cacheDir = await ensureCacheDir('nuget');\n const nupkgFile = upath.join(\n cacheDir,\n `${packageName}.${packageVersion}.nupkg`,\n );\n const nupkgContentsDir = upath.join(\n cacheDir,\n `${packageName}.${packageVersion}`,\n );\n const readStream = http.stream(nupkgUrl);\n try {\n const writeStream = fs.createCacheWriteStream(nupkgFile);\n await fs.pipeline(readStream, writeStream);\n const zip = new AdmZip(nupkgFile);\n zip.extractAllTo(nupkgContentsDir);\n const nuspecFile = upath.join(nupkgContentsDir, `${packageName}.nuspec`);\n const nuspec = new XmlDocument(\n await fs.readCacheFile(nuspecFile, 'utf8'),\n );\n return nuspec.valueWithPath('metadata.repository@url') ?? null;\n } finally {\n await fs.rmCache(nupkgFile);\n await fs.rmCache(nupkgContentsDir);\n }\n }\n\n getSourceUrlFromNupkg(\n http: Http,\n registryUrl: string,\n packageName: string,\n packageVersion: string | null,\n nupkgUrl: string,\n ): Promise<string | null> {\n return withCache(\n {\n namespace: NugetV3Api.cacheNamespace,\n key: `source-url:${registryUrl}:${packageName}`,\n ttlMinutes: 10080, // 1 week\n },\n () =>\n this._getSourceUrlFromNupkg(\n http,\n registryUrl,\n packageName,\n packageVersion,\n nupkgUrl,\n ),\n );\n }\n\n getDeprecationMessage(packageName: string): string {\n return `The package \\`${packageName}\\` is deprecated.`;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"v3.js","names":["packageCache.get","packageCache.set","p.all","versioning","HttpError","fs.createCacheWriteStream","fs.pipeline","fs.readCacheFile","fs.rmCache"],"sources":["../../../../lib/modules/datasource/nuget/v3.ts"],"sourcesContent":["import { isNonEmptyString } from '@sindresorhus/is';\nimport AdmZip from 'adm-zip';\nimport semver from 'semver';\nimport upath from 'upath';\nimport { XmlDocument } from 'xmldoc';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { coerceArray } from '../../../util/array.ts';\nimport * as packageCache from '../../../util/cache/package/index.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { getEnv } from '../../../util/env.ts';\nimport * as fs from '../../../util/fs/index.ts';\nimport { ensureCacheDir } from '../../../util/fs/index.ts';\nimport { memCacheProvider } from '../../../util/http/cache/memory-http-cache-provider.ts';\nimport type { Http } from '../../../util/http/index.ts';\nimport { HttpError } from '../../../util/http/index.ts';\nimport * as p from '../../../util/promises.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport { ensureTrailingSlash } from '../../../util/url.ts';\nimport { api as versioning } from '../../versioning/nuget/index.ts';\nimport type { Release, ReleaseResult } from '../types.ts';\nimport { massageUrl, removeBuildMeta, sortNugetVersions } from './common.ts';\nimport type { CatalogEntry } from './schema.ts';\nimport {\n CatalogPage,\n PackageRegistration,\n ServicesIndexRaw,\n} from './schema.ts';\n\nexport class NugetV3Api {\n static readonly cacheNamespace = 'datasource-nuget-v3';\n\n async getResourceUrl(\n http: Http,\n url: string,\n resourceType = 'RegistrationsBaseUrl',\n ): Promise<string | null> {\n // https://learn.microsoft.com/nuget/api/service-index\n const resultCacheKey = `${url}:${resourceType}`;\n const cachedResult = await packageCache.get<string>(\n NugetV3Api.cacheNamespace,\n resultCacheKey,\n );\n\n /* v8 ignore next 3 -- TODO: add test */\n if (cachedResult) {\n return cachedResult;\n }\n let servicesIndexRaw: ServicesIndexRaw | undefined;\n try {\n const responseCacheKey = url;\n servicesIndexRaw = await packageCache.get<ServicesIndexRaw>(\n NugetV3Api.cacheNamespace,\n responseCacheKey,\n );\n if (!servicesIndexRaw) {\n servicesIndexRaw = (\n await http.getJson(\n url,\n { cacheProvider: memCacheProvider },\n ServicesIndexRaw,\n )\n ).body;\n await packageCache.set(\n NugetV3Api.cacheNamespace,\n responseCacheKey,\n servicesIndexRaw,\n 3 * 24 * 60,\n );\n }\n\n const services = servicesIndexRaw.resources\n .map(({ '@id': serviceId, '@type': t }) => ({\n serviceId,\n type: t?.split('/')?.shift(),\n version: t?.split('/')?.pop(),\n }))\n .filter(\n ({ type, version }) => type === resourceType && semver.valid(version),\n )\n .sort((x, y) =>\n x.version && y.version\n ? semver.compare(x.version, y.version)\n : /* istanbul ignore next: hard to test */ 0,\n );\n\n if (services.length === 0) {\n await packageCache.set(\n NugetV3Api.cacheNamespace,\n resultCacheKey,\n null,\n 60,\n );\n logger.debug(\n { url, servicesIndexRaw },\n `no ${resourceType} services found`,\n );\n return null;\n }\n\n const { serviceId, version } = services.pop()!;\n\n // istanbul ignore if\n if (\n resourceType === 'RegistrationsBaseUrl' &&\n version &&\n !version.startsWith('3.0.0-') &&\n !semver.satisfies(version, '^3.0.0')\n ) {\n logger.warn(\n { url, version },\n `Nuget: Unknown version returned. Only v3 is supported`,\n );\n }\n\n await packageCache.set(\n NugetV3Api.cacheNamespace,\n resultCacheKey,\n serviceId,\n 60,\n );\n return serviceId;\n } catch (err) {\n // istanbul ignore if: not easy testable with nock\n if (err instanceof ExternalHostError) {\n throw err;\n }\n logger.debug(\n { err, url, servicesIndexRaw },\n `nuget registry failure: can't get ${resourceType}`,\n );\n return null;\n }\n }\n\n async getCatalogEntry(\n http: Http,\n catalogPage: CatalogPage,\n ): Promise<CatalogEntry[]> {\n let items = catalogPage.items;\n if (!items) {\n const url = catalogPage['@id'];\n if (!url) {\n return [];\n }\n const catalogPageFull = await http.getJson(url, CatalogPage);\n items = catalogPageFull.body.items;\n }\n return coerceArray(items).map(({ catalogEntry }) => catalogEntry);\n }\n\n async getReleases(\n http: Http,\n registryUrl: string,\n feedUrl: string,\n pkgName: string,\n ): Promise<ReleaseResult | null> {\n const baseUrl = feedUrl.replace(regEx(/\\/*$/), '');\n const url = `${baseUrl}/${pkgName.toLowerCase()}/index.json`;\n const packageRegistration = await http.getJson(url, PackageRegistration);\n const catalogPages = packageRegistration.body.items;\n const catalogPagesQueue = catalogPages.map(\n (page) => (): Promise<CatalogEntry[]> => this.getCatalogEntry(http, page),\n );\n const catalogEntries = (await p.all(catalogPagesQueue))\n .flat()\n .sort((a, b) => sortNugetVersions(a.version, b.version));\n\n let homepage: string | null = null;\n let latestStable: string | null = null;\n let nupkgUrl: string | null = null;\n const releases = catalogEntries.map(\n ({\n version,\n published,\n projectUrl,\n listed,\n packageContent,\n deprecation,\n }) => {\n const release: Release = { version: removeBuildMeta(version) };\n const releaseTimestamp = asTimestamp(published);\n if (releaseTimestamp) {\n release.releaseTimestamp = releaseTimestamp;\n }\n if (\n versioning.isValid(version) &&\n versioning.isStable(version) &&\n listed\n ) {\n latestStable = removeBuildMeta(version);\n homepage = projectUrl ? massageUrl(projectUrl) : homepage;\n nupkgUrl = massageUrl(packageContent);\n }\n\n if (listed === false || deprecation) {\n release.isDeprecated = true;\n }\n return release;\n },\n );\n\n if (!releases.length) {\n return null;\n }\n\n // istanbul ignore next: only happens when no stable version exists\n if (latestStable === null && catalogPages.length) {\n const last = catalogEntries.pop()!;\n latestStable = removeBuildMeta(last.version);\n homepage ??= last.projectUrl ?? null;\n nupkgUrl ??= massageUrl(last.packageContent);\n }\n\n const dep: ReleaseResult = {\n releases,\n };\n\n if (releases.every((release) => release.isDeprecated === true)) {\n dep.deprecationMessage = this.getDeprecationMessage(pkgName);\n }\n\n try {\n const packageBaseAddress = await this.getResourceUrl(\n http,\n registryUrl,\n 'PackageBaseAddress',\n );\n let shouldTryNupkg = false;\n if (isNonEmptyString(packageBaseAddress)) {\n const nuspecUrl = `${ensureTrailingSlash(\n packageBaseAddress,\n )}${pkgName.toLowerCase()}/${\n latestStable\n }/${pkgName.toLowerCase()}.nuspec`;\n try {\n const metaresult = await http.getText(nuspecUrl, {\n cacheProvider: memCacheProvider,\n });\n const nuspec = new XmlDocument(metaresult.body);\n const releaseNotes = nuspec.valueWithPath('metadata.releaseNotes');\n if (releaseNotes) {\n dep.changelogContent = releaseNotes;\n }\n const sourceUrl = nuspec.valueWithPath('metadata.repository@url');\n if (sourceUrl) {\n dep.sourceUrl = massageUrl(sourceUrl);\n }\n } catch (err) {\n /* v8 ignore else -- not easy testable with nock */\n if (err instanceof HttpError && err.response?.statusCode === 404) {\n shouldTryNupkg = true;\n logger.debug(\n { registryUrl, pkgName, pkgVersion: latestStable },\n `package manifest (.nuspec) not found`,\n );\n } else {\n throw err;\n }\n }\n } else {\n shouldTryNupkg = true;\n }\n\n if (!dep.sourceUrl && shouldTryNupkg && nupkgUrl) {\n const sourceUrl = await this.getSourceUrlFromNupkg(\n http,\n registryUrl,\n pkgName,\n latestStable,\n nupkgUrl,\n );\n if (sourceUrl) {\n dep.sourceUrl = massageUrl(sourceUrl);\n logger.debug(`Determined sourceUrl ${sourceUrl} from ${nupkgUrl}`);\n }\n }\n } catch (err) {\n // istanbul ignore if: not easy testable with nock\n if (err instanceof ExternalHostError) {\n throw err;\n }\n // ignore / silence 404. Seen on proget, if remote connector is used and package is not yet cached\n if (err instanceof HttpError && err.response?.statusCode === 404) {\n logger.debug(\n { registryUrl, pkgName, pkgVersion: latestStable },\n `package manifest (.nuspec) not found`,\n );\n } else {\n logger.debug(\n { err, registryUrl, pkgName, pkgVersion: latestStable },\n `Cannot obtain sourceUrl`,\n );\n }\n }\n\n if (homepage) {\n // only assign if not assigned\n dep.sourceUrl ??= homepage;\n dep.homepage ??= homepage;\n }\n\n return dep;\n }\n\n private async _getSourceUrlFromNupkg(\n http: Http,\n _registryUrl: string,\n packageName: string,\n packageVersion: string | null,\n nupkgUrl: string,\n ): Promise<string | null> {\n /* v8 ignore if -- specs enable RENOVATE_X_NUGET_DOWNLOAD_NUPKGS, so the disabled path is unexercised */\n if (!getEnv().RENOVATE_X_NUGET_DOWNLOAD_NUPKGS) {\n logger.once.debug('RENOVATE_X_NUGET_DOWNLOAD_NUPKGS is not set');\n return null;\n }\n const cacheDir = await ensureCacheDir('nuget');\n const nupkgFile = upath.join(\n cacheDir,\n `${packageName}.${packageVersion}.nupkg`,\n );\n const nupkgContentsDir = upath.join(\n cacheDir,\n `${packageName}.${packageVersion}`,\n );\n const readStream = http.stream(nupkgUrl);\n try {\n const writeStream = fs.createCacheWriteStream(nupkgFile);\n await fs.pipeline(readStream, writeStream);\n const zip = new AdmZip(nupkgFile);\n zip.extractAllTo(nupkgContentsDir);\n const nuspecFile = upath.join(nupkgContentsDir, `${packageName}.nuspec`);\n const nuspec = new XmlDocument(\n await fs.readCacheFile(nuspecFile, 'utf8'),\n );\n return nuspec.valueWithPath('metadata.repository@url') ?? null;\n } finally {\n await fs.rmCache(nupkgFile);\n await fs.rmCache(nupkgContentsDir);\n }\n }\n\n getSourceUrlFromNupkg(\n http: Http,\n registryUrl: string,\n packageName: string,\n packageVersion: string | null,\n nupkgUrl: string,\n ): Promise<string | null> {\n return withCache(\n {\n namespace: NugetV3Api.cacheNamespace,\n key: `source-url:${registryUrl}:${packageName}`,\n ttlMinutes: 10080, // 1 week\n },\n () =>\n this._getSourceUrlFromNupkg(\n http,\n registryUrl,\n packageName,\n packageVersion,\n nupkgUrl,\n ),\n );\n }\n\n getDeprecationMessage(packageName: string): string {\n return `The package \\`${packageName}\\` is deprecated.`;\n }\n}\n"],"mappings":"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"}
|
|
@@ -65,7 +65,8 @@ var PackagistDatasource = class PackagistDatasource extends Datasource {
|
|
|
65
65
|
}
|
|
66
66
|
static getPackagistFileUrl(regUrl, regFile) {
|
|
67
67
|
const { key, hash } = regFile;
|
|
68
|
-
|
|
68
|
+
const fileName = hash ? key.replace("%hash%", hash) : /* istanbul ignore next: hard to test */ key;
|
|
69
|
+
return resolveBaseUrl(regUrl, fileName);
|
|
69
70
|
}
|
|
70
71
|
async _getPackagistFile(regUrl, regFile) {
|
|
71
72
|
const url = PackagistDatasource.getPackagistFileUrl(regUrl, regFile);
|
|
@@ -96,7 +97,8 @@ var PackagistDatasource = class PackagistDatasource extends Datasource {
|
|
|
96
97
|
const pkgPromise = this.getJson(pkgUrl, z.unknown());
|
|
97
98
|
const devUrl = replaceUrlPath(registryUrl, metadataUrl.replace("%package%", `${packageName}~dev`));
|
|
98
99
|
const devPromise = this.getJson(devUrl, z.unknown()).then((x) => x, () => null);
|
|
99
|
-
|
|
100
|
+
const responses = await Promise.all([pkgPromise, devPromise]).then((responses) => responses.filter(isObject));
|
|
101
|
+
return parsePackagesResponses(packageName, responses);
|
|
100
102
|
}
|
|
101
103
|
packagistV2Lookup(registryUrl, metadataUrl, packageName) {
|
|
102
104
|
return withCache({
|
|
@@ -129,10 +131,11 @@ var PackagistDatasource = class PackagistDatasource extends Datasource {
|
|
|
129
131
|
await this.fetchProviderPackages(registryUrl, meta);
|
|
130
132
|
const pkgUrl = this.getPkgUrl(packageName, registryUrl, meta);
|
|
131
133
|
if (!pkgUrl) return null;
|
|
132
|
-
const
|
|
134
|
+
const pkgRes = await this.getJson(pkgUrl, PackagesResponse);
|
|
135
|
+
const dep = extractDepReleases(pkgRes.packages[packageName]);
|
|
133
136
|
logger.trace({ dep }, "dep");
|
|
134
137
|
return dep;
|
|
135
|
-
} catch (err)
|
|
138
|
+
} catch (err) /* istanbul ignore next */ {
|
|
136
139
|
if (isDefaultPackagistHost(registryUrl) && isTransientPackagistError(err)) throw new ExternalHostError(err);
|
|
137
140
|
throw err;
|
|
138
141
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["composerVersioning.id","hostRules.find","p.map"],"sources":["../../../../lib/modules/datasource/packagist/index.ts"],"sourcesContent":["import { isNumber, isObject } from '@sindresorhus/is';\nimport { z } from 'zod/v4';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport type { HttpOptions } from '../../../util/http/types.ts';\nimport * as p from '../../../util/promises.ts';\nimport { parseUrl, replaceUrlPath, resolveBaseUrl } from '../../../util/url.ts';\nimport * as composerVersioning from '../../versioning/composer/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type { GetReleasesConfig, ReleaseResult } from '../types.ts';\nimport type { RegistryFile } from './schema.ts';\nimport {\n PackagesResponse,\n PackagistFile,\n RegistryMeta,\n extractDepReleases,\n parsePackagesResponses,\n} from './schema.ts';\n\ninterface PackagistLookupError {\n code?: string;\n statusCode?: number;\n}\n\nfunction isDefaultPackagistHost(registryUrl: string): boolean {\n const url = parseUrl(registryUrl);\n\n /* v8 ignore if -- typescript strict null check */\n if (!url) {\n return false;\n }\n\n return ['repo.packagist.org', 'packagist.org'].includes(url.host);\n}\n\nfunction isTransientPackagistError(err: PackagistLookupError): boolean {\n const { code: errCode, statusCode } = err;\n\n if (errCode && ['ECONNRESET', 'ETIMEDOUT'].includes(errCode)) {\n return true;\n }\n\n if (!isNumber(statusCode)) {\n return false;\n }\n\n if (statusCode === 429 || (statusCode >= 500 && statusCode < 600)) {\n return true;\n }\n\n return false;\n}\n\nexport class PackagistDatasource extends Datasource {\n static readonly id = 'packagist';\n\n constructor() {\n super(PackagistDatasource.id);\n }\n\n override readonly defaultRegistryUrls = ['https://repo.packagist.org'];\n\n override readonly defaultVersioning = composerVersioning.id;\n\n override readonly registryStrategy = 'hunt';\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'The release timestamp is determined from the `time` field in the results.';\n // Note: this can be changed to 'release', as the source is present in each release but we remove it while processing\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'The source URL is determined from `source` field in the results.';\n\n // We calculate auth at this datasource layer so that we can know whether it's safe to cache or not\n private static getHostOpts(url: string): HttpOptions {\n const { username, password } = hostRules.find({\n hostType: PackagistDatasource.id,\n url,\n });\n return username && password ? { username, password } : {};\n }\n\n private async getJson<Schema extends z.ZodType<any, any, any>>(\n url: string,\n schema: Schema,\n ): Promise<z.infer<Schema>> {\n const opts = PackagistDatasource.getHostOpts(url);\n const { body } = await this.http.getJson(url, opts, schema);\n return body;\n }\n\n private async _getRegistryMeta(regUrl: string): Promise<RegistryMeta> {\n const url = resolveBaseUrl(regUrl, 'packages.json');\n const result = await this.getJson(url, RegistryMeta);\n return result;\n }\n\n getRegistryMeta(regUrl: string): Promise<RegistryMeta> {\n return withCache(\n {\n namespace: `datasource-${PackagistDatasource.id}`,\n key: `getRegistryMeta:${regUrl}`,\n },\n () => this._getRegistryMeta(regUrl),\n );\n }\n\n private static isPrivatePackage(regUrl: string): boolean {\n const opts = PackagistDatasource.getHostOpts(regUrl);\n return !!opts.password;\n }\n\n private static getPackagistFileUrl(\n regUrl: string,\n regFile: RegistryFile,\n ): string {\n const { key, hash } = regFile;\n const fileName = hash\n ? key.replace('%hash%', hash)\n : /* istanbul ignore next: hard to test */ key;\n const url = resolveBaseUrl(regUrl, fileName);\n return url;\n }\n\n private async _getPackagistFile(\n regUrl: string,\n regFile: RegistryFile,\n ): Promise<PackagistFile> {\n const url = PackagistDatasource.getPackagistFileUrl(regUrl, regFile);\n const packagistFile = await this.getJson(url, PackagistFile);\n return packagistFile;\n }\n\n getPackagistFile(\n regUrl: string,\n regFile: RegistryFile,\n ): Promise<PackagistFile> {\n return withCache(\n {\n namespace: `datasource-${PackagistDatasource.id}`,\n key: `getPackagistFile:${PackagistDatasource.getPackagistFileUrl(regUrl, regFile)}`,\n ttlMinutes: 1440,\n cacheable: !PackagistDatasource.isPrivatePackage(regUrl),\n },\n () => this._getPackagistFile(regUrl, regFile),\n );\n }\n\n async fetchProviderPackages(\n regUrl: string,\n meta: RegistryMeta,\n ): Promise<void> {\n await p.map(meta.files, async (file) => {\n const res = await this.getPackagistFile(regUrl, file);\n Object.assign(meta.providerPackages, res.providers);\n });\n }\n\n async fetchIncludesPackages(\n regUrl: string,\n meta: RegistryMeta,\n ): Promise<void> {\n await p.map(meta.includesFiles, async (file) => {\n const res = await this.getPackagistFile(regUrl, file);\n for (const [key, val] of Object.entries(res.packages)) {\n meta.includesPackages[key] = extractDepReleases(val);\n }\n });\n }\n\n private async _packagistV2Lookup(\n registryUrl: string,\n metadataUrl: string,\n packageName: string,\n ): Promise<ReleaseResult | null> {\n const pkgUrl = replaceUrlPath(\n registryUrl,\n metadataUrl.replace('%package%', packageName),\n );\n const pkgPromise = this.getJson(pkgUrl, z.unknown());\n\n const devUrl = replaceUrlPath(\n registryUrl,\n metadataUrl.replace('%package%', `${packageName}~dev`),\n );\n const devPromise = this.getJson(devUrl, z.unknown()).then(\n (x) => x,\n () => null,\n );\n\n const responses: NonNullable<unknown>[] = await Promise.all([\n pkgPromise,\n devPromise,\n ]).then((responses) => responses.filter(isObject));\n return parsePackagesResponses(packageName, responses);\n }\n\n packagistV2Lookup(\n registryUrl: string,\n metadataUrl: string,\n packageName: string,\n ): Promise<ReleaseResult | null> {\n return withCache(\n {\n namespace: `datasource-${PackagistDatasource.id}`,\n key: `packagistV2Lookup:${registryUrl}:${metadataUrl}:${packageName}`,\n ttlMinutes: 10,\n },\n () => this._packagistV2Lookup(registryUrl, metadataUrl, packageName),\n );\n }\n\n public getPkgUrl(\n packageName: string,\n registryUrl: string,\n registryMeta: RegistryMeta,\n ): string | null {\n if (\n registryMeta.providersUrl &&\n packageName in registryMeta.providerPackages\n ) {\n let url = registryMeta.providersUrl.replace('%package%', packageName);\n const hash = registryMeta.providerPackages[packageName];\n if (hash) {\n url = url.replace('%hash%', hash);\n }\n return replaceUrlPath(registryUrl, url);\n }\n\n if (registryMeta.providersLazyUrl) {\n return replaceUrlPath(\n registryUrl,\n registryMeta.providersLazyUrl.replace('%package%', packageName),\n );\n }\n\n return null;\n }\n\n public override async getReleases({\n packageName,\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n logger.trace(`getReleases(${packageName})`);\n\n /* v8 ignore next 3 -- should never happen */\n if (!registryUrl) {\n return null;\n }\n\n try {\n const meta = await this.getRegistryMeta(registryUrl);\n\n if (\n meta.availablePackages &&\n !meta.availablePackages.includes(packageName)\n ) {\n return null;\n }\n\n if (meta.metadataUrl) {\n const packagistResult = await this.packagistV2Lookup(\n registryUrl,\n meta.metadataUrl,\n packageName,\n );\n return packagistResult;\n }\n\n if (meta.packages[packageName]) {\n const result = extractDepReleases(meta.packages[packageName]);\n return result;\n }\n\n await this.fetchIncludesPackages(registryUrl, meta);\n if (meta.includesPackages[packageName]) {\n return meta.includesPackages[packageName];\n }\n\n await this.fetchProviderPackages(registryUrl, meta);\n const pkgUrl = this.getPkgUrl(packageName, registryUrl, meta);\n if (!pkgUrl) {\n return null;\n }\n\n const pkgRes = await this.getJson(pkgUrl, PackagesResponse);\n const dep = extractDepReleases(pkgRes.packages[packageName]);\n logger.trace({ dep }, 'dep');\n return dep;\n } catch (err) /* istanbul ignore next */ {\n if (\n isDefaultPackagistHost(registryUrl) &&\n isTransientPackagistError(err)\n ) {\n throw new ExternalHostError(err);\n }\n throw err;\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["composerVersioning.id","hostRules.find","p.map"],"sources":["../../../../lib/modules/datasource/packagist/index.ts"],"sourcesContent":["import { isNumber, isObject } from '@sindresorhus/is';\nimport { z } from 'zod/v4';\nimport { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport type { HttpOptions } from '../../../util/http/types.ts';\nimport * as p from '../../../util/promises.ts';\nimport { parseUrl, replaceUrlPath, resolveBaseUrl } from '../../../util/url.ts';\nimport * as composerVersioning from '../../versioning/composer/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type { GetReleasesConfig, ReleaseResult } from '../types.ts';\nimport type { RegistryFile } from './schema.ts';\nimport {\n PackagesResponse,\n PackagistFile,\n RegistryMeta,\n extractDepReleases,\n parsePackagesResponses,\n} from './schema.ts';\n\ninterface PackagistLookupError {\n code?: string;\n statusCode?: number;\n}\n\nfunction isDefaultPackagistHost(registryUrl: string): boolean {\n const url = parseUrl(registryUrl);\n\n /* v8 ignore if -- typescript strict null check */\n if (!url) {\n return false;\n }\n\n return ['repo.packagist.org', 'packagist.org'].includes(url.host);\n}\n\nfunction isTransientPackagistError(err: PackagistLookupError): boolean {\n const { code: errCode, statusCode } = err;\n\n if (errCode && ['ECONNRESET', 'ETIMEDOUT'].includes(errCode)) {\n return true;\n }\n\n if (!isNumber(statusCode)) {\n return false;\n }\n\n if (statusCode === 429 || (statusCode >= 500 && statusCode < 600)) {\n return true;\n }\n\n return false;\n}\n\nexport class PackagistDatasource extends Datasource {\n static readonly id = 'packagist';\n\n constructor() {\n super(PackagistDatasource.id);\n }\n\n override readonly defaultRegistryUrls = ['https://repo.packagist.org'];\n\n override readonly defaultVersioning = composerVersioning.id;\n\n override readonly registryStrategy = 'hunt';\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'The release timestamp is determined from the `time` field in the results.';\n // Note: this can be changed to 'release', as the source is present in each release but we remove it while processing\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'The source URL is determined from `source` field in the results.';\n\n // We calculate auth at this datasource layer so that we can know whether it's safe to cache or not\n private static getHostOpts(url: string): HttpOptions {\n const { username, password } = hostRules.find({\n hostType: PackagistDatasource.id,\n url,\n });\n return username && password ? { username, password } : {};\n }\n\n private async getJson<Schema extends z.ZodType<any, any, any>>(\n url: string,\n schema: Schema,\n ): Promise<z.infer<Schema>> {\n const opts = PackagistDatasource.getHostOpts(url);\n const { body } = await this.http.getJson(url, opts, schema);\n return body;\n }\n\n private async _getRegistryMeta(regUrl: string): Promise<RegistryMeta> {\n const url = resolveBaseUrl(regUrl, 'packages.json');\n const result = await this.getJson(url, RegistryMeta);\n return result;\n }\n\n getRegistryMeta(regUrl: string): Promise<RegistryMeta> {\n return withCache(\n {\n namespace: `datasource-${PackagistDatasource.id}`,\n key: `getRegistryMeta:${regUrl}`,\n },\n () => this._getRegistryMeta(regUrl),\n );\n }\n\n private static isPrivatePackage(regUrl: string): boolean {\n const opts = PackagistDatasource.getHostOpts(regUrl);\n return !!opts.password;\n }\n\n private static getPackagistFileUrl(\n regUrl: string,\n regFile: RegistryFile,\n ): string {\n const { key, hash } = regFile;\n const fileName = hash\n ? key.replace('%hash%', hash)\n : /* istanbul ignore next: hard to test */ key;\n const url = resolveBaseUrl(regUrl, fileName);\n return url;\n }\n\n private async _getPackagistFile(\n regUrl: string,\n regFile: RegistryFile,\n ): Promise<PackagistFile> {\n const url = PackagistDatasource.getPackagistFileUrl(regUrl, regFile);\n const packagistFile = await this.getJson(url, PackagistFile);\n return packagistFile;\n }\n\n getPackagistFile(\n regUrl: string,\n regFile: RegistryFile,\n ): Promise<PackagistFile> {\n return withCache(\n {\n namespace: `datasource-${PackagistDatasource.id}`,\n key: `getPackagistFile:${PackagistDatasource.getPackagistFileUrl(regUrl, regFile)}`,\n ttlMinutes: 1440,\n cacheable: !PackagistDatasource.isPrivatePackage(regUrl),\n },\n () => this._getPackagistFile(regUrl, regFile),\n );\n }\n\n async fetchProviderPackages(\n regUrl: string,\n meta: RegistryMeta,\n ): Promise<void> {\n await p.map(meta.files, async (file) => {\n const res = await this.getPackagistFile(regUrl, file);\n Object.assign(meta.providerPackages, res.providers);\n });\n }\n\n async fetchIncludesPackages(\n regUrl: string,\n meta: RegistryMeta,\n ): Promise<void> {\n await p.map(meta.includesFiles, async (file) => {\n const res = await this.getPackagistFile(regUrl, file);\n for (const [key, val] of Object.entries(res.packages)) {\n meta.includesPackages[key] = extractDepReleases(val);\n }\n });\n }\n\n private async _packagistV2Lookup(\n registryUrl: string,\n metadataUrl: string,\n packageName: string,\n ): Promise<ReleaseResult | null> {\n const pkgUrl = replaceUrlPath(\n registryUrl,\n metadataUrl.replace('%package%', packageName),\n );\n const pkgPromise = this.getJson(pkgUrl, z.unknown());\n\n const devUrl = replaceUrlPath(\n registryUrl,\n metadataUrl.replace('%package%', `${packageName}~dev`),\n );\n const devPromise = this.getJson(devUrl, z.unknown()).then(\n (x) => x,\n () => null,\n );\n\n const responses: NonNullable<unknown>[] = await Promise.all([\n pkgPromise,\n devPromise,\n ]).then((responses) => responses.filter(isObject));\n return parsePackagesResponses(packageName, responses);\n }\n\n packagistV2Lookup(\n registryUrl: string,\n metadataUrl: string,\n packageName: string,\n ): Promise<ReleaseResult | null> {\n return withCache(\n {\n namespace: `datasource-${PackagistDatasource.id}`,\n key: `packagistV2Lookup:${registryUrl}:${metadataUrl}:${packageName}`,\n ttlMinutes: 10,\n },\n () => this._packagistV2Lookup(registryUrl, metadataUrl, packageName),\n );\n }\n\n public getPkgUrl(\n packageName: string,\n registryUrl: string,\n registryMeta: RegistryMeta,\n ): string | null {\n if (\n registryMeta.providersUrl &&\n packageName in registryMeta.providerPackages\n ) {\n let url = registryMeta.providersUrl.replace('%package%', packageName);\n const hash = registryMeta.providerPackages[packageName];\n if (hash) {\n url = url.replace('%hash%', hash);\n }\n return replaceUrlPath(registryUrl, url);\n }\n\n if (registryMeta.providersLazyUrl) {\n return replaceUrlPath(\n registryUrl,\n registryMeta.providersLazyUrl.replace('%package%', packageName),\n );\n }\n\n return null;\n }\n\n public override async getReleases({\n packageName,\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n logger.trace(`getReleases(${packageName})`);\n\n /* v8 ignore next 3 -- should never happen */\n if (!registryUrl) {\n return null;\n }\n\n try {\n const meta = await this.getRegistryMeta(registryUrl);\n\n if (\n meta.availablePackages &&\n !meta.availablePackages.includes(packageName)\n ) {\n return null;\n }\n\n if (meta.metadataUrl) {\n const packagistResult = await this.packagistV2Lookup(\n registryUrl,\n meta.metadataUrl,\n packageName,\n );\n return packagistResult;\n }\n\n if (meta.packages[packageName]) {\n const result = extractDepReleases(meta.packages[packageName]);\n return result;\n }\n\n await this.fetchIncludesPackages(registryUrl, meta);\n if (meta.includesPackages[packageName]) {\n return meta.includesPackages[packageName];\n }\n\n await this.fetchProviderPackages(registryUrl, meta);\n const pkgUrl = this.getPkgUrl(packageName, registryUrl, meta);\n if (!pkgUrl) {\n return null;\n }\n\n const pkgRes = await this.getJson(pkgUrl, PackagesResponse);\n const dep = extractDepReleases(pkgRes.packages[packageName]);\n logger.trace({ dep }, 'dep');\n return dep;\n } catch (err) /* istanbul ignore next */ {\n if (\n isDefaultPackagistHost(registryUrl) &&\n isTransientPackagistError(err)\n ) {\n throw new ExternalHostError(err);\n }\n throw err;\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -41,7 +41,9 @@ async function downloadGzipFile(url, compressedFile, http, lastDownloadTimestamp
|
|
|
41
41
|
logger.debug(`No need to download ${url}, file is up to date.`);
|
|
42
42
|
return false;
|
|
43
43
|
}
|
|
44
|
-
|
|
44
|
+
const readStream = http.stream(url);
|
|
45
|
+
const writeStream = createCacheWriteStream(compressedFile);
|
|
46
|
+
await pipeline(readStream, writeStream);
|
|
45
47
|
const compressedStats = await statCacheFile(compressedFile);
|
|
46
48
|
if (!compressedStats || compressedStats.size === 0) {
|
|
47
49
|
logger.debug(`Empty response body from getting ${url}.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.js","names":["fs.statCacheFile","fs.createCacheWriteStream","fs.pipeline","fs.createCacheReadStream","fs.ensureCacheDir","fs.renameCacheFile","fs.cachePathExists","fs.rmCache"],"sources":["../../../../../lib/modules/datasource/rpm/providers/common.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { createGunzip } from 'node:zlib';\nimport upath from 'upath';\nimport { logger } from '../../../../logger/index.ts';\nimport * as fs from '../../../../util/fs/index.ts';\nimport { toSha256 } from '../../../../util/hash.ts';\nimport type { Http, HttpOptions } from '../../../../util/http/index.ts';\nimport { acquireLock } from '../../../../util/mutex.ts';\nimport type { ReleaseResult } from '../../types.ts';\nimport { datasource } from '../common.ts';\n\nconst cacheSubDir = datasource;\n\ntype RpmVersionValue = boolean | number | string | null | undefined;\n\nexport function formatRpmVersion(\n ver: RpmVersionValue,\n rel?: RpmVersionValue,\n): string | null {\n if (ver === undefined || ver === null) {\n return null;\n }\n\n const version = String(ver);\n\n if (rel === undefined || rel === null) {\n return version;\n }\n\n return `${version}-${String(rel)}`;\n}\n\nexport function buildReleaseResult(\n versions: Iterable<string>,\n): ReleaseResult | null {\n const uniqueVersions = [...new Set(versions)];\n\n if (uniqueVersions.length === 0) {\n return null;\n }\n\n return {\n releases: uniqueVersions.map((version) => ({ version })),\n };\n}\n\nasync function getFileCreationTime(\n filePath: string,\n): Promise<Date | undefined> {\n const stats = await fs.statCacheFile(filePath);\n return stats?.ctime;\n}\n\nasync function checkIfModified(\n url: string,\n lastDownloadTimestamp: Date,\n http: Http,\n): Promise<boolean> {\n const options: HttpOptions = {\n headers: {\n 'If-Modified-Since': lastDownloadTimestamp.toUTCString(),\n },\n };\n\n try {\n const response = await http.head(url, options);\n return response.statusCode !== 304;\n } catch (err) {\n logger.warn(\n {\n err,\n lastDownloadTimestamp,\n url,\n },\n 'Could not determine if metadata file is modified since last download',\n );\n return true;\n }\n}\n\nasync function downloadGzipFile(\n url: string,\n compressedFile: string,\n http: Http,\n lastDownloadTimestamp?: Date,\n): Promise<boolean> {\n let needsToDownload = true;\n\n if (lastDownloadTimestamp) {\n needsToDownload = await checkIfModified(url, lastDownloadTimestamp, http);\n }\n\n if (!needsToDownload) {\n logger.debug(`No need to download ${url}, file is up to date.`);\n return false;\n }\n\n const readStream = http.stream(url);\n const writeStream = fs.createCacheWriteStream(compressedFile);\n await fs.pipeline(readStream, writeStream);\n\n const compressedStats = await fs.statCacheFile(compressedFile);\n if (!compressedStats || compressedStats.size === 0) {\n logger.debug(`Empty response body from getting ${url}.`);\n throw new Error(`Empty response body from getting ${url}.`);\n }\n\n return true;\n}\n\nasync function extractGzipFile(\n compressedFile: string,\n extractedFile: string,\n): Promise<void> {\n await fs.pipeline(\n fs.createCacheReadStream(compressedFile),\n createGunzip(),\n fs.createCacheWriteStream(extractedFile),\n );\n}\n\nexport async function getCachedGunzippedFile(\n http: Http,\n url: string,\n extension: 'xml',\n): Promise<string> {\n const releaseLock = await acquireLock(\n `gunzipped-file:${url}:${extension}`,\n 'datasource-rpm',\n );\n\n try {\n const cacheDir = await fs.ensureCacheDir(cacheSubDir);\n const urlHash = toSha256(url);\n const extractedFile = upath.join(cacheDir, `${urlHash}.${extension}`);\n let lastTimestamp = await getFileCreationTime(extractedFile);\n\n const compressedFile = upath.join(\n cacheDir,\n `${randomUUID()}_${urlHash}.gz`,\n );\n const extractedTempFile = upath.join(\n cacheDir,\n `${randomUUID()}_${urlHash}.${extension}`,\n );\n\n try {\n const wasUpdated = await downloadGzipFile(\n url,\n compressedFile,\n http,\n lastTimestamp,\n );\n\n if (wasUpdated || !lastTimestamp) {\n try {\n // Only replace the shared cache file after a successful extract.\n await extractGzipFile(compressedFile, extractedTempFile);\n await fs.renameCacheFile(extractedTempFile, extractedFile);\n lastTimestamp = await getFileCreationTime(extractedFile);\n } catch (err) {\n logger.warn(\n {\n compressedFile,\n err,\n extension,\n extractedFile,\n url,\n },\n 'Failed to extract RPM metadata file from compressed file',\n );\n }\n }\n\n if (!lastTimestamp) {\n throw new Error('Missing metadata in extracted RPM metadata file!');\n }\n\n return extractedFile;\n } finally {\n if (await fs.cachePathExists(compressedFile)) {\n await fs.rmCache(compressedFile);\n }\n if (await fs.cachePathExists(extractedTempFile)) {\n await fs.rmCache(extractedTempFile);\n }\n }\n } finally {\n releaseLock();\n }\n}\n"],"mappings":";;;;;;;;AAWA,MAAM,cAAA;AAIN,SAAgB,iBACd,KACA,KACe;CACf,IAAI,QAAQ,KAAA,KAAa,QAAQ,MAC/B,OAAO;CAGT,MAAM,UAAU,OAAO,GAAG;CAE1B,IAAI,QAAQ,KAAA,KAAa,QAAQ,MAC/B,OAAO;CAGT,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG;AACjC;AAEA,SAAgB,mBACd,UACsB;CACtB,MAAM,iBAAiB,CAAC,GAAG,IAAI,IAAI,QAAQ,CAAC;CAE5C,IAAI,eAAe,WAAW,GAC5B,OAAO;CAGT,OAAO,EACL,UAAU,eAAe,KAAK,aAAa,EAAE,QAAQ,EAAE,EACzD;AACF;AAEA,eAAe,oBACb,UAC2B;CAE3B,QAAO,MADaA,cAAiB,QAAQ,EAAA,EAC/B;AAChB;AAEA,eAAe,gBACb,KACA,uBACA,MACkB;CAClB,MAAM,UAAuB,EAC3B,SAAS,EACP,qBAAqB,sBAAsB,YAAY,EACzD,EACF;CAEA,IAAI;EAEF,QAAO,MADgB,KAAK,KAAK,KAAK,OAAO,EAAA,CAC7B,eAAe;CACjC,SAAS,KAAK;EACZ,OAAO,KACL;GACE;GACA;GACA;EACF,GACA,sEACF;EACA,OAAO;CACT;AACF;AAEA,eAAe,iBACb,KACA,gBACA,MACA,uBACkB;CAClB,IAAI,kBAAkB;CAEtB,IAAI,uBACF,kBAAkB,MAAM,gBAAgB,KAAK,uBAAuB,IAAI;CAG1E,IAAI,CAAC,iBAAiB;EACpB,OAAO,MAAM,uBAAuB,IAAI,sBAAsB;EAC9D,OAAO;CACT;
|
|
1
|
+
{"version":3,"file":"common.js","names":["fs.statCacheFile","fs.createCacheWriteStream","fs.pipeline","fs.createCacheReadStream","fs.ensureCacheDir","fs.renameCacheFile","fs.cachePathExists","fs.rmCache"],"sources":["../../../../../lib/modules/datasource/rpm/providers/common.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { createGunzip } from 'node:zlib';\nimport upath from 'upath';\nimport { logger } from '../../../../logger/index.ts';\nimport * as fs from '../../../../util/fs/index.ts';\nimport { toSha256 } from '../../../../util/hash.ts';\nimport type { Http, HttpOptions } from '../../../../util/http/index.ts';\nimport { acquireLock } from '../../../../util/mutex.ts';\nimport type { ReleaseResult } from '../../types.ts';\nimport { datasource } from '../common.ts';\n\nconst cacheSubDir = datasource;\n\ntype RpmVersionValue = boolean | number | string | null | undefined;\n\nexport function formatRpmVersion(\n ver: RpmVersionValue,\n rel?: RpmVersionValue,\n): string | null {\n if (ver === undefined || ver === null) {\n return null;\n }\n\n const version = String(ver);\n\n if (rel === undefined || rel === null) {\n return version;\n }\n\n return `${version}-${String(rel)}`;\n}\n\nexport function buildReleaseResult(\n versions: Iterable<string>,\n): ReleaseResult | null {\n const uniqueVersions = [...new Set(versions)];\n\n if (uniqueVersions.length === 0) {\n return null;\n }\n\n return {\n releases: uniqueVersions.map((version) => ({ version })),\n };\n}\n\nasync function getFileCreationTime(\n filePath: string,\n): Promise<Date | undefined> {\n const stats = await fs.statCacheFile(filePath);\n return stats?.ctime;\n}\n\nasync function checkIfModified(\n url: string,\n lastDownloadTimestamp: Date,\n http: Http,\n): Promise<boolean> {\n const options: HttpOptions = {\n headers: {\n 'If-Modified-Since': lastDownloadTimestamp.toUTCString(),\n },\n };\n\n try {\n const response = await http.head(url, options);\n return response.statusCode !== 304;\n } catch (err) {\n logger.warn(\n {\n err,\n lastDownloadTimestamp,\n url,\n },\n 'Could not determine if metadata file is modified since last download',\n );\n return true;\n }\n}\n\nasync function downloadGzipFile(\n url: string,\n compressedFile: string,\n http: Http,\n lastDownloadTimestamp?: Date,\n): Promise<boolean> {\n let needsToDownload = true;\n\n if (lastDownloadTimestamp) {\n needsToDownload = await checkIfModified(url, lastDownloadTimestamp, http);\n }\n\n if (!needsToDownload) {\n logger.debug(`No need to download ${url}, file is up to date.`);\n return false;\n }\n\n const readStream = http.stream(url);\n const writeStream = fs.createCacheWriteStream(compressedFile);\n await fs.pipeline(readStream, writeStream);\n\n const compressedStats = await fs.statCacheFile(compressedFile);\n if (!compressedStats || compressedStats.size === 0) {\n logger.debug(`Empty response body from getting ${url}.`);\n throw new Error(`Empty response body from getting ${url}.`);\n }\n\n return true;\n}\n\nasync function extractGzipFile(\n compressedFile: string,\n extractedFile: string,\n): Promise<void> {\n await fs.pipeline(\n fs.createCacheReadStream(compressedFile),\n createGunzip(),\n fs.createCacheWriteStream(extractedFile),\n );\n}\n\nexport async function getCachedGunzippedFile(\n http: Http,\n url: string,\n extension: 'xml',\n): Promise<string> {\n const releaseLock = await acquireLock(\n `gunzipped-file:${url}:${extension}`,\n 'datasource-rpm',\n );\n\n try {\n const cacheDir = await fs.ensureCacheDir(cacheSubDir);\n const urlHash = toSha256(url);\n const extractedFile = upath.join(cacheDir, `${urlHash}.${extension}`);\n let lastTimestamp = await getFileCreationTime(extractedFile);\n\n const compressedFile = upath.join(\n cacheDir,\n `${randomUUID()}_${urlHash}.gz`,\n );\n const extractedTempFile = upath.join(\n cacheDir,\n `${randomUUID()}_${urlHash}.${extension}`,\n );\n\n try {\n const wasUpdated = await downloadGzipFile(\n url,\n compressedFile,\n http,\n lastTimestamp,\n );\n\n if (wasUpdated || !lastTimestamp) {\n try {\n // Only replace the shared cache file after a successful extract.\n await extractGzipFile(compressedFile, extractedTempFile);\n await fs.renameCacheFile(extractedTempFile, extractedFile);\n lastTimestamp = await getFileCreationTime(extractedFile);\n } catch (err) {\n logger.warn(\n {\n compressedFile,\n err,\n extension,\n extractedFile,\n url,\n },\n 'Failed to extract RPM metadata file from compressed file',\n );\n }\n }\n\n if (!lastTimestamp) {\n throw new Error('Missing metadata in extracted RPM metadata file!');\n }\n\n return extractedFile;\n } finally {\n if (await fs.cachePathExists(compressedFile)) {\n await fs.rmCache(compressedFile);\n }\n if (await fs.cachePathExists(extractedTempFile)) {\n await fs.rmCache(extractedTempFile);\n }\n }\n } finally {\n releaseLock();\n }\n}\n"],"mappings":"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"}
|
|
@@ -10,7 +10,8 @@ function getPrimaryRepodataUrl(xml, registryUrl, repomdUrl) {
|
|
|
10
10
|
if (!locationElement) throw new Error(`No location element found in ${repomdUrl}`);
|
|
11
11
|
const href = locationElement.attr.href;
|
|
12
12
|
if (!href) throw new Error(`No href found in ${repomdUrl}`);
|
|
13
|
-
|
|
13
|
+
const registryUrlWithoutRepodata = registryUrl.replace(/\/repodata\/?$/, "/");
|
|
14
|
+
return joinUrlParts(registryUrlWithoutRepodata, href);
|
|
14
15
|
}
|
|
15
16
|
async function fetchPrimaryGzipUrl(http, registryUrl) {
|
|
16
17
|
const repomdUrl = joinUrlParts(registryUrl, repomdXmlFileName);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repomd.js","names":[],"sources":["../../../../lib/modules/datasource/rpm/repomd.ts"],"sourcesContent":["import { XmlDocument } from 'xmldoc';\nimport { logger } from '../../../logger/index.ts';\nimport type { Http } from '../../../util/http/index.ts';\nimport { joinUrlParts } from '../../../util/url.ts';\nimport { datasource, repomdXmlFileName } from './common.ts';\n\nfunction getPrimaryRepodataUrl(\n xml: XmlDocument,\n registryUrl: string,\n repomdUrl: string,\n): string {\n const primaryData = xml.childWithAttribute('type', 'primary');\n\n if (!primaryData) {\n throw new Error(`No primary data found in ${repomdUrl}`);\n }\n\n const locationElement = primaryData.childNamed('location');\n if (!locationElement) {\n throw new Error(`No location element found in ${repomdUrl}`);\n }\n\n const href = locationElement.attr.href;\n if (!href) {\n throw new Error(`No href found in ${repomdUrl}`);\n }\n\n // replace trailing \"repodata/\" from registryUrl, if it exists, with a \"/\"\n // because href includes \"repodata/\"\n const registryUrlWithoutRepodata = registryUrl.replace(/\\/repodata\\/?$/, '/');\n\n return joinUrlParts(registryUrlWithoutRepodata, href);\n}\n\nexport async function fetchPrimaryGzipUrl(\n http: Http,\n registryUrl: string,\n): Promise<string> {\n const repomdUrl = joinUrlParts(registryUrl, repomdXmlFileName);\n const response = await http.getText(repomdUrl.toString());\n const repomdBody = response.body.trimStart();\n\n // repomd.xml may omit the XML declaration and start directly with the root element\n if (!(repomdBody.startsWith('<?xml') || repomdBody.startsWith('<repomd'))) {\n logger.debug({ datasource, url: repomdUrl }, 'Invalid response format');\n throw new Error(\n `${repomdUrl} is not in XML format. Response body: ${response.body}`,\n );\n }\n\n const xml = new XmlDocument(repomdBody);\n\n try {\n return getPrimaryRepodataUrl(xml, registryUrl, repomdUrl.toString());\n } catch (err) {\n if (\n err instanceof Error &&\n err.message.startsWith('No primary data found')\n ) {\n logger.debug(\n `No primary data found in ${repomdUrl}, xml contents: ${response.body}`,\n );\n }\n\n throw err;\n }\n}\n"],"mappings":";;;;;AAMA,SAAS,sBACP,KACA,aACA,WACQ;CACR,MAAM,cAAc,IAAI,mBAAmB,QAAQ,SAAS;CAE5D,IAAI,CAAC,aACH,MAAM,IAAI,MAAM,4BAA4B,WAAW;CAGzD,MAAM,kBAAkB,YAAY,WAAW,UAAU;CACzD,IAAI,CAAC,iBACH,MAAM,IAAI,MAAM,gCAAgC,WAAW;CAG7D,MAAM,OAAO,gBAAgB,KAAK;CAClC,IAAI,CAAC,MACH,MAAM,IAAI,MAAM,oBAAoB,WAAW;
|
|
1
|
+
{"version":3,"file":"repomd.js","names":[],"sources":["../../../../lib/modules/datasource/rpm/repomd.ts"],"sourcesContent":["import { XmlDocument } from 'xmldoc';\nimport { logger } from '../../../logger/index.ts';\nimport type { Http } from '../../../util/http/index.ts';\nimport { joinUrlParts } from '../../../util/url.ts';\nimport { datasource, repomdXmlFileName } from './common.ts';\n\nfunction getPrimaryRepodataUrl(\n xml: XmlDocument,\n registryUrl: string,\n repomdUrl: string,\n): string {\n const primaryData = xml.childWithAttribute('type', 'primary');\n\n if (!primaryData) {\n throw new Error(`No primary data found in ${repomdUrl}`);\n }\n\n const locationElement = primaryData.childNamed('location');\n if (!locationElement) {\n throw new Error(`No location element found in ${repomdUrl}`);\n }\n\n const href = locationElement.attr.href;\n if (!href) {\n throw new Error(`No href found in ${repomdUrl}`);\n }\n\n // replace trailing \"repodata/\" from registryUrl, if it exists, with a \"/\"\n // because href includes \"repodata/\"\n const registryUrlWithoutRepodata = registryUrl.replace(/\\/repodata\\/?$/, '/');\n\n return joinUrlParts(registryUrlWithoutRepodata, href);\n}\n\nexport async function fetchPrimaryGzipUrl(\n http: Http,\n registryUrl: string,\n): Promise<string> {\n const repomdUrl = joinUrlParts(registryUrl, repomdXmlFileName);\n const response = await http.getText(repomdUrl.toString());\n const repomdBody = response.body.trimStart();\n\n // repomd.xml may omit the XML declaration and start directly with the root element\n if (!(repomdBody.startsWith('<?xml') || repomdBody.startsWith('<repomd'))) {\n logger.debug({ datasource, url: repomdUrl }, 'Invalid response format');\n throw new Error(\n `${repomdUrl} is not in XML format. Response body: ${response.body}`,\n );\n }\n\n const xml = new XmlDocument(repomdBody);\n\n try {\n return getPrimaryRepodataUrl(xml, registryUrl, repomdUrl.toString());\n } catch (err) {\n if (\n err instanceof Error &&\n err.message.startsWith('No primary data found')\n ) {\n logger.debug(\n `No primary data found in ${repomdUrl}, xml contents: ${response.body}`,\n );\n }\n\n throw err;\n }\n}\n"],"mappings":";;;;;AAMA,SAAS,sBACP,KACA,aACA,WACQ;CACR,MAAM,cAAc,IAAI,mBAAmB,QAAQ,SAAS;CAE5D,IAAI,CAAC,aACH,MAAM,IAAI,MAAM,4BAA4B,WAAW;CAGzD,MAAM,kBAAkB,YAAY,WAAW,UAAU;CACzD,IAAI,CAAC,iBACH,MAAM,IAAI,MAAM,gCAAgC,WAAW;CAG7D,MAAM,OAAO,gBAAgB,KAAK;CAClC,IAAI,CAAC,MACH,MAAM,IAAI,MAAM,oBAAoB,WAAW;CAKjD,MAAM,6BAA6B,YAAY,QAAQ,kBAAkB,GAAG;CAE5E,OAAO,aAAa,4BAA4B,IAAI;AACtD;AAEA,eAAsB,oBACpB,MACA,aACiB;CACjB,MAAM,YAAY,aAAa,aAAa,iBAAiB;CAC7D,MAAM,WAAW,MAAM,KAAK,QAAQ,UAAU,SAAS,CAAC;CACxD,MAAM,aAAa,SAAS,KAAK,UAAU;CAG3C,IAAI,EAAE,WAAW,WAAW,OAAO,KAAK,WAAW,WAAW,SAAS,IAAI;EACzE,OAAO,MAAM;GAAE,YAAA;GAAY,KAAK;EAAU,GAAG,yBAAyB;EACtE,MAAM,IAAI,MACR,GAAG,UAAU,wCAAwC,SAAS,MAChE;CACF;CAEA,MAAM,MAAM,IAAI,YAAY,UAAU;CAEtC,IAAI;EACF,OAAO,sBAAsB,KAAK,aAAa,UAAU,SAAS,CAAC;CACrE,SAAS,KAAK;EACZ,IACE,eAAe,SACf,IAAI,QAAQ,WAAW,uBAAuB,GAE9C,OAAO,MACL,4BAA4B,UAAU,kBAAkB,SAAS,MACnE;EAGF,MAAM;CACR;AACF"}
|
|
@@ -26,7 +26,8 @@ var RubyVersionDatasource = class RubyVersionDatasource extends Datasource {
|
|
|
26
26
|
};
|
|
27
27
|
const rubyVersionsUrl = `${registryUrl}en/downloads/releases/`;
|
|
28
28
|
try {
|
|
29
|
-
|
|
29
|
+
const response = await this.http.getText(rubyVersionsUrl);
|
|
30
|
+
(parse(response.body).querySelector(".release-list")?.querySelectorAll("tr") ?? []).forEach((row) => {
|
|
30
31
|
const tds = row.querySelectorAll("td");
|
|
31
32
|
const columns = [];
|
|
32
33
|
tds.forEach((td) => columns.push(td.innerHTML));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["rubyVersioningId"],"sources":["../../../../lib/modules/datasource/ruby-version/index.ts"],"sourcesContent":["import { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { parse } from '../../../util/html.ts';\nimport type { HttpError } from '../../../util/http/index.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport {\n isVersion,\n id as rubyVersioningId,\n} from '../../versioning/ruby/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type { GetReleasesConfig, ReleaseResult } from '../types.ts';\n\nexport class RubyVersionDatasource extends Datasource {\n static readonly id = 'ruby-version';\n\n constructor() {\n super(RubyVersionDatasource.id);\n }\n\n override readonly defaultRegistryUrls = ['https://www.ruby-lang.org/'];\n\n override readonly customRegistrySupport = false;\n\n override readonly defaultVersioning = rubyVersioningId;\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'The release timestamp is determined from the `release-list` table in the results.';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'We use the URL: https://github.com/ruby/ruby.';\n\n private async _getReleases({\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n const res: ReleaseResult = {\n homepage: 'https://www.ruby-lang.org',\n sourceUrl: 'https://github.com/ruby/ruby',\n releases: [],\n };\n // TODO: types (#22198)\n const rubyVersionsUrl = `${registryUrl}en/downloads/releases/`;\n try {\n const response = await this.http.getText(rubyVersionsUrl);\n\n const root = parse(response.body);\n const rows =\n root.querySelector('.release-list')?.querySelectorAll('tr') ?? [];\n rows.forEach((row) => {\n const tds = row.querySelectorAll('td');\n const columns: string[] = [];\n tds.forEach((td) => columns.push(td.innerHTML));\n if (columns.length) {\n const version = columns[0].replace('Ruby ', '');\n if (isVersion(version)) {\n const releaseTimestamp = asTimestamp(columns[1]);\n const changelogUrl = columns[2]\n .replace('<a href=\"', 'https://www.ruby-lang.org')\n .replace('\">more...</a>', '');\n res.releases.push({ version, releaseTimestamp, changelogUrl });\n }\n }\n });\n if (!res.releases.length) {\n logger.warn({ registryUrl }, 'Missing ruby releases');\n return null;\n }\n } catch (err) {\n this.handleGenericErrors(err);\n }\n\n return res;\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n return withCache(\n {\n namespace: `datasource-${RubyVersionDatasource.id}`,\n key: 'all',\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n\n override handleHttpErrors(err: HttpError): never | void {\n throw new ExternalHostError(err);\n }\n}\n"],"mappings":";;;;;;;;AAaA,IAAa,wBAAb,MAAa,8BAA8B,WAAW;CACpD,OAAgB,KAAK;CAErB,cAAc;EACZ,MAAM,sBAAsB,EAAE;CAChC;CAEA,sBAAwC,CAAC,4BAA4B;CAErE,wBAA0C;CAE1C,oBAAsCA;CAEtC,0BAA4C;CAC5C,uBACE;CACF,mBAAqC;CACrC,gBACE;CAEF,MAAc,aAAa,EACzB,eACmD;EACnD,MAAM,MAAqB;GACzB,UAAU;GACV,WAAW;GACX,UAAU,CAAC;EACb;EAEA,MAAM,kBAAkB,GAAG,YAAY;EACvC,IAAI;
|
|
1
|
+
{"version":3,"file":"index.js","names":["rubyVersioningId"],"sources":["../../../../lib/modules/datasource/ruby-version/index.ts"],"sourcesContent":["import { logger } from '../../../logger/index.ts';\nimport { ExternalHostError } from '../../../types/errors/external-host-error.ts';\nimport { withCache } from '../../../util/cache/package/with-cache.ts';\nimport { parse } from '../../../util/html.ts';\nimport type { HttpError } from '../../../util/http/index.ts';\nimport { asTimestamp } from '../../../util/timestamp.ts';\nimport {\n isVersion,\n id as rubyVersioningId,\n} from '../../versioning/ruby/index.ts';\nimport { Datasource } from '../datasource.ts';\nimport type { GetReleasesConfig, ReleaseResult } from '../types.ts';\n\nexport class RubyVersionDatasource extends Datasource {\n static readonly id = 'ruby-version';\n\n constructor() {\n super(RubyVersionDatasource.id);\n }\n\n override readonly defaultRegistryUrls = ['https://www.ruby-lang.org/'];\n\n override readonly customRegistrySupport = false;\n\n override readonly defaultVersioning = rubyVersioningId;\n\n override readonly releaseTimestampSupport = true;\n override readonly releaseTimestampNote =\n 'The release timestamp is determined from the `release-list` table in the results.';\n override readonly sourceUrlSupport = 'package';\n override readonly sourceUrlNote =\n 'We use the URL: https://github.com/ruby/ruby.';\n\n private async _getReleases({\n registryUrl,\n }: GetReleasesConfig): Promise<ReleaseResult | null> {\n const res: ReleaseResult = {\n homepage: 'https://www.ruby-lang.org',\n sourceUrl: 'https://github.com/ruby/ruby',\n releases: [],\n };\n // TODO: types (#22198)\n const rubyVersionsUrl = `${registryUrl}en/downloads/releases/`;\n try {\n const response = await this.http.getText(rubyVersionsUrl);\n\n const root = parse(response.body);\n const rows =\n root.querySelector('.release-list')?.querySelectorAll('tr') ?? [];\n rows.forEach((row) => {\n const tds = row.querySelectorAll('td');\n const columns: string[] = [];\n tds.forEach((td) => columns.push(td.innerHTML));\n if (columns.length) {\n const version = columns[0].replace('Ruby ', '');\n if (isVersion(version)) {\n const releaseTimestamp = asTimestamp(columns[1]);\n const changelogUrl = columns[2]\n .replace('<a href=\"', 'https://www.ruby-lang.org')\n .replace('\">more...</a>', '');\n res.releases.push({ version, releaseTimestamp, changelogUrl });\n }\n }\n });\n if (!res.releases.length) {\n logger.warn({ registryUrl }, 'Missing ruby releases');\n return null;\n }\n } catch (err) {\n this.handleGenericErrors(err);\n }\n\n return res;\n }\n\n getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {\n return withCache(\n {\n namespace: `datasource-${RubyVersionDatasource.id}`,\n key: 'all',\n fallback: true,\n },\n () => this._getReleases(config),\n );\n }\n\n override handleHttpErrors(err: HttpError): never | void {\n throw new ExternalHostError(err);\n }\n}\n"],"mappings":";;;;;;;;AAaA,IAAa,wBAAb,MAAa,8BAA8B,WAAW;CACpD,OAAgB,KAAK;CAErB,cAAc;EACZ,MAAM,sBAAsB,EAAE;CAChC;CAEA,sBAAwC,CAAC,4BAA4B;CAErE,wBAA0C;CAE1C,oBAAsCA;CAEtC,0BAA4C;CAC5C,uBACE;CACF,mBAAqC;CACrC,gBACE;CAEF,MAAc,aAAa,EACzB,eACmD;EACnD,MAAM,MAAqB;GACzB,UAAU;GACV,WAAW;GACX,UAAU,CAAC;EACb;EAEA,MAAM,kBAAkB,GAAG,YAAY;EACvC,IAAI;GACF,MAAM,WAAW,MAAM,KAAK,KAAK,QAAQ,eAAe;GAKxD,CAHa,MAAM,SAAS,IAEvB,CAAC,CAAC,cAAc,eAAe,CAAC,EAAE,iBAAiB,IAAI,KAAK,CAAC,EAAA,CAC7D,SAAS,QAAQ;IACpB,MAAM,MAAM,IAAI,iBAAiB,IAAI;IACrC,MAAM,UAAoB,CAAC;IAC3B,IAAI,SAAS,OAAO,QAAQ,KAAK,GAAG,SAAS,CAAC;IAC9C,IAAI,QAAQ,QAAQ;KAClB,MAAM,UAAU,QAAQ,EAAE,CAAC,QAAQ,SAAS,EAAE;KAC9C,IAAI,UAAU,OAAO,GAAG;MACtB,MAAM,mBAAmB,YAAY,QAAQ,EAAE;MAC/C,MAAM,eAAe,QAAQ,EAAE,CAC5B,QAAQ,cAAa,2BAA2B,CAAC,CACjD,QAAQ,kBAAiB,EAAE;MAC9B,IAAI,SAAS,KAAK;OAAE;OAAS;OAAkB;MAAa,CAAC;KAC/D;IACF;GACF,CAAC;GACD,IAAI,CAAC,IAAI,SAAS,QAAQ;IACxB,OAAO,KAAK,EAAE,YAAY,GAAG,uBAAuB;IACpD,OAAO;GACT;EACF,SAAS,KAAK;GACZ,KAAK,oBAAoB,GAAG;EAC9B;EAEA,OAAO;CACT;CAEA,YAAY,QAA0D;EACpE,OAAO,UACL;GACE,WAAW,cAAc,sBAAsB;GAC/C,KAAK;GACL,UAAU;EACZ,SACM,KAAK,aAAa,MAAM,CAChC;CACF;CAEA,iBAA0B,KAA8B;EACtD,MAAM,IAAI,kBAAkB,GAAG;CACjC;AACF"}
|
|
@@ -28,7 +28,7 @@ var MetadataCache = class {
|
|
|
28
28
|
});
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
|
-
async function saveCache(cache, ttlMinutes =
|
|
31
|
+
async function saveCache(cache, ttlMinutes = 144e3, ttlDelta = 14400) {
|
|
32
32
|
if (parseUrl(registryUrl)?.hostname === "rubygems.org") {
|
|
33
33
|
const ttl = ttlMinutes + Math.floor(Math.random() * ttlDelta);
|
|
34
34
|
await set(cacheNs, cacheKey, cache, ttl);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata-cache.js","names":["packageCache.get","packageCache.set"],"sources":["../../../../lib/modules/datasource/rubygems/metadata-cache.ts"],"sourcesContent":["import { logger } from '../../../logger/index.ts';\nimport * as packageCache from '../../../util/cache/package/index.ts';\nimport { toSha256 } from '../../../util/hash.ts';\nimport type { Http } from '../../../util/http/index.ts';\nimport type { AsyncResult } from '../../../util/result.ts';\nimport { Result } from '../../../util/result.ts';\nimport { parseUrl } from '../../../util/url.ts';\nimport type { ReleaseResult } from '../types.ts';\nimport { getV1Releases } from './common.ts';\n\ninterface CacheRecord {\n hash: string;\n data: ReleaseResult;\n isFallback?: true;\n}\n\nfunction hashVersions(versions: string[]): string {\n return toSha256(versions.sort().join(','));\n}\n\nfunction hashReleases(releases: ReleaseResult): string {\n return hashVersions(releases.releases.map((release) => release.version));\n}\n\ninterface CacheNotFoundError {\n type: 'cache-not-found';\n}\ninterface CacheStaleError {\n type: 'cache-stale';\n cache: CacheRecord;\n}\ninterface CacheInvalidError {\n type: 'cache-invalid';\n}\ntype CacheLoadError = CacheNotFoundError | CacheStaleError;\ntype CacheError = CacheNotFoundError | CacheStaleError | CacheInvalidError;\n\nexport class MetadataCache {\n private readonly http: Http;\n\n constructor(http: Http) {\n this.http = http;\n }\n\n async getRelease(\n registryUrl: string,\n packageName: string,\n versions: string[],\n ): Promise<ReleaseResult> {\n const cacheNs = `datasource-rubygems`;\n const cacheKey = `metadata-cache:${registryUrl}:${packageName}`;\n const versionsHash = hashVersions(versions);\n\n function loadCache(): AsyncResult<ReleaseResult, CacheLoadError> {\n return Result.wrapNullable<CacheRecord, CacheLoadError, CacheLoadError>(\n packageCache.get<CacheRecord>(cacheNs, cacheKey),\n { type: 'cache-not-found' },\n ).transform((cache) => {\n return versionsHash === cache.hash\n ? Result.ok(cache.data)\n : Result.err({ type: 'cache-stale', cache });\n });\n }\n\n async function saveCache(\n cache: CacheRecord,\n ttlMinutes = 100 * 24 * 60,\n ttlDelta = 10 * 24 * 60,\n ): Promise<void> {\n const registryHostname = parseUrl(registryUrl)?.hostname;\n if (registryHostname === 'rubygems.org') {\n const ttlRandomDelta = Math.floor(Math.random() * ttlDelta);\n const ttl = ttlMinutes + ttlRandomDelta;\n await packageCache.set(cacheNs, cacheKey, cache, ttl);\n }\n }\n\n return await loadCache()\n .catch((err) =>\n getV1Releases(this.http, registryUrl, packageName).transform(\n async (\n data: ReleaseResult,\n ): Promise<Result<ReleaseResult, CacheError>> => {\n const dataHash = hashReleases(data);\n if (dataHash === versionsHash) {\n await saveCache({\n hash: dataHash,\n data,\n });\n return Result.ok(data);\n }\n\n /**\n * Return stale cache for 24 hours,\n * if metadata is inconsistent with versions list.\n */\n if (err.type === 'cache-stale') {\n const staleCache = err.cache;\n if (!staleCache.isFallback) {\n await saveCache(\n { ...staleCache, isFallback: true },\n 24 * 60,\n 0,\n );\n }\n return Result.ok(staleCache.data);\n }\n\n return Result.err({ type: 'cache-invalid' });\n },\n ),\n )\n .catch((err) => {\n logger.debug(\n { err },\n 'Rubygems: error fetching rubygems data, falling back to versions-only result',\n );\n const releases = versions.map((version) => ({ version }));\n return Result.ok({ releases });\n })\n .unwrapOrThrow();\n }\n}\n"],"mappings":";;;;;;;AAgBA,SAAS,aAAa,UAA4B;CAChD,OAAO,SAAS,SAAS,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC;AAC3C;AAEA,SAAS,aAAa,UAAiC;CACrD,OAAO,aAAa,SAAS,SAAS,KAAK,YAAY,QAAQ,OAAO,CAAC;AACzE;AAeA,IAAa,gBAAb,MAA2B;CACzB;CAEA,YAAY,MAAY;EACtB,KAAK,OAAO;CACd;CAEA,MAAM,WACJ,aACA,aACA,UACwB;EACxB,MAAM,UAAU;EAChB,MAAM,WAAW,kBAAkB,YAAY,GAAG;EAClD,MAAM,eAAe,aAAa,QAAQ;EAE1C,SAAS,YAAwD;GAC/D,OAAO,OAAO,aACZA,IAA8B,SAAS,QAAQ,GAC/C,EAAE,MAAM,kBAAkB,CAC5B,CAAC,CAAC,WAAW,UAAU;IACrB,OAAO,iBAAiB,MAAM,OAC1B,OAAO,GAAG,MAAM,IAAI,IACpB,OAAO,IAAI;KAAE,MAAM;KAAe;IAAM,CAAC;GAC/C,CAAC;EACH;EAEA,eAAe,UACb,OACA,aAAa,
|
|
1
|
+
{"version":3,"file":"metadata-cache.js","names":["packageCache.get","packageCache.set"],"sources":["../../../../lib/modules/datasource/rubygems/metadata-cache.ts"],"sourcesContent":["import { logger } from '../../../logger/index.ts';\nimport * as packageCache from '../../../util/cache/package/index.ts';\nimport { toSha256 } from '../../../util/hash.ts';\nimport type { Http } from '../../../util/http/index.ts';\nimport type { AsyncResult } from '../../../util/result.ts';\nimport { Result } from '../../../util/result.ts';\nimport { parseUrl } from '../../../util/url.ts';\nimport type { ReleaseResult } from '../types.ts';\nimport { getV1Releases } from './common.ts';\n\ninterface CacheRecord {\n hash: string;\n data: ReleaseResult;\n isFallback?: true;\n}\n\nfunction hashVersions(versions: string[]): string {\n return toSha256(versions.sort().join(','));\n}\n\nfunction hashReleases(releases: ReleaseResult): string {\n return hashVersions(releases.releases.map((release) => release.version));\n}\n\ninterface CacheNotFoundError {\n type: 'cache-not-found';\n}\ninterface CacheStaleError {\n type: 'cache-stale';\n cache: CacheRecord;\n}\ninterface CacheInvalidError {\n type: 'cache-invalid';\n}\ntype CacheLoadError = CacheNotFoundError | CacheStaleError;\ntype CacheError = CacheNotFoundError | CacheStaleError | CacheInvalidError;\n\nexport class MetadataCache {\n private readonly http: Http;\n\n constructor(http: Http) {\n this.http = http;\n }\n\n async getRelease(\n registryUrl: string,\n packageName: string,\n versions: string[],\n ): Promise<ReleaseResult> {\n const cacheNs = `datasource-rubygems`;\n const cacheKey = `metadata-cache:${registryUrl}:${packageName}`;\n const versionsHash = hashVersions(versions);\n\n function loadCache(): AsyncResult<ReleaseResult, CacheLoadError> {\n return Result.wrapNullable<CacheRecord, CacheLoadError, CacheLoadError>(\n packageCache.get<CacheRecord>(cacheNs, cacheKey),\n { type: 'cache-not-found' },\n ).transform((cache) => {\n return versionsHash === cache.hash\n ? Result.ok(cache.data)\n : Result.err({ type: 'cache-stale', cache });\n });\n }\n\n async function saveCache(\n cache: CacheRecord,\n ttlMinutes = 100 * 24 * 60,\n ttlDelta = 10 * 24 * 60,\n ): Promise<void> {\n const registryHostname = parseUrl(registryUrl)?.hostname;\n if (registryHostname === 'rubygems.org') {\n const ttlRandomDelta = Math.floor(Math.random() * ttlDelta);\n const ttl = ttlMinutes + ttlRandomDelta;\n await packageCache.set(cacheNs, cacheKey, cache, ttl);\n }\n }\n\n return await loadCache()\n .catch((err) =>\n getV1Releases(this.http, registryUrl, packageName).transform(\n async (\n data: ReleaseResult,\n ): Promise<Result<ReleaseResult, CacheError>> => {\n const dataHash = hashReleases(data);\n if (dataHash === versionsHash) {\n await saveCache({\n hash: dataHash,\n data,\n });\n return Result.ok(data);\n }\n\n /**\n * Return stale cache for 24 hours,\n * if metadata is inconsistent with versions list.\n */\n if (err.type === 'cache-stale') {\n const staleCache = err.cache;\n if (!staleCache.isFallback) {\n await saveCache(\n { ...staleCache, isFallback: true },\n 24 * 60,\n 0,\n );\n }\n return Result.ok(staleCache.data);\n }\n\n return Result.err({ type: 'cache-invalid' });\n },\n ),\n )\n .catch((err) => {\n logger.debug(\n { err },\n 'Rubygems: error fetching rubygems data, falling back to versions-only result',\n );\n const releases = versions.map((version) => ({ version }));\n return Result.ok({ releases });\n })\n .unwrapOrThrow();\n }\n}\n"],"mappings":";;;;;;;AAgBA,SAAS,aAAa,UAA4B;CAChD,OAAO,SAAS,SAAS,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC;AAC3C;AAEA,SAAS,aAAa,UAAiC;CACrD,OAAO,aAAa,SAAS,SAAS,KAAK,YAAY,QAAQ,OAAO,CAAC;AACzE;AAeA,IAAa,gBAAb,MAA2B;CACzB;CAEA,YAAY,MAAY;EACtB,KAAK,OAAO;CACd;CAEA,MAAM,WACJ,aACA,aACA,UACwB;EACxB,MAAM,UAAU;EAChB,MAAM,WAAW,kBAAkB,YAAY,GAAG;EAClD,MAAM,eAAe,aAAa,QAAQ;EAE1C,SAAS,YAAwD;GAC/D,OAAO,OAAO,aACZA,IAA8B,SAAS,QAAQ,GAC/C,EAAE,MAAM,kBAAkB,CAC5B,CAAC,CAAC,WAAW,UAAU;IACrB,OAAO,iBAAiB,MAAM,OAC1B,OAAO,GAAG,MAAM,IAAI,IACpB,OAAO,IAAI;KAAE,MAAM;KAAe;IAAM,CAAC;GAC/C,CAAC;EACH;EAEA,eAAe,UACb,OACA,aAAa,OACb,WAAW,OACI;GAEf,IADyB,SAAS,WAAW,CAAC,EAAE,aACvB,gBAAgB;IAEvC,MAAM,MAAM,aADW,KAAK,MAAM,KAAK,OAAO,IAAI,QACZ;IACtC,MAAMC,IAAiB,SAAS,UAAU,OAAO,GAAG;GACtD;EACF;EAEA,OAAO,MAAM,UAAU,CAAC,CACrB,OAAO,QACN,cAAc,KAAK,MAAM,aAAa,WAAW,CAAC,CAAC,UACjD,OACE,SAC+C;GAC/C,MAAM,WAAW,aAAa,IAAI;GAClC,IAAI,aAAa,cAAc;IAC7B,MAAM,UAAU;KACd,MAAM;KACN;IACF,CAAC;IACD,OAAO,OAAO,GAAG,IAAI;GACvB;;;;;GAMA,IAAI,IAAI,SAAS,eAAe;IAC9B,MAAM,aAAa,IAAI;IACvB,IAAI,CAAC,WAAW,YACd,MAAM,UACJ;KAAE,GAAG;KAAY,YAAY;IAAK,GAClC,MACA,CACF;IAEF,OAAO,OAAO,GAAG,WAAW,IAAI;GAClC;GAEA,OAAO,OAAO,IAAI,EAAE,MAAM,gBAAgB,CAAC;EAC7C,CACF,CACF,CAAC,CACA,OAAO,QAAQ;GACd,OAAO,MACL,EAAE,IAAI,GACN,8EACF;GACA,MAAM,WAAW,SAAS,KAAK,aAAa,EAAE,QAAQ,EAAE;GACxD,OAAO,OAAO,GAAG,EAAE,SAAS,CAAC;EAC/B,CAAC,CAAC,CACD,cAAc;CACnB;AACF"}
|