dependabot-npm_and_yarn 0.309.0 → 0.310.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 654bda07376dec9e868f07e36470b6cf1a972402825d7b1c38ac526b3ffe2c97
4
- data.tar.gz: 640ee97a0a8b68227d475b511866578ddbabc4300b65153f9d793e44816c3c8d
3
+ metadata.gz: 9a5cb78b6d6b57d7c62cd5ab60e63db0848277800d48ce32d3a6ea35d06955e9
4
+ data.tar.gz: 5180f0822f3bc3588db82562bc9273841651748b92a216aae5e94670e2efe916
5
5
  SHA512:
6
- metadata.gz: 7d90cf279e19ce426628c3f7296f5178794bafd7c8d681235aee2bbf6c7f7d7b1ff84483cc18f9faf47943b9ccab25bb77504977f458f3423a0e2101716b2ba6
7
- data.tar.gz: bf955d3e9b54a5b99de7a1d7bb8f4c03cdfd8efed54cbf06c19977e083cfe1f3a2e6f72b8b72fd42df3f8e382f5359c5e910c011a0ac0a85a15a13a1442701dc
6
+ metadata.gz: 53a449f37470153cd80797d0fa6e6a8f48eb2eb3908d89e9b3f2e0f6217ec2eeca704638022525c2b1454919ee439c17221dc707a288628f398d1a43a84fb3d3
7
+ data.tar.gz: 60886b10224dcb526953f150f591e814c5333be22747cad39c8b2bee03122b64b252b8846b580d83493de5d9bc0dbd3bb8a80efbb21cc65737eb24dd0da31ab7
@@ -1,42 +1,61 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
5
+
4
6
  require "dependabot/errors"
7
+ require "dependabot/dependency"
8
+ require "dependabot/file_parsers/base"
9
+ require "dependabot/npm_and_yarn/native_helpers"
10
+ require "dependabot/shared_helpers"
5
11
 
6
12
  module Dependabot
7
13
  module NpmAndYarn
8
14
  class FileParser < Dependabot::FileParsers::Base
9
15
  class PnpmLock
16
+ extend T::Sig
17
+
18
+ sig { params(dependency_file: Dependabot::DependencyFile).void }
10
19
  def initialize(dependency_file)
11
20
  @dependency_file = dependency_file
12
21
  end
13
22
 
23
+ sig { returns(T::Array[T::Hash[String, T.untyped]]) }
14
24
  def parsed
15
- @parsed ||= SharedHelpers.in_a_temporary_directory do
16
- File.write("pnpm-lock.yaml", @dependency_file.content)
17
-
18
- SharedHelpers.run_helper_subprocess(
19
- command: NativeHelpers.helper_path,
20
- function: "pnpm:parseLockfile",
21
- args: [Dir.pwd]
22
- )
23
- rescue SharedHelpers::HelperSubprocessFailed
24
- raise Dependabot::DependencyFileNotParseable, @dependency_file.path
25
- end
25
+ @parsed ||= T.let(
26
+ T.cast(
27
+ SharedHelpers.in_a_temporary_directory do
28
+ File.write("pnpm-lock.yaml", @dependency_file.content)
29
+
30
+ SharedHelpers.run_helper_subprocess(
31
+ command: NativeHelpers.helper_path,
32
+ function: "pnpm:parseLockfile",
33
+ args: [Dir.pwd]
34
+ )
35
+ rescue SharedHelpers::HelperSubprocessFailed
36
+ raise Dependabot::DependencyFileNotParseable, @dependency_file.path
37
+ end,
38
+ T::Array[T::Hash[String, T.untyped]]
39
+ ),
40
+ T.nilable(T::Array[T::Hash[String, T.untyped]])
41
+ )
26
42
  end
27
43
 
44
+ # rubocop:disable Metrics/MethodLength
45
+ # rubocop:disable Metrics/AbcSize
46
+ sig { returns(Dependabot::FileParsers::Base::DependencySet) }
28
47
  def dependencies
29
48
  dependency_set = Dependabot::FileParsers::Base::DependencySet.new
30
49
 
31
50
  # Separate dependencies into two categories: with specifiers and without specifiers.
32
- dependencies_with_specifiers = [] # Main dependencies with specifiers.
33
- dependencies_without_specifiers = [] # Subdependencies without specifiers.
51
+ dependencies_with_specifiers = T.let([], T::Array[T::Hash[Symbol, T.untyped]])
52
+ dependencies_without_specifiers = T.let([], T::Array[T::Hash[Symbol, T.untyped]])
34
53
 
35
54
  parsed.each do |details|
36
55
  next if details["aliased"]
37
56
 
38
- name = details["name"]
39
- version = details["version"]
57
+ name = T.cast(details["name"], String)
58
+ version = T.cast(details["version"], T.nilable(String))
40
59
 
41
60
  dependency_args = {
42
61
  name: name,
@@ -58,16 +77,38 @@ module Dependabot
58
77
 
59
78
  # Add prioritized dependencies to the dependency set.
60
79
  dependencies_with_specifiers.each do |dependency_args|
61
- dependency_set << Dependency.new(**dependency_args)
80
+ dependency_set << Dependency.new(
81
+ name: dependency_args[:name],
82
+ version: dependency_args[:version],
83
+ package_manager: dependency_args[:package_manager],
84
+ requirements: dependency_args[:requirements],
85
+ subdependency_metadata: dependency_args[:subdependency_metadata]
86
+ )
62
87
  end
63
88
 
64
89
  dependencies_without_specifiers.each do |dependency_args|
65
- dependency_set << Dependency.new(**dependency_args)
90
+ dependency_set << Dependency.new(
91
+ name: dependency_args[:name],
92
+ version: dependency_args[:version],
93
+ package_manager: dependency_args[:package_manager],
94
+ requirements: dependency_args[:requirements],
95
+ subdependency_metadata: dependency_args[:subdependency_metadata]
96
+ )
66
97
  end
67
98
 
68
99
  dependency_set
69
100
  end
70
-
101
+ # rubocop:enable Metrics/AbcSize
102
+ # rubocop:enable Metrics/MethodLength
103
+
104
+ sig do
105
+ params(
106
+ dependency_name: String,
107
+ requirement: T.nilable(String),
108
+ _manifest_name: T.nilable(String)
109
+ )
110
+ .returns(T.nilable(T::Hash[String, T.untyped]))
111
+ end
71
112
  def details(dependency_name, requirement, _manifest_name)
72
113
  details_candidates = parsed.select { |info| info["name"] == dependency_name }
73
114
 
@@ -1,4 +1,4 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/shared_helpers"
@@ -10,28 +10,39 @@ module Dependabot
10
10
  module NpmAndYarn
11
11
  class FileParser < Dependabot::FileParsers::Base
12
12
  class YarnLock
13
+ extend T::Sig
14
+
15
+ sig { params(dependency_file: Dependabot::DependencyFile).void }
13
16
  def initialize(dependency_file)
14
17
  @dependency_file = dependency_file
15
18
  end
16
19
 
20
+ sig { returns(T::Hash[String, T::Hash[String, T.untyped]]) }
17
21
  def parsed
18
- @parsed ||= SharedHelpers.in_a_temporary_directory do
19
- File.write("yarn.lock", @dependency_file.content)
22
+ @parsed ||= T.let(
23
+ T.cast(
24
+ SharedHelpers.in_a_temporary_directory do
25
+ File.write("yarn.lock", @dependency_file.content)
20
26
 
21
- SharedHelpers.run_helper_subprocess(
22
- command: NativeHelpers.helper_path,
23
- function: "yarn:parseLockfile",
24
- args: [Dir.pwd]
25
- )
26
- rescue SharedHelpers::HelperSubprocessFailed => e
27
- raise Dependabot::OutOfDisk, e.message if e.message.end_with?("No space left on device")
28
- raise Dependabot::OutOfDisk, e.message if e.message.end_with?("Out of diskspace")
29
- raise Dependabot::OutOfMemory, e.message if e.message.end_with?("MemoryError")
27
+ SharedHelpers.run_helper_subprocess(
28
+ command: NativeHelpers.helper_path,
29
+ function: "yarn:parseLockfile",
30
+ args: [Dir.pwd]
31
+ )
32
+ rescue SharedHelpers::HelperSubprocessFailed => e
33
+ raise Dependabot::OutOfDisk, e.message if e.message.end_with?("No space left on device")
34
+ raise Dependabot::OutOfDisk, e.message if e.message.end_with?("Out of diskspace")
35
+ raise Dependabot::OutOfMemory, e.message if e.message.end_with?("MemoryError")
30
36
 
31
- raise Dependabot::DependencyFileNotParseable, @dependency_file.path
32
- end
37
+ raise Dependabot::DependencyFileNotParseable, @dependency_file.path
38
+ end,
39
+ T::Hash[String, T::Hash[String, T.untyped]]
40
+ ),
41
+ T.nilable(T::Hash[String, T::Hash[String, T.untyped]])
42
+ )
33
43
  end
34
44
 
45
+ sig { returns(Dependabot::FileParsers::Base::DependencySet) }
35
46
  def dependencies
36
47
  dependency_set = Dependabot::FileParsers::Base::DependencySet.new
37
48
 
@@ -44,7 +55,7 @@ module Dependabot
44
55
  next if req == "__metadata"
45
56
 
46
57
  dependency_set << Dependency.new(
47
- name: req.split(/(?<=\w)\@/).first,
58
+ name: T.must(req.split(/(?<=\w)\@/).first),
48
59
  version: version.to_s,
49
60
  package_manager: "npm_and_yarn",
50
61
  requirements: []
@@ -55,6 +66,14 @@ module Dependabot
55
66
  dependency_set
56
67
  end
57
68
 
69
+ sig do
70
+ params(
71
+ dependency_name: String,
72
+ requirement: T.nilable(String),
73
+ _manifest_name: T.untyped
74
+ )
75
+ .returns(T.nilable(T::Hash[String, T.untyped]))
76
+ end
58
77
  def details(dependency_name, requirement, _manifest_name)
59
78
  details_candidates =
60
79
  parsed
@@ -63,7 +82,7 @@ module Dependabot
63
82
  # If there's only one entry for this dependency, use it, even if
64
83
  # the requirement in the lockfile doesn't match
65
84
  if details_candidates.one?
66
- details_candidates.first.last
85
+ T.must(details_candidates.first).last
67
86
  else
68
87
  details_candidates.find do |k, _|
69
88
  k.scan(/(?<=\w)\@(?:npm:)?([^\s,]+)/).flatten.include?(requirement)
@@ -73,10 +92,12 @@ module Dependabot
73
92
 
74
93
  private
75
94
 
95
+ sig { params(requirement: String).returns(T::Boolean) }
76
96
  def alias_package?(requirement)
77
97
  requirement.match?(/@npm:(.+@(?!npm))/)
78
98
  end
79
99
 
100
+ sig { params(requirement: String).returns(T::Boolean) }
80
101
  def workspace_package?(requirement)
81
102
  requirement.include?("@workspace:")
82
103
  end
@@ -1,6 +1,8 @@
1
- # typed: true
1
+ # typed: strong
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
5
+
4
6
  require "dependabot/npm_and_yarn/helpers"
5
7
  require "dependabot/npm_and_yarn/package/registry_finder"
6
8
  require "dependabot/npm_and_yarn/registry_parser"
@@ -10,9 +12,20 @@ module Dependabot
10
12
  module NpmAndYarn
11
13
  class FileUpdater < Dependabot::FileUpdaters::Base
12
14
  class BunLockfileUpdater
15
+ extend T::Sig
16
+
13
17
  require_relative "npmrc_builder"
14
18
  require_relative "package_json_updater"
15
19
 
20
+ sig do
21
+ params(
22
+ dependencies: T::Array[Dependabot::Dependency],
23
+ dependency_files: T::Array[Dependabot::DependencyFile],
24
+ repo_contents_path: String,
25
+ credentials: T::Array[Dependabot::Credential]
26
+ )
27
+ .void
28
+ end
16
29
  def initialize(dependencies:, dependency_files:, repo_contents_path:, credentials:)
17
30
  @dependencies = dependencies
18
31
  @dependency_files = dependency_files
@@ -20,9 +33,10 @@ module Dependabot
20
33
  @credentials = credentials
21
34
  end
22
35
 
36
+ sig { params(bun_lock: Dependabot::DependencyFile).returns(String) }
23
37
  def updated_bun_lock_content(bun_lock)
24
- @updated_bun_lock_content ||= {}
25
- return @updated_bun_lock_content[bun_lock.name] if @updated_bun_lock_content[bun_lock.name]
38
+ @updated_bun_lock_content ||= T.let({}, T.nilable(T::Hash[String, String]))
39
+ return T.must(@updated_bun_lock_content[bun_lock.name]) if @updated_bun_lock_content[bun_lock.name]
26
40
 
27
41
  new_content = run_bun_update(bun_lock: bun_lock)
28
42
  @updated_bun_lock_content[bun_lock.name] = new_content
@@ -32,19 +46,30 @@ module Dependabot
32
46
 
33
47
  private
34
48
 
49
+ sig { returns(T::Array[Dependabot::Dependency]) }
35
50
  attr_reader :dependencies
51
+
52
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
36
53
  attr_reader :dependency_files
54
+
55
+ sig { returns(String) }
37
56
  attr_reader :repo_contents_path
38
- attr_reader :credentials
39
57
 
40
- ERR_PATTERNS = {
41
- /get .* 404/i => Dependabot::DependencyNotFound,
42
- /installfailed cloning repository/i => Dependabot::DependencyNotFound,
43
- /file:.* failed to resolve/i => Dependabot::DependencyNotFound,
44
- /no version matching/i => Dependabot::DependencyFileNotResolvable,
45
- /failed to resolve/i => Dependabot::DependencyFileNotResolvable
46
- }.freeze
58
+ sig { returns(T::Array[Dependabot::Credential]) }
59
+ attr_reader :credentials
47
60
 
61
+ ERR_PATTERNS = T.let(
62
+ {
63
+ /get .* 404/i => Dependabot::DependencyNotFound,
64
+ /installfailed cloning repository/i => Dependabot::DependencyNotFound,
65
+ /file:.* failed to resolve/i => Dependabot::DependencyNotFound,
66
+ /no version matching/i => Dependabot::DependencyFileNotResolvable,
67
+ /failed to resolve/i => Dependabot::DependencyFileNotResolvable
68
+ }.freeze,
69
+ T::Hash[Regexp, Dependabot::DependabotError]
70
+ )
71
+
72
+ sig { params(bun_lock: Dependabot::DependencyFile).returns(String) }
48
73
  def run_bun_update(bun_lock:)
49
74
  SharedHelpers.in_a_temporary_repo_directory(base_dir, repo_contents_path) do
50
75
  File.write(".npmrc", npmrc_content(bun_lock))
@@ -61,6 +86,7 @@ module Dependabot
61
86
  end
62
87
  end
63
88
 
89
+ sig { void }
64
90
  def run_bun_updater
65
91
  dependency_updates = dependencies.map do |d|
66
92
  "#{d.name}@#{d.version}"
@@ -72,14 +98,16 @@ module Dependabot
72
98
  )
73
99
  end
74
100
 
101
+ sig { void }
75
102
  def run_bun_install
76
103
  Helpers.run_bun_command(
77
104
  "install --save-text-lockfile"
78
105
  )
79
106
  end
80
107
 
108
+ sig { params(lockfile: Dependabot::DependencyFile).returns(T::Array[Dependabot::Dependency]) }
81
109
  def lockfile_dependencies(lockfile)
82
- @lockfile_dependencies ||= {}
110
+ @lockfile_dependencies ||= T.let({}, T.nilable(T::Hash[String, T::Array[Dependabot::Dependency]]))
83
111
  @lockfile_dependencies[lockfile.name] ||=
84
112
  NpmAndYarn::FileParser.new(
85
113
  dependency_files: [lockfile, *package_files],
@@ -88,6 +116,7 @@ module Dependabot
88
116
  ).parse
89
117
  end
90
118
 
119
+ sig { params(error: Dependabot::DependabotError, _bun_lock: Dependabot::DependencyFile).returns(T.noreturn) }
91
120
  def handle_bun_lock_updater_error(error, _bun_lock)
92
121
  error_message = error.message
93
122
 
@@ -98,6 +127,7 @@ module Dependabot
98
127
  raise error
99
128
  end
100
129
 
130
+ sig { void }
101
131
  def write_final_package_json_files
102
132
  package_files.each do |file|
103
133
  path = file.name
@@ -106,6 +136,7 @@ module Dependabot
106
136
  end
107
137
  end
108
138
 
139
+ sig { params(bun_lock: Dependabot::DependencyFile).returns(String) }
109
140
  def npmrc_content(bun_lock)
110
141
  NpmrcBuilder.new(
111
142
  credentials: credentials,
@@ -114,27 +145,37 @@ module Dependabot
114
145
  ).npmrc_content
115
146
  end
116
147
 
148
+ sig { params(file: Dependabot::DependencyFile).returns(String) }
117
149
  def updated_package_json_content(file)
118
- @updated_package_json_content ||= {}
150
+ @updated_package_json_content ||= T.let({}, T.nilable(T::Hash[String, String]))
119
151
  @updated_package_json_content[file.name] ||=
120
- PackageJsonUpdater.new(
121
- package_json: file,
122
- dependencies: dependencies
123
- ).updated_package_json.content
152
+ T.must(
153
+ PackageJsonUpdater.new(
154
+ package_json: file,
155
+ dependencies: dependencies
156
+ ).updated_package_json.content
157
+ )
124
158
  end
125
159
 
160
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
126
161
  def package_files
127
- @package_files ||= dependency_files.select { |f| f.name.end_with?("package.json") }
162
+ @package_files ||= T.let(
163
+ dependency_files.select { |f| f.name.end_with?("package.json") },
164
+ T.nilable(T::Array[Dependabot::DependencyFile])
165
+ )
128
166
  end
129
167
 
168
+ sig { returns(String) }
130
169
  def base_dir
131
- dependency_files.first.directory
170
+ T.must(dependency_files.first).directory
132
171
  end
133
172
 
173
+ sig { returns(T.nilable(Dependabot::DependencyFile)) }
134
174
  def npmrc_file
135
175
  dependency_files.find { |f| f.name == ".npmrc" }
136
176
  end
137
177
 
178
+ sig { params(message: String).returns(String) }
138
179
  def sanitize_message(message)
139
180
  message.gsub(/"|\[|\]|\}|\{/, "")
140
181
  end
@@ -1,6 +1,8 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
5
+
4
6
  require "dependabot/npm_and_yarn/file_updater"
5
7
  require "dependabot/npm_and_yarn/file_parser"
6
8
 
@@ -8,10 +10,14 @@ module Dependabot
8
10
  module NpmAndYarn
9
11
  class FileUpdater < Dependabot::FileUpdaters::Base
10
12
  class PackageJsonPreparer
13
+ extend T::Sig
14
+
15
+ sig { params(package_json_content: String).void }
11
16
  def initialize(package_json_content:)
12
17
  @package_json_content = package_json_content
13
18
  end
14
19
 
20
+ sig { returns(String) }
15
21
  def prepared_content
16
22
  content = package_json_content
17
23
  content = replace_ssh_sources(content)
@@ -20,6 +26,7 @@ module Dependabot
20
26
  content
21
27
  end
22
28
 
29
+ sig { params(content: String).returns(String) }
23
30
  def replace_ssh_sources(content)
24
31
  updated_content = content
25
32
 
@@ -33,6 +40,7 @@ module Dependabot
33
40
 
34
41
  # A bug prevents Yarn recognising that a directory is part of a
35
42
  # workspace if it is specified with a `./` prefix.
43
+ sig { params(content: String).returns(String) }
36
44
  def remove_workspace_path_prefixes(content)
37
45
  json = JSON.parse(content)
38
46
  return content unless json.key?("workspaces")
@@ -52,6 +60,7 @@ module Dependabot
52
60
  JSON.pretty_generate(json)
53
61
  end
54
62
 
63
+ sig { params(content: String).returns(String) }
55
64
  def remove_invalid_characters(content)
56
65
  content
57
66
  .gsub(/\{\{[^\}]*?\}\}/, "something") # {{ nm }} syntax not allowed
@@ -59,28 +68,31 @@ module Dependabot
59
68
  .gsub(%r{^\s*//.*}, " ") # comments are not allowed
60
69
  end
61
70
 
71
+ sig { returns(T::Array[String]) }
62
72
  def swapped_ssh_requirements
63
73
  git_ssh_requirements_to_swap
64
74
  end
65
75
 
66
76
  private
67
77
 
78
+ sig { returns(String) }
68
79
  attr_reader :package_json_content
69
80
 
81
+ sig { returns(T::Array[String]) }
70
82
  def git_ssh_requirements_to_swap
71
83
  return @git_ssh_requirements_to_swap if @git_ssh_requirements_to_swap
72
84
 
73
- @git_ssh_requirements_to_swap = []
85
+ @git_ssh_requirements_to_swap = T.let([], T.nilable(T::Array[String]))
74
86
 
75
87
  NpmAndYarn::FileParser.each_dependency(JSON.parse(package_json_content)) do |_, req, _t|
76
88
  next unless req.is_a?(String)
77
89
  next unless req.start_with?("git+ssh:")
78
90
 
79
91
  req = req.split("#").first
80
- @git_ssh_requirements_to_swap << req
92
+ T.must(@git_ssh_requirements_to_swap) << T.must(req)
81
93
  end
82
94
 
83
- @git_ssh_requirements_to_swap
95
+ T.must(@git_ssh_requirements_to_swap)
84
96
  end
85
97
  end
86
98
  end