dependabot-npm_and_yarn 0.249.0 → 0.251.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d151652a4b121a997ad0d4bc33f9a7c8ea85be7b80243caff0b206fe98546c10
4
- data.tar.gz: 5855c2d02fd81e6e83c603a1cc2ef6a096a8ce4d16f821e75d31aef2aa8f37b3
3
+ metadata.gz: f78d3094eb768e1b940b7aa2874e3b4650f9eb3c8068652beacf06985a871a31
4
+ data.tar.gz: 7666b40e35e99f5125e180cbee69c69622ab8319646747c68cf813fea77492af
5
5
  SHA512:
6
- metadata.gz: b0cb6772b69527887eb0a55c4c7e315b772c9290fa19f0e744ffd75c4c8fc3b736e035049a6049c8c4c16638f3c5b79a6206c66476b43e1b4a9778a2ba52c849
7
- data.tar.gz: fbe325addd40ac04e91c0582167b6704e9f990e6df936faa441319e948e5e58c8917fdfe0b2346f5712571eef883c2baced7d840abca176428e66012d5667a43
6
+ metadata.gz: 3de7cc328a5be904dee3b9834ac4103c4f9dedbe7116310599f666598f076b7e4cf158dfed5a8ddd8d2727930d69dec902afba4e1b2d54aca4743e5c2c97aaa9
7
+ data.tar.gz: a497a53407c28ab282f1398ecf8e23caad3fd1dfe2ce1258f7e2a624ed6a252e98dd48ad362bc088f12927cdba9c012b9fef22747f0be08e946a447e0f10a8f5
@@ -1,8 +1,9 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/utils"
5
5
  require "dependabot/npm_and_yarn/file_parser/lockfile_parser"
6
+ require "sorbet-runtime"
6
7
 
7
8
  # Used in the version resolver and file updater to only run yarn/npm helpers on
8
9
  # dependency files that require updates. This is useful for large monorepos with
@@ -10,52 +11,67 @@ require "dependabot/npm_and_yarn/file_parser/lockfile_parser"
10
11
  module Dependabot
11
12
  module NpmAndYarn
12
13
  class DependencyFilesFilterer
14
+ extend T::Sig
15
+
16
+ sig { params(dependency_files: T::Array[DependencyFile], updated_dependencies: T::Array[Dependency]).void }
13
17
  def initialize(dependency_files:, updated_dependencies:)
14
18
  @dependency_files = dependency_files
15
19
  @updated_dependencies = updated_dependencies
16
20
  end
17
21
 
22
+ sig { returns(T::Array[String]) }
18
23
  def paths_requiring_update_check
19
- @paths_requiring_update_check ||= fetch_paths_requiring_update_check
24
+ @paths_requiring_update_check ||= T.let(fetch_paths_requiring_update_check, T.nilable(T::Array[String]))
20
25
  end
21
26
 
27
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
22
28
  def files_requiring_update
23
- @files_requiring_update ||=
29
+ @files_requiring_update ||= T.let(
24
30
  dependency_files.select do |file|
25
31
  package_files_requiring_update.include?(file) ||
26
32
  package_required_lockfile?(file) ||
27
33
  workspaces_lockfile?(file)
28
- end
34
+ end, T.nilable(T::Array[DependencyFile])
35
+ )
29
36
  end
30
37
 
38
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
31
39
  def package_files_requiring_update
32
- @package_files_requiring_update ||=
40
+ @package_files_requiring_update ||= T.let(
33
41
  dependency_files.select do |file|
34
42
  dependency_manifest_requirements.include?(file.name)
35
- end
43
+ end, T.nilable(T::Array[DependencyFile])
44
+ )
36
45
  end
37
46
 
38
47
  private
39
48
 
49
+ sig { returns(T::Array[DependencyFile]) }
40
50
  attr_reader :dependency_files
51
+
52
+ sig { returns(T::Array[Dependency]) }
41
53
  attr_reader :updated_dependencies
42
54
 
55
+ sig { returns(T::Array[String]) }
43
56
  def fetch_paths_requiring_update_check
44
57
  # if only a root lockfile exists, it tracks all dependencies
45
- return [File.dirname(root_lockfile.name)] if lockfiles == [root_lockfile]
58
+ return [File.dirname(T.must(root_lockfile).name)] if lockfiles == [root_lockfile]
46
59
 
47
60
  package_files_requiring_update.map do |file|
48
61
  File.dirname(file.name)
49
62
  end
50
63
  end
51
64
 
65
+ sig { returns(T::Array[String]) }
52
66
  def dependency_manifest_requirements
53
- @dependency_manifest_requirements ||=
67
+ @dependency_manifest_requirements ||= T.let(
54
68
  updated_dependencies.flat_map do |dep|
55
69
  dep.requirements.map { |requirement| requirement[:file] }
56
- end
70
+ end, T.nilable(T::Array[String])
71
+ )
57
72
  end
58
73
 
74
+ sig { params(lockfile: DependencyFile).returns(T::Boolean) }
59
75
  def package_required_lockfile?(lockfile)
60
76
  return false unless lockfile?(lockfile)
61
77
 
@@ -64,6 +80,7 @@ module Dependabot
64
80
  end
65
81
  end
66
82
 
83
+ sig { params(lockfile: DependencyFile).returns(T::Boolean) }
67
84
  def workspaces_lockfile?(lockfile)
68
85
  return false unless ["yarn.lock", "package-lock.json", "pnpm-lock.yaml"].include?(lockfile.name)
69
86
 
@@ -74,28 +91,35 @@ module Dependabot
74
91
  updated_dependencies_in_lockfile?(lockfile)
75
92
  end
76
93
 
94
+ sig { returns(T.nilable(DependencyFile)) }
77
95
  def root_lockfile
78
- @root_lockfile ||=
96
+ @root_lockfile ||= T.let(
79
97
  lockfiles.find do |file|
80
98
  File.dirname(file.name) == "."
81
- end
99
+ end, T.nilable(DependencyFile)
100
+ )
82
101
  end
83
102
 
103
+ sig { returns(T::Array[DependencyFile]) }
84
104
  def lockfiles
85
- @lockfiles ||=
105
+ @lockfiles ||= T.let(
86
106
  dependency_files.select do |file|
87
107
  lockfile?(file)
88
- end
108
+ end, T.nilable(T::Array[DependencyFile])
109
+ )
89
110
  end
90
111
 
112
+ sig { returns(T::Hash[String, T.untyped]) }
91
113
  def parsed_root_package_json
92
- @parsed_root_package_json ||=
114
+ @parsed_root_package_json ||= T.let(
93
115
  begin
94
- package = dependency_files.find { |f| f.name == "package.json" }
95
- JSON.parse(package.content)
96
- end
116
+ package = T.must(dependency_files.find { |f| f.name == "package.json" })
117
+ JSON.parse(T.must(package.content))
118
+ end, T.nilable(T::Hash[String, T.untyped])
119
+ )
97
120
  end
98
121
 
122
+ sig { params(lockfile: Dependabot::DependencyFile).returns(T::Boolean) }
99
123
  def updated_dependencies_in_lockfile?(lockfile)
100
124
  lockfile_dependencies(lockfile).any? do |sub_dep|
101
125
  updated_dependencies.any? do |updated_dep|
@@ -104,18 +128,21 @@ module Dependabot
104
128
  end
105
129
  end
106
130
 
131
+ sig { params(lockfile: DependencyFile).returns(T::Array[Dependency]) }
107
132
  def lockfile_dependencies(lockfile)
108
- @lockfile_dependencies ||= {}
133
+ @lockfile_dependencies ||= T.let({}, T.nilable(T::Hash[String, T::Array[Dependency]]))
109
134
  @lockfile_dependencies[lockfile.name] ||=
110
135
  NpmAndYarn::FileParser::LockfileParser.new(
111
136
  dependency_files: [lockfile]
112
137
  ).parse
113
138
  end
114
139
 
140
+ sig { params(file: DependencyFile).returns(T::Boolean) }
115
141
  def manifest?(file)
116
142
  file.name.end_with?("package.json")
117
143
  end
118
144
 
145
+ sig { params(file: DependencyFile).returns(T::Boolean) }
119
146
  def lockfile?(file)
120
147
  file.name.end_with?(
121
148
  "package-lock.json",
@@ -1,15 +1,28 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "json"
5
5
  require "dependabot/dependency_file"
6
6
  require "dependabot/errors"
7
7
  require "dependabot/npm_and_yarn/file_fetcher"
8
+ require "sorbet-runtime"
8
9
 
9
10
  module Dependabot
10
11
  module NpmAndYarn
11
12
  class FileFetcher
12
13
  class PathDependencyBuilder
14
+ extend T::Sig
15
+
16
+ sig do
17
+ params(
18
+ dependency_name: String,
19
+ path: String,
20
+ directory: String,
21
+ package_lock: T.nilable(DependencyFile),
22
+ yarn_lock: T.nilable(DependencyFile)
23
+ )
24
+ .void
25
+ end
13
26
  def initialize(dependency_name:, path:, directory:, package_lock:,
14
27
  yarn_lock:)
15
28
  @dependency_name = dependency_name
@@ -19,6 +32,7 @@ module Dependabot
19
32
  @yarn_lock = yarn_lock
20
33
  end
21
34
 
35
+ sig { returns(DependencyFile) }
22
36
  def dependency_file
23
37
  filename = File.join(path, "package.json")
24
38
 
@@ -32,22 +46,33 @@ module Dependabot
32
46
 
33
47
  private
34
48
 
49
+ sig { returns(String) }
35
50
  attr_reader :dependency_name
51
+
52
+ sig { returns(String) }
36
53
  attr_reader :path
54
+
55
+ sig { returns(T.nilable(DependencyFile)) }
37
56
  attr_reader :package_lock
57
+
58
+ sig { returns(T.nilable(DependencyFile)) }
38
59
  attr_reader :yarn_lock
60
+
61
+ sig { returns(String) }
39
62
  attr_reader :directory
40
63
 
64
+ sig { returns(T.untyped) }
41
65
  def details_from_yarn_lock
42
66
  path_starts = FileFetcher::PATH_DEPENDENCY_STARTS
43
67
  parsed_yarn_lock.to_a
44
68
  .find do |n, _|
45
69
  next false unless n.split(/(?<=\w)\@/).first == dependency_name
46
70
 
47
- n.split(/(?<=\w)\@/).last.start_with?(*path_starts)
71
+ T.must(n.split(/(?<=\w)\@/).last).start_with?(*path_starts)
48
72
  end&.last
49
73
  end
50
74
 
75
+ sig { returns(T.untyped) }
51
76
  def details_from_npm_lock
52
77
  path_starts = FileFetcher::NPM_PATH_DEPENDENCY_STARTS
53
78
  path_deps = parsed_package_lock.fetch("dependencies", []).to_a
@@ -57,6 +82,7 @@ module Dependabot
57
82
  path_deps.find { |n, _| n == dependency_name }&.last
58
83
  end
59
84
 
85
+ sig { params(dependency_name: String).returns(String) }
60
86
  def build_path_dep_content(dependency_name)
61
87
  unless details_from_yarn_lock || details_from_npm_lock
62
88
  raise Dependabot::PathDependenciesNotReachable, [dependency_name]
@@ -89,6 +115,7 @@ module Dependabot
89
115
  # relative. Worse, they may point to the user's local cache.
90
116
  # We work around this by constructing a relative path to the
91
117
  # (second-level) path dependencies.
118
+ sig { params(dependencies_hash: T.nilable(T::Hash[String, T.untyped])).returns(T.untyped) }
92
119
  def replace_yarn_lockfile_paths(dependencies_hash)
93
120
  return unless dependencies_hash
94
121
 
@@ -101,7 +128,7 @@ module Dependabot
101
128
  .find do |n, _|
102
129
  next false unless n.split(/(?<=\w)\@/).first == name
103
130
 
104
- n.split(/(?<=\w)\@/).last
131
+ T.must(n.split(/(?<=\w)\@/).last)
105
132
  .start_with?(*FileFetcher::PATH_DEPENDENCY_STARTS)
106
133
  end&.first&.split(/(?<=\w)\@/)&.last
107
134
 
@@ -113,32 +140,36 @@ module Dependabot
113
140
  end
114
141
  end
115
142
 
143
+ sig { returns(T.untyped) }
116
144
  def parsed_package_lock
117
145
  return {} unless package_lock
118
146
 
119
- JSON.parse(package_lock.content)
147
+ JSON.parse(T.must(T.must(package_lock).content))
120
148
  rescue JSON::ParserError
121
149
  {}
122
150
  end
123
151
 
152
+ sig { returns(T.nilable(T::Hash[String, T.untyped])) }
124
153
  def parsed_yarn_lock
125
- return {} unless yarn_lock
126
-
127
- @parsed_yarn_lock ||=
128
- SharedHelpers.in_a_temporary_directory do
129
- File.write("yarn.lock", yarn_lock.content)
130
-
131
- SharedHelpers.run_helper_subprocess(
132
- command: NativeHelpers.helper_path,
133
- function: "yarn:parseLockfile",
134
- args: [Dir.pwd]
135
- )
136
- rescue SharedHelpers::HelperSubprocessFailed
137
- raise Dependabot::DependencyFileNotParseable, yarn_lock.path
138
- end
154
+ return unless yarn_lock
155
+ return @parsed_yarn_lock if defined?(@parsed_yarn_lock)
156
+
157
+ parsed = T.cast(SharedHelpers.in_a_temporary_directory do
158
+ File.write("yarn.lock", T.must(yarn_lock).content)
159
+
160
+ SharedHelpers.run_helper_subprocess(
161
+ command: NativeHelpers.helper_path,
162
+ function: "yarn:parseLockfile",
163
+ args: [Dir.pwd]
164
+ )
165
+ rescue SharedHelpers::HelperSubprocessFailed
166
+ raise Dependabot::DependencyFileNotParseable, T.must(yarn_lock).path
167
+ end, T::Hash[String, T.untyped])
168
+ @parsed_yarn_lock = T.let(parsed, T.nilable(T::Hash[String, T.untyped]))
139
169
  end
140
170
 
141
171
  # The path back to the root lockfile
172
+ sig { returns(String) }
142
173
  def inverted_path
143
174
  path.split("/").map do |part|
144
175
  next part if part == "."