dependabot-bun 0.296.2 → 0.296.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/.eslintrc +11 -0
  3. data/helpers/README.md +29 -0
  4. data/helpers/build +26 -0
  5. data/helpers/jest.config.js +5 -0
  6. data/helpers/lib/npm/conflicting-dependency-parser.js +78 -0
  7. data/helpers/lib/npm/index.js +9 -0
  8. data/helpers/lib/npm/vulnerability-auditor.js +291 -0
  9. data/helpers/lib/npm6/helpers.js +25 -0
  10. data/helpers/lib/npm6/index.js +9 -0
  11. data/helpers/lib/npm6/peer-dependency-checker.js +111 -0
  12. data/helpers/lib/npm6/remove-dependencies-from-lockfile.js +22 -0
  13. data/helpers/lib/npm6/subdependency-updater.js +78 -0
  14. data/helpers/lib/npm6/updater.js +199 -0
  15. data/helpers/lib/pnpm/index.js +5 -0
  16. data/helpers/lib/pnpm/lockfile-parser.js +82 -0
  17. data/helpers/lib/yarn/conflicting-dependency-parser.js +176 -0
  18. data/helpers/lib/yarn/fix-duplicates.js +80 -0
  19. data/helpers/lib/yarn/helpers.js +54 -0
  20. data/helpers/lib/yarn/index.js +14 -0
  21. data/helpers/lib/yarn/lockfile-parser.js +21 -0
  22. data/helpers/lib/yarn/peer-dependency-checker.js +132 -0
  23. data/helpers/lib/yarn/replace-lockfile-declaration.js +57 -0
  24. data/helpers/lib/yarn/subdependency-updater.js +83 -0
  25. data/helpers/lib/yarn/updater.js +209 -0
  26. data/helpers/package-lock.json +28519 -0
  27. data/helpers/package.json +29 -0
  28. data/helpers/patches/npm++pacote+9.5.12.patch +14 -0
  29. data/helpers/run.js +30 -0
  30. data/helpers/test/npm6/conflicting-dependency-parser.test.js +66 -0
  31. data/helpers/test/npm6/fixtures/conflicting-dependency-parser/deeply-nested/package-lock.json +591 -0
  32. data/helpers/test/npm6/fixtures/conflicting-dependency-parser/deeply-nested/package.json +14 -0
  33. data/helpers/test/npm6/fixtures/conflicting-dependency-parser/nested/package-lock.json +188 -0
  34. data/helpers/test/npm6/fixtures/conflicting-dependency-parser/nested/package.json +14 -0
  35. data/helpers/test/npm6/fixtures/conflicting-dependency-parser/simple/package-lock.json +27 -0
  36. data/helpers/test/npm6/fixtures/conflicting-dependency-parser/simple/package.json +14 -0
  37. data/helpers/test/npm6/fixtures/updater/original/package-lock.json +16 -0
  38. data/helpers/test/npm6/fixtures/updater/original/package.json +9 -0
  39. data/helpers/test/npm6/fixtures/updater/updated/package-lock.json +16 -0
  40. data/helpers/test/npm6/helpers.js +21 -0
  41. data/helpers/test/npm6/updater.test.js +30 -0
  42. data/helpers/test/pnpm/fixtures/parser/empty_version/pnpm-lock.yaml +72 -0
  43. data/helpers/test/pnpm/fixtures/parser/no_lockfile_change/pnpm-lock.yaml +2744 -0
  44. data/helpers/test/pnpm/fixtures/parser/only_dev_dependencies/pnpm-lock.yaml +16 -0
  45. data/helpers/test/pnpm/fixtures/parser/peer_disambiguation/pnpm-lock.yaml +855 -0
  46. data/helpers/test/pnpm/lockfile-parser.test.js +62 -0
  47. data/helpers/test/yarn/conflicting-dependency-parser.test.js +83 -0
  48. data/helpers/test/yarn/fixtures/conflicting-dependency-parser/deeply-nested/package.json +14 -0
  49. data/helpers/test/yarn/fixtures/conflicting-dependency-parser/deeply-nested/yarn.lock +496 -0
  50. data/helpers/test/yarn/fixtures/conflicting-dependency-parser/dev-dependencies/package.json +14 -0
  51. data/helpers/test/yarn/fixtures/conflicting-dependency-parser/dev-dependencies/yarn.lock +21 -0
  52. data/helpers/test/yarn/fixtures/conflicting-dependency-parser/nested/package.json +14 -0
  53. data/helpers/test/yarn/fixtures/conflicting-dependency-parser/nested/yarn.lock +183 -0
  54. data/helpers/test/yarn/fixtures/conflicting-dependency-parser/simple/package.json +14 -0
  55. data/helpers/test/yarn/fixtures/conflicting-dependency-parser/simple/yarn.lock +21 -0
  56. data/helpers/test/yarn/fixtures/updater/illegal_character/package.json +8 -0
  57. data/helpers/test/yarn/fixtures/updater/illegal_character/yarn.lock +14 -0
  58. data/helpers/test/yarn/fixtures/updater/original/package.json +6 -0
  59. data/helpers/test/yarn/fixtures/updater/original/yarn.lock +11 -0
  60. data/helpers/test/yarn/fixtures/updater/updated/yarn.lock +12 -0
  61. data/helpers/test/yarn/fixtures/updater/with-version-comments/package.json +5 -0
  62. data/helpers/test/yarn/fixtures/updater/with-version-comments/yarn.lock +13 -0
  63. data/helpers/test/yarn/helpers.js +18 -0
  64. data/helpers/test/yarn/updater.test.js +117 -0
  65. data/lib/dependabot/bun/bun_package_manager.rb +47 -0
  66. data/lib/dependabot/bun/constraint_helper.rb +359 -0
  67. data/lib/dependabot/bun/dependency_files_filterer.rb +157 -0
  68. data/lib/dependabot/bun/file_fetcher/path_dependency_builder.rb +184 -0
  69. data/lib/dependabot/bun/file_fetcher.rb +402 -0
  70. data/lib/dependabot/bun/file_parser/bun_lock.rb +140 -0
  71. data/lib/dependabot/bun/file_parser/lockfile_parser.rb +105 -0
  72. data/lib/dependabot/bun/file_parser.rb +477 -0
  73. data/lib/dependabot/bun/file_updater/bun_lockfile_updater.rb +144 -0
  74. data/lib/dependabot/bun/file_updater/npmrc_builder.rb +256 -0
  75. data/lib/dependabot/bun/file_updater/package_json_preparer.rb +88 -0
  76. data/lib/dependabot/bun/file_updater/package_json_updater.rb +378 -0
  77. data/lib/dependabot/bun/file_updater.rb +203 -0
  78. data/lib/dependabot/bun/helpers.rb +93 -0
  79. data/lib/dependabot/bun/language.rb +45 -0
  80. data/lib/dependabot/bun/metadata_finder.rb +214 -0
  81. data/lib/dependabot/bun/native_helpers.rb +19 -0
  82. data/lib/dependabot/bun/package_manager.rb +280 -0
  83. data/lib/dependabot/bun/package_name.rb +118 -0
  84. data/lib/dependabot/bun/pnpm_package_manager.rb +55 -0
  85. data/lib/dependabot/bun/registry_helper.rb +188 -0
  86. data/lib/dependabot/bun/registry_parser.rb +93 -0
  87. data/lib/dependabot/bun/requirement.rb +146 -0
  88. data/lib/dependabot/bun/sub_dependency_files_filterer.rb +82 -0
  89. data/lib/dependabot/bun/update_checker/conflicting_dependency_resolver.rb +59 -0
  90. data/lib/dependabot/bun/update_checker/dependency_files_builder.rb +79 -0
  91. data/lib/dependabot/bun/update_checker/latest_version_finder.rb +448 -0
  92. data/lib/dependabot/bun/update_checker/library_detector.rb +76 -0
  93. data/lib/dependabot/bun/update_checker/registry_finder.rb +279 -0
  94. data/lib/dependabot/bun/update_checker/requirements_updater.rb +206 -0
  95. data/lib/dependabot/bun/update_checker/subdependency_version_resolver.rb +154 -0
  96. data/lib/dependabot/bun/update_checker/version_resolver.rb +583 -0
  97. data/lib/dependabot/bun/update_checker/vulnerability_auditor.rb +164 -0
  98. data/lib/dependabot/bun/update_checker.rb +455 -0
  99. data/lib/dependabot/bun/version.rb +138 -0
  100. data/lib/dependabot/bun/version_selector.rb +61 -0
  101. data/lib/dependabot/bun.rb +337 -35
  102. metadata +108 -65
  103. data/lib/dependabot/javascript/bun/file_fetcher.rb +0 -77
  104. data/lib/dependabot/javascript/bun/file_parser/bun_lock.rb +0 -156
  105. data/lib/dependabot/javascript/bun/file_parser/lockfile_parser.rb +0 -55
  106. data/lib/dependabot/javascript/bun/file_parser.rb +0 -74
  107. data/lib/dependabot/javascript/bun/file_updater/lockfile_updater.rb +0 -138
  108. data/lib/dependabot/javascript/bun/file_updater.rb +0 -75
  109. data/lib/dependabot/javascript/bun/helpers.rb +0 -72
  110. data/lib/dependabot/javascript/bun/package_manager.rb +0 -48
  111. data/lib/dependabot/javascript/bun/requirement.rb +0 -11
  112. data/lib/dependabot/javascript/bun/update_checker/conflicting_dependency_resolver.rb +0 -64
  113. data/lib/dependabot/javascript/bun/update_checker/dependency_files_builder.rb +0 -47
  114. data/lib/dependabot/javascript/bun/update_checker/latest_version_finder.rb +0 -450
  115. data/lib/dependabot/javascript/bun/update_checker/library_detector.rb +0 -76
  116. data/lib/dependabot/javascript/bun/update_checker/requirements_updater.rb +0 -203
  117. data/lib/dependabot/javascript/bun/update_checker/subdependency_version_resolver.rb +0 -144
  118. data/lib/dependabot/javascript/bun/update_checker/version_resolver.rb +0 -525
  119. data/lib/dependabot/javascript/bun/update_checker/vulnerability_auditor.rb +0 -165
  120. data/lib/dependabot/javascript/bun/update_checker.rb +0 -440
  121. data/lib/dependabot/javascript/bun/version.rb +0 -11
  122. data/lib/dependabot/javascript/shared/constraint_helper.rb +0 -359
  123. data/lib/dependabot/javascript/shared/dependency_files_filterer.rb +0 -164
  124. data/lib/dependabot/javascript/shared/file_fetcher.rb +0 -283
  125. data/lib/dependabot/javascript/shared/file_parser/lockfile_parser.rb +0 -106
  126. data/lib/dependabot/javascript/shared/file_parser.rb +0 -454
  127. data/lib/dependabot/javascript/shared/file_updater/npmrc_builder.rb +0 -394
  128. data/lib/dependabot/javascript/shared/file_updater/package_json_preparer.rb +0 -87
  129. data/lib/dependabot/javascript/shared/file_updater/package_json_updater.rb +0 -376
  130. data/lib/dependabot/javascript/shared/file_updater.rb +0 -179
  131. data/lib/dependabot/javascript/shared/language.rb +0 -45
  132. data/lib/dependabot/javascript/shared/metadata_finder.rb +0 -209
  133. data/lib/dependabot/javascript/shared/native_helpers.rb +0 -21
  134. data/lib/dependabot/javascript/shared/package_manager_detector.rb +0 -72
  135. data/lib/dependabot/javascript/shared/package_name.rb +0 -118
  136. data/lib/dependabot/javascript/shared/registry_helper.rb +0 -190
  137. data/lib/dependabot/javascript/shared/registry_parser.rb +0 -93
  138. data/lib/dependabot/javascript/shared/requirement.rb +0 -144
  139. data/lib/dependabot/javascript/shared/sub_dependency_files_filterer.rb +0 -79
  140. data/lib/dependabot/javascript/shared/update_checker/dependency_files_builder.rb +0 -87
  141. data/lib/dependabot/javascript/shared/update_checker/registry_finder.rb +0 -358
  142. data/lib/dependabot/javascript/shared/version.rb +0 -133
  143. data/lib/dependabot/javascript/shared/version_selector.rb +0 -60
  144. data/lib/dependabot/javascript.rb +0 -39
@@ -0,0 +1,138 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require "dependabot/version"
5
+ require "dependabot/utils"
6
+ require "sorbet-runtime"
7
+
8
+ # JavaScript pre-release versions use 1.0.1-rc1 syntax, which Gem::Version
9
+ # converts into 1.0.1.pre.rc1. We override the `to_s` method to stop that
10
+ # alteration.
11
+ #
12
+ # See https://semver.org/ for details of node's version syntax.
13
+
14
+ module Dependabot
15
+ module Bun
16
+ class Version < Dependabot::Version
17
+ extend T::Sig
18
+
19
+ sig { returns(T.nilable(String)) }
20
+ attr_reader :build_info
21
+
22
+ # These are possible npm versioning tags that can be used in place of a version.
23
+ # See https://docs.npmjs.com/cli/v10/commands/npm-dist-tag#purpose for more details.
24
+ VERSION_TAGS = T.let([
25
+ "alpha", # Alpha version, early testing phase
26
+ "beta", # Beta version, more stable than alpha
27
+ "canary", # Canary version, often used for cutting-edge builds
28
+ "dev", # Development version, ongoing development
29
+ "experimental", # Experimental version, unstable and new features
30
+ "latest", # Latest stable version, used by npm to identify the current version of a package
31
+ "legacy", # Legacy version, older version maintained for compatibility
32
+ "next", # Next version, used by some projects to identify the upcoming version
33
+ "nightly", # Nightly build, daily builds often including latest changes
34
+ "rc", # Release candidate, potential final version
35
+ "release", # General release version
36
+ "stable" # Stable version, thoroughly tested and stable
37
+ ].freeze.map(&:freeze), T::Array[String])
38
+
39
+ VERSION_PATTERN = T.let(Gem::Version::VERSION_PATTERN + '(\+[0-9a-zA-Z\-.]+)?', String)
40
+ ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})?\s*\z/
41
+
42
+ sig { override.params(version: VersionParameter).returns(T::Boolean) }
43
+ def self.correct?(version)
44
+ version = version.gsub(/^v/, "") if version.is_a?(String)
45
+
46
+ return false if version.nil?
47
+
48
+ version.to_s.match?(ANCHORED_VERSION_PATTERN)
49
+ end
50
+
51
+ sig { params(version: VersionParameter).returns(VersionParameter) }
52
+ def self.semver_for(version)
53
+ # The next two lines are to guard against improperly formatted
54
+ # versions in a lockfile, such as an empty string or additional
55
+ # characters. NPM/yarn fixes these when running an update, so we can
56
+ # safely ignore these versions.
57
+ return if version == ""
58
+ return unless correct?(version)
59
+
60
+ version
61
+ end
62
+
63
+ sig { override.params(version: VersionParameter).void }
64
+ def initialize(version)
65
+ version = clean_version(version)
66
+
67
+ @version_string = T.let(version.to_s, String)
68
+
69
+ @build_info = T.let(nil, T.nilable(String))
70
+
71
+ version, @build_info = version.to_s.split("+") if version.to_s.include?("+")
72
+
73
+ super(T.must(version))
74
+ end
75
+
76
+ sig { params(version: VersionParameter).returns(VersionParameter) }
77
+ def clean_version(version)
78
+ # Check if version is a string before attempting to match
79
+ if version.is_a?(String)
80
+ # Matches @ followed by x.y.z (digits separated by dots)
81
+ if (match = version.match(/@(\d+\.\d+\.\d+)/))
82
+ version = match[1] # Just "4.5.3"
83
+
84
+ # Extract version in case the output contains Corepack verbose data
85
+ elsif version.include?("Corepack")
86
+ version = T.must(T.must(version.tr("\n", " ").match(/(\d+\.\d+\.\d+)/))[-1])
87
+ end
88
+ version = version&.gsub(/^v/, "")
89
+ end
90
+
91
+ version
92
+ end
93
+
94
+ sig { override.params(version: VersionParameter).returns(Dependabot::Bun::Version) }
95
+ def self.new(version)
96
+ T.cast(super, Dependabot::Bun::Version)
97
+ end
98
+
99
+ sig { returns(Integer) }
100
+ def major
101
+ @major ||= T.let(segments[0].to_i, T.nilable(Integer))
102
+ end
103
+
104
+ sig { returns(Integer) }
105
+ def minor
106
+ @minor ||= T.let(segments[1].to_i, T.nilable(Integer))
107
+ end
108
+
109
+ sig { returns(Integer) }
110
+ def patch
111
+ @patch ||= T.let(segments[2].to_i, T.nilable(Integer))
112
+ end
113
+
114
+ sig { params(other: Dependabot::Bun::Version).returns(T::Boolean) }
115
+ def backwards_compatible_with?(other)
116
+ case major
117
+ when 0
118
+ self == other
119
+ else
120
+ major == other.major && minor >= other.minor
121
+ end
122
+ end
123
+
124
+ sig { override.returns(String) }
125
+ def to_s
126
+ @version_string
127
+ end
128
+
129
+ sig { override.returns(String) }
130
+ def inspect
131
+ "#<#{self.class} #{@version_string}>"
132
+ end
133
+ end
134
+ end
135
+ end
136
+
137
+ Dependabot::Utils
138
+ .register_version_class("bun", Dependabot::Bun::Version)
@@ -0,0 +1,61 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require "dependabot/shared_helpers"
5
+ require "dependabot/bun/constraint_helper"
6
+
7
+ module Dependabot
8
+ module Bun
9
+ class VersionSelector
10
+ extend T::Sig
11
+ extend T::Helpers
12
+
13
+ # For limited testing, allowing only specific versions defined in engines in package.json
14
+ # such as "20.8.7", "8.1.2", "8.21.2",
15
+ NODE_ENGINE_SUPPORTED_REGEX = /^\d+(?:\.\d+)*$/
16
+
17
+ # Sets up engine versions from the given manifest JSON.
18
+ #
19
+ # @param manifest_json [Hash] The manifest JSON containing version information.
20
+ # @param name [String] The engine name to match.
21
+ # @return [Hash] A hash with selected versions, if found.
22
+ sig do
23
+ params(
24
+ manifest_json: T::Hash[String, T.untyped],
25
+ name: String,
26
+ dependabot_versions: T.nilable(T::Array[Dependabot::Version])
27
+ )
28
+ .returns(T::Hash[Symbol, T.untyped])
29
+ end
30
+ def setup(manifest_json, name, dependabot_versions = nil)
31
+ engine_versions = manifest_json["engines"]
32
+
33
+ # Return an empty hash if no engine versions are specified
34
+ return {} if engine_versions.nil?
35
+
36
+ versions = {}
37
+
38
+ if Dependabot::Experiments.enabled?(:enable_engine_version_detection)
39
+ engine_versions.each do |engine, value|
40
+ next unless engine.to_s.match(name)
41
+
42
+ versions[name] = ConstraintHelper.find_highest_version_from_constraint_expression(
43
+ value, dependabot_versions
44
+ )
45
+ end
46
+ else
47
+ versions = engine_versions.select do |engine, value|
48
+ engine.to_s.match(name) && valid_extracted_version?(value)
49
+ end
50
+ end
51
+
52
+ versions
53
+ end
54
+
55
+ sig { params(version: String).returns(T::Boolean) }
56
+ def valid_extracted_version?(version)
57
+ version.match?(NODE_ENGINE_SUPPORTED_REGEX)
58
+ end
59
+ end
60
+ end
61
+ end
@@ -1,49 +1,351 @@
1
- # typed: strong
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- require "zeitwerk"
4
+ # These all need to be required so the various classes can be registered in a
5
+ # lookup table of package manager names to concrete classes.
6
+ require "dependabot/bun/file_fetcher"
7
+ require "dependabot/bun/file_parser"
8
+ require "dependabot/bun/update_checker"
9
+ require "dependabot/bun/file_updater"
10
+ require "dependabot/bun/metadata_finder"
11
+ require "dependabot/bun/requirement"
12
+ require "dependabot/bun/version"
5
13
 
6
- loader = Zeitwerk::Loader.new
14
+ require "dependabot/pull_request_creator/labeler"
15
+ Dependabot::PullRequestCreator::Labeler
16
+ .register_label_details("bun", name: "javascript", colour: "168700")
7
17
 
8
- # Set autoload paths for common/lib, excluding files whose content does not match the filename
9
- loader.push_dir(File.join(__dir__, "../../../common/lib"))
10
- loader.ignore(File.join(__dir__, "../../../common/lib/dependabot/errors.rb"))
11
- loader.ignore(File.join(__dir__, "../../../common/lib/dependabot/logger.rb"))
12
- loader.ignore(File.join(__dir__, "../../../common/lib/dependabot/notices.rb"))
13
- loader.ignore(File.join(__dir__, "../../../common/lib/dependabot/clients/codecommit.rb"))
18
+ require "dependabot/dependency"
19
+ Dependabot::Dependency.register_production_check(
20
+ "bun",
21
+ lambda do |groups|
22
+ return true if groups.empty?
23
+ return true if groups.include?("optionalDependencies")
14
24
 
15
- loader.push_dir(File.join(__dir__, ".."))
16
- loader.ignore("#{__dir__}/../script", "#{__dir__}/../spec", "#{__dir__}/../dependabot-bun.gemspec")
25
+ groups.include?("dependencies")
26
+ end
27
+ )
17
28
 
18
- loader.on_load do |_file|
19
- require "json"
20
- require "sorbet-runtime"
21
- require "dependabot/errors"
22
- require "dependabot/logger"
23
- require "dependabot/notices"
24
- require "dependabot/clients/codecommit"
29
+ ## A type used for defining a proc that creates a new error object
30
+ ErrorHandler = T.type_alias do
31
+ T.proc
32
+ .params(message: String, error: Dependabot::DependabotError, params: T::Hash[Symbol, T.untyped])
33
+ .returns(Dependabot::DependabotError)
25
34
  end
26
35
 
27
- loader.log! if ENV["DEBUG"]
28
- loader.setup
36
+ module Dependabot
37
+ module Bun
38
+ NODE_VERSION_NOT_SATISFY_REGEX = /The current Node version (?<current_version>v?\d+\.\d+\.\d+) does not satisfy the required version (?<required_version>v?\d+\.\d+\.\d+)\./ # rubocop:disable Layout/LineLength
29
39
 
30
- Dependabot::PullRequestCreator::Labeler
31
- .register_label_details("bun", name: "javascript", colour: "168700")
40
+ # Used to check if package manager registry is public npm registry
41
+ NPM_REGISTRY = "registry.npmjs.org"
32
42
 
33
- Dependabot::Dependency.register_production_check("bun", ->(_) { true })
43
+ # Used to check if url is http or https
44
+ HTTP_CHECK_REGEX = %r{https?://}
34
45
 
35
- module Dependabot
36
- module Javascript
37
- module Bun
38
- ECOSYSTEM = "bun"
46
+ # Used to check capture url match in regex capture group
47
+ URL_CAPTURE = "url"
48
+
49
+ # When package name contains package.json name cannot contain characters like empty string or @.
50
+ INVALID_NAME_IN_PACKAGE_JSON = "Name contains illegal characters"
51
+
52
+ # Used to identify error messages indicating a package is missing, unreachable,
53
+ # or there are network issues (e.g., ENOBUFS, ETIMEDOUT, registry down).
54
+ PACKAGE_MISSING_REGEX = /(ENOBUFS|ETIMEDOUT|The registry may be down)/
55
+
56
+ # Used to check if error message contains timeout fetching package
57
+ TIMEOUT_FETCHING_PACKAGE_REGEX = %r{(?<url>.+)/(?<package>[^/]+): ETIMEDOUT}
58
+
59
+ ESOCKETTIMEDOUT = /(?<package>.*?): ESOCKETTIMEDOUT/
60
+
61
+ SOCKET_HANG_UP = /(?<url>.*?): socket hang up/
62
+
63
+ # Misc errors
64
+ EEXIST = /EEXIST: file already exists, mkdir '(?<regis>.*)'/
65
+
66
+ # registry access errors
67
+ REQUEST_ERROR_E403 = /Request "(?<url>.*)" returned a 403/ # Forbidden access to the URL.
68
+ AUTH_REQUIRED_ERROR = /(?<url>.*): authentication required/ # Authentication is required for the URL.
69
+ PERMISSION_DENIED = /(?<url>.*): Permission denied/ # Lack of permission to access the URL.
70
+ BAD_REQUEST = /(?<url>.*): bad_request/ # Inconsistent request while accessing resource.
71
+ INTERNAL_SERVER_ERROR = /Request failed "500 Internal Server Error"/ # Server error response by remote registry.
72
+
73
+ # Used to identify git unreachable error
74
+ UNREACHABLE_GIT_CHECK_REGEX = /ls-remote --tags --heads (?<url>.*)/
75
+
76
+ # Used to check if yarn workspace is enabled in non-private workspace
77
+ ONLY_PRIVATE_WORKSPACE_TEXT = "Workspaces can only be enabled in priva"
78
+
79
+ # Used to identify local path error in yarn when installing sub-dependency
80
+ SUB_DEP_LOCAL_PATH_TEXT = "refers to a non-existing file"
81
+
82
+ # Used to identify invalid package error when package is not found in registry
83
+ INVALID_PACKAGE_REGEX = /Can't add "[\w\-.]+": invalid/
84
+
85
+ # Used to identify error if package not found in registry
86
+ PACKAGE_NOT_FOUND = "Couldn't find package"
87
+ PACKAGE_NOT_FOUND_PACKAGE_NAME_REGEX = /package "(?<package_req>.*?)"/
88
+ PACKAGE_NOT_FOUND_PACKAGE_NAME_CAPTURE = "package_req"
89
+ PACKAGE_NOT_FOUND_PACKAGE_NAME_CAPTURE_SPLIT_REGEX = /(?<=\w)\@/
90
+
91
+ YARN_PACKAGE_NOT_FOUND_CODE = /npm package "(?<dep>.*)" does not exist under owner "(?<regis>.*)"/
92
+ YARN_PACKAGE_NOT_FOUND_CODE_1 = /Couldn't find package "[^@].*(?<dep>.*)" on the "(?<regis>.*)" registry./
93
+ YARN_PACKAGE_NOT_FOUND_CODE_2 = /Couldn't find package "[^@].*(?<dep>.*)" required by "(?<pkg>.*)" on the "(?<regis>.*)" registry./ # rubocop:disable Layout/LineLength
94
+
95
+ PACKAGE_NOT_FOUND2 = %r{/[^/]+: Not found}
96
+ PACKAGE_NOT_FOUND2_PACKAGE_NAME_REGEX = %r{/(?<package_name>[^/]+): Not found}
97
+ PACKAGE_NOT_FOUND2_PACKAGE_NAME_CAPTURE = "package_name"
98
+
99
+ # Used to identify error if package not found in registry
100
+ DEPENDENCY_VERSION_NOT_FOUND = "Couldn't find any versions"
101
+ DEPENDENCY_NOT_FOUND = ": Not found"
102
+ DEPENDENCY_MATCH_NOT_FOUND = "Couldn't find match for"
103
+
104
+ DEPENDENCY_NO_VERSION_FOUND = "Couldn't find any versions"
105
+
106
+ # Manifest not found
107
+ MANIFEST_NOT_FOUND = /Cannot read properties of undefined \(reading '(?<file>.*)'\)/
108
+
109
+ # Used to identify error if node_modules state file not resolved
110
+ NODE_MODULES_STATE_FILE_NOT_FOUND = "Couldn't find the node_modules state file"
111
+
112
+ # Used to find error message in yarn error output
113
+ YARN_USAGE_ERROR_TEXT = "Usage Error:"
114
+
115
+ # Used to identify error if tarball is not in network
116
+ TARBALL_IS_NOT_IN_NETWORK = "Tarball is not in network and can not be located in cache"
117
+
118
+ # Used to identify if authentication failure error
119
+ AUTHENTICATION_TOKEN_NOT_PROVIDED = "authentication token not provided"
120
+ AUTHENTICATION_IS_NOT_CONFIGURED = "No authentication configured for request"
121
+ AUTHENTICATION_HEADER_NOT_PROVIDED = "Unauthenticated: request did not include an Authorization header."
122
+
123
+ # Used to identify if error message is related to yarn workspaces
124
+ DEPENDENCY_FILE_NOT_RESOLVABLE = "conflicts with direct dependency"
125
+
126
+ ENV_VAR_NOT_RESOLVABLE = /Failed to replace env in config: \$\{(?<var>.*)\}/
127
+
128
+ OUT_OF_DISKSPACE = / Out of diskspace/
129
+
130
+ # registry returns malformed response
131
+ REGISTRY_NOT_REACHABLE = /Received malformed response from registry for "(?<ver>.*)". The registry may be down./
132
+
133
+ class Utils
134
+ extend T::Sig
135
+
136
+ sig { params(error_message: String).returns(T::Hash[Symbol, String]) }
137
+ def self.extract_node_versions(error_message)
138
+ match_data = error_message.match(NODE_VERSION_NOT_SATISFY_REGEX)
139
+ return {} unless match_data
140
+
141
+ {
142
+ current_version: match_data[:current_version],
143
+ required_version: match_data[:required_version]
144
+ }
145
+ end
146
+
147
+ sig { params(error_message: String).returns(String) }
148
+ def self.extract_var(error_message)
149
+ match_data = T.must(error_message.match(ENV_VAR_NOT_RESOLVABLE)).named_captures["var"]
150
+ return "" unless match_data
151
+
152
+ match_data
153
+ end
154
+
155
+ sig do
156
+ params(
157
+ error_message: String,
158
+ dependencies: T::Array[Dependabot::Dependency],
159
+ yarn_lock: Dependabot::DependencyFile
160
+ ).returns(String)
161
+ end
162
+ def self.sanitize_resolvability_message(error_message, dependencies, yarn_lock)
163
+ dependency_names = dependencies.map(&:name).join(", ")
164
+ "Error whilst updating #{dependency_names} in #{yarn_lock.path}:\n#{error_message}"
165
+ end
39
166
  end
167
+
168
+ # Group of patterns to validate error message and raise specific error
169
+ VALIDATION_GROUP_PATTERNS = T.let([
170
+ {
171
+ patterns: [INVALID_NAME_IN_PACKAGE_JSON],
172
+ handler: lambda { |message, _error, _params|
173
+ Dependabot::DependencyFileNotResolvable.new(message)
174
+ },
175
+ in_usage: false,
176
+ matchfn: nil
177
+ },
178
+ {
179
+ # Check if sub dependency is using local path and raise a resolvability error
180
+ patterns: [INVALID_PACKAGE_REGEX, SUB_DEP_LOCAL_PATH_TEXT],
181
+ handler: lambda { |message, _error, params|
182
+ Dependabot::DependencyFileNotResolvable.new(
183
+ Utils.sanitize_resolvability_message(
184
+ message,
185
+ params[:dependencies],
186
+ params[:yarn_lock]
187
+ )
188
+ )
189
+ },
190
+ in_usage: false,
191
+ matchfn: nil
192
+ },
193
+ {
194
+ patterns: [NODE_MODULES_STATE_FILE_NOT_FOUND],
195
+ handler: lambda { |message, _error, _params|
196
+ Dependabot::MisconfiguredTooling.new("Yarn", message)
197
+ },
198
+ in_usage: true,
199
+ matchfn: nil
200
+ },
201
+ {
202
+ patterns: [TARBALL_IS_NOT_IN_NETWORK],
203
+ handler: lambda { |message, _error, _params|
204
+ Dependabot::DependencyFileNotResolvable.new(message)
205
+ },
206
+ in_usage: false,
207
+ matchfn: nil
208
+ },
209
+ {
210
+ patterns: [NODE_VERSION_NOT_SATISFY_REGEX],
211
+ handler: lambda { |message, _error, _params|
212
+ versions = Utils.extract_node_versions(message)
213
+ current_version = versions[:current_version]
214
+ required_version = versions[:required_version]
215
+
216
+ return Dependabot::DependabotError.new(message) unless current_version && required_version
217
+
218
+ Dependabot::ToolVersionNotSupported.new("Yarn", current_version, required_version)
219
+ },
220
+ in_usage: false,
221
+ matchfn: nil
222
+ },
223
+ {
224
+ patterns: [AUTHENTICATION_TOKEN_NOT_PROVIDED, AUTHENTICATION_IS_NOT_CONFIGURED,
225
+ AUTHENTICATION_HEADER_NOT_PROVIDED],
226
+ handler: lambda { |message, _error, _params|
227
+ Dependabot::PrivateSourceAuthenticationFailure.new(message)
228
+ },
229
+ in_usage: false,
230
+ matchfn: nil
231
+ },
232
+ {
233
+ patterns: [DEPENDENCY_FILE_NOT_RESOLVABLE],
234
+ handler: lambda { |message, _error, _params|
235
+ DependencyFileNotResolvable.new(message)
236
+ },
237
+ in_usage: false,
238
+ matchfn: nil
239
+ },
240
+ {
241
+ patterns: [ENV_VAR_NOT_RESOLVABLE],
242
+ handler: lambda { |message, _error, _params|
243
+ var = Utils.extract_var(message)
244
+
245
+ Dependabot::MissingEnvironmentVariable.new(var, message)
246
+ },
247
+ in_usage: false,
248
+ matchfn: nil
249
+ },
250
+ {
251
+ patterns: [ONLY_PRIVATE_WORKSPACE_TEXT],
252
+ handler: lambda { |message, _error, _params|
253
+ Dependabot::DependencyFileNotEvaluatable.new(message)
254
+ },
255
+ in_usage: false,
256
+ matchfn: nil
257
+ },
258
+ {
259
+ patterns: [UNREACHABLE_GIT_CHECK_REGEX],
260
+ handler: lambda { |message, _error, _params|
261
+ dependency_url = message.match(UNREACHABLE_GIT_CHECK_REGEX).named_captures.fetch(URL_CAPTURE)
262
+
263
+ Dependabot::GitDependenciesNotReachable.new(dependency_url)
264
+ },
265
+ in_usage: false,
266
+ matchfn: nil
267
+ },
268
+ {
269
+ patterns: [SOCKET_HANG_UP],
270
+ handler: lambda { |message, _error, _params|
271
+ url = message.match(SOCKET_HANG_UP).named_captures.fetch(URL_CAPTURE)
272
+
273
+ Dependabot::PrivateSourceTimedOut.new(url.gsub(HTTP_CHECK_REGEX, ""))
274
+ },
275
+ in_usage: false,
276
+ matchfn: nil
277
+ },
278
+ {
279
+ patterns: [ESOCKETTIMEDOUT],
280
+ handler: lambda { |message, _error, _params|
281
+ package_req = message.match(ESOCKETTIMEDOUT).named_captures.fetch("package")
282
+
283
+ Dependabot::PrivateSourceTimedOut.new(package_req.gsub(HTTP_CHECK_REGEX, ""))
284
+ },
285
+ in_usage: false,
286
+ matchfn: nil
287
+ },
288
+ {
289
+ patterns: [OUT_OF_DISKSPACE],
290
+ handler: lambda { |message, _error, _params|
291
+ Dependabot::OutOfDisk.new(message)
292
+ },
293
+ in_usage: false,
294
+ matchfn: nil
295
+ },
296
+ {
297
+ patterns: [YARN_PACKAGE_NOT_FOUND_CODE, YARN_PACKAGE_NOT_FOUND_CODE_1, YARN_PACKAGE_NOT_FOUND_CODE_2],
298
+ handler: lambda { |message, _error, _params|
299
+ msg = message.match(YARN_PACKAGE_NOT_FOUND_CODE) || message.match(YARN_PACKAGE_NOT_FOUND_CODE_1) ||
300
+ message.match(YARN_PACKAGE_NOT_FOUND_CODE_2)
301
+
302
+ Dependabot::DependencyFileNotResolvable.new(msg)
303
+ },
304
+ in_usage: false,
305
+ matchfn: nil
306
+ },
307
+ {
308
+ patterns: [REQUEST_ERROR_E403, AUTH_REQUIRED_ERROR, PERMISSION_DENIED, BAD_REQUEST],
309
+ handler: lambda { |message, _error, _params|
310
+ dependency_url = T.must(URI.decode_www_form_component(message).split("https://").last).split("/").first
311
+
312
+ Dependabot::PrivateSourceAuthenticationFailure.new(dependency_url)
313
+ },
314
+ in_usage: false,
315
+ matchfn: nil
316
+ },
317
+ {
318
+ patterns: [MANIFEST_NOT_FOUND],
319
+ handler: lambda { |message, _error, _params|
320
+ msg = message.match(MANIFEST_NOT_FOUND)
321
+ Dependabot::DependencyFileNotResolvable.new(msg)
322
+ },
323
+ in_usage: false,
324
+ matchfn: nil
325
+ },
326
+ {
327
+ patterns: [INTERNAL_SERVER_ERROR],
328
+ handler: lambda { |message, _error, _params|
329
+ msg = message.match(INTERNAL_SERVER_ERROR)
330
+ Dependabot::DependencyFileNotResolvable.new(msg)
331
+ },
332
+ in_usage: false,
333
+ matchfn: nil
334
+ },
335
+ {
336
+ patterns: [REGISTRY_NOT_REACHABLE],
337
+ handler: lambda { |message, _error, _params|
338
+ msg = message.match(REGISTRY_NOT_REACHABLE)
339
+ Dependabot::DependencyFileNotResolvable.new(msg)
340
+ },
341
+ in_usage: false,
342
+ matchfn: nil
343
+ }
344
+ ].freeze, T::Array[{
345
+ patterns: T::Array[T.any(String, Regexp)],
346
+ handler: ErrorHandler,
347
+ in_usage: T.nilable(T::Boolean),
348
+ matchfn: T.nilable(T.proc.params(usage: String, message: String).returns(T::Boolean))
349
+ }])
40
350
  end
41
351
  end
42
-
43
- Dependabot::FileFetchers.register("bun", Dependabot::Javascript::Bun::FileFetcher)
44
- Dependabot::FileParsers.register("bun", Dependabot::Javascript::Bun::FileParser)
45
- Dependabot::FileUpdaters.register("bun", Dependabot::Javascript::Bun::FileUpdater)
46
- Dependabot::UpdateCheckers.register("bun", Dependabot::Javascript::Bun::UpdateChecker)
47
- Dependabot::MetadataFinders.register("bun", Dependabot::Javascript::Shared::MetadataFinder)
48
- Dependabot::Utils.register_requirement_class("bun", Dependabot::Javascript::Bun::Requirement)
49
- Dependabot::Utils.register_version_class("bun", Dependabot::Javascript::Bun::Version)