@socketsecurity/cli-with-sentry 0.14.93 → 0.14.95

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.
Files changed (84) hide show
  1. package/dist/constants.js +3 -3
  2. package/dist/constants.js.map +1 -1
  3. package/dist/instrument-with-sentry.js +2 -2
  4. package/dist/instrument-with-sentry.js.map +1 -1
  5. package/dist/module-sync/cli.js +177 -157
  6. package/dist/module-sync/cli.js.map +1 -1
  7. package/dist/module-sync/shadow-bin.js +3 -14
  8. package/dist/module-sync/shadow-bin.js.map +1 -1
  9. package/dist/module-sync/shadow-npm-inject.js +68 -59
  10. package/dist/module-sync/shadow-npm-inject.js.map +1 -1
  11. package/dist/module-sync/shadow-npm-paths.js +16 -29
  12. package/dist/module-sync/shadow-npm-paths.js.map +1 -1
  13. package/dist/module-sync/vendor.d.ts +0 -0
  14. package/dist/module-sync/vendor.js +85829 -12598
  15. package/dist/module-sync/vendor.js.map +1 -1
  16. package/dist/require/cli.js +159 -138
  17. package/dist/require/cli.js.map +1 -1
  18. package/dist/require/shadow-bin.d.ts +5 -0
  19. package/dist/require/shadow-bin.js +108 -1
  20. package/dist/require/shadow-bin.js.map +1 -0
  21. package/dist/require/shadow-npm-inject.d.ts +1 -0
  22. package/dist/require/shadow-npm-inject.js +2335 -1
  23. package/dist/require/shadow-npm-inject.js.map +1 -0
  24. package/dist/require/shadow-npm-paths.d.ts +29 -0
  25. package/dist/require/shadow-npm-paths.js +454 -1
  26. package/dist/require/shadow-npm-paths.js.map +1 -0
  27. package/package.json +29 -29
  28. package/dist/blessed/lib/alias.js +0 -521
  29. package/dist/blessed/lib/blessed.js +0 -34
  30. package/dist/blessed/lib/colors.js +0 -492
  31. package/dist/blessed/lib/events.js +0 -197
  32. package/dist/blessed/lib/gpmclient.js +0 -247
  33. package/dist/blessed/lib/helpers.js +0 -172
  34. package/dist/blessed/lib/keys.js +0 -514
  35. package/dist/blessed/lib/program.js +0 -4532
  36. package/dist/blessed/lib/tput.js +0 -3113
  37. package/dist/blessed/lib/unicode.js +0 -914
  38. package/dist/blessed/lib/widget.js +0 -62
  39. package/dist/blessed/lib/widgets/ansiimage.js +0 -175
  40. package/dist/blessed/lib/widgets/bigtext.js +0 -172
  41. package/dist/blessed/lib/widgets/box.js +0 -36
  42. package/dist/blessed/lib/widgets/button.js +0 -64
  43. package/dist/blessed/lib/widgets/checkbox.js +0 -97
  44. package/dist/blessed/lib/widgets/element.js +0 -2873
  45. package/dist/blessed/lib/widgets/filemanager.js +0 -225
  46. package/dist/blessed/lib/widgets/form.js +0 -303
  47. package/dist/blessed/lib/widgets/image.js +0 -73
  48. package/dist/blessed/lib/widgets/input.js +0 -36
  49. package/dist/blessed/lib/widgets/layout.js +0 -251
  50. package/dist/blessed/lib/widgets/line.js +0 -61
  51. package/dist/blessed/lib/widgets/list.js +0 -654
  52. package/dist/blessed/lib/widgets/listbar.js +0 -454
  53. package/dist/blessed/lib/widgets/listtable.js +0 -267
  54. package/dist/blessed/lib/widgets/loading.js +0 -90
  55. package/dist/blessed/lib/widgets/log.js +0 -84
  56. package/dist/blessed/lib/widgets/message.js +0 -147
  57. package/dist/blessed/lib/widgets/node.js +0 -315
  58. package/dist/blessed/lib/widgets/overlayimage.js +0 -796
  59. package/dist/blessed/lib/widgets/progressbar.js +0 -168
  60. package/dist/blessed/lib/widgets/prompt.js +0 -129
  61. package/dist/blessed/lib/widgets/question.js +0 -131
  62. package/dist/blessed/lib/widgets/radiobutton.js +0 -64
  63. package/dist/blessed/lib/widgets/radioset.js +0 -38
  64. package/dist/blessed/lib/widgets/screen.js +0 -2487
  65. package/dist/blessed/lib/widgets/scrollablebox.js +0 -417
  66. package/dist/blessed/lib/widgets/scrollabletext.js +0 -37
  67. package/dist/blessed/lib/widgets/table.js +0 -385
  68. package/dist/blessed/lib/widgets/terminal.js +0 -454
  69. package/dist/blessed/lib/widgets/text.js +0 -37
  70. package/dist/blessed/lib/widgets/textarea.js +0 -378
  71. package/dist/blessed/lib/widgets/textbox.js +0 -81
  72. package/dist/blessed/lib/widgets/video.js +0 -132
  73. package/dist/blessed/usr/fonts/AUTHORS +0 -1
  74. package/dist/blessed/usr/fonts/LICENSE +0 -94
  75. package/dist/blessed/usr/fonts/README +0 -340
  76. package/dist/blessed/usr/fonts/ter-u14b.json +0 -17826
  77. package/dist/blessed/usr/fonts/ter-u14n.json +0 -17826
  78. package/dist/blessed/usr/linux +0 -0
  79. package/dist/blessed/usr/windows-ansi +0 -0
  80. package/dist/blessed/usr/xterm +0 -0
  81. package/dist/blessed/usr/xterm-256color +0 -0
  82. package/dist/blessed/usr/xterm.termcap +0 -243
  83. package/dist/blessed/usr/xterm.terminfo +0 -1977
  84. package/dist/blessed/vendor/tng.js +0 -1878
@@ -1,3 +1,2337 @@
1
1
  'use strict'
2
2
 
3
- module.exports = require('../module-sync/shadow-npm-inject.js')
3
+ const shadowNpmPaths = require('./shadow-npm-paths.js')
4
+ const process$1 = require('node:process')
5
+ const vendor = require('./vendor.js')
6
+ const logger = require('@socketsecurity/registry/lib/logger')
7
+ const constants = require('./constants.js')
8
+ const packageurlJs = require('@socketregistry/packageurl-js')
9
+ const registry = require('@socketsecurity/registry')
10
+ const arrays = require('@socketsecurity/registry/lib/arrays')
11
+ const debug = require('@socketsecurity/registry/lib/debug')
12
+ const objects = require('@socketsecurity/registry/lib/objects')
13
+ const isInteractive = require('@socketregistry/is-interactive/index.cjs')
14
+ const registryConstants = require('@socketsecurity/registry/lib/constants')
15
+ const prompts = require('@socketsecurity/registry/lib/prompts')
16
+ const strings = require('@socketsecurity/registry/lib/strings')
17
+ const sdk = require('@socketsecurity/sdk')
18
+ const require$$0 = require('node:fs')
19
+ const os = require('node:os')
20
+ const path = require('node:path')
21
+ const promises = require('node:timers/promises')
22
+ const packages = require('@socketsecurity/registry/lib/packages')
23
+ const sorts = require('@socketsecurity/registry/lib/sorts')
24
+ const indentString = require('@socketregistry/indent-string/index.cjs')
25
+
26
+ const { abortSignal } = constants
27
+ async function findUp(name, { cwd = process$1.cwd(), signal = abortSignal }) {
28
+ let dir = path.resolve(cwd)
29
+ const { root } = path.parse(dir)
30
+ const names = [name].flat()
31
+ while (dir && dir !== root) {
32
+ for (const name of names) {
33
+ if (signal?.aborted) {
34
+ return undefined
35
+ }
36
+ const filePath = path.join(dir, name)
37
+ try {
38
+ // eslint-disable-next-line no-await-in-loop
39
+ const stats = await require$$0.promises.stat(filePath)
40
+ if (stats.isFile()) {
41
+ return filePath
42
+ }
43
+ } catch {}
44
+ }
45
+ dir = path.dirname(dir)
46
+ }
47
+ return undefined
48
+ }
49
+ async function readFileBinary(filepath, options) {
50
+ return await require$$0.promises.readFile(filepath, {
51
+ signal: abortSignal,
52
+ ...options,
53
+ encoding: 'binary'
54
+ })
55
+ }
56
+ async function readFileUtf8(filepath, options) {
57
+ return await require$$0.promises.readFile(filepath, {
58
+ signal: abortSignal,
59
+ ...options,
60
+ encoding: 'utf8'
61
+ })
62
+ }
63
+ async function safeReadFile(filepath, options) {
64
+ try {
65
+ return await require$$0.promises.readFile(filepath, {
66
+ encoding: 'utf8',
67
+ signal: abortSignal,
68
+ ...(typeof options === 'string'
69
+ ? {
70
+ encoding: options
71
+ }
72
+ : options)
73
+ })
74
+ } catch {}
75
+ return undefined
76
+ }
77
+ function safeReadFileSync(filepath, options) {
78
+ try {
79
+ return require$$0.readFileSync(filepath, {
80
+ encoding: 'utf8',
81
+ ...(typeof options === 'string'
82
+ ? {
83
+ encoding: options
84
+ }
85
+ : options)
86
+ })
87
+ } catch {}
88
+ return undefined
89
+ }
90
+
91
+ const { LOCALAPPDATA, SOCKET_APP_DIR, XDG_DATA_HOME } = constants
92
+ const supportedConfigKeys = new Map([
93
+ ['apiBaseUrl', 'Base URL of the API endpoint'],
94
+ ['apiProxy', 'A proxy through which to access the API'],
95
+ ['apiToken', 'The API token required to access most API endpoints'],
96
+ [
97
+ 'defaultOrg',
98
+ 'The default org slug to use; usually the org your API token has access to. When set, all orgSlug arguments are implied to be this value.'
99
+ ],
100
+ [
101
+ 'enforcedOrgs',
102
+ 'Orgs in this list have their security policies enforced on this machine'
103
+ ]
104
+ ])
105
+ const sensitiveConfigKeys = new Set(['apiToken'])
106
+ let _cachedConfig
107
+ // When using --config or SOCKET_CLI_CONFIG, do not persist the config.
108
+ let _readOnlyConfig = false
109
+ function overrideCachedConfig(jsonConfig) {
110
+ let config
111
+ try {
112
+ config = JSON.parse(String(jsonConfig))
113
+ if (!config || typeof config !== 'object') {
114
+ // Just throw to reuse the error message. `null` is valid json,
115
+ // so are primitive values. They're not valid config objects :)
116
+ throw new Error()
117
+ }
118
+ } catch {
119
+ return {
120
+ ok: false,
121
+ message:
122
+ "Could not JSON parse the config override. Make sure it's a proper JSON object (double-quoted keys and strings, no unquoted `undefined`) and try again."
123
+ }
124
+ }
125
+
126
+ // @ts-ignore if you want to override an illegal object, so be it?
127
+ _cachedConfig = config
128
+ _readOnlyConfig = true
129
+
130
+ // Normalize apiKey to apiToken.
131
+ if (_cachedConfig['apiKey']) {
132
+ if (_cachedConfig['apiToken']) {
133
+ logger.logger.warn(
134
+ 'Note: The config override had both apiToken and apiKey. Using the apiToken value. Remove the apiKey to get rid of this message.'
135
+ )
136
+ }
137
+ _cachedConfig['apiToken'] = _cachedConfig['apiKey']
138
+ delete _cachedConfig['apiKey']
139
+ }
140
+ return {
141
+ ok: true,
142
+ message: undefined
143
+ }
144
+ }
145
+ function overrideConfigApiToken(apiToken) {
146
+ // Set token to the local cached config and mark it read-only so it doesn't persist
147
+ _cachedConfig = {
148
+ ...vendor.configExports,
149
+ ...(apiToken === undefined
150
+ ? {}
151
+ : {
152
+ apiToken: String(apiToken)
153
+ })
154
+ }
155
+ _readOnlyConfig = true
156
+ }
157
+ function getConfigValues() {
158
+ if (_cachedConfig === undefined) {
159
+ _cachedConfig = {}
160
+ // Order: env var > --config flag > file
161
+ const configPath = getConfigPath()
162
+ if (configPath) {
163
+ const raw = safeReadFileSync(configPath)
164
+ if (raw) {
165
+ try {
166
+ Object.assign(
167
+ _cachedConfig,
168
+ JSON.parse(Buffer.from(raw, 'base64').toString())
169
+ )
170
+ } catch {
171
+ logger.logger.warn(`Failed to parse config at ${configPath}`)
172
+ }
173
+ // Normalize apiKey to apiToken and persist it.
174
+ // This is a one time migration per user.
175
+ if (_cachedConfig['apiKey']) {
176
+ const token = _cachedConfig['apiKey']
177
+ delete _cachedConfig['apiKey']
178
+ updateConfigValue('apiToken', token)
179
+ }
180
+ } else {
181
+ require$$0.mkdirSync(path.dirname(configPath), {
182
+ recursive: true
183
+ })
184
+ }
185
+ }
186
+ }
187
+ return _cachedConfig
188
+ }
189
+ let _configPath
190
+ let _warnedConfigPathWin32Missing = false
191
+ function getConfigPath() {
192
+ // Get the OS app data folder:
193
+ // - Win: %LOCALAPPDATA% or fail?
194
+ // - Mac: %XDG_DATA_HOME% or fallback to "~/Library/Application Support/"
195
+ // - Linux: %XDG_DATA_HOME% or fallback to "~/.local/share/"
196
+ // Note: LOCALAPPDATA is typically: C:\Users\USERNAME\AppData
197
+ // Note: XDG stands for "X Desktop Group", nowadays "freedesktop.org"
198
+ // On most systems that path is: $HOME/.local/share
199
+ // Then append `socket/settings`, so:
200
+ // - Win: %LOCALAPPDATA%\socket\settings or return undefined
201
+ // - Mac: %XDG_DATA_HOME%/socket/settings or "~/Library/Application Support/socket/settings"
202
+ // - Linux: %XDG_DATA_HOME%/socket/settings or "~/.local/share/socket/settings"
203
+
204
+ if (_configPath === undefined) {
205
+ // Lazily access constants.WIN32.
206
+ const { WIN32 } = constants
207
+ let dataHome = WIN32
208
+ ? // Lazily access constants.ENV[LOCALAPPDATA]
209
+ constants.ENV[LOCALAPPDATA]
210
+ : // Lazily access constants.ENV[XDG_DATA_HOME]
211
+ constants.ENV[XDG_DATA_HOME]
212
+ if (!dataHome) {
213
+ if (WIN32) {
214
+ if (!_warnedConfigPathWin32Missing) {
215
+ _warnedConfigPathWin32Missing = true
216
+ logger.logger.warn(`Missing %${LOCALAPPDATA}%`)
217
+ }
218
+ } else {
219
+ dataHome = path.join(
220
+ os.homedir(),
221
+ ...(process$1.platform === 'darwin'
222
+ ? ['Library', 'Application Support']
223
+ : ['.local', 'share'])
224
+ )
225
+ }
226
+ }
227
+ _configPath = dataHome ? path.join(dataHome, SOCKET_APP_DIR) : undefined
228
+ }
229
+ return _configPath
230
+ }
231
+ function normalizeConfigKey(key) {
232
+ // Note: apiKey was the old name of the token. When we load a config with
233
+ // property apiKey, we'll copy that to apiToken and delete the old property.
234
+ const normalizedKey = key === 'apiKey' ? 'apiToken' : key
235
+ if (!supportedConfigKeys.has(normalizedKey)) {
236
+ throw new Error(`Invalid config key: ${normalizedKey}`)
237
+ }
238
+ return normalizedKey
239
+ }
240
+ function findSocketYmlSync(dir = process$1.cwd()) {
241
+ let prevDir = null
242
+ while (dir !== prevDir) {
243
+ let ymlPath = path.join(dir, 'socket.yml')
244
+ let yml = safeReadFileSync(ymlPath)
245
+ if (yml === undefined) {
246
+ ymlPath = path.join(dir, 'socket.yaml')
247
+ yml = safeReadFileSync(ymlPath)
248
+ }
249
+ if (typeof yml === 'string') {
250
+ try {
251
+ return {
252
+ path: ymlPath,
253
+ parsed: vendor.configExports.parseSocketConfig(yml)
254
+ }
255
+ } catch {
256
+ throw new Error(`Found file but was unable to parse ${ymlPath}`)
257
+ }
258
+ }
259
+ prevDir = dir
260
+ dir = path.join(dir, '..')
261
+ }
262
+ return null
263
+ }
264
+ function getConfigValue(key) {
265
+ const localConfig = getConfigValues()
266
+ return localConfig[normalizeConfigKey(key)]
267
+ }
268
+ function isReadOnlyConfig() {
269
+ return _readOnlyConfig
270
+ }
271
+ let _pendingSave = false
272
+ function updateConfigValue(key, value) {
273
+ const localConfig = getConfigValues()
274
+ localConfig[normalizeConfigKey(key)] = value
275
+ if (_readOnlyConfig) {
276
+ logger.logger.warn(
277
+ 'Not persisting config change; current config overridden through env var or flag'
278
+ )
279
+ } else if (!_pendingSave) {
280
+ _pendingSave = true
281
+ process$1.nextTick(() => {
282
+ _pendingSave = false
283
+ const configPath = getConfigPath()
284
+ if (configPath) {
285
+ require$$0.writeFileSync(
286
+ configPath,
287
+ Buffer.from(JSON.stringify(localConfig)).toString('base64')
288
+ )
289
+ }
290
+ })
291
+ }
292
+ }
293
+
294
+ const {
295
+ kInternalsSymbol: kInternalsSymbol$1,
296
+ [kInternalsSymbol$1]: { getSentry }
297
+ } = constants
298
+ class AuthError extends Error {}
299
+ class InputError extends Error {
300
+ constructor(message, body) {
301
+ super(message)
302
+ this.body = body
303
+ }
304
+ }
305
+ async function captureException(exception, hint) {
306
+ const result = captureExceptionSync(exception, hint)
307
+ // "Sleep" for a second, just in case, hopefully enough time to initiate fetch.
308
+ await promises.setTimeout(1000)
309
+ return result
310
+ }
311
+ function captureExceptionSync(exception, hint) {
312
+ const Sentry = getSentry()
313
+ if (!Sentry) {
314
+ return ''
315
+ }
316
+ debug.debugLog('captureException: Sending exception to Sentry')
317
+ return Sentry.captureException(exception, hint)
318
+ }
319
+
320
+ const {
321
+ SOCKET_CLI_NO_API_TOKEN,
322
+ SOCKET_SECURITY_API_BASE_URL,
323
+ SOCKET_SECURITY_API_PROXY,
324
+ SOCKET_SECURITY_API_TOKEN
325
+ } = constants
326
+
327
+ // The API server that should be used for operations.
328
+ function getDefaultApiBaseUrl() {
329
+ const baseUrl =
330
+ // Lazily access constants.ENV[SOCKET_SECURITY_API_BASE_URL].
331
+ constants.ENV[SOCKET_SECURITY_API_BASE_URL] || getConfigValue('apiBaseUrl')
332
+ return strings.isNonEmptyString(baseUrl) ? baseUrl : undefined
333
+ }
334
+
335
+ // The API server that should be used for operations.
336
+ function getDefaultHttpProxy() {
337
+ const apiProxy =
338
+ // Lazily access constants.ENV[SOCKET_SECURITY_API_PROXY].
339
+ constants.ENV[SOCKET_SECURITY_API_PROXY] || getConfigValue('apiProxy')
340
+ return strings.isNonEmptyString(apiProxy) ? apiProxy : undefined
341
+ }
342
+
343
+ // This API key should be stored globally for the duration of the CLI execution.
344
+ let _defaultToken
345
+ function getDefaultToken() {
346
+ // Lazily access constants.ENV[SOCKET_CLI_NO_API_TOKEN].
347
+ if (constants.ENV[SOCKET_CLI_NO_API_TOKEN]) {
348
+ _defaultToken = undefined
349
+ } else {
350
+ const key =
351
+ // Lazily access constants.ENV[SOCKET_SECURITY_API_TOKEN].
352
+ constants.ENV[SOCKET_SECURITY_API_TOKEN] ||
353
+ getConfigValue('apiToken') ||
354
+ _defaultToken
355
+ _defaultToken = strings.isNonEmptyString(key) ? key : undefined
356
+ }
357
+ return _defaultToken
358
+ }
359
+ function getPublicToken() {
360
+ return (
361
+ // Lazily access constants.ENV[SOCKET_SECURITY_API_TOKEN].
362
+ (constants.ENV[SOCKET_SECURITY_API_TOKEN] || getDefaultToken()) ??
363
+ registryConstants.SOCKET_PUBLIC_API_TOKEN
364
+ )
365
+ }
366
+ async function setupSdk(
367
+ apiToken = getDefaultToken(),
368
+ apiBaseUrl = getDefaultApiBaseUrl(),
369
+ proxy = getDefaultHttpProxy()
370
+ ) {
371
+ if (typeof apiToken !== 'string' && isInteractive()) {
372
+ apiToken = await prompts.password({
373
+ message:
374
+ 'Enter your Socket.dev API key (not saved, use socket login to persist)'
375
+ })
376
+ _defaultToken = apiToken
377
+ }
378
+ if (!apiToken) {
379
+ throw new AuthError('You need to provide an API key')
380
+ }
381
+ return new sdk.SocketSdk(apiToken, {
382
+ agent: proxy
383
+ ? new vendor.HttpsProxyAgent({
384
+ proxy
385
+ })
386
+ : undefined,
387
+ baseUrl: apiBaseUrl,
388
+ userAgent: sdk.createUserAgentFromPkgJson({
389
+ // The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_NAME']".
390
+ name: '@socketsecurity/cli',
391
+ // The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_VERSION']".
392
+ version: '0.14.95',
393
+ // The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_HOMEPAGE']".
394
+ homepage: 'https://github.com/SocketDev/socket-cli'
395
+ })
396
+ })
397
+ }
398
+
399
+ const DiffAction = /*#__PURE__*/ (function (DiffAction) {
400
+ DiffAction['add'] = 'ADD'
401
+ DiffAction['change'] = 'CHANGE'
402
+ DiffAction['remove'] = 'REMOVE'
403
+ return DiffAction
404
+ })({})
405
+
406
+ const depValid = require(shadowNpmPaths.getArboristDepValidPath())
407
+
408
+ const { UNDEFINED_TOKEN } = constants
409
+ function tryRequire(req, ...ids) {
410
+ for (const data of ids) {
411
+ let id
412
+ let transformer
413
+ if (Array.isArray(data)) {
414
+ id = data[0]
415
+ transformer = data[1]
416
+ } else {
417
+ id = data
418
+ transformer = mod => mod
419
+ }
420
+ try {
421
+ // Check that the transformed value isn't `undefined` because older
422
+ // versions of packages like 'proc-log' may not export a `log` method.
423
+ const exported = transformer(req(id))
424
+ if (exported !== undefined) {
425
+ return exported
426
+ }
427
+ } catch {}
428
+ }
429
+ return undefined
430
+ }
431
+ let _log = UNDEFINED_TOKEN
432
+ function getLogger() {
433
+ if (_log === UNDEFINED_TOKEN) {
434
+ _log = tryRequire(
435
+ shadowNpmPaths.getNpmRequire(),
436
+ [
437
+ 'proc-log/lib/index.js',
438
+ // The proc-log DefinitelyTyped definition is incorrect. The type definition
439
+ // is really that of its export log.
440
+ mod => mod.log
441
+ ],
442
+ 'npmlog/lib/log.js'
443
+ )
444
+ }
445
+ return _log
446
+ }
447
+
448
+ const OverrideSet = require(shadowNpmPaths.getArboristOverrideSetClassPath())
449
+
450
+ // Implementation code not related to patch https://github.com/npm/cli/pull/8089
451
+ // is based on https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/override-set.js:
452
+ class SafeOverrideSet extends OverrideSet {
453
+ // Patch adding doOverrideSetsConflict is based on
454
+ // https://github.com/npm/cli/pull/8089.
455
+ static doOverrideSetsConflict(first, second) {
456
+ // If override sets contain one another then we can try to use the more
457
+ // specific one. If neither one is more specific, then we consider them to
458
+ // be in conflict.
459
+ return this.findSpecificOverrideSet(first, second) === undefined
460
+ }
461
+
462
+ // Patch adding findSpecificOverrideSet is based on
463
+ // https://github.com/npm/cli/pull/8089.
464
+ static findSpecificOverrideSet(first, second) {
465
+ for (
466
+ let overrideSet = second;
467
+ overrideSet;
468
+ overrideSet = overrideSet.parent
469
+ ) {
470
+ if (overrideSet.isEqual(first)) {
471
+ return second
472
+ }
473
+ }
474
+ for (
475
+ let overrideSet = first;
476
+ overrideSet;
477
+ overrideSet = overrideSet.parent
478
+ ) {
479
+ if (overrideSet.isEqual(second)) {
480
+ return first
481
+ }
482
+ }
483
+ // The override sets are incomparable. Neither one contains the other.
484
+ const log = getLogger()
485
+ log?.silly('Conflicting override sets', first, second)
486
+ return undefined
487
+ }
488
+
489
+ // Patch adding childrenAreEqual is based on
490
+ // https://github.com/npm/cli/pull/8089.
491
+ childrenAreEqual(otherOverrideSet) {
492
+ if (this.children.size !== otherOverrideSet.children.size) {
493
+ return false
494
+ }
495
+ for (const { 0: key, 1: childOverrideSet } of this.children) {
496
+ const otherChildOverrideSet = otherOverrideSet.children.get(key)
497
+ if (!otherChildOverrideSet) {
498
+ return false
499
+ }
500
+ if (childOverrideSet.value !== otherChildOverrideSet.value) {
501
+ return false
502
+ }
503
+ if (!childOverrideSet.childrenAreEqual(otherChildOverrideSet)) {
504
+ return false
505
+ }
506
+ }
507
+ return true
508
+ }
509
+ getEdgeRule(edge) {
510
+ for (const rule of this.ruleset.values()) {
511
+ if (rule.name !== edge.name) {
512
+ continue
513
+ }
514
+ // If keySpec is * we found our override.
515
+ if (rule.keySpec === '*') {
516
+ return rule
517
+ }
518
+ // Patch replacing
519
+ // let spec = npa(`${edge.name}@${edge.spec}`)
520
+ // is based on https://github.com/npm/cli/pull/8089.
521
+ //
522
+ // We need to use the rawSpec here, because the spec has the overrides
523
+ // applied to it already. The rawSpec can be undefined, so we need to use
524
+ // the fallback value of spec if it is.
525
+ let spec = vendor.npaExports(`${edge.name}@${edge.rawSpec || edge.spec}`)
526
+ if (spec.type === 'alias') {
527
+ spec = spec.subSpec
528
+ }
529
+ if (spec.type === 'git') {
530
+ if (
531
+ spec.gitRange &&
532
+ vendor.semverExports.intersects(spec.gitRange, rule.keySpec)
533
+ ) {
534
+ return rule
535
+ }
536
+ continue
537
+ }
538
+ if (spec.type === 'range' || spec.type === 'version') {
539
+ if (vendor.semverExports.intersects(spec.fetchSpec, rule.keySpec)) {
540
+ return rule
541
+ }
542
+ continue
543
+ }
544
+ // If we got this far, the spec type is one of tag, directory or file
545
+ // which means we have no real way to make version comparisons, so we
546
+ // just accept the override.
547
+ return rule
548
+ }
549
+ return this
550
+ }
551
+
552
+ // Patch adding isEqual is based on
553
+ // https://github.com/npm/cli/pull/8089.
554
+ isEqual(otherOverrideSet) {
555
+ if (this === otherOverrideSet) {
556
+ return true
557
+ }
558
+ if (!otherOverrideSet) {
559
+ return false
560
+ }
561
+ if (
562
+ this.key !== otherOverrideSet.key ||
563
+ this.value !== otherOverrideSet.value
564
+ ) {
565
+ return false
566
+ }
567
+ if (!this.childrenAreEqual(otherOverrideSet)) {
568
+ return false
569
+ }
570
+ if (!this.parent) {
571
+ return !otherOverrideSet.parent
572
+ }
573
+ return this.parent.isEqual(otherOverrideSet.parent)
574
+ }
575
+ }
576
+
577
+ const Node = require(shadowNpmPaths.getArboristNodeClassPath())
578
+
579
+ // Implementation code not related to patch https://github.com/npm/cli/pull/8089
580
+ // is based on https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/node.js:
581
+ class SafeNode extends Node {
582
+ // Return true if it's safe to remove this node, because anything that is
583
+ // depending on it would be fine with the thing that they would resolve to if
584
+ // it was removed, or nothing is depending on it in the first place.
585
+ canDedupe(preferDedupe = false) {
586
+ // Not allowed to mess with shrinkwraps or bundles.
587
+ if (this.inDepBundle || this.inShrinkwrap) {
588
+ return false
589
+ }
590
+ // It's a top level pkg, or a dep of one.
591
+ if (!this.resolveParent?.resolveParent) {
592
+ return false
593
+ }
594
+ // No one wants it, remove it.
595
+ if (this.edgesIn.size === 0) {
596
+ return true
597
+ }
598
+ const other = this.resolveParent.resolveParent.resolve(this.name)
599
+ // Nothing else, need this one.
600
+ if (!other) {
601
+ return false
602
+ }
603
+ // If it's the same thing, then always fine to remove.
604
+ if (other.matches(this)) {
605
+ return true
606
+ }
607
+ // If the other thing can't replace this, then skip it.
608
+ if (!other.canReplace(this)) {
609
+ return false
610
+ }
611
+ // Patch replacing
612
+ // if (preferDedupe || semver.gte(other.version, this.version)) {
613
+ // return true
614
+ // }
615
+ // is based on https://github.com/npm/cli/pull/8089.
616
+ //
617
+ // If we prefer dedupe, or if the version is equal, take the other.
618
+ if (preferDedupe || vendor.semverExports.eq(other.version, this.version)) {
619
+ return true
620
+ }
621
+ // If our current version isn't the result of an override, then prefer to
622
+ // take the greater version.
623
+ if (
624
+ !this.overridden &&
625
+ vendor.semverExports.gt(other.version, this.version)
626
+ ) {
627
+ return true
628
+ }
629
+ return false
630
+ }
631
+
632
+ // Is it safe to replace one node with another? check the edges to
633
+ // make sure no one will get upset. Note that the node might end up
634
+ // having its own unmet dependencies, if the new node has new deps.
635
+ // Note that there are cases where Arborist will opt to insert a node
636
+ // into the tree even though this function returns false! This is
637
+ // necessary when a root dependency is added or updated, or when a
638
+ // root dependency brings peer deps along with it. In that case, we
639
+ // will go ahead and create the invalid state, and then try to resolve
640
+ // it with more tree construction, because it's a user request.
641
+ canReplaceWith(node, ignorePeers) {
642
+ if (this.name !== node.name || this.packageName !== node.packageName) {
643
+ return false
644
+ }
645
+ // Patch replacing
646
+ // if (node.overrides !== this.overrides) {
647
+ // return false
648
+ // }
649
+ // is based on https://github.com/npm/cli/pull/8089.
650
+ //
651
+ // If this node has no dependencies, then it's irrelevant to check the
652
+ // override rules of the replacement node.
653
+ if (this.edgesOut.size) {
654
+ // XXX need to check for two root nodes?
655
+ if (node.overrides) {
656
+ if (!node.overrides.isEqual(this.overrides)) {
657
+ return false
658
+ }
659
+ } else {
660
+ if (this.overrides) {
661
+ return false
662
+ }
663
+ }
664
+ }
665
+ // To satisfy the patch we ensure `node.overrides === this.overrides`
666
+ // so that the condition we want to replace,
667
+ // if (this.overrides !== node.overrides) {
668
+ // , is not hit.`
669
+ const oldOverrideSet = this.overrides
670
+ let result = true
671
+ if (oldOverrideSet !== node.overrides) {
672
+ this.overrides = node.overrides
673
+ }
674
+ try {
675
+ result = super.canReplaceWith(node, ignorePeers)
676
+ this.overrides = oldOverrideSet
677
+ } catch (e) {
678
+ this.overrides = oldOverrideSet
679
+ throw e
680
+ }
681
+ return result
682
+ }
683
+
684
+ // Patch adding deleteEdgeIn is based on https://github.com/npm/cli/pull/8089.
685
+ deleteEdgeIn(edge) {
686
+ this.edgesIn.delete(edge)
687
+ const { overrides } = edge
688
+ if (overrides) {
689
+ this.updateOverridesEdgeInRemoved(overrides)
690
+ }
691
+ }
692
+ addEdgeIn(edge) {
693
+ // Patch replacing
694
+ // if (edge.overrides) {
695
+ // this.overrides = edge.overrides
696
+ // }
697
+ // is based on https://github.com/npm/cli/pull/8089.
698
+ //
699
+ // We need to handle the case where the new edge in has an overrides field
700
+ // which is different from the current value.
701
+ if (!this.overrides || !this.overrides.isEqual(edge.overrides)) {
702
+ this.updateOverridesEdgeInAdded(edge.overrides)
703
+ }
704
+ this.edgesIn.add(edge)
705
+ // Try to get metadata from the yarn.lock file.
706
+ this.root.meta?.addEdge(edge)
707
+ }
708
+
709
+ // @ts-ignore: Incorrectly typed as a property instead of an accessor.
710
+ get overridden() {
711
+ // Patch replacing
712
+ // return !!(this.overrides && this.overrides.value && this.overrides.name === this.name)
713
+ // is based on https://github.com/npm/cli/pull/8089.
714
+ if (
715
+ !this.overrides ||
716
+ !this.overrides.value ||
717
+ this.overrides.name !== this.name
718
+ ) {
719
+ return false
720
+ }
721
+ // The overrides rule is for a package with this name, but some override
722
+ // rules only apply to specific versions. To make sure this package was
723
+ // actually overridden, we check whether any edge going in had the rule
724
+ // applied to it, in which case its overrides set is different than its
725
+ // source node.
726
+ for (const edge of this.edgesIn) {
727
+ if (
728
+ edge.overrides &&
729
+ edge.overrides.name === this.name &&
730
+ edge.overrides.value === this.version
731
+ ) {
732
+ if (!edge.overrides.isEqual(edge.from?.overrides)) {
733
+ return true
734
+ }
735
+ }
736
+ }
737
+ return false
738
+ }
739
+ set parent(newParent) {
740
+ // Patch removing
741
+ // if (parent.overrides) {
742
+ // this.overrides = parent.overrides.getNodeRule(this)
743
+ // }
744
+ // is based on https://github.com/npm/cli/pull/8089.
745
+ //
746
+ // The "parent" setter is a really large and complex function. To satisfy
747
+ // the patch we hold on to the old overrides value and set `this.overrides`
748
+ // to `undefined` so that the condition we want to remove is not hit.
749
+ const { overrides } = this
750
+ if (overrides) {
751
+ this.overrides = undefined
752
+ }
753
+ try {
754
+ super.parent = newParent
755
+ this.overrides = overrides
756
+ } catch (e) {
757
+ this.overrides = overrides
758
+ throw e
759
+ }
760
+ }
761
+
762
+ // Patch adding recalculateOutEdgesOverrides is based on
763
+ // https://github.com/npm/cli/pull/8089.
764
+ recalculateOutEdgesOverrides() {
765
+ // For each edge out propagate the new overrides through.
766
+ for (const edge of this.edgesOut.values()) {
767
+ edge.reload(true)
768
+ if (edge.to) {
769
+ edge.to.updateOverridesEdgeInAdded(edge.overrides)
770
+ }
771
+ }
772
+ }
773
+
774
+ // @ts-ignore: Incorrectly typed to accept null.
775
+ set root(newRoot) {
776
+ // Patch removing
777
+ // if (!this.overrides && this.parent && this.parent.overrides) {
778
+ // this.overrides = this.parent.overrides.getNodeRule(this)
779
+ // }
780
+ // is based on https://github.com/npm/cli/pull/8089.
781
+ //
782
+ // The "root" setter is a really large and complex function. To satisfy the
783
+ // patch we add a dummy value to `this.overrides` so that the condition we
784
+ // want to remove is not hit.
785
+ if (!this.overrides) {
786
+ this.overrides = new SafeOverrideSet({
787
+ overrides: ''
788
+ })
789
+ }
790
+ try {
791
+ super.root = newRoot
792
+ this.overrides = undefined
793
+ } catch (e) {
794
+ this.overrides = undefined
795
+ throw e
796
+ }
797
+ }
798
+
799
+ // Patch adding updateOverridesEdgeInAdded is based on
800
+ // https://github.com/npm/cli/pull/7025.
801
+ //
802
+ // This logic isn't perfect either. When we have two edges in that have
803
+ // different override sets, then we have to decide which set is correct. This
804
+ // function assumes the more specific override set is applicable, so if we have
805
+ // dependencies A->B->C and A->C and an override set that specifies what happens
806
+ // for C under A->B, this will work even if the new A->C edge comes along and
807
+ // tries to change the override set. The strictly correct logic is not to allow
808
+ // two edges with different overrides to point to the same node, because even
809
+ // if this node can satisfy both, one of its dependencies might need to be
810
+ // different depending on the edge leading to it. However, this might cause a
811
+ // lot of duplication, because the conflict in the dependencies might never
812
+ // actually happen.
813
+ updateOverridesEdgeInAdded(otherOverrideSet) {
814
+ if (!otherOverrideSet) {
815
+ // Assuming there are any overrides at all, the overrides field is never
816
+ // undefined for any node at the end state of the tree. So if the new edge's
817
+ // overrides is undefined it will be updated later. So we can wait with
818
+ // updating the node's overrides field.
819
+ return false
820
+ }
821
+ if (!this.overrides) {
822
+ this.overrides = otherOverrideSet
823
+ this.recalculateOutEdgesOverrides()
824
+ return true
825
+ }
826
+ if (this.overrides.isEqual(otherOverrideSet)) {
827
+ return false
828
+ }
829
+ const newOverrideSet = SafeOverrideSet.findSpecificOverrideSet(
830
+ this.overrides,
831
+ otherOverrideSet
832
+ )
833
+ if (newOverrideSet) {
834
+ if (this.overrides.isEqual(newOverrideSet)) {
835
+ return false
836
+ }
837
+ this.overrides = newOverrideSet
838
+ this.recalculateOutEdgesOverrides()
839
+ return true
840
+ }
841
+ // This is an error condition. We can only get here if the new override set
842
+ // is in conflict with the existing.
843
+ const log = getLogger()
844
+ log?.silly('Conflicting override sets', this.name)
845
+ return false
846
+ }
847
+
848
+ // Patch adding updateOverridesEdgeInRemoved is based on
849
+ // https://github.com/npm/cli/pull/7025.
850
+ updateOverridesEdgeInRemoved(otherOverrideSet) {
851
+ // If this edge's overrides isn't equal to this node's overrides,
852
+ // then removing it won't change newOverrideSet later.
853
+ if (!this.overrides || !this.overrides.isEqual(otherOverrideSet)) {
854
+ return false
855
+ }
856
+ let newOverrideSet
857
+ for (const edge of this.edgesIn) {
858
+ const { overrides: edgeOverrides } = edge
859
+ if (newOverrideSet && edgeOverrides) {
860
+ newOverrideSet = SafeOverrideSet.findSpecificOverrideSet(
861
+ edgeOverrides,
862
+ newOverrideSet
863
+ )
864
+ } else {
865
+ newOverrideSet = edgeOverrides
866
+ }
867
+ }
868
+ if (this.overrides.isEqual(newOverrideSet)) {
869
+ return false
870
+ }
871
+ this.overrides = newOverrideSet
872
+ if (newOverrideSet) {
873
+ // Optimization: If there's any override set at all, then no non-extraneous
874
+ // node has an empty override set. So if we temporarily have no override set
875
+ // (for example, we removed all the edges in), there's no use updating all
876
+ // the edges out right now. Let's just wait until we have an actual override
877
+ // set later.
878
+ this.recalculateOutEdgesOverrides()
879
+ }
880
+ return true
881
+ }
882
+ }
883
+
884
+ const Edge = require(shadowNpmPaths.getArboristEdgeClassPath())
885
+
886
+ // The Edge class makes heavy use of private properties which subclasses do NOT
887
+ // have access to. So we have to recreate any functionality that relies on those
888
+ // private properties and use our own "safe" prefixed non-conflicting private
889
+ // properties. Implementation code not related to patch https://github.com/npm/cli/pull/8089
890
+ // is based on https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/edge.js.
891
+ //
892
+ // The npm application
893
+ // Copyright (c) npm, Inc. and Contributors
894
+ // Licensed on the terms of The Artistic License 2.0
895
+ //
896
+ // An edge in the dependency graph.
897
+ // Represents a dependency relationship of some kind.
898
+ class SafeEdge extends Edge {
899
+ #safeError
900
+ #safeExplanation
901
+ #safeFrom
902
+ #safeTo
903
+ constructor(options) {
904
+ const { from } = options
905
+ // Defer to supper to validate options and assign non-private values.
906
+ super(options)
907
+ if (from.constructor !== SafeNode) {
908
+ Reflect.setPrototypeOf(from, SafeNode.prototype)
909
+ }
910
+ this.#safeError = null
911
+ this.#safeExplanation = null
912
+ this.#safeFrom = from
913
+ this.#safeTo = null
914
+ this.reload(true)
915
+ }
916
+ get bundled() {
917
+ return !!this.#safeFrom?.package?.bundleDependencies?.includes(this.name)
918
+ }
919
+ get error() {
920
+ if (!this.#safeError) {
921
+ if (!this.#safeTo) {
922
+ if (this.optional) {
923
+ this.#safeError = null
924
+ } else {
925
+ this.#safeError = 'MISSING'
926
+ }
927
+ } else if (
928
+ this.peer &&
929
+ this.#safeFrom === this.#safeTo.parent &&
930
+ // Patch adding "?." use based on
931
+ // https://github.com/npm/cli/pull/8089.
932
+ !this.#safeFrom?.isTop
933
+ ) {
934
+ this.#safeError = 'PEER LOCAL'
935
+ } else if (!this.satisfiedBy(this.#safeTo)) {
936
+ this.#safeError = 'INVALID'
937
+ }
938
+ // Patch adding "else if" condition is based on
939
+ // https://github.com/npm/cli/pull/8089.
940
+ else if (
941
+ this.overrides &&
942
+ this.#safeTo.edgesOut.size &&
943
+ SafeOverrideSet.doOverrideSetsConflict(
944
+ this.overrides,
945
+ this.#safeTo.overrides
946
+ )
947
+ ) {
948
+ // Any inconsistency between the edge's override set and the target's
949
+ // override set is potentially problematic. But we only say the edge is
950
+ // in error if the override sets are plainly conflicting. Note that if
951
+ // the target doesn't have any dependencies of their own, then this
952
+ // inconsistency is irrelevant.
953
+ this.#safeError = 'INVALID'
954
+ } else {
955
+ this.#safeError = 'OK'
956
+ }
957
+ }
958
+ if (this.#safeError === 'OK') {
959
+ return null
960
+ }
961
+ return this.#safeError
962
+ }
963
+
964
+ // @ts-ignore: Incorrectly typed as a property instead of an accessor.
965
+ get from() {
966
+ return this.#safeFrom
967
+ }
968
+
969
+ // @ts-ignore: Incorrectly typed as a property instead of an accessor.
970
+ get spec() {
971
+ if (
972
+ this.overrides?.value &&
973
+ this.overrides.value !== '*' &&
974
+ this.overrides.name === this.name
975
+ ) {
976
+ if (this.overrides.value.startsWith('$')) {
977
+ const ref = this.overrides.value.slice(1)
978
+ // We may be a virtual root, if we are we want to resolve reference
979
+ // overrides from the real root, not the virtual one.
980
+ //
981
+ // Patch adding "?." use based on
982
+ // https://github.com/npm/cli/pull/8089.
983
+ const pkg = this.#safeFrom?.sourceReference
984
+ ? this.#safeFrom?.sourceReference.root.package
985
+ : this.#safeFrom?.root?.package
986
+ if (pkg?.devDependencies?.[ref]) {
987
+ return pkg.devDependencies[ref]
988
+ }
989
+ if (pkg?.optionalDependencies?.[ref]) {
990
+ return pkg.optionalDependencies[ref]
991
+ }
992
+ if (pkg?.dependencies?.[ref]) {
993
+ return pkg.dependencies[ref]
994
+ }
995
+ if (pkg?.peerDependencies?.[ref]) {
996
+ return pkg.peerDependencies[ref]
997
+ }
998
+ throw new Error(`Unable to resolve reference ${this.overrides.value}`)
999
+ }
1000
+ return this.overrides.value
1001
+ }
1002
+ return this.rawSpec
1003
+ }
1004
+
1005
+ // @ts-ignore: Incorrectly typed as a property instead of an accessor.
1006
+ get to() {
1007
+ return this.#safeTo
1008
+ }
1009
+ detach() {
1010
+ this.#safeExplanation = null
1011
+ // Patch replacing
1012
+ // if (this.#to) {
1013
+ // this.#to.edgesIn.delete(this)
1014
+ // }
1015
+ // this.#from.edgesOut.delete(this.#name)
1016
+ // is based on https://github.com/npm/cli/pull/8089.
1017
+ this.#safeTo?.deleteEdgeIn(this)
1018
+ this.#safeFrom?.edgesOut.delete(this.name)
1019
+ this.#safeTo = null
1020
+ this.#safeError = 'DETACHED'
1021
+ this.#safeFrom = null
1022
+ }
1023
+
1024
+ // Return the edge data, and an explanation of how that edge came to be here.
1025
+ // @ts-ignore: Edge#explain is defined with an unused `seen = []` param.
1026
+ explain() {
1027
+ if (!this.#safeExplanation) {
1028
+ const explanation = {
1029
+ type: this.type,
1030
+ name: this.name,
1031
+ spec: this.spec,
1032
+ bundled: false,
1033
+ overridden: false,
1034
+ error: undefined,
1035
+ from: undefined,
1036
+ rawSpec: undefined
1037
+ }
1038
+ if (this.rawSpec !== this.spec) {
1039
+ explanation.rawSpec = this.rawSpec
1040
+ explanation.overridden = true
1041
+ }
1042
+ if (this.bundled) {
1043
+ explanation.bundled = this.bundled
1044
+ }
1045
+ if (this.error) {
1046
+ explanation.error = this.error
1047
+ }
1048
+ if (this.#safeFrom) {
1049
+ explanation.from = this.#safeFrom.explain()
1050
+ }
1051
+ this.#safeExplanation = explanation
1052
+ }
1053
+ return this.#safeExplanation
1054
+ }
1055
+ reload(hard = false) {
1056
+ this.#safeExplanation = null
1057
+ // Patch replacing
1058
+ // if (this.#from.overrides) {
1059
+ // is based on https://github.com/npm/cli/pull/8089.
1060
+ let needToUpdateOverrideSet = false
1061
+ let newOverrideSet
1062
+ let oldOverrideSet
1063
+ if (this.#safeFrom?.overrides) {
1064
+ newOverrideSet = this.#safeFrom.overrides.getEdgeRule(this)
1065
+ if (newOverrideSet && !newOverrideSet.isEqual(this.overrides)) {
1066
+ // If there's a new different override set we need to propagate it to
1067
+ // the nodes. If we're deleting the override set then there's no point
1068
+ // propagating it right now since it will be filled with another value
1069
+ // later.
1070
+ needToUpdateOverrideSet = true
1071
+ oldOverrideSet = this.overrides
1072
+ this.overrides = newOverrideSet
1073
+ }
1074
+ } else {
1075
+ this.overrides = undefined
1076
+ }
1077
+ // Patch adding "?." use based on
1078
+ // https://github.com/npm/cli/pull/8089.
1079
+ const newTo = this.#safeFrom?.resolve(this.name)
1080
+ if (newTo !== this.#safeTo) {
1081
+ // Patch replacing
1082
+ // this.#to.edgesIn.delete(this)
1083
+ // is based on https://github.com/npm/cli/pull/8089.
1084
+ this.#safeTo?.deleteEdgeIn(this)
1085
+ this.#safeTo = newTo ?? null
1086
+ this.#safeError = null
1087
+ this.#safeTo?.addEdgeIn(this)
1088
+ } else if (hard) {
1089
+ this.#safeError = null
1090
+ }
1091
+ // Patch adding "else if" condition based on
1092
+ // https://github.com/npm/cli/pull/8089.
1093
+ else if (needToUpdateOverrideSet && this.#safeTo) {
1094
+ // Propagate the new override set to the target node.
1095
+ this.#safeTo.updateOverridesEdgeInRemoved(oldOverrideSet)
1096
+ this.#safeTo.updateOverridesEdgeInAdded(newOverrideSet)
1097
+ }
1098
+ }
1099
+ satisfiedBy(node) {
1100
+ // Patch replacing
1101
+ // if (node.name !== this.#name) {
1102
+ // return false
1103
+ // }
1104
+ // is based on https://github.com/npm/cli/pull/8089.
1105
+ if (node.name !== this.name || !this.#safeFrom) {
1106
+ return false
1107
+ }
1108
+ // NOTE: this condition means we explicitly do not support overriding
1109
+ // bundled or shrinkwrapped dependencies
1110
+ if (node.hasShrinkwrap || node.inShrinkwrap || node.inBundle) {
1111
+ return depValid(node, this.rawSpec, this.accept, this.#safeFrom)
1112
+ }
1113
+ // Patch replacing
1114
+ // return depValid(node, this.spec, this.#accept, this.#from)
1115
+ // is based on https://github.com/npm/cli/pull/8089.
1116
+ //
1117
+ // If there's no override we just use the spec.
1118
+ if (!this.overrides?.keySpec) {
1119
+ return depValid(node, this.spec, this.accept, this.#safeFrom)
1120
+ }
1121
+ // There's some override. If the target node satisfies the overriding spec
1122
+ // then it's okay.
1123
+ if (depValid(node, this.spec, this.accept, this.#safeFrom)) {
1124
+ return true
1125
+ }
1126
+ // If it doesn't, then it should at least satisfy the original spec.
1127
+ if (!depValid(node, this.rawSpec, this.accept, this.#safeFrom)) {
1128
+ return false
1129
+ }
1130
+ // It satisfies the original spec, not the overriding spec. We need to make
1131
+ // sure it doesn't use the overridden spec.
1132
+ // For example:
1133
+ // we might have an ^8.0.0 rawSpec, and an override that makes
1134
+ // keySpec=8.23.0 and the override value spec=9.0.0.
1135
+ // If the node is 9.0.0, then it's okay because it's consistent with spec.
1136
+ // If the node is 8.24.0, then it's okay because it's consistent with the rawSpec.
1137
+ // If the node is 8.23.0, then it's not okay because even though it's consistent
1138
+ // with the rawSpec, it's also consistent with the keySpec.
1139
+ // So we're looking for ^8.0.0 or 9.0.0 and not 8.23.0.
1140
+ return !depValid(node, this.overrides.keySpec, this.accept, this.#safeFrom)
1141
+ }
1142
+ }
1143
+
1144
+ const {
1145
+ ALERT_TYPE_CRITICAL_CVE,
1146
+ ALERT_TYPE_CVE,
1147
+ ALERT_TYPE_MEDIUM_CVE,
1148
+ ALERT_TYPE_MILD_CVE
1149
+ } = constants
1150
+ function isArtifactAlertCve(alert) {
1151
+ const { type } = alert
1152
+ return (
1153
+ type === ALERT_TYPE_CVE ||
1154
+ type === ALERT_TYPE_MEDIUM_CVE ||
1155
+ type === ALERT_TYPE_MILD_CVE ||
1156
+ type === ALERT_TYPE_CRITICAL_CVE
1157
+ )
1158
+ }
1159
+
1160
+ const ALERT_FIX_TYPE = /*#__PURE__*/ (function (ALERT_FIX_TYPE) {
1161
+ ALERT_FIX_TYPE['cve'] = 'cve'
1162
+ ALERT_FIX_TYPE['upgrade'] = 'upgrade'
1163
+ return ALERT_FIX_TYPE
1164
+ })({})
1165
+
1166
+ function pick(input, keys) {
1167
+ const result = {}
1168
+ for (const key of keys) {
1169
+ result[key] = input[key]
1170
+ }
1171
+ return result
1172
+ }
1173
+
1174
+ function stringJoinWithSeparateFinalSeparator(list, separator = ' and ') {
1175
+ const values = list.filter(Boolean)
1176
+ const { length } = values
1177
+ if (!length) {
1178
+ return ''
1179
+ }
1180
+ if (length === 1) {
1181
+ return values[0]
1182
+ }
1183
+ const finalValue = values.pop()
1184
+ return `${values.join(', ')}${separator}${finalValue}`
1185
+ }
1186
+
1187
+ const ALERT_SEVERITY = /*#__PURE__*/ (function (ALERT_SEVERITY) {
1188
+ ALERT_SEVERITY['critical'] = 'critical'
1189
+ ALERT_SEVERITY['high'] = 'high'
1190
+ ALERT_SEVERITY['middle'] = 'middle'
1191
+ ALERT_SEVERITY['low'] = 'low'
1192
+ return ALERT_SEVERITY
1193
+ })({})
1194
+ // Ordered from most severe to least.
1195
+ const ALERT_SEVERITIES_SORTED = Object.freeze([
1196
+ 'critical',
1197
+ 'high',
1198
+ 'middle',
1199
+ 'low'
1200
+ ])
1201
+ function getDesiredSeverities(lowestToInclude) {
1202
+ const result = []
1203
+ for (const severity of ALERT_SEVERITIES_SORTED) {
1204
+ result.push(severity)
1205
+ if (severity === lowestToInclude) {
1206
+ break
1207
+ }
1208
+ }
1209
+ return result
1210
+ }
1211
+ function formatSeverityCount(severityCount) {
1212
+ const summary = []
1213
+ for (const severity of ALERT_SEVERITIES_SORTED) {
1214
+ if (severityCount[severity]) {
1215
+ summary.push(`${severityCount[severity]} ${severity}`)
1216
+ }
1217
+ }
1218
+ return stringJoinWithSeparateFinalSeparator(summary)
1219
+ }
1220
+ function getSeverityCount(issues, lowestToInclude) {
1221
+ const severityCount = pick(
1222
+ {
1223
+ low: 0,
1224
+ middle: 0,
1225
+ high: 0,
1226
+ critical: 0
1227
+ },
1228
+ getDesiredSeverities(lowestToInclude)
1229
+ )
1230
+ for (const issue of issues) {
1231
+ const { value } = issue
1232
+ if (!value) {
1233
+ continue
1234
+ }
1235
+ const { severity } = value
1236
+ if (severityCount[severity] !== undefined) {
1237
+ severityCount[severity] += 1
1238
+ }
1239
+ }
1240
+ return severityCount
1241
+ }
1242
+
1243
+ class ColorOrMarkdown {
1244
+ constructor(useMarkdown) {
1245
+ this.useMarkdown = !!useMarkdown
1246
+ }
1247
+ bold(text) {
1248
+ return this.useMarkdown
1249
+ ? `**${text}**`
1250
+ : vendor.yoctocolorsCjsExports.bold(`${text}`)
1251
+ }
1252
+ header(text, level = 1) {
1253
+ return this.useMarkdown
1254
+ ? `\n${''.padStart(level, '#')} ${text}\n`
1255
+ : vendor.yoctocolorsCjsExports.underline(
1256
+ `\n${level === 1 ? vendor.yoctocolorsCjsExports.bold(text) : text}\n`
1257
+ )
1258
+ }
1259
+ hyperlink(text, url, { fallback = true, fallbackToUrl } = {}) {
1260
+ if (url) {
1261
+ return this.useMarkdown
1262
+ ? `[${text}](${url})`
1263
+ : vendor.terminalLinkExports(text, url, {
1264
+ fallback: fallbackToUrl ? (_text, url) => url : fallback
1265
+ })
1266
+ }
1267
+ return text
1268
+ }
1269
+ indent(...args) {
1270
+ return indentString(...args)
1271
+ }
1272
+ italic(text) {
1273
+ return this.useMarkdown
1274
+ ? `_${text}_`
1275
+ : vendor.yoctocolorsCjsExports.italic(`${text}`)
1276
+ }
1277
+ json(value) {
1278
+ return this.useMarkdown
1279
+ ? '```json\n' + JSON.stringify(value) + '\n```'
1280
+ : JSON.stringify(value)
1281
+ }
1282
+ list(items) {
1283
+ const indentedContent = items.map(item => this.indent(item).trimStart())
1284
+ return this.useMarkdown
1285
+ ? `* ${indentedContent.join('\n* ')}\n`
1286
+ : `${indentedContent.join('\n')}\n`
1287
+ }
1288
+ }
1289
+
1290
+ function getSocketDevAlertUrl(alertType) {
1291
+ return `https://socket.dev/alerts/${alertType}`
1292
+ }
1293
+ function getSocketDevPackageOverviewUrl(eco, name, version) {
1294
+ return `https://socket.dev/${eco}/package/${name}${version ? `/overview/${version}` : ''}`
1295
+ }
1296
+
1297
+ let _translations
1298
+ function getTranslations() {
1299
+ if (_translations === undefined) {
1300
+ _translations = require(
1301
+ // Lazily access constants.rootPath.
1302
+ path.join(constants.rootPath, 'translations.json')
1303
+ )
1304
+ }
1305
+ return _translations
1306
+ }
1307
+
1308
+ const ALERT_SEVERITY_COLOR = /*#__PURE__*/ (function (ALERT_SEVERITY_COLOR) {
1309
+ ALERT_SEVERITY_COLOR['critical'] = 'magenta'
1310
+ ALERT_SEVERITY_COLOR['high'] = 'red'
1311
+ ALERT_SEVERITY_COLOR['middle'] = 'yellow'
1312
+ ALERT_SEVERITY_COLOR['low'] = 'white'
1313
+ return ALERT_SEVERITY_COLOR
1314
+ })({})
1315
+ const ALERT_SEVERITY_ORDER = /*#__PURE__*/ (function (ALERT_SEVERITY_ORDER) {
1316
+ ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['critical'] = 0)] = 'critical'
1317
+ ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['high'] = 1)] = 'high'
1318
+ ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['middle'] = 2)] = 'middle'
1319
+ ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['low'] = 3)] = 'low'
1320
+ ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['none'] = 4)] = 'none'
1321
+ return ALERT_SEVERITY_ORDER
1322
+ })({})
1323
+ const { CVE_ALERT_PROPS_FIRST_PATCHED_VERSION_IDENTIFIER, NPM: NPM$2 } =
1324
+ constants
1325
+ const MIN_ABOVE_THE_FOLD_COUNT = 3
1326
+ const MIN_ABOVE_THE_FOLD_ALERT_COUNT = 1
1327
+ const format = new ColorOrMarkdown(false)
1328
+ function alertsHaveBlocked(alerts) {
1329
+ return alerts.find(a => a.blocked) !== undefined
1330
+ }
1331
+ function alertsHaveSeverity(alerts, severity) {
1332
+ return alerts.find(a => a.raw.severity === severity) !== undefined
1333
+ }
1334
+ function alertSeverityComparator(a, b) {
1335
+ return getAlertSeverityOrder(a) - getAlertSeverityOrder(b)
1336
+ }
1337
+ function getAlertSeverityOrder(alert) {
1338
+ const { severity } = alert.raw
1339
+ return severity === ALERT_SEVERITY.critical
1340
+ ? 0
1341
+ : severity === ALERT_SEVERITY.high
1342
+ ? 1
1343
+ : severity === ALERT_SEVERITY.middle
1344
+ ? 2
1345
+ : severity === ALERT_SEVERITY.low
1346
+ ? 3
1347
+ : 4
1348
+ }
1349
+ function getAlertsSeverityOrder(alerts) {
1350
+ return alertsHaveBlocked(alerts) ||
1351
+ alertsHaveSeverity(alerts, ALERT_SEVERITY.critical)
1352
+ ? 0
1353
+ : alertsHaveSeverity(alerts, ALERT_SEVERITY.high)
1354
+ ? 1
1355
+ : alertsHaveSeverity(alerts, ALERT_SEVERITY.middle)
1356
+ ? 2
1357
+ : alertsHaveSeverity(alerts, ALERT_SEVERITY.low)
1358
+ ? 3
1359
+ : 4
1360
+ }
1361
+ function getHiddenRiskCounts(hiddenAlerts) {
1362
+ const riskCounts = {
1363
+ critical: 0,
1364
+ high: 0,
1365
+ middle: 0,
1366
+ low: 0
1367
+ }
1368
+ for (const alert of hiddenAlerts) {
1369
+ switch (getAlertSeverityOrder(alert)) {
1370
+ case ALERT_SEVERITY_ORDER.critical:
1371
+ riskCounts.critical += 1
1372
+ break
1373
+ case ALERT_SEVERITY_ORDER.high:
1374
+ riskCounts.high += 1
1375
+ break
1376
+ case ALERT_SEVERITY_ORDER.middle:
1377
+ riskCounts.middle += 1
1378
+ break
1379
+ case ALERT_SEVERITY_ORDER.low:
1380
+ riskCounts.low += 1
1381
+ break
1382
+ }
1383
+ }
1384
+ return riskCounts
1385
+ }
1386
+ function getHiddenRisksDescription(riskCounts) {
1387
+ const descriptions = []
1388
+ if (riskCounts.critical) {
1389
+ descriptions.push(`${riskCounts.critical} ${getSeverityLabel('critical')}`)
1390
+ }
1391
+ if (riskCounts.high) {
1392
+ descriptions.push(`${riskCounts.high} ${getSeverityLabel('high')}`)
1393
+ }
1394
+ if (riskCounts.middle) {
1395
+ descriptions.push(`${riskCounts.middle} ${getSeverityLabel('middle')}`)
1396
+ }
1397
+ if (riskCounts.low) {
1398
+ descriptions.push(`${riskCounts.low} ${getSeverityLabel('low')}`)
1399
+ }
1400
+ return `(${descriptions.join('; ')})`
1401
+ }
1402
+ function getSeverityLabel(severity) {
1403
+ return severity === 'middle' ? 'moderate' : severity
1404
+ }
1405
+ async function addArtifactToAlertsMap(artifact, alertsByPkgId, options) {
1406
+ // Make TypeScript happy.
1407
+ if (!artifact.name || !artifact.version || !artifact.alerts?.length) {
1408
+ return alertsByPkgId
1409
+ }
1410
+ const {
1411
+ consolidate = false,
1412
+ include: _include,
1413
+ overrides
1414
+ } = {
1415
+ __proto__: null,
1416
+ ...options
1417
+ }
1418
+ const include = {
1419
+ __proto__: null,
1420
+ blocked: true,
1421
+ critical: true,
1422
+ cve: true,
1423
+ unfixable: true,
1424
+ upgradable: false,
1425
+ ..._include
1426
+ }
1427
+ const name = packages.resolvePackageName(artifact)
1428
+ const { version } = artifact
1429
+ const pkgId = `${name}@${version}`
1430
+ const major = vendor.semverExports.major(version)
1431
+ const socketYml = findSocketYmlSync()
1432
+ const enabledState = {
1433
+ __proto__: null,
1434
+ ...socketYml?.parsed.issueRules
1435
+ }
1436
+ let sockPkgAlerts = []
1437
+ for (const alert of artifact.alerts) {
1438
+ const action = alert.action ?? ''
1439
+ const enabledFlag = enabledState[alert.type]
1440
+ if (
1441
+ (action === 'ignore' && enabledFlag !== true) ||
1442
+ enabledFlag === false
1443
+ ) {
1444
+ continue
1445
+ }
1446
+ const blocked = action === 'error'
1447
+ const critical = alert.severity === ALERT_SEVERITY.critical
1448
+ const cve = isArtifactAlertCve(alert)
1449
+ const fixType = alert.fix?.type ?? ''
1450
+ const fixableCve = fixType === ALERT_FIX_TYPE.cve
1451
+ const fixableUpgrade = fixType === ALERT_FIX_TYPE.upgrade
1452
+ const fixable = fixableCve || fixableUpgrade
1453
+ const upgradable = fixableUpgrade && !objects.hasOwn(overrides, name)
1454
+ if (
1455
+ (include.blocked && blocked) ||
1456
+ (include.critical && critical) ||
1457
+ (include.cve && cve) ||
1458
+ (include.unfixable && !fixable) ||
1459
+ (include.upgradable && upgradable)
1460
+ ) {
1461
+ sockPkgAlerts.push({
1462
+ name,
1463
+ version,
1464
+ key: alert.key,
1465
+ type: alert.type,
1466
+ blocked,
1467
+ critical,
1468
+ fixable,
1469
+ raw: alert,
1470
+ upgradable
1471
+ })
1472
+ }
1473
+ }
1474
+ if (!sockPkgAlerts.length) {
1475
+ return alertsByPkgId
1476
+ }
1477
+ if (consolidate) {
1478
+ const highestForCve = new Map()
1479
+ const highestForUpgrade = new Map()
1480
+ const unfixableAlerts = []
1481
+ for (const sockPkgAlert of sockPkgAlerts) {
1482
+ const alert = sockPkgAlert.raw
1483
+ const fixType = alert.fix?.type ?? ''
1484
+ if (fixType === ALERT_FIX_TYPE.cve) {
1485
+ const patchedVersion =
1486
+ alert.props[CVE_ALERT_PROPS_FIRST_PATCHED_VERSION_IDENTIFIER]
1487
+ const patchedMajor = vendor.semverExports.major(patchedVersion)
1488
+ const oldHighest = highestForCve.get(patchedMajor)
1489
+ const highest = oldHighest?.version ?? '0.0.0'
1490
+ if (vendor.semverExports.gt(patchedVersion, highest)) {
1491
+ highestForCve.set(patchedMajor, {
1492
+ alert: sockPkgAlert,
1493
+ version: patchedVersion
1494
+ })
1495
+ }
1496
+ } else if (fixType === ALERT_FIX_TYPE.upgrade) {
1497
+ const oldHighest = highestForUpgrade.get(major)
1498
+ const highest = oldHighest?.version ?? '0.0.0'
1499
+ if (vendor.semverExports.gt(version, highest)) {
1500
+ highestForUpgrade.set(major, {
1501
+ alert: sockPkgAlert,
1502
+ version
1503
+ })
1504
+ }
1505
+ } else {
1506
+ unfixableAlerts.push(sockPkgAlert)
1507
+ }
1508
+ }
1509
+ sockPkgAlerts = [
1510
+ ...unfixableAlerts,
1511
+ ...[...highestForCve.values()].map(d => d.alert),
1512
+ ...[...highestForUpgrade.values()].map(d => d.alert)
1513
+ ]
1514
+ }
1515
+ if (sockPkgAlerts.length) {
1516
+ sockPkgAlerts.sort((a, b) => sorts.naturalCompare(a.type, b.type))
1517
+ alertsByPkgId.set(pkgId, sockPkgAlerts)
1518
+ }
1519
+ return alertsByPkgId
1520
+ }
1521
+ function getCveInfoByAlertsMap(alertsMap, options) {
1522
+ const exclude = {
1523
+ upgradable: true,
1524
+ ...{
1525
+ __proto__: null,
1526
+ ...options
1527
+ }.exclude
1528
+ }
1529
+ let infoByPkg = null
1530
+ for (const [pkgId, sockPkgAlerts] of alertsMap) {
1531
+ const purlObj = packageurlJs.PackageURL.fromString(`pkg:npm/${pkgId}`)
1532
+ const name = packages.resolvePackageName(purlObj)
1533
+ for (const sockPkgAlert of sockPkgAlerts) {
1534
+ const alert = sockPkgAlert.raw
1535
+ if (
1536
+ alert.fix?.type !== ALERT_FIX_TYPE.cve ||
1537
+ (exclude.upgradable && registry.getManifestData(NPM$2, name))
1538
+ ) {
1539
+ continue
1540
+ }
1541
+ if (!infoByPkg) {
1542
+ infoByPkg = new Map()
1543
+ }
1544
+ let infos = infoByPkg.get(name)
1545
+ if (!infos) {
1546
+ infos = []
1547
+ infoByPkg.set(name, infos)
1548
+ }
1549
+ const { firstPatchedVersionIdentifier, vulnerableVersionRange } =
1550
+ alert.props
1551
+ infos.push({
1552
+ firstPatchedVersionIdentifier,
1553
+ vulnerableVersionRange: new vendor.semverExports.Range(
1554
+ vulnerableVersionRange
1555
+ ).format()
1556
+ })
1557
+ }
1558
+ }
1559
+ return infoByPkg
1560
+ }
1561
+ function logAlertsMap(alertsMap, options) {
1562
+ const { hideAt = 'middle', output = process.stderr } = {
1563
+ __proto__: null,
1564
+ ...options
1565
+ }
1566
+ const translations = getTranslations()
1567
+ const sortedEntries = [...alertsMap.entries()].sort(
1568
+ (a, b) => getAlertsSeverityOrder(a[1]) - getAlertsSeverityOrder(b[1])
1569
+ )
1570
+ const aboveTheFoldPkgIds = new Set()
1571
+ const viewableAlertsByPkgId = new Map()
1572
+ const hiddenAlertsByPkgId = new Map()
1573
+ for (let i = 0, { length } = sortedEntries; i < length; i += 1) {
1574
+ const { 0: pkgId, 1: alerts } = sortedEntries[i]
1575
+ const hiddenAlerts = []
1576
+ const viewableAlerts = alerts.filter(a => {
1577
+ const keep =
1578
+ a.blocked || getAlertSeverityOrder(a) < ALERT_SEVERITY_ORDER[hideAt]
1579
+ if (!keep) {
1580
+ hiddenAlerts.push(a)
1581
+ }
1582
+ return keep
1583
+ })
1584
+ if (hiddenAlerts.length) {
1585
+ hiddenAlertsByPkgId.set(pkgId, hiddenAlerts.sort(alertSeverityComparator))
1586
+ }
1587
+ if (!viewableAlerts.length) {
1588
+ continue
1589
+ }
1590
+ viewableAlerts.sort(alertSeverityComparator)
1591
+ viewableAlertsByPkgId.set(pkgId, viewableAlerts)
1592
+ if (
1593
+ viewableAlerts.find(
1594
+ a => a.blocked || getAlertSeverityOrder(a) < ALERT_SEVERITY_ORDER.middle
1595
+ )
1596
+ ) {
1597
+ aboveTheFoldPkgIds.add(pkgId)
1598
+ }
1599
+ }
1600
+
1601
+ // If MIN_ABOVE_THE_FOLD_COUNT is NOT met add more from viewable pkg ids.
1602
+ for (const { 0: pkgId } of viewableAlertsByPkgId.entries()) {
1603
+ if (aboveTheFoldPkgIds.size >= MIN_ABOVE_THE_FOLD_COUNT) {
1604
+ break
1605
+ }
1606
+ aboveTheFoldPkgIds.add(pkgId)
1607
+ }
1608
+ // If MIN_ABOVE_THE_FOLD_COUNT is STILL NOT met add more from hidden pkg ids.
1609
+ for (const { 0: pkgId, 1: hiddenAlerts } of hiddenAlertsByPkgId.entries()) {
1610
+ if (aboveTheFoldPkgIds.size >= MIN_ABOVE_THE_FOLD_COUNT) {
1611
+ break
1612
+ }
1613
+ aboveTheFoldPkgIds.add(pkgId)
1614
+ const viewableAlerts = viewableAlertsByPkgId.get(pkgId) ?? []
1615
+ if (viewableAlerts.length < MIN_ABOVE_THE_FOLD_ALERT_COUNT) {
1616
+ const neededCount = MIN_ABOVE_THE_FOLD_ALERT_COUNT - viewableAlerts.length
1617
+ let removedHiddenAlerts
1618
+ if (hiddenAlerts.length - neededCount > 0) {
1619
+ removedHiddenAlerts = hiddenAlerts.splice(
1620
+ 0,
1621
+ MIN_ABOVE_THE_FOLD_ALERT_COUNT
1622
+ )
1623
+ } else {
1624
+ removedHiddenAlerts = hiddenAlerts
1625
+ hiddenAlertsByPkgId.delete(pkgId)
1626
+ }
1627
+ viewableAlertsByPkgId.set(pkgId, [
1628
+ ...viewableAlerts,
1629
+ ...removedHiddenAlerts
1630
+ ])
1631
+ }
1632
+ }
1633
+ const mentionedPkgIdsWithHiddenAlerts = new Set()
1634
+ for (
1635
+ let i = 0,
1636
+ prevAboveTheFold = true,
1637
+ entries = [...viewableAlertsByPkgId.entries()],
1638
+ { length } = entries;
1639
+ i < length;
1640
+ i += 1
1641
+ ) {
1642
+ const { 0: pkgId, 1: alerts } = entries[i]
1643
+ const lines = new Set()
1644
+ for (const alert of alerts) {
1645
+ const { type } = alert
1646
+ const severity = alert.raw.severity ?? ''
1647
+ const attributes = [
1648
+ ...(severity
1649
+ ? [
1650
+ vendor.yoctocolorsCjsExports[ALERT_SEVERITY_COLOR[severity]](
1651
+ getSeverityLabel(severity)
1652
+ )
1653
+ ]
1654
+ : []),
1655
+ ...(alert.blocked
1656
+ ? [
1657
+ vendor.yoctocolorsCjsExports.bold(
1658
+ vendor.yoctocolorsCjsExports.red('blocked')
1659
+ )
1660
+ ]
1661
+ : []),
1662
+ ...(alert.fixable ? ['fixable'] : [])
1663
+ ]
1664
+ const maybeAttributes = attributes.length
1665
+ ? ` ${vendor.yoctocolorsCjsExports.italic(`(${attributes.join('; ')})`)}`
1666
+ : ''
1667
+ // Based data from { pageProps: { alertTypes } } of:
1668
+ // https://socket.dev/_next/data/94666139314b6437ee4491a0864e72b264547585/en-US.json
1669
+ const info = translations.alerts[type]
1670
+ const title = info?.title ?? type
1671
+ const maybeDesc = info?.description ? ` - ${info.description}` : ''
1672
+ const content = `${title}${maybeAttributes}${maybeDesc}`
1673
+ // TODO: emoji seems to mis-align terminals sometimes
1674
+ lines.add(` ${content}`)
1675
+ }
1676
+ const purlObj = packageurlJs.PackageURL.fromString(`pkg:npm/${pkgId}`)
1677
+ const hyperlink = format.hyperlink(
1678
+ pkgId,
1679
+ getSocketDevPackageOverviewUrl(
1680
+ NPM$2,
1681
+ packages.resolvePackageName(purlObj),
1682
+ purlObj.version
1683
+ )
1684
+ )
1685
+ const isAboveTheFold = aboveTheFoldPkgIds.has(pkgId)
1686
+ if (isAboveTheFold) {
1687
+ aboveTheFoldPkgIds.add(pkgId)
1688
+ output.write(`${i ? '\n' : ''}${hyperlink}:\n`)
1689
+ } else {
1690
+ output.write(`${prevAboveTheFold ? '\n' : ''}${hyperlink}:\n`)
1691
+ }
1692
+ for (const line of lines) {
1693
+ output.write(`${line}\n`)
1694
+ }
1695
+ const hiddenAlerts = hiddenAlertsByPkgId.get(pkgId) ?? []
1696
+ const { length: hiddenAlertsCount } = hiddenAlerts
1697
+ if (hiddenAlertsCount) {
1698
+ mentionedPkgIdsWithHiddenAlerts.add(pkgId)
1699
+ if (hiddenAlertsCount === 1) {
1700
+ output.write(
1701
+ ` ${vendor.yoctocolorsCjsExports.dim(`+1 Hidden ${getSeverityLabel(hiddenAlerts[0].raw.severity ?? 'low')} risk alert`)}\n`
1702
+ )
1703
+ } else {
1704
+ output.write(
1705
+ ` ${vendor.yoctocolorsCjsExports.dim(`+${hiddenAlertsCount} Hidden alerts ${vendor.yoctocolorsCjsExports.italic(getHiddenRisksDescription(getHiddenRiskCounts(hiddenAlerts)))}`)}\n`
1706
+ )
1707
+ }
1708
+ }
1709
+ prevAboveTheFold = isAboveTheFold
1710
+ }
1711
+ const additionalHiddenCount =
1712
+ hiddenAlertsByPkgId.size - mentionedPkgIdsWithHiddenAlerts.size
1713
+ if (additionalHiddenCount) {
1714
+ const totalRiskCounts = {
1715
+ critical: 0,
1716
+ high: 0,
1717
+ middle: 0,
1718
+ low: 0
1719
+ }
1720
+ for (const { 0: pkgId, 1: alerts } of hiddenAlertsByPkgId.entries()) {
1721
+ if (mentionedPkgIdsWithHiddenAlerts.has(pkgId)) {
1722
+ continue
1723
+ }
1724
+ const riskCounts = getHiddenRiskCounts(alerts)
1725
+ totalRiskCounts.critical += riskCounts.critical
1726
+ totalRiskCounts.high += riskCounts.high
1727
+ totalRiskCounts.middle += riskCounts.middle
1728
+ totalRiskCounts.low += riskCounts.low
1729
+ }
1730
+ output.write(
1731
+ `${aboveTheFoldPkgIds.size ? '\n' : ''}${vendor.yoctocolorsCjsExports.dim(`${aboveTheFoldPkgIds.size ? '+' : ''}${additionalHiddenCount} Packages with hidden alerts ${vendor.yoctocolorsCjsExports.italic(getHiddenRisksDescription(totalRiskCounts))}`)}\n`
1732
+ )
1733
+ }
1734
+ output.write('\n')
1735
+ }
1736
+
1737
+ function assignDefaultFixOptions(options) {
1738
+ if (options.autoPilot === undefined) {
1739
+ options.autoPilot = false
1740
+ }
1741
+ if (options.autoMerge === undefined) {
1742
+ options.autoMerge = !!options.autoPilot
1743
+ }
1744
+ if (options.cwd === undefined) {
1745
+ options.cwd = process.cwd()
1746
+ }
1747
+ if (options.rangeStyle === undefined) {
1748
+ options.rangeStyle = 'preserve'
1749
+ }
1750
+ if (options.test === undefined) {
1751
+ options.test = !!options.autoPilot || !!options.testScript
1752
+ }
1753
+ if (options.testScript === undefined) {
1754
+ options.testScript = 'test'
1755
+ }
1756
+ return options
1757
+ }
1758
+ function applyRange(refRange, version, style = 'preserve') {
1759
+ switch (style) {
1760
+ case 'caret':
1761
+ return `^${version}`
1762
+ case 'gt':
1763
+ return `>${version}`
1764
+ case 'gte':
1765
+ return `>=${version}`
1766
+ case 'lt':
1767
+ return `<${version}`
1768
+ case 'lte':
1769
+ return `<=${version}`
1770
+ case 'preserve': {
1771
+ const comparators = [
1772
+ ...new vendor.semverExports.Range(refRange).set
1773
+ ].flat()
1774
+ const { length } = comparators
1775
+ return !length || length > 1
1776
+ ? version
1777
+ : `${comparators[0].operator}${version}`
1778
+ }
1779
+ case 'tilde':
1780
+ return `~${version}`
1781
+ case 'pin':
1782
+ default:
1783
+ return version
1784
+ }
1785
+ }
1786
+ const RangeStyles = ['caret', 'gt', 'lt', 'pin', 'preserve', 'tilde']
1787
+
1788
+ const { LOOP_SENTINEL, NPM: NPM$1, NPM_REGISTRY_URL } = constants
1789
+ function getDetailsFromDiff(diff_, options) {
1790
+ const details = []
1791
+ // `diff_` is `null` when `npm install --package-lock-only` is passed.
1792
+ if (!diff_) {
1793
+ return details
1794
+ }
1795
+ const include = {
1796
+ __proto__: null,
1797
+ unchanged: false,
1798
+ unknownOrigin: false,
1799
+ ...{
1800
+ __proto__: null,
1801
+ ...options
1802
+ }.include
1803
+ }
1804
+ const queue = [...diff_.children]
1805
+ let pos = 0
1806
+ let { length: queueLength } = queue
1807
+ while (pos < queueLength) {
1808
+ if (pos === LOOP_SENTINEL) {
1809
+ throw new Error('Detected infinite loop while walking Arborist diff')
1810
+ }
1811
+ const diff = queue[pos++]
1812
+ const { action } = diff
1813
+ if (action) {
1814
+ // The `pkgNode`, i.e. the `ideal` node, will be `undefined` if the diff
1815
+ // action is 'REMOVE'
1816
+ // The `oldNode`, i.e. the `actual` node, will be `undefined` if the diff
1817
+ // action is 'ADD'.
1818
+ const { actual: oldNode, ideal: pkgNode } = diff
1819
+ let existing
1820
+ let keep = false
1821
+ if (action === DiffAction.change) {
1822
+ if (pkgNode?.package.version !== oldNode?.package.version) {
1823
+ keep = true
1824
+ if (
1825
+ oldNode?.package.name &&
1826
+ oldNode.package.name === pkgNode?.package.name
1827
+ ) {
1828
+ existing = oldNode
1829
+ }
1830
+ } else {
1831
+ debug.debugLog('SKIPPING META CHANGE ON\n', diff)
1832
+ }
1833
+ } else {
1834
+ keep = action !== DiffAction.remove
1835
+ }
1836
+ if (keep && pkgNode?.resolved && (!oldNode || oldNode.resolved)) {
1837
+ if (
1838
+ include.unknownOrigin ||
1839
+ getUrlOrigin(pkgNode.resolved) === NPM_REGISTRY_URL
1840
+ ) {
1841
+ details.push({
1842
+ node: pkgNode,
1843
+ existing
1844
+ })
1845
+ }
1846
+ }
1847
+ }
1848
+ for (const child of diff.children) {
1849
+ queue[queueLength++] = child
1850
+ }
1851
+ }
1852
+ if (include.unchanged) {
1853
+ const { unchanged } = diff_
1854
+ for (let i = 0, { length } = unchanged; i < length; i += 1) {
1855
+ const pkgNode = unchanged[i]
1856
+ if (
1857
+ include.unknownOrigin ||
1858
+ getUrlOrigin(pkgNode.resolved) === NPM_REGISTRY_URL
1859
+ ) {
1860
+ details.push({
1861
+ node: pkgNode,
1862
+ existing: pkgNode
1863
+ })
1864
+ }
1865
+ }
1866
+ }
1867
+ return details
1868
+ }
1869
+ function getUrlOrigin(input) {
1870
+ try {
1871
+ // TODO: URL.parse is available in Node 22.1.0. We can use it when we drop Node 18.
1872
+ // https://nodejs.org/docs/latest-v22.x/api/url.html#urlparseinput-base
1873
+ // return URL.parse(input)?.origin ?? ''
1874
+ return new URL(input).origin ?? ''
1875
+ } catch {}
1876
+ return ''
1877
+ }
1878
+ function findBestPatchVersion(
1879
+ node,
1880
+ availableVersions,
1881
+ vulnerableVersionRange,
1882
+ _firstPatchedVersionIdentifier
1883
+ ) {
1884
+ const manifestData = registry.getManifestData(NPM$1, node.name)
1885
+ let eligibleVersions
1886
+ if (manifestData && manifestData.name === manifestData.package) {
1887
+ const major = vendor.semverExports.major(manifestData.version)
1888
+ eligibleVersions = availableVersions.filter(
1889
+ v => vendor.semverExports.major(v) === major
1890
+ )
1891
+ } else {
1892
+ const major = vendor.semverExports.major(node.version)
1893
+ eligibleVersions = availableVersions.filter(
1894
+ v =>
1895
+ // Filter for versions that are within the current major version and
1896
+ // are NOT in the vulnerable range.
1897
+ vendor.semverExports.major(v) === major &&
1898
+ (!vulnerableVersionRange ||
1899
+ !vendor.semverExports.satisfies(v, vulnerableVersionRange))
1900
+ )
1901
+ }
1902
+ return vendor.semverExports.maxSatisfying(eligibleVersions, '*')
1903
+ }
1904
+ function findPackageNode(tree, name, version) {
1905
+ const queue = [tree]
1906
+ let sentinel = 0
1907
+ while (queue.length) {
1908
+ if (sentinel++ === LOOP_SENTINEL) {
1909
+ throw new Error('Detected infinite loop in findPackageNodes')
1910
+ }
1911
+ const currentNode = queue.pop()
1912
+ const node = currentNode.children.get(name)
1913
+ if (node && (typeof version !== 'string' || node.version === version)) {
1914
+ return node
1915
+ }
1916
+ const children = [...currentNode.children.values()]
1917
+ for (let i = children.length - 1; i >= 0; i -= 1) {
1918
+ queue.push(children[i])
1919
+ }
1920
+ }
1921
+ }
1922
+ function findPackageNodes(tree, name, version) {
1923
+ const queue = [tree]
1924
+ const matches = []
1925
+ let sentinel = 0
1926
+ while (queue.length) {
1927
+ if (sentinel++ === LOOP_SENTINEL) {
1928
+ throw new Error('Detected infinite loop in findPackageNodes')
1929
+ }
1930
+ const currentNode = queue.pop()
1931
+ const node = currentNode.children.get(name)
1932
+ if (node && 'undefined' !== 'string') {
1933
+ matches.push(node)
1934
+ }
1935
+ const children = [...currentNode.children.values()]
1936
+ for (let i = children.length - 1; i >= 0; i -= 1) {
1937
+ queue.push(children[i])
1938
+ }
1939
+ }
1940
+ return matches
1941
+ }
1942
+ async function getAlertsMapFromArborist(arb, options_) {
1943
+ const options = {
1944
+ __proto__: null,
1945
+ consolidate: false,
1946
+ nothrow: false,
1947
+ ...options_
1948
+ }
1949
+ const include = {
1950
+ __proto__: null,
1951
+ actions: undefined,
1952
+ blocked: true,
1953
+ critical: true,
1954
+ cve: true,
1955
+ existing: false,
1956
+ unfixable: true,
1957
+ upgradable: false,
1958
+ ...options.include
1959
+ }
1960
+ const { spinner } = options
1961
+ const needInfoOn = getDetailsFromDiff(arb.diff, {
1962
+ include: {
1963
+ unchanged: include.existing
1964
+ }
1965
+ })
1966
+ const pkgIds = arrays.arrayUnique(needInfoOn.map(d => d.node.pkgid))
1967
+ let { length: remaining } = pkgIds
1968
+ const alertsByPkgId = new Map()
1969
+ if (!remaining) {
1970
+ return alertsByPkgId
1971
+ }
1972
+ const getText = () => `Looking up data for ${remaining} packages`
1973
+ spinner?.start(getText())
1974
+ let overrides
1975
+ const overridesMap = (
1976
+ arb.actualTree ??
1977
+ arb.idealTree ??
1978
+ (await arb.loadActual())
1979
+ )?.overrides?.children
1980
+ if (overridesMap) {
1981
+ overrides = Object.fromEntries(
1982
+ [...overridesMap.entries()].map(([key, overrideSet]) => {
1983
+ return [key, overrideSet.value]
1984
+ })
1985
+ )
1986
+ }
1987
+ const sockSdk = await setupSdk(getPublicToken())
1988
+ const toAlertsMapOptions = {
1989
+ overrides,
1990
+ consolidate: options.consolidate,
1991
+ include,
1992
+ spinner
1993
+ }
1994
+ for await (const batchResult of sockSdk.batchPackageStream(
1995
+ {
1996
+ alerts: 'true',
1997
+ compact: 'true',
1998
+ ...(include.actions
1999
+ ? {
2000
+ actions: include.actions.join(',')
2001
+ }
2002
+ : {}),
2003
+ ...(include.unfixable
2004
+ ? {}
2005
+ : {
2006
+ fixable: 'true'
2007
+ })
2008
+ },
2009
+ {
2010
+ components: pkgIds.map(id => ({
2011
+ purl: `pkg:npm/${id}`
2012
+ }))
2013
+ }
2014
+ )) {
2015
+ if (batchResult.success) {
2016
+ await addArtifactToAlertsMap(
2017
+ batchResult.data,
2018
+ alertsByPkgId,
2019
+ toAlertsMapOptions
2020
+ )
2021
+ } else if (!options.nothrow) {
2022
+ const statusCode = batchResult.status ?? 'unknown'
2023
+ const statusMessage = batchResult.error ?? 'No status message'
2024
+ throw new Error(
2025
+ `Socket API server error (${statusCode}): ${statusMessage}`
2026
+ )
2027
+ }
2028
+ remaining -= 1
2029
+ if (spinner && remaining > 0) {
2030
+ spinner.start()
2031
+ spinner.setText(getText())
2032
+ }
2033
+ }
2034
+ spinner?.stop()
2035
+ return alertsByPkgId
2036
+ }
2037
+ function isTopLevel(tree, node) {
2038
+ return tree.children.get(node.name) === node
2039
+ }
2040
+ function updateNode(
2041
+ node,
2042
+ packument,
2043
+ vulnerableVersionRange,
2044
+ firstPatchedVersionIdentifier
2045
+ ) {
2046
+ const availableVersions = Object.keys(packument.versions)
2047
+ // Find the highest non-vulnerable version within the same major range
2048
+ const targetVersion = findBestPatchVersion(
2049
+ node,
2050
+ availableVersions,
2051
+ vulnerableVersionRange
2052
+ )
2053
+ const targetPackument = targetVersion
2054
+ ? packument.versions[targetVersion]
2055
+ : undefined
2056
+ // Check !targetVersion to make TypeScript happy.
2057
+ if (!targetVersion || !targetPackument) {
2058
+ // No suitable patch version found.
2059
+ return false
2060
+ }
2061
+ // Object.defineProperty is needed to set the version property and replace
2062
+ // the old value with targetVersion.
2063
+ Object.defineProperty(node, 'version', {
2064
+ configurable: true,
2065
+ enumerable: true,
2066
+ get: () => targetVersion
2067
+ })
2068
+ // Update package.version associated with the node.
2069
+ node.package.version = targetVersion
2070
+ // Update node.resolved.
2071
+ const purlObj = packageurlJs.PackageURL.fromString(`pkg:npm/${node.name}`)
2072
+ node.resolved = `${NPM_REGISTRY_URL}/${node.name}/-/${purlObj.name}-${targetVersion}.tgz`
2073
+ // Update node.integrity with the targetPackument.dist.integrity value if available
2074
+ // else delete node.integrity so a new value is resolved for the target version.
2075
+ const { integrity } = targetPackument.dist
2076
+ if (integrity) {
2077
+ node.integrity = integrity
2078
+ } else {
2079
+ delete node.integrity
2080
+ }
2081
+ // Update node.package.deprecated based on targetPackument.deprecated.
2082
+ if (objects.hasOwn(targetPackument, 'deprecated')) {
2083
+ node.package['deprecated'] = targetPackument.deprecated
2084
+ } else {
2085
+ delete node.package['deprecated']
2086
+ }
2087
+ // Update node.package.dependencies.
2088
+ const newDeps = {
2089
+ ...targetPackument.dependencies
2090
+ }
2091
+ const { dependencies: oldDeps } = node.package
2092
+ node.package.dependencies = newDeps
2093
+ if (oldDeps) {
2094
+ for (const oldDepName of Object.keys(oldDeps)) {
2095
+ if (!objects.hasOwn(newDeps, oldDepName)) {
2096
+ // Detach old edges for dependencies that don't exist on the updated
2097
+ // node.package.dependencies.
2098
+ node.edgesOut.get(oldDepName)?.detach()
2099
+ }
2100
+ }
2101
+ }
2102
+ for (const newDepName of Object.keys(newDeps)) {
2103
+ if (!objects.hasOwn(oldDeps, newDepName)) {
2104
+ // Add new edges for dependencies that don't exist on the old
2105
+ // node.package.dependencies.
2106
+ node.addEdgeOut(
2107
+ new Edge({
2108
+ from: node,
2109
+ name: newDepName,
2110
+ spec: newDeps[newDepName],
2111
+ type: 'prod'
2112
+ })
2113
+ )
2114
+ }
2115
+ }
2116
+ return true
2117
+ }
2118
+ function updatePackageJsonFromNode(
2119
+ editablePkgJson,
2120
+ tree,
2121
+ node,
2122
+ targetVersion,
2123
+ rangeStyle
2124
+ ) {
2125
+ if (isTopLevel(tree, node)) {
2126
+ const { name } = node
2127
+ for (const depField of [
2128
+ 'dependencies',
2129
+ 'optionalDependencies',
2130
+ 'peerDependencies'
2131
+ ]) {
2132
+ const oldValue = editablePkgJson.content[depField]
2133
+ if (oldValue) {
2134
+ const refRange = oldValue[name]
2135
+ if (refRange) {
2136
+ editablePkgJson.update({
2137
+ [depField]: {
2138
+ ...oldValue,
2139
+ [name]: applyRange(refRange, targetVersion, rangeStyle)
2140
+ }
2141
+ })
2142
+ }
2143
+ }
2144
+ }
2145
+ }
2146
+ }
2147
+
2148
+ const {
2149
+ NPM,
2150
+ NPX,
2151
+ SOCKET_CLI_ACCEPT_RISKS,
2152
+ SOCKET_CLI_SAFE_BIN,
2153
+ SOCKET_CLI_SAFE_PROGRESS,
2154
+ SOCKET_CLI_VIEW_ALL_RISKS,
2155
+ kInternalsSymbol,
2156
+ [kInternalsSymbol]: { getIpc }
2157
+ } = constants
2158
+ const SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES = {
2159
+ __proto__: null,
2160
+ audit: false,
2161
+ dryRun: true,
2162
+ fund: false,
2163
+ ignoreScripts: true,
2164
+ progress: false,
2165
+ save: false,
2166
+ saveBundle: false,
2167
+ silent: true
2168
+ }
2169
+ const kCtorArgs = Symbol('ctorArgs')
2170
+ const kRiskyReify = Symbol('riskyReify')
2171
+ const Arborist = require(shadowNpmPaths.getArboristClassPath())
2172
+
2173
+ // Implementation code not related to our custom behavior is based on
2174
+ // https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/arborist/index.js:
2175
+ class SafeArborist extends Arborist {
2176
+ constructor(...ctorArgs) {
2177
+ super(
2178
+ {
2179
+ path:
2180
+ (ctorArgs.length ? ctorArgs[0]?.path : undefined) ?? process$1.cwd(),
2181
+ ...(ctorArgs.length ? ctorArgs[0] : undefined),
2182
+ ...SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
2183
+ },
2184
+ ...ctorArgs.slice(1)
2185
+ )
2186
+ this[kCtorArgs] = ctorArgs
2187
+ }
2188
+ async [kRiskyReify](...args) {
2189
+ const ctorArgs = this[kCtorArgs]
2190
+ const arb = new Arborist(
2191
+ {
2192
+ ...(ctorArgs.length ? ctorArgs[0] : undefined),
2193
+ progress: false
2194
+ },
2195
+ ...ctorArgs.slice(1)
2196
+ )
2197
+ const ret = await arb.reify(
2198
+ {
2199
+ ...(args.length ? args[0] : undefined),
2200
+ progress: false
2201
+ },
2202
+ ...args.slice(1)
2203
+ )
2204
+ Object.assign(this, arb)
2205
+ return ret
2206
+ }
2207
+
2208
+ // @ts-ignore Incorrectly typed.
2209
+ async reify(...args) {
2210
+ const options = {
2211
+ __proto__: null,
2212
+ ...(args.length ? args[0] : undefined)
2213
+ }
2214
+ const ipc = await getIpc()
2215
+ const binName = ipc[SOCKET_CLI_SAFE_BIN]
2216
+ if (!binName) {
2217
+ return await this[kRiskyReify](...args)
2218
+ }
2219
+ await super.reify(
2220
+ {
2221
+ ...options,
2222
+ ...SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES,
2223
+ progress: false
2224
+ },
2225
+ // @ts-ignore: TS gets grumpy about rest parameters.
2226
+ ...args.slice(1)
2227
+ )
2228
+ // Lazily access constants.ENV[SOCKET_CLI_ACCEPT_RISKS].
2229
+ const acceptRisks = constants.ENV[SOCKET_CLI_ACCEPT_RISKS]
2230
+ // Lazily access constants.ENV[SOCKET_CLI_VIEW_ALL_RISKS].
2231
+ const viewAllRisks = constants.ENV[SOCKET_CLI_VIEW_ALL_RISKS]
2232
+ const progress = ipc[SOCKET_CLI_SAFE_PROGRESS]
2233
+ const spinner =
2234
+ options['silent'] || !progress
2235
+ ? undefined
2236
+ : // Lazily access constants.spinner.
2237
+ constants.spinner
2238
+ const isSafeNpm = binName === NPM
2239
+ const isSafeNpx = binName === NPX
2240
+ const alertsMap = await getAlertsMapFromArborist(this, {
2241
+ spinner,
2242
+ include:
2243
+ acceptRisks || options.dryRun || options['yes']
2244
+ ? {
2245
+ actions: ['error'],
2246
+ blocked: true,
2247
+ critical: false,
2248
+ cve: false,
2249
+ existing: true,
2250
+ unfixable: false
2251
+ }
2252
+ : {
2253
+ existing: isSafeNpx,
2254
+ unfixable: isSafeNpm
2255
+ }
2256
+ })
2257
+ if (alertsMap.size) {
2258
+ process$1.exitCode = 1
2259
+ logAlertsMap(alertsMap, {
2260
+ hideAt: viewAllRisks ? 'none' : 'middle',
2261
+ output: process$1.stderr
2262
+ })
2263
+ throw new Error(vendor.stripIndents`
2264
+ Socket ${binName} exiting due to risks.${viewAllRisks ? '' : `\nView all risks - Rerun with environment variable ${SOCKET_CLI_VIEW_ALL_RISKS}=1.`}${acceptRisks ? '' : `\nAccept risks - Rerun with environment variable ${SOCKET_CLI_ACCEPT_RISKS}=1.`}
2265
+ `)
2266
+ } else if (!options['silent']) {
2267
+ logger.logger.success(
2268
+ `Socket ${binName} ${acceptRisks ? 'accepted' : 'found no'} risks`
2269
+ )
2270
+ if (binName === NPX) {
2271
+ logger.logger.log(`Running ${options.add[0]}`)
2272
+ }
2273
+ }
2274
+ return await this[kRiskyReify](...args)
2275
+ }
2276
+ }
2277
+
2278
+ function installSafeArborist() {
2279
+ // Override '@npmcli/arborist' module exports with patched variants based on
2280
+ // https://github.com/npm/cli/pull/8089.
2281
+ const cache = require.cache
2282
+ cache[shadowNpmPaths.getArboristClassPath()] = {
2283
+ exports: SafeArborist
2284
+ }
2285
+ cache[shadowNpmPaths.getArboristEdgeClassPath()] = {
2286
+ exports: SafeEdge
2287
+ }
2288
+ cache[shadowNpmPaths.getArboristNodeClassPath()] = {
2289
+ exports: SafeNode
2290
+ }
2291
+ cache[shadowNpmPaths.getArboristOverrideSetClassPath()] = {
2292
+ exports: SafeOverrideSet
2293
+ }
2294
+ }
2295
+
2296
+ installSafeArborist()
2297
+
2298
+ exports.ALERT_SEVERITY = ALERT_SEVERITY
2299
+ exports.Arborist = Arborist
2300
+ exports.AuthError = AuthError
2301
+ exports.ColorOrMarkdown = ColorOrMarkdown
2302
+ exports.InputError = InputError
2303
+ exports.RangeStyles = RangeStyles
2304
+ exports.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES =
2305
+ SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
2306
+ exports.SafeArborist = SafeArborist
2307
+ exports.addArtifactToAlertsMap = addArtifactToAlertsMap
2308
+ exports.applyRange = applyRange
2309
+ exports.assignDefaultFixOptions = assignDefaultFixOptions
2310
+ exports.captureException = captureException
2311
+ exports.findBestPatchVersion = findBestPatchVersion
2312
+ exports.findPackageNode = findPackageNode
2313
+ exports.findPackageNodes = findPackageNodes
2314
+ exports.findUp = findUp
2315
+ exports.formatSeverityCount = formatSeverityCount
2316
+ exports.getAlertsMapFromArborist = getAlertsMapFromArborist
2317
+ exports.getConfigValue = getConfigValue
2318
+ exports.getCveInfoByAlertsMap = getCveInfoByAlertsMap
2319
+ exports.getDefaultToken = getDefaultToken
2320
+ exports.getPublicToken = getPublicToken
2321
+ exports.getSeverityCount = getSeverityCount
2322
+ exports.getSocketDevAlertUrl = getSocketDevAlertUrl
2323
+ exports.getSocketDevPackageOverviewUrl = getSocketDevPackageOverviewUrl
2324
+ exports.isReadOnlyConfig = isReadOnlyConfig
2325
+ exports.overrideCachedConfig = overrideCachedConfig
2326
+ exports.overrideConfigApiToken = overrideConfigApiToken
2327
+ exports.readFileBinary = readFileBinary
2328
+ exports.readFileUtf8 = readFileUtf8
2329
+ exports.safeReadFile = safeReadFile
2330
+ exports.sensitiveConfigKeys = sensitiveConfigKeys
2331
+ exports.setupSdk = setupSdk
2332
+ exports.supportedConfigKeys = supportedConfigKeys
2333
+ exports.updateConfigValue = updateConfigValue
2334
+ exports.updateNode = updateNode
2335
+ exports.updatePackageJsonFromNode = updatePackageJsonFromNode
2336
+ //# debugId=4272984d-bd34-42be-a7cc-e1ca384ab62e
2337
+ //# sourceMappingURL=shadow-npm-inject.js.map