dependabot-npm_and_yarn 0.249.0 → 0.250.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,22 +1,27 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/dependency_file"
5
5
  require "dependabot/npm_and_yarn/file_parser"
6
6
  require "dependabot/npm_and_yarn/helpers"
7
+ require "sorbet-runtime"
7
8
 
8
9
  module Dependabot
9
10
  module NpmAndYarn
10
11
  class FileParser < Dependabot::FileParsers::Base
11
12
  class LockfileParser
13
+ extend T::Sig
14
+
12
15
  require "dependabot/npm_and_yarn/file_parser/yarn_lock"
13
16
  require "dependabot/npm_and_yarn/file_parser/pnpm_lock"
14
17
  require "dependabot/npm_and_yarn/file_parser/json_lock"
15
18
 
19
+ sig { params(dependency_files: T::Array[DependencyFile]).void }
16
20
  def initialize(dependency_files:)
17
21
  @dependency_files = dependency_files
18
22
  end
19
23
 
24
+ sig { returns(Dependabot::FileParsers::Base::DependencySet) }
20
25
  def parse_set
21
26
  dependency_set = Dependabot::FileParsers::Base::DependencySet.new
22
27
 
@@ -31,24 +36,32 @@ module Dependabot
31
36
  dependency_set
32
37
  end
33
38
 
39
+ sig { returns(T::Array[Dependency]) }
34
40
  def parse
35
41
  Helpers.dependencies_with_all_versions_metadata(parse_set)
36
42
  end
37
43
 
44
+ sig do
45
+ params(dependency_name: String, requirement: T.nilable(String), manifest_name: String)
46
+ .returns(T.nilable(T::Hash[String, T.untyped]))
47
+ end
38
48
  def lockfile_details(dependency_name:, requirement:, manifest_name:)
49
+ details = T.let(nil, T.nilable(T::Hash[String, T.untyped]))
39
50
  potential_lockfiles_for_manifest(manifest_name).each do |lockfile|
40
51
  details = lockfile_for(lockfile).details(dependency_name, requirement, manifest_name)
41
52
 
42
- return details if details
53
+ break if details
43
54
  end
44
55
 
45
- nil
56
+ details
46
57
  end
47
58
 
48
59
  private
49
60
 
61
+ sig { returns(T::Array[DependencyFile]) }
50
62
  attr_reader :dependency_files
51
63
 
64
+ sig { params(manifest_filename: String).returns(T::Array[DependencyFile]) }
52
65
  def potential_lockfiles_for_manifest(manifest_filename)
53
66
  dir_name = File.dirname(manifest_filename)
54
67
  possible_lockfile_names =
@@ -61,12 +74,9 @@ module Dependabot
61
74
  .filter_map { |nm| dependency_files.find { |f| f.name == nm } }
62
75
  end
63
76
 
64
- def parsed_lockfile(file)
65
- lockfile_for(file).parsed
66
- end
67
-
77
+ sig { params(file: DependencyFile).returns(T.any(JsonLock, YarnLock, PnpmLock)) }
68
78
  def lockfile_for(file)
69
- @lockfiles ||= {}
79
+ @lockfiles ||= T.let({}, T.nilable(T::Hash[String, T.any(JsonLock, YarnLock, PnpmLock)]))
70
80
  @lockfiles[file.name] ||= if [*package_locks, *shrinkwraps].include?(file)
71
81
  JsonLock.new(file)
72
82
  elsif yarn_locks.include?(file)
@@ -76,30 +86,39 @@ module Dependabot
76
86
  end
77
87
  end
78
88
 
89
+ sig { returns(T::Array[DependencyFile]) }
79
90
  def package_locks
80
- @package_locks ||=
91
+ @package_locks ||= T.let(
81
92
  dependency_files
82
- .select { |f| f.name.end_with?("package-lock.json") }
93
+ .select { |f| f.name.end_with?("package-lock.json") }, T.nilable(T::Array[DependencyFile])
94
+ )
83
95
  end
84
96
 
97
+ sig { returns(T::Array[DependencyFile]) }
85
98
  def pnpm_locks
86
- @pnpm_locks ||=
99
+ @pnpm_locks ||= T.let(
87
100
  dependency_files
88
- .select { |f| f.name.end_with?("pnpm-lock.yaml") }
101
+ .select { |f| f.name.end_with?("pnpm-lock.yaml") }, T.nilable(T::Array[DependencyFile])
102
+ )
89
103
  end
90
104
 
105
+ sig { returns(T::Array[DependencyFile]) }
91
106
  def yarn_locks
92
- @yarn_locks ||=
107
+ @yarn_locks ||= T.let(
93
108
  dependency_files
94
- .select { |f| f.name.end_with?("yarn.lock") }
109
+ .select { |f| f.name.end_with?("yarn.lock") }, T.nilable(T::Array[DependencyFile])
110
+ )
95
111
  end
96
112
 
113
+ sig { returns(T::Array[DependencyFile]) }
97
114
  def shrinkwraps
98
- @shrinkwraps ||=
115
+ @shrinkwraps ||= T.let(
99
116
  dependency_files
100
- .select { |f| f.name.end_with?("npm-shrinkwrap.json") }
117
+ .select { |f| f.name.end_with?("npm-shrinkwrap.json") }, T.nilable(T::Array[DependencyFile])
118
+ )
101
119
  end
102
120
 
121
+ sig { returns(T.class_of(Dependabot::NpmAndYarn::Version)) }
103
122
  def version_class
104
123
  NpmAndYarn::Version
105
124
  end
@@ -1,9 +1,10 @@
1
- # typed: false
1
+ # typed: true
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/shared_helpers"
5
5
  require "dependabot/errors"
6
6
  require "dependabot/npm_and_yarn/native_helpers"
7
+ require "sorbet-runtime"
7
8
 
8
9
  module Dependabot
9
10
  module NpmAndYarn
@@ -44,7 +45,7 @@ module Dependabot
44
45
 
45
46
  dependency_set << Dependency.new(
46
47
  name: req.split(/(?<=\w)\@/).first,
47
- version: version,
48
+ version: version.to_s,
48
49
  package_manager: "npm_and_yarn",
49
50
  requirements: []
50
51
  )
@@ -1,4 +1,4 @@
1
- # typed: false
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  # See https://docs.npmjs.com/files/package.json for package.json format docs.
@@ -15,15 +15,17 @@ require "dependabot/npm_and_yarn/registry_parser"
15
15
  require "dependabot/git_metadata_fetcher"
16
16
  require "dependabot/git_commit_checker"
17
17
  require "dependabot/errors"
18
+ require "sorbet-runtime"
18
19
 
19
20
  module Dependabot
20
21
  module NpmAndYarn
21
22
  class FileParser < Dependabot::FileParsers::Base
23
+ extend T::Sig
24
+
22
25
  require "dependabot/file_parsers/base/dependency_set"
23
26
  require_relative "file_parser/lockfile_parser"
24
27
 
25
- DEPENDENCY_TYPES =
26
- %w(dependencies devDependencies optionalDependencies).freeze
28
+ DEPENDENCY_TYPES = T.let(%w(dependencies devDependencies optionalDependencies).freeze, T::Array[String])
27
29
  GIT_URL_REGEX = %r{
28
30
  (?<git_prefix>^|^git.*?|^github:|^bitbucket:|^gitlab:|github\.com/)
29
31
  (?<username>[a-z0-9-]+)/
@@ -35,15 +37,23 @@ module Dependabot
35
37
  )?$
36
38
  }ix
37
39
 
38
- def self.each_dependency(json)
40
+ sig do
41
+ params(
42
+ json: T::Hash[String, T.untyped],
43
+ _block: T.proc.params(arg0: String, arg1: String, arg2: String).void
44
+ )
45
+ .void
46
+ end
47
+ def self.each_dependency(json, &_block)
39
48
  DEPENDENCY_TYPES.each do |type|
40
49
  deps = json[type] || {}
41
50
  deps.each do |name, requirement|
42
- yield name, requirement, type
51
+ yield(name, requirement, type)
43
52
  end
44
53
  end
45
54
  end
46
55
 
56
+ sig { override.returns(T::Array[Dependency]) }
47
57
  def parse
48
58
  dependency_set = DependencySet.new
49
59
  dependency_set += manifest_dependencies
@@ -70,11 +80,12 @@ module Dependabot
70
80
 
71
81
  private
72
82
 
83
+ sig { returns(Dependabot::FileParsers::Base::DependencySet) }
73
84
  def manifest_dependencies
74
85
  dependency_set = DependencySet.new
75
86
 
76
87
  package_files.each do |file|
77
- json = JSON.parse(file.content)
88
+ json = JSON.parse(T.must(file.content))
78
89
 
79
90
  # TODO: Currently, Dependabot can't handle flat dependency files
80
91
  # (and will error at the FileUpdater stage, because the
@@ -98,16 +109,22 @@ module Dependabot
98
109
  dependency_set
99
110
  end
100
111
 
112
+ sig { returns(LockfileParser) }
101
113
  def lockfile_parser
102
- @lockfile_parser ||= LockfileParser.new(
103
- dependency_files: dependency_files
104
- )
114
+ @lockfile_parser ||= T.let(LockfileParser.new(
115
+ dependency_files: dependency_files
116
+ ), T.nilable(Dependabot::NpmAndYarn::FileParser::LockfileParser))
105
117
  end
106
118
 
119
+ sig { returns(Dependabot::FileParsers::Base::DependencySet) }
107
120
  def lockfile_dependencies
108
121
  lockfile_parser.parse_set
109
122
  end
110
123
 
124
+ sig do
125
+ params(file: DependencyFile, type: T.untyped, name: String, requirement: String)
126
+ .returns(T.nilable(Dependency))
127
+ end
111
128
  def build_dependency(file:, type:, name:, requirement:)
112
129
  lockfile_details = lockfile_parser.lockfile_details(
113
130
  dependency_name: name,
@@ -115,6 +132,13 @@ module Dependabot
115
132
  manifest_name: file.name
116
133
  )
117
134
  version = version_for(requirement, lockfile_details)
135
+ converted_version = T.let(if version.nil?
136
+ nil
137
+ elsif version.is_a?(String)
138
+ version
139
+ else
140
+ Dependabot::Version.new(version)
141
+ end, T.nilable(T.any(String, Dependabot::Version)))
118
142
 
119
143
  return if lockfile_details && !version
120
144
  return if ignore_requirement?(requirement)
@@ -129,7 +153,7 @@ module Dependabot
129
153
 
130
154
  Dependency.new(
131
155
  name: name,
132
- version: version,
156
+ version: converted_version,
133
157
  package_manager: "npm_and_yarn",
134
158
  requirements: [{
135
159
  requirement: requirement_for(requirement),
@@ -140,10 +164,12 @@ module Dependabot
140
164
  )
141
165
  end
142
166
 
167
+ sig { override.void }
143
168
  def check_required_files
144
169
  raise "No package.json!" unless get_original_file("package.json")
145
170
  end
146
171
 
172
+ sig { params(requirement: String).returns(T::Boolean) }
147
173
  def ignore_requirement?(requirement)
148
174
  return true if local_path?(requirement)
149
175
  return true if non_git_url?(requirement)
@@ -153,37 +179,49 @@ module Dependabot
153
179
  alias_package?(requirement)
154
180
  end
155
181
 
182
+ sig { params(requirement: String).returns(T::Boolean) }
156
183
  def local_path?(requirement)
157
184
  requirement.start_with?("link:", "file:", "/", "./", "../", "~/")
158
185
  end
159
186
 
187
+ sig { params(requirement: String).returns(T::Boolean) }
160
188
  def alias_package?(requirement)
161
189
  requirement.start_with?("npm:")
162
190
  end
163
191
 
192
+ sig { params(requirement: String).returns(T::Boolean) }
164
193
  def non_git_url?(requirement)
165
194
  requirement.include?("://") && !git_url?(requirement)
166
195
  end
167
196
 
197
+ sig { params(requirement: String).returns(T::Boolean) }
168
198
  def git_url?(requirement)
169
199
  requirement.match?(GIT_URL_REGEX)
170
200
  end
171
201
 
202
+ sig { params(requirement: String).returns(T::Boolean) }
172
203
  def git_url_with_semver?(requirement)
173
204
  return false unless git_url?(requirement)
174
205
 
175
- !requirement.match(GIT_URL_REGEX).named_captures.fetch("semver").nil?
206
+ !T.must(requirement.match(GIT_URL_REGEX)).named_captures.fetch("semver").nil?
176
207
  end
177
208
 
209
+ sig { params(name: String).returns(T::Boolean) }
178
210
  def aliased_package_name?(name)
179
211
  name.include?("@npm:")
180
212
  end
181
213
 
214
+ sig { returns(T::Array[String]) }
182
215
  def workspace_package_names
183
- @workspace_package_names ||=
184
- package_files.filter_map { |f| JSON.parse(f.content)["name"] }
216
+ @workspace_package_names ||= T.let(package_files.filter_map do |f|
217
+ JSON.parse(T.must(f.content))["name"]
218
+ end, T.nilable(T::Array[String]))
185
219
  end
186
220
 
221
+ sig do
222
+ params(requirement: String, lockfile_details: T.nilable(T::Hash[String, T.untyped]))
223
+ .returns(T.nilable(T.any(String, Integer, Gem::Version)))
224
+ end
187
225
  def version_for(requirement, lockfile_details)
188
226
  if git_url_with_semver?(requirement)
189
227
  semver_version = lockfile_version_for(lockfile_details)
@@ -203,20 +241,25 @@ module Dependabot
203
241
  end
204
242
  end
205
243
 
244
+ sig { params(lockfile_details: T.nilable(T::Hash[String, T.untyped])).returns(T.nilable(String)) }
206
245
  def git_revision_for(lockfile_details)
246
+ version = T.cast(lockfile_details&.fetch("version", nil), T.nilable(String))
247
+ resolved = T.cast(lockfile_details&.fetch("resolved", nil), T.nilable(String))
207
248
  [
208
- lockfile_details&.fetch("version", nil)&.split("#")&.last,
209
- lockfile_details&.fetch("resolved", nil)&.split("#")&.last,
210
- lockfile_details&.fetch("resolved", nil)&.split("/")&.last
249
+ version&.split("#")&.last,
250
+ resolved&.split("#")&.last,
251
+ resolved&.split("/")&.last
211
252
  ].find { |str| commit_sha?(str) }
212
253
  end
213
254
 
255
+ sig { params(string: T.nilable(String)).returns(T::Boolean) }
214
256
  def commit_sha?(string)
215
257
  return false unless string.is_a?(String)
216
258
 
217
259
  string.match?(/^[0-9a-f]{40}$/)
218
260
  end
219
261
 
262
+ sig { params(requirement: String, git_revision: T.nilable(String)).returns(T.nilable(String)) }
220
263
  def version_from_git_revision(requirement, git_revision)
221
264
  tags =
222
265
  Dependabot::GitMetadataFetcher.new(
@@ -228,7 +271,7 @@ module Dependabot
228
271
  tags.each do |t|
229
272
  next unless t.name.match?(Dependabot::GitCommitChecker::VERSION_REGEX)
230
273
 
231
- version = t.name.match(Dependabot::GitCommitChecker::VERSION_REGEX)
274
+ version = T.must(t.name.match(Dependabot::GitCommitChecker::VERSION_REGEX))
232
275
  .named_captures.fetch("version")
233
276
  next unless version_class.correct?(version)
234
277
 
@@ -240,14 +283,20 @@ module Dependabot
240
283
  nil
241
284
  end
242
285
 
286
+ sig do
287
+ params(lockfile_details: T.nilable(T::Hash[String, T.untyped]))
288
+ .returns(T.nilable(T.any(String, Integer, Gem::Version)))
289
+ end
243
290
  def lockfile_version_for(lockfile_details)
244
291
  semver_version_for(lockfile_details&.fetch("version", ""))
245
292
  end
246
293
 
294
+ sig { params(version: String).returns(T.nilable(T.any(String, Integer, Gem::Version))) }
247
295
  def semver_version_for(version)
248
296
  version_class.semver_for(version)
249
297
  end
250
298
 
299
+ sig { params(requirement: String).returns(T.nilable(String)) }
251
300
  def exact_version_for(requirement)
252
301
  req = requirement_class.new(requirement)
253
302
  return unless req.exact?
@@ -257,6 +306,10 @@ module Dependabot
257
306
  # If it doesn't parse, it's definitely not exact
258
307
  end
259
308
 
309
+ sig do
310
+ params(name: String, requirement: String, lockfile_details: T.nilable(T::Hash[String, T.untyped]))
311
+ .returns(T.nilable(T::Hash[Symbol, T.untyped]))
312
+ end
260
313
  def source_for(name, requirement, lockfile_details)
261
314
  return git_source_for(requirement) if git_url?(requirement)
262
315
 
@@ -276,22 +329,24 @@ module Dependabot
276
329
  ).registry_source_for(name)
277
330
  end
278
331
 
332
+ sig { params(requirement: String).returns(T.nilable(String)) }
279
333
  def requirement_for(requirement)
280
334
  return requirement unless git_url?(requirement)
281
335
 
282
- details = requirement.match(GIT_URL_REGEX).named_captures
336
+ details = T.must(requirement.match(GIT_URL_REGEX)).named_captures
283
337
  details["semver"]
284
338
  end
285
339
 
340
+ sig { params(requirement: String).returns(T::Hash[Symbol, T.untyped]) }
286
341
  def git_source_for(requirement)
287
- details = requirement.match(GIT_URL_REGEX).named_captures
288
- prefix = details.fetch("git_prefix")
342
+ details = T.must(requirement.match(GIT_URL_REGEX)).named_captures
343
+ prefix = T.must(details.fetch("git_prefix"))
289
344
 
290
345
  host = if prefix.include?("git@") || prefix.include?("://")
291
- prefix.split("git@").last
292
- .sub(%r{.*?://}, "")
293
- .sub(%r{[:/]$}, "")
294
- .split("#").first
346
+ T.must(prefix.split("git@").last)
347
+ .sub(%r{.*?://}, "")
348
+ .sub(%r{[:/]$}, "")
349
+ .split("#").first
295
350
  elsif prefix.include?("bitbucket") then "bitbucket.org"
296
351
  elsif prefix.include?("gitlab") then "gitlab.com"
297
352
  else
@@ -306,29 +361,37 @@ module Dependabot
306
361
  }
307
362
  end
308
363
 
364
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
309
365
  def support_package_files
310
- @support_package_files ||= sub_package_files.select(&:support_file?)
366
+ @support_package_files ||= T.let(sub_package_files.select(&:support_file?), T.nilable(T::Array[DependencyFile]))
311
367
  end
312
368
 
369
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
313
370
  def sub_package_files
314
- @sub_package_files ||=
315
- dependency_files.select { |f| f.name.end_with?("package.json") }
316
- .reject { |f| f.name == "package.json" }
317
- .reject { |f| f.name.include?("node_modules/") }
371
+ return T.must(@sub_package_files) if defined?(@sub_package_files)
372
+
373
+ files = dependency_files.select { |f| f.name.end_with?("package.json") }
374
+ .reject { |f| f.name == "package.json" }
375
+ .reject { |f| f.name.include?("node_modules/") }
376
+ @sub_package_files ||= T.let(files, T.nilable(T::Array[Dependabot::DependencyFile]))
318
377
  end
319
378
 
379
+ sig { returns(T::Array[DependencyFile]) }
320
380
  def package_files
321
- @package_files ||=
381
+ @package_files ||= T.let(
322
382
  [
323
383
  dependency_files.find { |f| f.name == "package.json" },
324
384
  *sub_package_files
325
- ].compact
385
+ ].compact, T.nilable(T::Array[DependencyFile])
386
+ )
326
387
  end
327
388
 
389
+ sig { returns(T.class_of(Dependabot::NpmAndYarn::Version)) }
328
390
  def version_class
329
391
  NpmAndYarn::Version
330
392
  end
331
393
 
394
+ sig { returns(T.class_of(Dependabot::NpmAndYarn::Requirement)) }
332
395
  def requirement_class
333
396
  NpmAndYarn::Requirement
334
397
  end
@@ -7,10 +7,13 @@ require "dependabot/file_updaters/vendor_updater"
7
7
  require "dependabot/file_updaters/artifact_updater"
8
8
  require "dependabot/npm_and_yarn/dependency_files_filterer"
9
9
  require "dependabot/npm_and_yarn/sub_dependency_files_filterer"
10
+ require "sorbet-runtime"
10
11
 
11
12
  module Dependabot
12
13
  module NpmAndYarn
13
14
  class FileUpdater < Dependabot::FileUpdaters::Base
15
+ extend T::Sig
16
+
14
17
  require_relative "file_updater/package_json_updater"
15
18
  require_relative "file_updater/npm_lockfile_updater"
16
19
  require_relative "file_updater/yarn_lockfile_updater"
@@ -27,6 +30,7 @@ module Dependabot
27
30
  end
28
31
  end
29
32
 
33
+ sig { override.returns(T::Array[Regexp]) }
30
34
  def self.updated_files_regex
31
35
  [
32
36
  /^package\.json$/,
@@ -37,8 +41,9 @@ module Dependabot
37
41
  ]
38
42
  end
39
43
 
44
+ sig { override.returns(T::Array[DependencyFile]) }
40
45
  def updated_dependency_files
41
- updated_files = []
46
+ updated_files = T.let([], T::Array[DependencyFile])
42
47
 
43
48
  updated_files += updated_manifest_files
44
49
  updated_files += updated_lockfiles
@@ -68,7 +73,9 @@ module Dependabot
68
73
  pnp_updater.updated_files(base_directory: base_dir, only_paths: [".pnp.cjs", ".pnp.data.json"]).each do |file|
69
74
  updated_files << file
70
75
  end
71
- vendor_updater.updated_vendor_cache_files(base_directory: base_dir).each { |file| updated_files << file }
76
+ T.unsafe(vendor_updater).updated_vendor_cache_files(base_directory: base_dir).each do |file|
77
+ updated_files << file
78
+ end
72
79
  install_state_updater.updated_files(base_directory: base_dir).each do |file|
73
80
  updated_files << file
74
81
  end
@@ -89,6 +96,7 @@ module Dependabot
89
96
  @install_state_path = Helpers.fetch_yarnrc_yml_value("installStatePath", "./.yarn/install-state.gz")
90
97
  end
91
98
 
99
+ sig { returns(Dependabot::FileUpdaters::VendorUpdater) }
92
100
  def vendor_updater
93
101
  Dependabot::FileUpdaters::VendorUpdater.new(
94
102
  repo_contents_path: repo_contents_path,
@@ -96,6 +104,7 @@ module Dependabot
96
104
  )
97
105
  end
98
106
 
107
+ sig { returns(Dependabot::FileUpdaters::ArtifactUpdater) }
99
108
  def install_state_updater
100
109
  Dependabot::FileUpdaters::ArtifactUpdater.new(
101
110
  repo_contents_path: repo_contents_path,
@@ -103,6 +112,7 @@ module Dependabot
103
112
  )
104
113
  end
105
114
 
115
+ sig { returns(Dependabot::FileUpdaters::ArtifactUpdater) }
106
116
  def pnp_updater
107
117
  Dependabot::FileUpdaters::ArtifactUpdater.new(
108
118
  repo_contents_path: repo_contents_path,
@@ -110,8 +120,9 @@ module Dependabot
110
120
  )
111
121
  end
112
122
 
123
+ sig { returns(T::Array[DependencyFile]) }
113
124
  def filtered_dependency_files
114
- @filtered_dependency_files ||=
125
+ @filtered_dependency_files ||= T.let(
115
126
  if dependencies.any?(&:top_level?)
116
127
  DependencyFilesFilterer.new(
117
128
  dependency_files: dependency_files,
@@ -122,13 +133,16 @@ module Dependabot
122
133
  dependency_files: dependency_files,
123
134
  updated_dependencies: dependencies
124
135
  ).files_requiring_update
125
- end
136
+ end, T.nilable(T::Array[DependencyFile])
137
+ )
126
138
  end
127
139
 
140
+ sig { override.void }
128
141
  def check_required_files
129
142
  raise "No package.json!" unless get_original_file("package.json")
130
143
  end
131
144
 
145
+ sig { params(updated_files: T::Array[DependencyFile]).returns(T::Hash[Symbol, T.untyped]) }
132
146
  def error_context(updated_files:)
133
147
  {
134
148
  dependencies: dependencies.map(&:to_h),
@@ -161,11 +175,13 @@ module Dependabot
161
175
  .select { |f| f.name.end_with?("npm-shrinkwrap.json") }
162
176
  end
163
177
 
178
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
164
179
  def package_files
165
- @package_files ||=
180
+ @package_files ||= T.let(
166
181
  filtered_dependency_files.select do |f|
167
182
  f.name.end_with?("package.json")
168
- end
183
+ end, T.nilable(T::Array[DependencyFile])
184
+ )
169
185
  end
170
186
 
171
187
  def yarn_lock_changed?(yarn_lock)
@@ -184,6 +200,7 @@ module Dependabot
184
200
  shrinkwrap.content != updated_lockfile_content(shrinkwrap)
185
201
  end
186
202
 
203
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
187
204
  def updated_manifest_files
188
205
  package_files.filter_map do |file|
189
206
  updated_content = updated_package_json_content(file)