dependabot-npm_and_yarn 0.292.0 → 0.293.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/dependabot/npm_and_yarn/bun_package_manager.rb +46 -0
- data/lib/dependabot/npm_and_yarn/dependency_files_filterer.rb +2 -1
- data/lib/dependabot/npm_and_yarn/file_fetcher.rb +50 -33
- data/lib/dependabot/npm_and_yarn/file_parser/bun_lock.rb +141 -0
- data/lib/dependabot/npm_and_yarn/file_parser/lockfile_parser.rb +33 -27
- data/lib/dependabot/npm_and_yarn/file_parser/pnpm_lock.rb +47 -0
- data/lib/dependabot/npm_and_yarn/file_parser.rb +9 -1
- data/lib/dependabot/npm_and_yarn/file_updater/bun_lockfile_updater.rb +144 -0
- data/lib/dependabot/npm_and_yarn/file_updater/pnpm_lockfile_updater.rb +46 -0
- data/lib/dependabot/npm_and_yarn/file_updater.rb +48 -0
- data/lib/dependabot/npm_and_yarn/helpers.rb +40 -0
- data/lib/dependabot/npm_and_yarn/language.rb +45 -0
- data/lib/dependabot/npm_and_yarn/npm_package_manager.rb +70 -0
- data/lib/dependabot/npm_and_yarn/package_manager.rb +12 -194
- data/lib/dependabot/npm_and_yarn/pnpm_package_manager.rb +55 -0
- data/lib/dependabot/npm_and_yarn/sub_dependency_files_filterer.rb +1 -0
- data/lib/dependabot/npm_and_yarn/update_checker/dependency_files_builder.rb +14 -7
- data/lib/dependabot/npm_and_yarn/update_checker/subdependency_version_resolver.rb +14 -0
- data/lib/dependabot/npm_and_yarn/update_checker/version_resolver.rb +19 -0
- data/lib/dependabot/npm_and_yarn/yarn_package_manager.rb +56 -0
- metadata +12 -5
@@ -0,0 +1,144 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "dependabot/npm_and_yarn/helpers"
|
5
|
+
require "dependabot/npm_and_yarn/update_checker/registry_finder"
|
6
|
+
require "dependabot/npm_and_yarn/registry_parser"
|
7
|
+
require "dependabot/shared_helpers"
|
8
|
+
|
9
|
+
module Dependabot
|
10
|
+
module NpmAndYarn
|
11
|
+
class FileUpdater < Dependabot::FileUpdaters::Base
|
12
|
+
class BunLockfileUpdater
|
13
|
+
require_relative "npmrc_builder"
|
14
|
+
require_relative "package_json_updater"
|
15
|
+
|
16
|
+
def initialize(dependencies:, dependency_files:, repo_contents_path:, credentials:)
|
17
|
+
@dependencies = dependencies
|
18
|
+
@dependency_files = dependency_files
|
19
|
+
@repo_contents_path = repo_contents_path
|
20
|
+
@credentials = credentials
|
21
|
+
end
|
22
|
+
|
23
|
+
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]
|
26
|
+
|
27
|
+
new_content = run_bun_update(bun_lock: bun_lock)
|
28
|
+
@updated_bun_lock_content[bun_lock.name] = new_content
|
29
|
+
rescue SharedHelpers::HelperSubprocessFailed => e
|
30
|
+
handle_bun_lock_updater_error(e, bun_lock)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
attr_reader :dependencies
|
36
|
+
attr_reader :dependency_files
|
37
|
+
attr_reader :repo_contents_path
|
38
|
+
attr_reader :credentials
|
39
|
+
|
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
|
47
|
+
|
48
|
+
def run_bun_update(bun_lock:)
|
49
|
+
SharedHelpers.in_a_temporary_repo_directory(base_dir, repo_contents_path) do
|
50
|
+
File.write(".npmrc", npmrc_content(bun_lock))
|
51
|
+
|
52
|
+
SharedHelpers.with_git_configured(credentials: credentials) do
|
53
|
+
run_bun_updater
|
54
|
+
|
55
|
+
write_final_package_json_files
|
56
|
+
|
57
|
+
run_bun_install
|
58
|
+
|
59
|
+
File.read(bun_lock.name)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def run_bun_updater
|
65
|
+
dependency_updates = dependencies.map do |d|
|
66
|
+
"#{d.name}@#{d.version}"
|
67
|
+
end.join(" ")
|
68
|
+
|
69
|
+
Helpers.run_bun_command(
|
70
|
+
"install #{dependency_updates} --save-text-lockfile",
|
71
|
+
fingerprint: "install <dependency_updates> --save-text-lockfile"
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
def run_bun_install
|
76
|
+
Helpers.run_bun_command(
|
77
|
+
"install --save-text-lockfile"
|
78
|
+
)
|
79
|
+
end
|
80
|
+
|
81
|
+
def lockfile_dependencies(lockfile)
|
82
|
+
@lockfile_dependencies ||= {}
|
83
|
+
@lockfile_dependencies[lockfile.name] ||=
|
84
|
+
NpmAndYarn::FileParser.new(
|
85
|
+
dependency_files: [lockfile, *package_files],
|
86
|
+
source: nil,
|
87
|
+
credentials: credentials
|
88
|
+
).parse
|
89
|
+
end
|
90
|
+
|
91
|
+
def handle_bun_lock_updater_error(error, _bun_lock)
|
92
|
+
error_message = error.message
|
93
|
+
|
94
|
+
ERR_PATTERNS.each do |pattern, error_class|
|
95
|
+
raise error_class, error_message if error_message.match?(pattern)
|
96
|
+
end
|
97
|
+
|
98
|
+
raise error
|
99
|
+
end
|
100
|
+
|
101
|
+
def write_final_package_json_files
|
102
|
+
package_files.each do |file|
|
103
|
+
path = file.name
|
104
|
+
FileUtils.mkdir_p(Pathname.new(path).dirname)
|
105
|
+
File.write(path, updated_package_json_content(file))
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def npmrc_content(bun_lock)
|
110
|
+
NpmrcBuilder.new(
|
111
|
+
credentials: credentials,
|
112
|
+
dependency_files: dependency_files,
|
113
|
+
dependencies: lockfile_dependencies(bun_lock)
|
114
|
+
).npmrc_content
|
115
|
+
end
|
116
|
+
|
117
|
+
def updated_package_json_content(file)
|
118
|
+
@updated_package_json_content ||= {}
|
119
|
+
@updated_package_json_content[file.name] ||=
|
120
|
+
PackageJsonUpdater.new(
|
121
|
+
package_json: file,
|
122
|
+
dependencies: dependencies
|
123
|
+
).updated_package_json.content
|
124
|
+
end
|
125
|
+
|
126
|
+
def package_files
|
127
|
+
@package_files ||= dependency_files.select { |f| f.name.end_with?("package.json") }
|
128
|
+
end
|
129
|
+
|
130
|
+
def base_dir
|
131
|
+
dependency_files.first.directory
|
132
|
+
end
|
133
|
+
|
134
|
+
def npmrc_file
|
135
|
+
dependency_files.find { |f| f.name == ".npmrc" }
|
136
|
+
end
|
137
|
+
|
138
|
+
def sanitize_message(message)
|
139
|
+
message.gsub(/"|\[|\]|\}|\{/, "")
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -62,6 +62,13 @@ module Dependabot
|
|
62
62
|
|
63
63
|
ERR_PNPM_PATCH_NOT_APPLIED = /ERR_PNPM_PATCH_NOT_APPLIED/
|
64
64
|
|
65
|
+
# this intermittent issue is related with Node v20
|
66
|
+
ERR_INVALID_THIS = /ERR_INVALID_THIS/
|
67
|
+
URL_SEARCH_PARAMS = /URLSearchParams/
|
68
|
+
|
69
|
+
# A modules directory is present and is linked to a different store directory.
|
70
|
+
ERR_PNPM_UNEXPECTED_STORE = /ERR_PNPM_UNEXPECTED_STORE/
|
71
|
+
|
65
72
|
# ERR_PNPM_UNSUPPORTED_PLATFORM
|
66
73
|
ERR_PNPM_UNSUPPORTED_PLATFORM = /ERR_PNPM_UNSUPPORTED_PLATFORM/
|
67
74
|
PLATFORM_PACAKGE_DEP = /Unsupported platform for (?<dep>.*)\: wanted/
|
@@ -78,6 +85,16 @@ module Dependabot
|
|
78
85
|
ERR_PNPM_LINKED_PKG_DIR_NOT_FOUND = /ERR_PNPM_LINKED_PKG_DIR_NOT_FOUND*.*Could not install from \"(?<dir>.*)\" /
|
79
86
|
ERR_PNPM_WORKSPACE_PKG_NOT_FOUND = /ERR_PNPM_WORKSPACE_PKG_NOT_FOUND/
|
80
87
|
|
88
|
+
# Unparsable package.json file
|
89
|
+
ERR_PNPM_INVALID_PACKAGE_JSON = /Invalid package.json in package/
|
90
|
+
|
91
|
+
# Unparsable lockfile
|
92
|
+
ERR_PNPM_UNEXPECTED_PKG_CONTENT_IN_STORE = /ERR_PNPM_UNEXPECTED_PKG_CONTENT_IN_STORE/
|
93
|
+
ERR_PNPM_OUTDATED_LOCKFILE = /ERR_PNPM_OUTDATED_LOCKFILE/
|
94
|
+
|
95
|
+
# Peer dependencies configuration error
|
96
|
+
ERR_PNPM_PEER_DEP_ISSUES = /ERR_PNPM_PEER_DEP_ISSUES/
|
97
|
+
|
81
98
|
def run_pnpm_update(pnpm_lock:)
|
82
99
|
SharedHelpers.in_a_temporary_repo_directory(base_dir, repo_contents_path) do
|
83
100
|
File.write(".npmrc", npmrc_content(pnpm_lock))
|
@@ -196,10 +213,39 @@ module Dependabot
|
|
196
213
|
raise Dependabot::DependencyFileNotResolvable, msg
|
197
214
|
end
|
198
215
|
|
216
|
+
if error_message.match?(ERR_PNPM_INVALID_PACKAGE_JSON) || error_message.match?(ERR_PNPM_UNEXPECTED_STORE)
|
217
|
+
msg = "Error while resolving package.json."
|
218
|
+
Dependabot.logger.warn(error_message)
|
219
|
+
raise Dependabot::DependencyFileNotResolvable, msg
|
220
|
+
end
|
221
|
+
|
222
|
+
[ERR_PNPM_UNEXPECTED_PKG_CONTENT_IN_STORE, ERR_PNPM_OUTDATED_LOCKFILE]
|
223
|
+
.each do |regexp|
|
224
|
+
next unless error_message.match?(regexp)
|
225
|
+
|
226
|
+
error_msg = T.let("Error while resolving pnpm-lock.yaml file.", String)
|
227
|
+
|
228
|
+
Dependabot.logger.warn(error_message)
|
229
|
+
raise Dependabot::DependencyFileNotResolvable, error_msg
|
230
|
+
end
|
231
|
+
|
232
|
+
if error_message.match?(ERR_PNPM_PEER_DEP_ISSUES)
|
233
|
+
msg = "Missing or invalid configuration while installing peer dependencies."
|
234
|
+
|
235
|
+
Dependabot.logger.warn(error_message)
|
236
|
+
raise Dependabot::DependencyFileNotResolvable, msg
|
237
|
+
end
|
238
|
+
|
199
239
|
raise_patch_dependency_error(error_message) if error_message.match?(ERR_PNPM_PATCH_NOT_APPLIED)
|
200
240
|
|
201
241
|
raise_unsupported_engine_error(error_message, pnpm_lock) if error_message.match?(ERR_PNPM_UNSUPPORTED_ENGINE)
|
202
242
|
|
243
|
+
if error_message.match?(ERR_INVALID_THIS) && error_message.match?(URL_SEARCH_PARAMS)
|
244
|
+
msg = "Error while resolving dependencies."
|
245
|
+
Dependabot.logger.warn(error_message)
|
246
|
+
raise Dependabot::DependencyFileNotResolvable, msg
|
247
|
+
end
|
248
|
+
|
203
249
|
if error_message.match?(ERR_PNPM_UNSUPPORTED_PLATFORM)
|
204
250
|
raise_unsupported_platform_error(error_message,
|
205
251
|
pnpm_lock)
|
@@ -18,6 +18,7 @@ module Dependabot
|
|
18
18
|
require_relative "file_updater/npm_lockfile_updater"
|
19
19
|
require_relative "file_updater/yarn_lockfile_updater"
|
20
20
|
require_relative "file_updater/pnpm_lockfile_updater"
|
21
|
+
require_relative "file_updater/bun_lockfile_updater"
|
21
22
|
|
22
23
|
class NoChangeError < StandardError
|
23
24
|
extend T::Sig
|
@@ -189,6 +190,15 @@ module Dependabot
|
|
189
190
|
)
|
190
191
|
end
|
191
192
|
|
193
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
194
|
+
def bun_locks
|
195
|
+
@bun_locks ||= T.let(
|
196
|
+
filtered_dependency_files
|
197
|
+
.select { |f| f.name.end_with?("bun.lock") },
|
198
|
+
T.nilable(T::Array[Dependabot::DependencyFile])
|
199
|
+
)
|
200
|
+
end
|
201
|
+
|
192
202
|
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
193
203
|
def shrinkwraps
|
194
204
|
@shrinkwraps ||= T.let(
|
@@ -217,6 +227,11 @@ module Dependabot
|
|
217
227
|
pnpm_lock.content != updated_pnpm_lock_content(pnpm_lock)
|
218
228
|
end
|
219
229
|
|
230
|
+
sig { params(bun_lock: Dependabot::DependencyFile).returns(T::Boolean) }
|
231
|
+
def bun_lock_changed?(bun_lock)
|
232
|
+
bun_lock.content != updated_bun_lock_content(bun_lock)
|
233
|
+
end
|
234
|
+
|
220
235
|
sig { params(package_lock: Dependabot::DependencyFile).returns(T::Boolean) }
|
221
236
|
def package_lock_changed?(package_lock)
|
222
237
|
package_lock.content != updated_lockfile_content(package_lock)
|
@@ -237,6 +252,8 @@ module Dependabot
|
|
237
252
|
end
|
238
253
|
end
|
239
254
|
|
255
|
+
# rubocop:disable Metrics/MethodLength
|
256
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
240
257
|
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
241
258
|
def updated_lockfiles
|
242
259
|
updated_files = []
|
@@ -259,6 +276,15 @@ module Dependabot
|
|
259
276
|
)
|
260
277
|
end
|
261
278
|
|
279
|
+
bun_locks.each do |bun_lock|
|
280
|
+
next unless bun_lock_changed?(bun_lock)
|
281
|
+
|
282
|
+
updated_files << updated_file(
|
283
|
+
file: bun_lock,
|
284
|
+
content: updated_bun_lock_content(bun_lock)
|
285
|
+
)
|
286
|
+
end
|
287
|
+
|
262
288
|
package_locks.each do |package_lock|
|
263
289
|
next unless package_lock_changed?(package_lock)
|
264
290
|
|
@@ -279,6 +305,8 @@ module Dependabot
|
|
279
305
|
|
280
306
|
updated_files
|
281
307
|
end
|
308
|
+
# rubocop:enable Metrics/MethodLength
|
309
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
282
310
|
|
283
311
|
sig { params(yarn_lock: Dependabot::DependencyFile).returns(String) }
|
284
312
|
def updated_yarn_lock_content(yarn_lock)
|
@@ -294,6 +322,13 @@ module Dependabot
|
|
294
322
|
pnpm_lockfile_updater.updated_pnpm_lock_content(pnpm_lock)
|
295
323
|
end
|
296
324
|
|
325
|
+
sig { params(bun_lock: Dependabot::DependencyFile).returns(String) }
|
326
|
+
def updated_bun_lock_content(bun_lock)
|
327
|
+
@updated_bun_lock_content ||= T.let({}, T.nilable(T::Hash[String, T.nilable(String)]))
|
328
|
+
@updated_bun_lock_content[bun_lock.name] ||=
|
329
|
+
bun_lockfile_updater.updated_bun_lock_content(bun_lock)
|
330
|
+
end
|
331
|
+
|
297
332
|
sig { returns(Dependabot::NpmAndYarn::FileUpdater::YarnLockfileUpdater) }
|
298
333
|
def yarn_lockfile_updater
|
299
334
|
@yarn_lockfile_updater ||= T.let(
|
@@ -320,6 +355,19 @@ module Dependabot
|
|
320
355
|
)
|
321
356
|
end
|
322
357
|
|
358
|
+
sig { returns(Dependabot::NpmAndYarn::FileUpdater::BunLockfileUpdater) }
|
359
|
+
def bun_lockfile_updater
|
360
|
+
@bun_lockfile_updater ||= T.let(
|
361
|
+
BunLockfileUpdater.new(
|
362
|
+
dependencies: dependencies,
|
363
|
+
dependency_files: dependency_files,
|
364
|
+
repo_contents_path: repo_contents_path,
|
365
|
+
credentials: credentials
|
366
|
+
),
|
367
|
+
T.nilable(Dependabot::NpmAndYarn::FileUpdater::BunLockfileUpdater)
|
368
|
+
)
|
369
|
+
end
|
370
|
+
|
323
371
|
sig { params(file: Dependabot::DependencyFile).returns(T.nilable(String)) }
|
324
372
|
def updated_lockfile_content(file)
|
325
373
|
@updated_lockfile_content ||= T.let({}, T.nilable(T::Hash[String, T.nilable(String)]))
|
@@ -29,6 +29,10 @@ module Dependabot
|
|
29
29
|
PNPM_DEFAULT_VERSION = PNPM_V9
|
30
30
|
PNPM_FALLBACK_VERSION = PNPM_V6
|
31
31
|
|
32
|
+
# BUN Version Constants
|
33
|
+
BUN_V1 = 1
|
34
|
+
BUN_DEFAULT_VERSION = BUN_V1
|
35
|
+
|
32
36
|
# YARN Version Constants
|
33
37
|
YARN_V3 = 3
|
34
38
|
YARN_V2 = 2
|
@@ -159,6 +163,11 @@ module Dependabot
|
|
159
163
|
PNPM_FALLBACK_VERSION
|
160
164
|
end
|
161
165
|
|
166
|
+
sig { params(_bun_lock: T.nilable(DependencyFile)).returns(Integer) }
|
167
|
+
def self.bun_version_numeric(_bun_lock)
|
168
|
+
BUN_DEFAULT_VERSION
|
169
|
+
end
|
170
|
+
|
162
171
|
sig { params(key: String, default_value: String).returns(T.untyped) }
|
163
172
|
def self.fetch_yarnrc_yml_value(key, default_value)
|
164
173
|
if File.exist?(".yarnrc.yml") && (yarnrc = YAML.load_file(".yarnrc.yml"))
|
@@ -352,6 +361,35 @@ module Dependabot
|
|
352
361
|
raise
|
353
362
|
end
|
354
363
|
|
364
|
+
sig { returns(T.nilable(String)) }
|
365
|
+
def self.bun_version
|
366
|
+
version = run_bun_command("--version", fingerprint: "--version").strip
|
367
|
+
if version.include?("+")
|
368
|
+
version.split("+").first # Remove build info, if present
|
369
|
+
end
|
370
|
+
rescue StandardError => e
|
371
|
+
Dependabot.logger.error("Error retrieving Bun version: #{e.message}")
|
372
|
+
nil
|
373
|
+
end
|
374
|
+
|
375
|
+
sig { params(command: String, fingerprint: T.nilable(String)).returns(String) }
|
376
|
+
def self.run_bun_command(command, fingerprint: nil)
|
377
|
+
full_command = "bun #{command}"
|
378
|
+
|
379
|
+
Dependabot.logger.info("Running bun command: #{full_command}")
|
380
|
+
|
381
|
+
result = Dependabot::SharedHelpers.run_shell_command(
|
382
|
+
full_command,
|
383
|
+
fingerprint: "bun #{fingerprint || command}"
|
384
|
+
)
|
385
|
+
|
386
|
+
Dependabot.logger.info("Command executed successfully: #{full_command}")
|
387
|
+
result
|
388
|
+
rescue StandardError => e
|
389
|
+
Dependabot.logger.error("Error running bun command: #{full_command}, Error: #{e.message}")
|
390
|
+
raise
|
391
|
+
end
|
392
|
+
|
355
393
|
# Setup yarn and run a single yarn command returning stdout/stderr
|
356
394
|
sig { params(command: String, fingerprint: T.nilable(String)).returns(String) }
|
357
395
|
def self.run_yarn_command(command, fingerprint: nil)
|
@@ -496,6 +534,8 @@ module Dependabot
|
|
496
534
|
).returns(String)
|
497
535
|
end
|
498
536
|
def self.package_manager_run_command(name, command, fingerprint: nil)
|
537
|
+
return run_bun_command(command, fingerprint: fingerprint) if name == BunPackageManager::NAME
|
538
|
+
|
499
539
|
full_command = "corepack #{name} #{command}"
|
500
540
|
|
501
541
|
result = Dependabot::SharedHelpers.run_shell_command(
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# typed: strong
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "dependabot/npm_and_yarn/package_manager"
|
5
|
+
|
6
|
+
module Dependabot
|
7
|
+
module NpmAndYarn
|
8
|
+
class Language < Ecosystem::VersionManager
|
9
|
+
extend T::Sig
|
10
|
+
NAME = "node"
|
11
|
+
|
12
|
+
SUPPORTED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version])
|
13
|
+
|
14
|
+
DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version])
|
15
|
+
|
16
|
+
sig do
|
17
|
+
params(
|
18
|
+
detected_version: T.nilable(String),
|
19
|
+
raw_version: T.nilable(String),
|
20
|
+
requirement: T.nilable(Dependabot::NpmAndYarn::Requirement)
|
21
|
+
).void
|
22
|
+
end
|
23
|
+
def initialize(detected_version: nil, raw_version: nil, requirement: nil)
|
24
|
+
super(
|
25
|
+
name: NAME,
|
26
|
+
detected_version: detected_version ? Version.new(detected_version) : nil,
|
27
|
+
version: raw_version ? Version.new(raw_version) : nil,
|
28
|
+
deprecated_versions: DEPRECATED_VERSIONS,
|
29
|
+
supported_versions: SUPPORTED_VERSIONS,
|
30
|
+
requirement: requirement
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
sig { override.returns(T::Boolean) }
|
35
|
+
def deprecated?
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
39
|
+
sig { override.returns(T::Boolean) }
|
40
|
+
def unsupported?
|
41
|
+
false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# typed: strong
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "dependabot/npm_and_yarn/package_manager"
|
5
|
+
|
6
|
+
module Dependabot
|
7
|
+
module NpmAndYarn
|
8
|
+
class NpmPackageManager < Ecosystem::VersionManager
|
9
|
+
extend T::Sig
|
10
|
+
NAME = "npm"
|
11
|
+
RC_FILENAME = ".npmrc"
|
12
|
+
LOCKFILE_NAME = "package-lock.json"
|
13
|
+
SHRINKWRAP_LOCKFILE_NAME = "npm-shrinkwrap.json"
|
14
|
+
|
15
|
+
NPM_V6 = "6"
|
16
|
+
NPM_V7 = "7"
|
17
|
+
NPM_V8 = "8"
|
18
|
+
NPM_V9 = "9"
|
19
|
+
NPM_V10 = "10"
|
20
|
+
|
21
|
+
# Keep versions in ascending order
|
22
|
+
SUPPORTED_VERSIONS = T.let([
|
23
|
+
Version.new(NPM_V7),
|
24
|
+
Version.new(NPM_V8),
|
25
|
+
Version.new(NPM_V9),
|
26
|
+
Version.new(NPM_V10)
|
27
|
+
].freeze, T::Array[Dependabot::Version])
|
28
|
+
|
29
|
+
DEPRECATED_VERSIONS = T.let([Version.new(NPM_V6)].freeze, T::Array[Dependabot::Version])
|
30
|
+
|
31
|
+
sig do
|
32
|
+
params(
|
33
|
+
detected_version: T.nilable(String),
|
34
|
+
raw_version: T.nilable(String),
|
35
|
+
requirement: T.nilable(Dependabot::NpmAndYarn::Requirement)
|
36
|
+
).void
|
37
|
+
end
|
38
|
+
def initialize(detected_version: nil, raw_version: nil, requirement: nil)
|
39
|
+
super(
|
40
|
+
name: NAME,
|
41
|
+
detected_version: detected_version ? Version.new(detected_version) : nil,
|
42
|
+
version: raw_version ? Version.new(raw_version) : nil,
|
43
|
+
deprecated_versions: DEPRECATED_VERSIONS,
|
44
|
+
supported_versions: SUPPORTED_VERSIONS,
|
45
|
+
requirement: requirement
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
sig { override.returns(T::Boolean) }
|
50
|
+
def deprecated?
|
51
|
+
return false unless detected_version
|
52
|
+
|
53
|
+
return false if unsupported?
|
54
|
+
|
55
|
+
return false unless Dependabot::Experiments.enabled?(:npm_v6_deprecation_warning)
|
56
|
+
|
57
|
+
deprecated_versions.include?(detected_version)
|
58
|
+
end
|
59
|
+
|
60
|
+
sig { override.returns(T::Boolean) }
|
61
|
+
def unsupported?
|
62
|
+
return false unless detected_version
|
63
|
+
|
64
|
+
return false unless Dependabot::Experiments.enabled?(:npm_v6_unsupported_error)
|
65
|
+
|
66
|
+
supported_versions.all? { |supported| supported > detected_version }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|