@socketsecurity/cli 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/README.md +22 -22
  2. package/bin/npm +2 -0
  3. package/bin/npx +2 -0
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +3928 -0
  7. package/dist/errors.d.ts +7 -0
  8. package/dist/link.d.ts +2 -0
  9. package/dist/link.js +45 -0
  10. package/dist/npm-cli.d.ts +2 -0
  11. package/dist/npm-cli.js +84 -0
  12. package/dist/npm-injection.d.ts +1 -0
  13. package/dist/npm-injection.js +913 -0
  14. package/dist/npm-injection2.d.ts +25 -0
  15. package/dist/npm-injection2.js +899 -0
  16. package/dist/npx-cli.d.ts +2 -0
  17. package/dist/npx-cli.js +60 -0
  18. package/dist/path-resolve.d.ts +12 -0
  19. package/dist/path-resolve.js +139 -0
  20. package/dist/sdk.d.ts +27 -0
  21. package/dist/sdk.js +224 -0
  22. package/dist/settings.d.ts +9 -0
  23. package/dist/type-helpers.d.ts +3 -0
  24. package/dist/vendor.js +25421 -0
  25. package/package.json +108 -52
  26. package/{lib/shadow/translations.json → translations.json} +20 -20
  27. package/cli.js +0 -72
  28. package/lib/commands/audit-log/index.js +0 -162
  29. package/lib/commands/cdxgen/index.js +0 -211
  30. package/lib/commands/dependencies/index.js +0 -150
  31. package/lib/commands/index.js +0 -15
  32. package/lib/commands/info/index.js +0 -287
  33. package/lib/commands/login/index.js +0 -170
  34. package/lib/commands/logout/index.js +0 -35
  35. package/lib/commands/npm/index.js +0 -27
  36. package/lib/commands/npx/index.js +0 -22
  37. package/lib/commands/organizations/index.js +0 -81
  38. package/lib/commands/raw-npm/index.js +0 -59
  39. package/lib/commands/raw-npx/index.js +0 -59
  40. package/lib/commands/report/create.js +0 -251
  41. package/lib/commands/report/index.js +0 -24
  42. package/lib/commands/report/view.js +0 -176
  43. package/lib/commands/repos/create.js +0 -166
  44. package/lib/commands/repos/delete.js +0 -93
  45. package/lib/commands/repos/index.js +0 -30
  46. package/lib/commands/repos/list.js +0 -170
  47. package/lib/commands/repos/update.js +0 -166
  48. package/lib/commands/repos/view.js +0 -128
  49. package/lib/commands/scan/create.js +0 -245
  50. package/lib/commands/scan/delete.js +0 -112
  51. package/lib/commands/scan/index.js +0 -30
  52. package/lib/commands/scan/list.js +0 -192
  53. package/lib/commands/scan/metadata.js +0 -113
  54. package/lib/commands/scan/stream.js +0 -115
  55. package/lib/commands/wrapper/index.js +0 -199
  56. package/lib/flags/command.js +0 -14
  57. package/lib/flags/index.js +0 -3
  58. package/lib/flags/output.js +0 -16
  59. package/lib/flags/validation.js +0 -14
  60. package/lib/shadow/bin/npm +0 -2
  61. package/lib/shadow/bin/npx +0 -2
  62. package/lib/shadow/link.cjs +0 -50
  63. package/lib/shadow/npm-cli.cjs +0 -27
  64. package/lib/shadow/npm-injection.cjs +0 -649
  65. package/lib/shadow/npx-cli.cjs +0 -27
  66. package/lib/shadow/package.json +0 -3
  67. package/lib/shadow/tty-server.cjs +0 -222
  68. package/lib/shadow/update-notifier.mjs +0 -3
  69. package/lib/utils/api-helpers.js +0 -42
  70. package/lib/utils/chalk-markdown.js +0 -125
  71. package/lib/utils/errors.js +0 -14
  72. package/lib/utils/flags.js +0 -27
  73. package/lib/utils/format-issues.js +0 -99
  74. package/lib/utils/formatting.js +0 -47
  75. package/lib/utils/issue-rules.cjs +0 -180
  76. package/lib/utils/meow-with-subcommands.js +0 -87
  77. package/lib/utils/misc.js +0 -61
  78. package/lib/utils/path-resolve.js +0 -204
  79. package/lib/utils/sdk.js +0 -99
  80. package/lib/utils/settings.js +0 -69
  81. package/lib/utils/type-helpers.cjs +0 -13
  82. package/lib/utils/update-notifier.js +0 -18
@@ -1,649 +0,0 @@
1
- /* eslint-disable no-console */
2
- // THIS MUST BE CJS TO WORK WITH --require
3
- 'use strict'
4
-
5
- const events = require('events')
6
- const fs = require('fs')
7
- const https = require('https')
8
- const path = require('path')
9
- const rl = require('readline')
10
- const { PassThrough } = require('stream')
11
-
12
- const config = require('@socketsecurity/config')
13
-
14
- const oraPromise = import('ora')
15
- const isInteractivePromise = import('is-interactive')
16
- const chalkPromise = import('chalk')
17
- const chalkMarkdownPromise = import('../utils/chalk-markdown.js')
18
- const settingsPromise = import('../utils/settings.js')
19
- const sdkPromise = import('../utils/sdk.js')
20
- const createTTYServer = require('./tty-server.cjs')
21
- const { createIssueUXLookup } = require('../utils/issue-rules.cjs')
22
- const { isErrnoException } = require('../utils/type-helpers.cjs')
23
-
24
- try {
25
- // due to update-notifier pkg being ESM only we actually spawn a subprocess sadly
26
- require('child_process').spawnSync(process.execPath, [
27
- path.join(__dirname, 'update-notifier.mjs')
28
- ], {
29
- stdio: 'inherit'
30
- })
31
- } catch (e) {
32
- // ignore if update notification fails
33
- }
34
-
35
- /**
36
- * @typedef {import('stream').Readable} Readable
37
- */
38
- /**
39
- * @typedef {import('stream').Writable} Writable
40
- */
41
-
42
- const pubTokenPromise = sdkPromise.then(({ getDefaultKey, FREE_API_KEY }) => getDefaultKey() || FREE_API_KEY)
43
- const apiKeySettingsInit = sdkPromise.then(async ({ setupSdk }) => {
44
- try {
45
- const sdk = await setupSdk(await pubTokenPromise)
46
- const orgResult = await sdk.getOrganizations()
47
- if (!orgResult.success) {
48
- throw new Error('Failed to fetch Socket organization info: ' + orgResult.error.message)
49
- }
50
- /**
51
- * @type {(Exclude<typeof orgResult.data.organizations[string], undefined>)[]}
52
- */
53
- const orgs = []
54
- for (const org of Object.values(orgResult.data.organizations)) {
55
- if (org) {
56
- orgs.push(org)
57
- }
58
- }
59
- const result = await sdk.postSettings(orgs.map(org => {
60
- return {
61
- organization: org.id
62
- }
63
- }))
64
- if (!result.success) {
65
- throw new Error('Failed to fetch API key settings: ' + result.error.message)
66
- }
67
- return {
68
- orgs,
69
- settings: result.data
70
- }
71
- } catch (e) {
72
- if (e && typeof e === 'object' && 'cause' in e) {
73
- const cause = e.cause
74
- if (isErrnoException(cause)) {
75
- if (cause.code === 'ENOTFOUND' || cause.code === 'ECONNREFUSED') {
76
- throw new Error('Unable to connect to socket.dev, ensure internet connectivity before retrying', {
77
- cause: e
78
- })
79
- }
80
- }
81
- }
82
- throw e
83
- }
84
- })
85
- // mark apiKeySettingsInit as handled
86
- apiKeySettingsInit.catch(() => {})
87
-
88
- /**
89
- *
90
- */
91
- async function findSocketYML () {
92
- let prevDir = null
93
- let dir = process.cwd()
94
- const fs = require('fs/promises')
95
- while (dir !== prevDir) {
96
- const ymlPath = path.join(dir, 'socket.yml')
97
- const yml = fs.readFile(ymlPath, 'utf-8')
98
- // mark as handled
99
- yml.catch(() => {})
100
- const yamlPath = path.join(dir, 'socket.yaml')
101
- const yaml = fs.readFile(yamlPath, 'utf-8')
102
- // mark as handled
103
- yaml.catch(() => {})
104
- /**
105
- * @param {unknown} e
106
- * @returns {boolean}
107
- */
108
- function checkFileFoundError (e) {
109
- if (isErrnoException(e)) {
110
- if (e.code !== 'ENOENT' && e.code !== 'EISDIR') {
111
- throw e
112
- }
113
- return false
114
- }
115
- return true
116
- }
117
- try {
118
- return {
119
- path: ymlPath,
120
- parsed: config.parseSocketConfig(await yml)
121
- }
122
- } catch (e) {
123
- if (checkFileFoundError(e)) {
124
- throw new Error('Found file but was unable to parse ' + ymlPath)
125
- }
126
- }
127
- try {
128
- return {
129
- path: ymlPath,
130
- parsed: config.parseSocketConfig(await yaml)
131
- }
132
- } catch (e) {
133
- if (checkFileFoundError(e)) {
134
- throw new Error('Found file but was unable to parse ' + yamlPath)
135
- }
136
- }
137
- prevDir = dir
138
- dir = path.join(dir, '..')
139
- }
140
- return null
141
- }
142
-
143
- /**
144
- * @type {Promise<ReturnType<import('../utils/issue-rules.cjs')['createIssueUXLookup']> | undefined>}
145
- */
146
- const uxLookupInit = settingsPromise.then(async ({ getSetting }) => {
147
- const enforcedOrgs = getSetting('enforcedOrgs') ?? []
148
- const remoteSettings = await apiKeySettingsInit
149
- const { orgs, settings } = remoteSettings
150
-
151
- // remove any organizations not being enforced
152
- for (const [i, org] of orgs.entries()) {
153
- if (!enforcedOrgs.includes(org.id)) {
154
- settings.entries.splice(i, 1)
155
- }
156
- }
157
-
158
- const socketYml = await findSocketYML()
159
- if (socketYml) {
160
- settings.entries.push({
161
- start: socketYml.path,
162
- // @ts-ignore
163
- settings: {
164
- [socketYml.path]: {
165
- deferTo: null,
166
- issueRules: socketYml.parsed.issueRules
167
- }
168
- }
169
- })
170
- }
171
- return createIssueUXLookup(settings)
172
- })
173
- // mark uxLookupInit as handled
174
- uxLookupInit.catch(() => {})
175
-
176
- // shadow `npm` and `npx` to mitigate subshells
177
- require('./link.cjs')(fs.realpathSync(path.join(__dirname, 'bin')), 'npm')
178
-
179
- /**
180
- *
181
- * @param {string} pkgid
182
- * @returns {{name: string, version: string}}
183
- */
184
- const pkgidParts = (pkgid) => {
185
- const delimiter = pkgid.lastIndexOf('@')
186
- const name = pkgid.slice(0, delimiter)
187
- const version = pkgid.slice(delimiter + 1)
188
- return { name, version }
189
- }
190
-
191
- /**
192
- * @typedef PURLParts
193
- * @property {'npm'} type
194
- * @property {string} namespace_and_name
195
- * @property {string} version
196
- * @property {URL['href']} repository_url
197
- */
198
-
199
- /**
200
- * @param {string[]} pkgids
201
- * @returns {AsyncGenerator<{eco: string, pkg: string, ver: string } & ({type: 'missing'} | {type: 'success', value: { issues: any[] }})>}
202
- */
203
- async function * batchScan (
204
- pkgids
205
- ) {
206
- const pubToken = await pubTokenPromise
207
- const query = {
208
- packages: pkgids.map(pkgid => {
209
- const { name, version } = pkgidParts(pkgid)
210
- return {
211
- eco: 'npm', pkg: name, ver: version, top: true
212
- }
213
- })
214
- }
215
- // TODO: migrate to SDK
216
- const pkgDataReq = https.request(
217
- 'https://api.socket.dev/v0/scan/batch',
218
- {
219
- method: 'POST',
220
- headers: {
221
- Authorization: `Basic ${Buffer.from(`${pubToken}:`).toString('base64url')}`
222
- }
223
- }
224
- ).end(
225
- JSON.stringify(query)
226
- )
227
- const [res] = await events.once(pkgDataReq, 'response')
228
- const isSuccess = res.statusCode === 200
229
- if (!isSuccess) {
230
- throw new Error('Socket API Error: ' + res.statusCode)
231
- }
232
- const rli = rl.createInterface(res)
233
- for await (const line of rli) {
234
- const result = JSON.parse(line)
235
- yield result
236
- }
237
- }
238
-
239
- /**
240
- * @type {import('./translations.json') | null}
241
- */
242
- let translations = null
243
- /**
244
- * @type {import('../utils/chalk-markdown.js').ChalkOrMarkdown | null}
245
- */
246
- let formatter = null
247
-
248
- const ttyServerPromise = chalkPromise.then(async (chalk) => {
249
- return createTTYServer(chalk.default.level, (await isInteractivePromise).default({
250
- stream: process.stdin
251
- }), npmlog)
252
- })
253
-
254
- const npmEntrypoint = fs.realpathSync(`${process.argv[1]}`)
255
- /**
256
- * @param {string} filepath
257
- * @returns {string | null}
258
- */
259
- function findRoot (filepath) {
260
- if (path.basename(filepath) === 'npm') {
261
- return filepath
262
- }
263
- const parent = path.dirname(filepath)
264
- if (parent === filepath) {
265
- return null
266
- }
267
- return findRoot(parent)
268
- }
269
- const npmDir = findRoot(path.dirname(npmEntrypoint))
270
- if (npmDir === null) {
271
- console.error('Unable to find npm cli install directory, this is potentiall a bug with socket-npm caused by changes to npm cli.')
272
- console.error(`Searched parent directories of ${npmEntrypoint}`)
273
- process.exit(127)
274
- }
275
- let arboristLibClassPath
276
- try {
277
- arboristLibClassPath = path.join(npmDir, 'node_modules', '@npmcli', 'arborist', 'lib', 'arborist', 'index.js')
278
- } catch (e) {
279
- console.error('Unable to integrate with npm cli internals, this is potentially a bug with socket-npm caused by changes to npm cli.')
280
- process.exit(127);
281
- }
282
-
283
- let npmlog
284
-
285
- try {
286
- npmlog = require(path.join(npmDir, 'node_modules', 'npmlog', 'lib', 'log.js'))
287
- } catch {
288
- try {
289
- const { log } = require(path.join(npmDir, 'node_modules', 'proc-log', 'lib', 'index.js'))
290
- npmlog = log
291
- } catch {
292
- console.error('Unable to integrate with npm cli logging infrastructure, this is potentially a bug with socket-npm caused by changes to npm cli.')
293
- process.exit(127);
294
- }
295
- }
296
-
297
- /**
298
- * @type {import('pacote')}
299
- */
300
- const pacote = require(path.join(npmDir, 'node_modules', 'pacote'))
301
-
302
- /**
303
- * @type {typeof import('@npmcli/arborist')}
304
- */
305
- const Arborist = require(arboristLibClassPath)
306
-
307
- const kCtorArgs = Symbol('ctorArgs')
308
- const kRiskyReify = Symbol('riskyReify')
309
- class SafeArborist extends Arborist {
310
- /**
311
- * @param {ConstructorParameters<typeof Arborist>} ctorArgs
312
- */
313
- constructor (...ctorArgs) {
314
- const mutedArguments = [{
315
- ...(ctorArgs[0] ?? {}),
316
- audit: true,
317
- dryRun: true,
318
- ignoreScripts: true,
319
- save: false,
320
- saveBundle: false,
321
- // progress: false,
322
- fund: false
323
- }, ctorArgs.slice(1)]
324
- super(...mutedArguments)
325
- this[kCtorArgs] = ctorArgs
326
- }
327
-
328
- /**
329
- * @param {Parameters<InstanceType<typeof Arborist>['reify']>} args
330
- */
331
- async [kRiskyReify] (...args) {
332
- // safe arborist has suffered side effects and must be rebuilt from scratch
333
- const arb = new Arborist(...this[kCtorArgs])
334
- const ret = await arb.reify(...args)
335
- Object.assign(this, arb)
336
- return ret
337
- }
338
-
339
- /**
340
- * @param {Parameters<InstanceType<typeof Arborist>['reify']>} args
341
- * @override
342
- */
343
- async reify (...args) {
344
- // @ts-expect-error types are wrong
345
- if (args[0]?.dryRun) {
346
- return this[kRiskyReify](...args)
347
- }
348
- args[0] ??= {}
349
- const old = {
350
- dryRun: false,
351
- save: Boolean(args[0].save ?? true),
352
- saveBundle: Boolean(args[0].saveBundle ?? false),
353
- ...args[0]
354
- }
355
- // @ts-expect-error types are wrong
356
- args[0].dryRun = true
357
- args[0].save = false
358
- args[0].saveBundle = false
359
- // const originalDescriptors = Object.getOwnPropertyDescriptors(this)
360
- // TODO: make this deal w/ any refactor to private fields by punching the class itself
361
- await super.reify(...args)
362
- const diff = gatherDiff(this)
363
- // @ts-expect-error types are wrong
364
- args[0].dryRun = old.dryRun
365
- args[0].save = old.save
366
- args[0].saveBundle = old.saveBundle
367
- // nothing to check, mmm already installed or all private?
368
- if (diff.findIndex(c => c.newPackage.repository_url === 'https://registry.npmjs.org') === -1) {
369
- return this[kRiskyReify](...args)
370
- }
371
- const ttyServer = await ttyServerPromise
372
- const proceed = await ttyServer.captureTTY(async (input, output, colorLevel) => {
373
- if (input && output) {
374
- const chalkNS = await chalkPromise
375
- chalkNS.default.level = colorLevel
376
- const oraNS = await oraPromise
377
- const ora = () => {
378
- return oraNS.default({
379
- stream: output,
380
- color: 'cyan',
381
- isEnabled: true,
382
- isSilent: false,
383
- hideCursor: true,
384
- discardStdin: true,
385
- spinner: oraNS.spinners.dots,
386
- })
387
- }
388
- const risky = await packagesHaveRiskyIssues(this, this.registry, diff, ora, input, output)
389
- if (!risky) {
390
- return true
391
- }
392
- const rl = require('readline')
393
- const rlin = new PassThrough()
394
- input.pipe(rlin, {
395
- end: true
396
- })
397
- const rlout = new PassThrough()
398
- rlout.pipe(output, {
399
- end: false
400
- })
401
- const rli = rl.createInterface(rlin, rlout)
402
- try {
403
- while (true) {
404
- /**
405
- * @type {string}
406
- */
407
- const answer = await new Promise((resolve) => {
408
- rli.question('Accept risks of installing these packages (y/N)? ', (str) => resolve(str))
409
- })
410
- if (/^\s*y(es)?\s*$/i.test(answer)) {
411
- return true
412
- } else if (/^(\s*no?\s*|)$/i.test(answer)) {
413
- return false
414
- }
415
- }
416
- } finally {
417
- rli.close()
418
- }
419
- } else {
420
- if (await packagesHaveRiskyIssues(this, this.registry, diff, null, null, output)) {
421
- throw new Error('Socket npm Unable to prompt to accept risk, need TTY to do so')
422
- }
423
- return true
424
- }
425
- // @ts-ignore paranoia
426
- // eslint-disable-next-line
427
- return false
428
- })
429
- if (proceed) {
430
- return this[kRiskyReify](...args)
431
- } else {
432
- throw new Error('Socket npm exiting due to risks')
433
- }
434
- }
435
- }
436
- // @ts-ignore
437
- require.cache[arboristLibClassPath].exports = SafeArborist
438
-
439
- /**
440
- * @typedef {{
441
- * check: InstallEffect[],
442
- * unknowns: InstallEffect[]
443
- * }} InstallDiff
444
- */
445
-
446
- /**
447
- * @param {InstanceType<typeof Arborist>} arb
448
- * @returns {InstallEffect[]}
449
- */
450
- function gatherDiff (arb) {
451
- return walk(arb.diff)
452
- }
453
- /**
454
- * @typedef InstallEffect
455
- * @property {import('@npmcli/arborist').Diff['action']} action
456
- * @property {import('@npmcli/arborist').Node['pkgid'] | null} existing
457
- * @property {import('@npmcli/arborist').Node['pkgid']} pkgid
458
- * @property {import('@npmcli/arborist').Node['resolved']} resolved
459
- * @property {import('@npmcli/arborist').Node['location']} location
460
- * @property {PURLParts | null} oldPackage
461
- * @property {PURLParts} newPackage
462
- */
463
- /**
464
- * @param {import('@npmcli/arborist').Diff | null} diff
465
- * @param {InstallEffect[]} needInfoOn
466
- * @returns {InstallEffect[]}
467
- */
468
- function walk (diff, needInfoOn = []) {
469
- if (!diff) {
470
- return needInfoOn
471
- }
472
-
473
- if (diff.action) {
474
- const sameVersion = diff.actual?.package.version === diff.ideal?.package.version
475
- let keep = false
476
- let existing = null
477
- if (diff.action === 'CHANGE') {
478
- if (!sameVersion) {
479
- existing = diff.actual.pkgid
480
- keep = true
481
- } else {
482
- // console.log('SKIPPING META CHANGE ON', diff)
483
- }
484
- } else {
485
- keep = diff.action !== 'REMOVE'
486
- }
487
- if (keep) {
488
- if (diff.ideal?.pkgid) {
489
- /**
490
- *
491
- * @param {string} pkgid - `pkg@ver`
492
- * @param {string} resolved - tarball link, should match `/name/-/name-ver.tgz` as tail, used to obtain repository_url
493
- * @returns {PURLParts}
494
- */
495
- function toPURL (pkgid, resolved) {
496
- const repo = resolved
497
- .replace(/#[\s\S]*$/u, '')
498
- .replace(/\?[\s\S]*$/u, '')
499
- .replace(/\/[^/]*\/-\/[\s\S]*$/u, '')
500
- const { name, version } = pkgidParts(pkgid)
501
- return {
502
- type: 'npm',
503
- namespace_and_name: name,
504
- version,
505
- repository_url: repo
506
- }
507
- }
508
- if (diff.ideal.resolved && (!diff.actual || diff.actual.resolved)) {
509
- needInfoOn.push({
510
- existing,
511
- action: diff.action,
512
- location: diff.ideal.location,
513
- pkgid: diff.ideal.pkgid,
514
- newPackage: toPURL(diff.ideal.pkgid, diff.ideal.resolved),
515
- oldPackage: diff.actual && diff.actual.resolved ? toPURL(diff.actual.pkgid, diff.actual.resolved) : null,
516
- resolved: diff.ideal.resolved,
517
- })
518
- }
519
- }
520
- }
521
- }
522
- if (diff.children) {
523
- for (const child of diff.children) {
524
- walk(child, needInfoOn)
525
- }
526
- }
527
- return needInfoOn
528
- }
529
-
530
- /**
531
- * @param {SafeArborist} safeArb
532
- * @param {string} _registry
533
- * @param {InstallEffect[]} pkgs
534
- * @param {import('ora')['default'] | null} ora
535
- * @param {Readable | null} [_input]
536
- * @param {Writable | null} [output]
537
- * @returns {Promise<boolean>}
538
- */
539
- async function packagesHaveRiskyIssues (safeArb, _registry, pkgs, ora = null, _input, output) {
540
- let failed = false
541
- if (pkgs.length) {
542
- let remaining = pkgs.length
543
- /**
544
- *
545
- * @returns {string}
546
- */
547
- function getText () {
548
- return `Looking up data for ${remaining} packages`
549
- }
550
- const spinner = ora ? ora().start(getText()) : null
551
- const pkgDatas = []
552
- try {
553
- // TODO: determine org based on cwd, pass in
554
- const uxLookup = await uxLookupInit
555
-
556
- for await (const pkgData of batchScan(pkgs.map(pkg => pkg.pkgid))) {
557
- /**
558
- * @type {Array<any>}
559
- */
560
- let failures = []
561
- let displayWarning = false
562
- const name = pkgData.pkg
563
- const version = pkgData.ver
564
- let blocked = false
565
- if (pkgData.type === 'missing') {
566
- failed = true
567
- failures.push({
568
- type: 'missingDependency'
569
- })
570
- continue
571
- } else {
572
- for (const failure of pkgData.value.issues) {
573
- const ux = await uxLookup({ package: { name, version }, issue: { type: failure.type } })
574
- if (ux.display || ux.block) {
575
- failures.push({ raw: failure, block: ux.block })
576
- // before we ask about problematic issues, check to see if they already existed in the old version
577
- // if they did, be quiet
578
- const pkg = pkgs.find(pkg => pkg.pkgid === `${pkgData.pkg}@${pkgData.ver}` && pkg.existing?.startsWith(pkgData.pkg + '@'))
579
- if (pkg?.existing) {
580
- for await (const oldPkgData of batchScan([pkg.existing])) {
581
- if (oldPkgData.type === 'success') {
582
- failures = failures.filter(
583
- issue => oldPkgData.value.issues.find(oldIssue => oldIssue.type === issue.raw.type) == null
584
- )
585
- }
586
- }
587
- }
588
- }
589
- if (ux.block) {
590
- failed = true
591
- blocked = true
592
- }
593
- if (ux.display) {
594
- displayWarning = true
595
- }
596
- }
597
- }
598
- if (!blocked) {
599
- const pkg = pkgs.find(pkg => pkg.pkgid === `${pkgData.pkg}@${pkgData.ver}`)
600
- if (pkg) {
601
- pacote.tarball.stream(pkg.pkgid, (stream) => {
602
- stream.resume()
603
- // @ts-ignore pacote does a naughty
604
- return stream.promise()
605
- }, { ...safeArb[kCtorArgs][0] })
606
- }
607
- }
608
- if (displayWarning) {
609
- translations ??= JSON.parse(fs.readFileSync(path.join(__dirname, '/translations.json'), 'utf-8'))
610
- formatter ??= new ((await chalkMarkdownPromise).ChalkOrMarkdown)(false)
611
- spinner?.stop()
612
- output?.write(`(socket) ${formatter.hyperlink(`${name}@${version}`, `https://socket.dev/npm/package/${name}/overview/${version}`)} contains risks:\n`)
613
- const lines = new Set()
614
- for (const failure of failures.sort((a, b) => a.raw.type < b.raw.type ? -1 : 1)) {
615
- const type = failure.raw.type
616
- if (type) {
617
- // @ts-ignore
618
- const issueTypeTranslation = translations.issues[type]
619
- // TODO: emoji seems to misalign terminals sometimes
620
- // @ts-ignore
621
- lines.add(` ${issueTypeTranslation?.title ?? type}${failure.block ? '' : ' (non-blocking)'} - ${issueTypeTranslation?.description ?? ''}\n`)
622
- }
623
- }
624
- for (const line of lines) {
625
- output?.write(line)
626
- }
627
- spinner?.start()
628
- }
629
- remaining--
630
- if (remaining !== 0) {
631
- if (spinner) {
632
- spinner.text = getText()
633
- }
634
- }
635
- pkgDatas.push(pkgData)
636
- }
637
- return failed
638
- } finally {
639
- if (spinner?.isSpinning) {
640
- spinner?.stop()
641
- }
642
- }
643
- } else {
644
- if (ora) {
645
- ora('').succeed('No changes detected')
646
- }
647
- return false
648
- }
649
- }
@@ -1,27 +0,0 @@
1
- #!/usr/bin/env node
2
- // THIS FILE USES .cjs to get around the extension-free entrypoint problem with ESM
3
- 'use strict'
4
- const { spawn } = require('child_process')
5
- const { realpathSync } = require('fs')
6
- const path = require('path')
7
-
8
- const realFilename = realpathSync(__filename)
9
- const realDirname = path.dirname(realFilename)
10
-
11
- /**
12
- */
13
- async function main () {
14
- const npxpath = await require('./link.cjs')(path.join(realDirname, 'bin'), 'npx')
15
- process.exitCode = 1
16
- const injectionpath = path.join(realDirname, 'npm-injection.cjs')
17
- spawn(process.execPath, ['--require', injectionpath, npxpath, ...process.argv.slice(2)], {
18
- stdio: 'inherit'
19
- }).on('exit', (code, signal) => {
20
- if (signal) {
21
- process.kill(process.pid, signal)
22
- } else if (code !== null) {
23
- process.exit(code)
24
- }
25
- })
26
- }
27
- main()
@@ -1,3 +0,0 @@
1
- {
2
- "type": "commonjs"
3
- }