@socketsecurity/cli 0.14.66 → 0.14.67
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.
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +10 -2
- package/dist/constants.js.map +1 -1
- package/dist/module-sync/cli.js +872 -391
- package/dist/module-sync/cli.js.map +1 -1
- package/dist/module-sync/config.d.ts +19 -0
- package/dist/module-sync/fs.d.ts +22 -0
- package/dist/module-sync/path-resolve.d.ts +2 -2
- package/dist/module-sync/shadow-npm-inject.js +93 -83
- package/dist/module-sync/shadow-npm-inject.js.map +1 -1
- package/dist/module-sync/shadow-npm-paths.js +3 -3
- package/dist/module-sync/shadow-npm-paths.js.map +1 -1
- package/dist/require/cli.js +872 -391
- package/dist/require/cli.js.map +1 -1
- package/package.json +10 -10
- package/dist/module-sync/settings.d.ts +0 -15
package/dist/require/cli.js
CHANGED
|
@@ -55,8 +55,7 @@ var tinyglobby = _socketInterop(require('tinyglobby'));
|
|
|
55
55
|
var promises = require('@socketsecurity/registry/lib/promises');
|
|
56
56
|
var yaml = _socketInterop(require('yaml'));
|
|
57
57
|
var betterAjvErrors = _socketInterop(require('@apideck/better-ajv-errors'));
|
|
58
|
-
var config$
|
|
59
|
-
var assert = require('node:assert');
|
|
58
|
+
var config$H = require('@socketsecurity/config');
|
|
60
59
|
var readline = require('node:readline/promises');
|
|
61
60
|
var BoxWidget = _socketInterop(require('blessed/lib/widgets/box'));
|
|
62
61
|
var TableWidget = _socketInterop(require('blessed-contrib/lib/widget/table'));
|
|
@@ -103,7 +102,7 @@ function getLastFiveOfApiToken(token) {
|
|
|
103
102
|
|
|
104
103
|
// The API server that should be used for operations.
|
|
105
104
|
function getDefaultApiBaseUrl() {
|
|
106
|
-
const baseUrl = process$1.env['SOCKET_SECURITY_API_BASE_URL'] || shadowNpmInject.
|
|
105
|
+
const baseUrl = process$1.env['SOCKET_SECURITY_API_BASE_URL'] || shadowNpmInject.getConfigValue('apiBaseUrl');
|
|
107
106
|
return strings.isNonEmptyString(baseUrl) ? baseUrl : undefined;
|
|
108
107
|
}
|
|
109
108
|
async function queryApi(path, apiToken) {
|
|
@@ -117,8 +116,8 @@ async function queryApi(path, apiToken) {
|
|
|
117
116
|
}
|
|
118
117
|
|
|
119
118
|
async function fetchOrgAnalyticsData(time, spinner, apiToken) {
|
|
120
|
-
const
|
|
121
|
-
const result = await handleApiCall(
|
|
119
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
120
|
+
const result = await handleApiCall(sockSdk.getOrgAnalytics(time.toString()), 'fetching analytics data');
|
|
122
121
|
if (result.success === false) {
|
|
123
122
|
handleUnsuccessfulApiResponse('getOrgAnalytics', result);
|
|
124
123
|
return undefined;
|
|
@@ -132,8 +131,8 @@ async function fetchOrgAnalyticsData(time, spinner, apiToken) {
|
|
|
132
131
|
}
|
|
133
132
|
|
|
134
133
|
async function fetchRepoAnalyticsData(repo, time, spinner, apiToken) {
|
|
135
|
-
const
|
|
136
|
-
const result = await handleApiCall(
|
|
134
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
135
|
+
const result = await handleApiCall(sockSdk.getRepoAnalytics(repo, time.toString()), 'fetching analytics data');
|
|
137
136
|
if (result.success === false) {
|
|
138
137
|
handleUnsuccessfulApiResponse('getRepoAnalytics', result);
|
|
139
138
|
return undefined;
|
|
@@ -653,9 +652,9 @@ function emitBanner(name) {
|
|
|
653
652
|
}
|
|
654
653
|
function getAsciiHeader(command) {
|
|
655
654
|
const cliVersion = // The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_VERSION_HASH']".
|
|
656
|
-
"0.14.
|
|
655
|
+
"0.14.67:a2db5d2:39ede5c0:pub";
|
|
657
656
|
const nodeVersion = process.version;
|
|
658
|
-
const apiToken = shadowNpmInject.
|
|
657
|
+
const apiToken = shadowNpmInject.getConfigValue('apiToken');
|
|
659
658
|
const shownToken = apiToken ? getLastFiveOfApiToken(apiToken) : 'no';
|
|
660
659
|
const relCwd = path.normalizePath(process.cwd().replace(new RegExp(`^${regexps.escapeRegExp(constants.homePath)}(?:${path$1.sep}|$)`, 'i'), '~/'));
|
|
661
660
|
const body = `
|
|
@@ -667,9 +666,9 @@ function getAsciiHeader(command) {
|
|
|
667
666
|
}
|
|
668
667
|
|
|
669
668
|
const {
|
|
670
|
-
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
669
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$F
|
|
671
670
|
} = constants;
|
|
672
|
-
const config$
|
|
671
|
+
const config$G = {
|
|
673
672
|
commandName: 'analytics',
|
|
674
673
|
description: `Look up analytics data`,
|
|
675
674
|
hidden: false,
|
|
@@ -720,16 +719,16 @@ const config$C = {
|
|
|
720
719
|
`
|
|
721
720
|
};
|
|
722
721
|
const cmdAnalytics = {
|
|
723
|
-
description: config$
|
|
724
|
-
hidden: config$
|
|
725
|
-
run: run$
|
|
722
|
+
description: config$G.description,
|
|
723
|
+
hidden: config$G.hidden,
|
|
724
|
+
run: run$G
|
|
726
725
|
};
|
|
727
|
-
async function run$
|
|
726
|
+
async function run$G(argv, importMeta, {
|
|
728
727
|
parentName
|
|
729
728
|
}) {
|
|
730
729
|
const cli = meowOrExit({
|
|
731
730
|
argv,
|
|
732
|
-
config: config$
|
|
731
|
+
config: config$G,
|
|
733
732
|
importMeta,
|
|
734
733
|
parentName
|
|
735
734
|
});
|
|
@@ -766,7 +765,7 @@ async function run$C(argv, importMeta, {
|
|
|
766
765
|
return;
|
|
767
766
|
}
|
|
768
767
|
if (cli.flags['dryRun']) {
|
|
769
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
768
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$F);
|
|
770
769
|
return;
|
|
771
770
|
}
|
|
772
771
|
return await displayAnalytics({
|
|
@@ -809,8 +808,8 @@ async function fetchAuditLogWithToken(apiToken, {
|
|
|
809
808
|
spinner
|
|
810
809
|
} = constants;
|
|
811
810
|
spinner.start(`Looking up audit log for ${orgSlug}`);
|
|
812
|
-
const
|
|
813
|
-
const result = await handleApiCall(
|
|
811
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
812
|
+
const result = await handleApiCall(sockSdk.getAuditLogEvents(orgSlug, {
|
|
814
813
|
// I'm not sure this is used at all.
|
|
815
814
|
outputJson: String(outputKind === 'json'),
|
|
816
815
|
// I'm not sure this is used at all.
|
|
@@ -953,9 +952,9 @@ async function handleAuditLog({
|
|
|
953
952
|
}
|
|
954
953
|
|
|
955
954
|
const {
|
|
956
|
-
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
955
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$E
|
|
957
956
|
} = constants;
|
|
958
|
-
const config$
|
|
957
|
+
const config$F = {
|
|
959
958
|
commandName: 'audit-log',
|
|
960
959
|
description: 'Look up the audit log for an organization',
|
|
961
960
|
hidden: false,
|
|
@@ -996,16 +995,16 @@ const config$B = {
|
|
|
996
995
|
`
|
|
997
996
|
};
|
|
998
997
|
const cmdAuditLog = {
|
|
999
|
-
description: config$
|
|
1000
|
-
hidden: config$
|
|
1001
|
-
run: run$
|
|
998
|
+
description: config$F.description,
|
|
999
|
+
hidden: config$F.hidden,
|
|
1000
|
+
run: run$F
|
|
1002
1001
|
};
|
|
1003
|
-
async function run$
|
|
1002
|
+
async function run$F(argv, importMeta, {
|
|
1004
1003
|
parentName
|
|
1005
1004
|
}) {
|
|
1006
1005
|
const cli = meowOrExit({
|
|
1007
1006
|
argv,
|
|
1008
|
-
config: config$
|
|
1007
|
+
config: config$F,
|
|
1009
1008
|
importMeta,
|
|
1010
1009
|
parentName
|
|
1011
1010
|
});
|
|
@@ -1030,7 +1029,7 @@ async function run$B(argv, importMeta, {
|
|
|
1030
1029
|
return;
|
|
1031
1030
|
}
|
|
1032
1031
|
if (cli.flags['dryRun']) {
|
|
1033
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
1032
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$E);
|
|
1034
1033
|
return;
|
|
1035
1034
|
}
|
|
1036
1035
|
await handleAuditLog({
|
|
@@ -1147,7 +1146,7 @@ function isHelpFlag(cmdArg) {
|
|
|
1147
1146
|
|
|
1148
1147
|
// import { meowOrExit } from '../../utils/meow-with-subcommands'
|
|
1149
1148
|
const {
|
|
1150
|
-
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
1149
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$D
|
|
1151
1150
|
} = constants;
|
|
1152
1151
|
|
|
1153
1152
|
// TODO: convert yargs to meow. Or convert all the other things to yargs.
|
|
@@ -1224,7 +1223,7 @@ const yargsConfig = {
|
|
|
1224
1223
|
'yes'],
|
|
1225
1224
|
string: ['api-key', 'lifecycle', 'output', 'parent-project-id', 'profile', 'project-group', 'project-name', 'project-version', 'project-id', 'server-host', 'server-port', 'server-url', 'spec-version']
|
|
1226
1225
|
};
|
|
1227
|
-
const config$
|
|
1226
|
+
const config$E = {
|
|
1228
1227
|
commandName: 'cdxgen',
|
|
1229
1228
|
description: 'Create an SBOM with CycloneDX generator (cdxgen)',
|
|
1230
1229
|
hidden: false,
|
|
@@ -1240,18 +1239,18 @@ const config$A = {
|
|
|
1240
1239
|
`
|
|
1241
1240
|
};
|
|
1242
1241
|
const cmdCdxgen = {
|
|
1243
|
-
description: config$
|
|
1244
|
-
hidden: config$
|
|
1245
|
-
run: run$
|
|
1242
|
+
description: config$E.description,
|
|
1243
|
+
hidden: config$E.hidden,
|
|
1244
|
+
run: run$E
|
|
1246
1245
|
};
|
|
1247
|
-
async function run$
|
|
1246
|
+
async function run$E(argv, importMeta, {
|
|
1248
1247
|
parentName
|
|
1249
1248
|
}) {
|
|
1250
1249
|
const cli = meowOrExit({
|
|
1251
1250
|
allowUnknownFlags: true,
|
|
1252
1251
|
// Don't let meow take over --help.
|
|
1253
1252
|
argv: argv.filter(a => !isHelpFlag(a)),
|
|
1254
|
-
config: config$
|
|
1253
|
+
config: config$E,
|
|
1255
1254
|
importMeta,
|
|
1256
1255
|
parentName
|
|
1257
1256
|
});
|
|
@@ -1283,7 +1282,7 @@ async function run$A(argv, importMeta, {
|
|
|
1283
1282
|
return;
|
|
1284
1283
|
}
|
|
1285
1284
|
if (cli.flags['dryRun']) {
|
|
1286
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
1285
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$D);
|
|
1287
1286
|
return;
|
|
1288
1287
|
}
|
|
1289
1288
|
if (yargv.output === undefined) {
|
|
@@ -1292,6 +1291,405 @@ async function run$A(argv, importMeta, {
|
|
|
1292
1291
|
await runCycloneDX(yargv);
|
|
1293
1292
|
}
|
|
1294
1293
|
|
|
1294
|
+
async function outputConfigGet(key, value, outputKind) {
|
|
1295
|
+
if (outputKind === 'json') {
|
|
1296
|
+
logger.logger.log(JSON.stringify({
|
|
1297
|
+
success: true,
|
|
1298
|
+
result: {
|
|
1299
|
+
key,
|
|
1300
|
+
value
|
|
1301
|
+
}
|
|
1302
|
+
}));
|
|
1303
|
+
} else if (outputKind === 'markdown') {
|
|
1304
|
+
logger.logger.log(`# Config Value`);
|
|
1305
|
+
logger.logger.log('');
|
|
1306
|
+
logger.logger.log(`Config key '${key}' has value '${value}`);
|
|
1307
|
+
} else {
|
|
1308
|
+
logger.logger.log(`${key}: ${value}`);
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
async function handleConfigGet({
|
|
1313
|
+
key,
|
|
1314
|
+
outputKind
|
|
1315
|
+
}) {
|
|
1316
|
+
const value = shadowNpmInject.getConfigValue(key);
|
|
1317
|
+
await outputConfigGet(key, value, outputKind);
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
const {
|
|
1321
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$C
|
|
1322
|
+
} = constants;
|
|
1323
|
+
const config$D = {
|
|
1324
|
+
commandName: 'get',
|
|
1325
|
+
description: 'Get the value of a local CLI config item',
|
|
1326
|
+
hidden: false,
|
|
1327
|
+
flags: {
|
|
1328
|
+
...commonFlags,
|
|
1329
|
+
...outputFlags
|
|
1330
|
+
},
|
|
1331
|
+
help: (command, config) => `
|
|
1332
|
+
Usage
|
|
1333
|
+
$ ${command} <org slug>
|
|
1334
|
+
|
|
1335
|
+
Options
|
|
1336
|
+
${getFlagListOutput(config.flags, 6)}
|
|
1337
|
+
|
|
1338
|
+
Keys:
|
|
1339
|
+
|
|
1340
|
+
${Array.from(shadowNpmInject.supportedConfigKeys.entries()).map(([key, desc]) => ` - ${key} -- ${desc}`).join('\n')}
|
|
1341
|
+
|
|
1342
|
+
Examples
|
|
1343
|
+
$ ${command} FakeOrg --repoName=test-repo
|
|
1344
|
+
`
|
|
1345
|
+
};
|
|
1346
|
+
const cmdConfigGet = {
|
|
1347
|
+
description: config$D.description,
|
|
1348
|
+
hidden: config$D.hidden,
|
|
1349
|
+
run: run$D
|
|
1350
|
+
};
|
|
1351
|
+
async function run$D(argv, importMeta, {
|
|
1352
|
+
parentName
|
|
1353
|
+
}) {
|
|
1354
|
+
const cli = meowOrExit({
|
|
1355
|
+
argv,
|
|
1356
|
+
config: config$D,
|
|
1357
|
+
importMeta,
|
|
1358
|
+
parentName
|
|
1359
|
+
});
|
|
1360
|
+
const {
|
|
1361
|
+
json,
|
|
1362
|
+
markdown
|
|
1363
|
+
} = cli.flags;
|
|
1364
|
+
const [key = ''] = cli.input;
|
|
1365
|
+
if (!shadowNpmInject.supportedConfigKeys.has(key) && key !== 'test') {
|
|
1366
|
+
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
1367
|
+
// options or missing arguments.
|
|
1368
|
+
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
1369
|
+
process.exitCode = 2;
|
|
1370
|
+
logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
|
|
1371
|
+
|
|
1372
|
+
- Config key should be the first arg ${!key ? colors.red('(missing!)') : !shadowNpmInject.supportedConfigKeys.has(key) ? colors.red('(invalid config key!)') : colors.green('(ok)')}
|
|
1373
|
+
`);
|
|
1374
|
+
return;
|
|
1375
|
+
}
|
|
1376
|
+
if (cli.flags['dryRun']) {
|
|
1377
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$C);
|
|
1378
|
+
return;
|
|
1379
|
+
}
|
|
1380
|
+
await handleConfigGet({
|
|
1381
|
+
key: key,
|
|
1382
|
+
outputKind: json ? 'json' : markdown ? 'markdown' : 'text'
|
|
1383
|
+
});
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
async function outputConfigList({
|
|
1387
|
+
full,
|
|
1388
|
+
outputKind
|
|
1389
|
+
}) {
|
|
1390
|
+
if (outputKind === 'json') {
|
|
1391
|
+
const obj = {};
|
|
1392
|
+
for (const key of shadowNpmInject.supportedConfigKeys.keys()) {
|
|
1393
|
+
let value = shadowNpmInject.getConfigValue(key);
|
|
1394
|
+
if (!full && shadowNpmInject.sensitiveConfigKeys.has(key)) {
|
|
1395
|
+
value = '********';
|
|
1396
|
+
}
|
|
1397
|
+
if (full || value !== undefined) {
|
|
1398
|
+
obj[key] = value ?? '<none>';
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
logger.logger.log(JSON.stringify({
|
|
1402
|
+
success: true,
|
|
1403
|
+
full,
|
|
1404
|
+
config: obj
|
|
1405
|
+
}, null, 2));
|
|
1406
|
+
} else {
|
|
1407
|
+
const maxWidth = Array.from(shadowNpmInject.supportedConfigKeys.keys()).reduce((a, b) => Math.max(a, b.length), 0);
|
|
1408
|
+
logger.logger.log('# Local CLI Config');
|
|
1409
|
+
logger.logger.log('');
|
|
1410
|
+
logger.logger.log(`This is the local CLI config (full=${!!full}):`);
|
|
1411
|
+
logger.logger.log('');
|
|
1412
|
+
for (const key of shadowNpmInject.supportedConfigKeys.keys()) {
|
|
1413
|
+
let value = shadowNpmInject.getConfigValue(key);
|
|
1414
|
+
if (!full && shadowNpmInject.sensitiveConfigKeys.has(key)) {
|
|
1415
|
+
value = '********';
|
|
1416
|
+
}
|
|
1417
|
+
if (full || value !== undefined) {
|
|
1418
|
+
logger.logger.log(`- ${key}:${' '.repeat(Math.max(0, maxWidth - key.length + 3))} ${Array.isArray(value) ? value.join(', ') || '<none>' : value ?? '<none>'}`);
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
const {
|
|
1425
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$B
|
|
1426
|
+
} = constants;
|
|
1427
|
+
const config$C = {
|
|
1428
|
+
commandName: 'list',
|
|
1429
|
+
description: 'Show all local CLI config items and their values',
|
|
1430
|
+
hidden: false,
|
|
1431
|
+
flags: {
|
|
1432
|
+
...commonFlags,
|
|
1433
|
+
...outputFlags,
|
|
1434
|
+
full: {
|
|
1435
|
+
type: 'boolean',
|
|
1436
|
+
default: false,
|
|
1437
|
+
description: 'Show full tokens in plaintext (unsafe)'
|
|
1438
|
+
}
|
|
1439
|
+
},
|
|
1440
|
+
help: (command, config) => `
|
|
1441
|
+
Usage
|
|
1442
|
+
$ ${command} <org slug>
|
|
1443
|
+
|
|
1444
|
+
Options
|
|
1445
|
+
${getFlagListOutput(config.flags, 6)}
|
|
1446
|
+
|
|
1447
|
+
Keys:
|
|
1448
|
+
|
|
1449
|
+
${Array.from(shadowNpmInject.supportedConfigKeys.entries()).map(([key, desc]) => ` - ${key} -- ${desc}`).join('\n')}
|
|
1450
|
+
|
|
1451
|
+
Examples
|
|
1452
|
+
$ ${command} FakeOrg --repoName=test-repo
|
|
1453
|
+
`
|
|
1454
|
+
};
|
|
1455
|
+
const cmdConfigList = {
|
|
1456
|
+
description: config$C.description,
|
|
1457
|
+
hidden: config$C.hidden,
|
|
1458
|
+
run: run$C
|
|
1459
|
+
};
|
|
1460
|
+
async function run$C(argv, importMeta, {
|
|
1461
|
+
parentName
|
|
1462
|
+
}) {
|
|
1463
|
+
const cli = meowOrExit({
|
|
1464
|
+
argv,
|
|
1465
|
+
config: config$C,
|
|
1466
|
+
importMeta,
|
|
1467
|
+
parentName
|
|
1468
|
+
});
|
|
1469
|
+
const {
|
|
1470
|
+
full,
|
|
1471
|
+
json,
|
|
1472
|
+
markdown
|
|
1473
|
+
} = cli.flags;
|
|
1474
|
+
if (cli.flags['dryRun']) {
|
|
1475
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$B);
|
|
1476
|
+
return;
|
|
1477
|
+
}
|
|
1478
|
+
await outputConfigList({
|
|
1479
|
+
full: !!full,
|
|
1480
|
+
outputKind: json ? 'json' : markdown ? 'markdown' : 'text'
|
|
1481
|
+
});
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
async function outputConfigSet(key, _value, outputKind) {
|
|
1485
|
+
if (outputKind === 'json') {
|
|
1486
|
+
logger.logger.log(JSON.stringify({
|
|
1487
|
+
success: true,
|
|
1488
|
+
message: `Config key '${key}' was updated`
|
|
1489
|
+
}));
|
|
1490
|
+
} else if (outputKind === 'markdown') {
|
|
1491
|
+
logger.logger.log(`# Update config`);
|
|
1492
|
+
logger.logger.log('');
|
|
1493
|
+
logger.logger.log(`Config key '${key}' was updated`);
|
|
1494
|
+
} else {
|
|
1495
|
+
logger.logger.log(`OK`);
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
async function handleConfigSet({
|
|
1500
|
+
key,
|
|
1501
|
+
outputKind,
|
|
1502
|
+
value
|
|
1503
|
+
}) {
|
|
1504
|
+
shadowNpmInject.updateConfigValue(key, value);
|
|
1505
|
+
await outputConfigSet(key, value, outputKind);
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
const {
|
|
1509
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$A
|
|
1510
|
+
} = constants;
|
|
1511
|
+
const config$B = {
|
|
1512
|
+
commandName: 'set',
|
|
1513
|
+
description: 'Update the value of a local CLI config item',
|
|
1514
|
+
hidden: false,
|
|
1515
|
+
flags: {
|
|
1516
|
+
...commonFlags,
|
|
1517
|
+
...outputFlags
|
|
1518
|
+
},
|
|
1519
|
+
help: (command, config) => `
|
|
1520
|
+
Usage
|
|
1521
|
+
$ ${command} <key> <value>
|
|
1522
|
+
|
|
1523
|
+
Options
|
|
1524
|
+
${getFlagListOutput(config.flags, 6)}
|
|
1525
|
+
|
|
1526
|
+
This is a crude way of updating the local configuration for this CLI tool.
|
|
1527
|
+
|
|
1528
|
+
Note that updating a value here is nothing more than updating a key/value
|
|
1529
|
+
store entry. No validation is happening. The server may reject your config.
|
|
1530
|
+
|
|
1531
|
+
Keys:
|
|
1532
|
+
|
|
1533
|
+
${Array.from(shadowNpmInject.supportedConfigKeys.entries()).map(([key, desc]) => ` - ${key} -- ${desc}`).join('\n')}
|
|
1534
|
+
|
|
1535
|
+
Examples
|
|
1536
|
+
$ ${command} apiProxy https://example.com
|
|
1537
|
+
`
|
|
1538
|
+
};
|
|
1539
|
+
const cmdConfigSet = {
|
|
1540
|
+
description: config$B.description,
|
|
1541
|
+
hidden: config$B.hidden,
|
|
1542
|
+
run: run$B
|
|
1543
|
+
};
|
|
1544
|
+
async function run$B(argv, importMeta, {
|
|
1545
|
+
parentName
|
|
1546
|
+
}) {
|
|
1547
|
+
const cli = meowOrExit({
|
|
1548
|
+
argv,
|
|
1549
|
+
config: config$B,
|
|
1550
|
+
importMeta,
|
|
1551
|
+
parentName
|
|
1552
|
+
});
|
|
1553
|
+
const {
|
|
1554
|
+
json,
|
|
1555
|
+
markdown
|
|
1556
|
+
} = cli.flags;
|
|
1557
|
+
const [key = '', ...rest] = cli.input;
|
|
1558
|
+
const value = rest.join(' ');
|
|
1559
|
+
if (!shadowNpmInject.supportedConfigKeys.has(key) && key !== 'test' || !value) {
|
|
1560
|
+
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
1561
|
+
// options or missing arguments.
|
|
1562
|
+
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
1563
|
+
process.exitCode = 2;
|
|
1564
|
+
logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
|
|
1565
|
+
|
|
1566
|
+
- Config key should be the first arg ${!key ? colors.red('(missing!)') : !shadowNpmInject.supportedConfigKeys.has(key) ? colors.red('(invalid config key!)') : colors.green('(ok)')}
|
|
1567
|
+
|
|
1568
|
+
- Key value should be the remaining args (use \`del\` to unset a value) ${!value ? colors.red('(missing!)') : colors.green('(ok)')}`);
|
|
1569
|
+
return;
|
|
1570
|
+
}
|
|
1571
|
+
if (cli.flags['dryRun']) {
|
|
1572
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$A);
|
|
1573
|
+
return;
|
|
1574
|
+
}
|
|
1575
|
+
await handleConfigSet({
|
|
1576
|
+
key: key,
|
|
1577
|
+
outputKind: json ? 'json' : markdown ? 'markdown' : 'text',
|
|
1578
|
+
value
|
|
1579
|
+
});
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1582
|
+
async function outputConfigUnset(key, outputKind) {
|
|
1583
|
+
if (outputKind === 'json') {
|
|
1584
|
+
logger.logger.log(JSON.stringify({
|
|
1585
|
+
success: true,
|
|
1586
|
+
message: `Config key '${key}' was unset`
|
|
1587
|
+
}));
|
|
1588
|
+
} else if (outputKind === 'markdown') {
|
|
1589
|
+
logger.logger.log(`# Update config`);
|
|
1590
|
+
logger.logger.log('');
|
|
1591
|
+
logger.logger.log(`Config key '${key}' was unset`);
|
|
1592
|
+
} else {
|
|
1593
|
+
logger.logger.log(`OK`);
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
async function handleConfigUnset({
|
|
1598
|
+
key,
|
|
1599
|
+
outputKind
|
|
1600
|
+
}) {
|
|
1601
|
+
shadowNpmInject.updateConfigValue(key, undefined);
|
|
1602
|
+
await outputConfigUnset(key, outputKind);
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
const {
|
|
1606
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$z
|
|
1607
|
+
} = constants;
|
|
1608
|
+
const config$A = {
|
|
1609
|
+
commandName: 'unset',
|
|
1610
|
+
description: 'Clear the value of a local CLI config item',
|
|
1611
|
+
hidden: false,
|
|
1612
|
+
flags: {
|
|
1613
|
+
...commonFlags,
|
|
1614
|
+
...outputFlags
|
|
1615
|
+
},
|
|
1616
|
+
help: (command, config) => `
|
|
1617
|
+
Usage
|
|
1618
|
+
$ ${command} <org slug>
|
|
1619
|
+
|
|
1620
|
+
Options
|
|
1621
|
+
${getFlagListOutput(config.flags, 6)}
|
|
1622
|
+
|
|
1623
|
+
Keys:
|
|
1624
|
+
|
|
1625
|
+
${Array.from(shadowNpmInject.supportedConfigKeys.entries()).map(([key, desc]) => ` - ${key} -- ${desc}`).join('\n')}
|
|
1626
|
+
|
|
1627
|
+
Examples
|
|
1628
|
+
$ ${command} FakeOrg --repoName=test-repo
|
|
1629
|
+
`
|
|
1630
|
+
};
|
|
1631
|
+
const cmdConfigUnset = {
|
|
1632
|
+
description: config$A.description,
|
|
1633
|
+
hidden: config$A.hidden,
|
|
1634
|
+
run: run$A
|
|
1635
|
+
};
|
|
1636
|
+
async function run$A(argv, importMeta, {
|
|
1637
|
+
parentName
|
|
1638
|
+
}) {
|
|
1639
|
+
const cli = meowOrExit({
|
|
1640
|
+
argv,
|
|
1641
|
+
config: config$A,
|
|
1642
|
+
importMeta,
|
|
1643
|
+
parentName
|
|
1644
|
+
});
|
|
1645
|
+
const {
|
|
1646
|
+
json,
|
|
1647
|
+
markdown
|
|
1648
|
+
} = cli.flags;
|
|
1649
|
+
const [key = ''] = cli.input;
|
|
1650
|
+
if (!shadowNpmInject.supportedConfigKeys.has(key) && key !== 'test') {
|
|
1651
|
+
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
1652
|
+
// options or missing arguments.
|
|
1653
|
+
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
1654
|
+
process.exitCode = 2;
|
|
1655
|
+
logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
|
|
1656
|
+
|
|
1657
|
+
- Config key should be the first arg ${!key ? colors.red('(missing!)') : !shadowNpmInject.supportedConfigKeys.has(key) ? colors.red('(invalid config key!)') : colors.green('(ok)')}
|
|
1658
|
+
`);
|
|
1659
|
+
return;
|
|
1660
|
+
}
|
|
1661
|
+
if (cli.flags['dryRun']) {
|
|
1662
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$z);
|
|
1663
|
+
return;
|
|
1664
|
+
}
|
|
1665
|
+
await handleConfigUnset({
|
|
1666
|
+
key: key,
|
|
1667
|
+
outputKind: json ? 'json' : markdown ? 'markdown' : 'text'
|
|
1668
|
+
});
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
const description$7 = 'Commands related to the local CLI configuration';
|
|
1672
|
+
const cmdConfig = {
|
|
1673
|
+
description: description$7,
|
|
1674
|
+
hidden: true,
|
|
1675
|
+
// [beta]
|
|
1676
|
+
async run(argv, importMeta, {
|
|
1677
|
+
parentName
|
|
1678
|
+
}) {
|
|
1679
|
+
await meowWithSubcommands({
|
|
1680
|
+
unset: cmdConfigUnset,
|
|
1681
|
+
get: cmdConfigGet,
|
|
1682
|
+
list: cmdConfigList,
|
|
1683
|
+
set: cmdConfigSet
|
|
1684
|
+
}, {
|
|
1685
|
+
argv,
|
|
1686
|
+
description: description$7,
|
|
1687
|
+
importMeta,
|
|
1688
|
+
name: `${parentName} config`
|
|
1689
|
+
});
|
|
1690
|
+
}
|
|
1691
|
+
};
|
|
1692
|
+
|
|
1295
1693
|
async function fetchDependencies({
|
|
1296
1694
|
limit,
|
|
1297
1695
|
offset
|
|
@@ -1314,8 +1712,8 @@ async function fetchDependenciesWithToken(apiToken, {
|
|
|
1314
1712
|
spinner
|
|
1315
1713
|
} = constants;
|
|
1316
1714
|
spinner.start('Fetching organization dependencies...');
|
|
1317
|
-
const
|
|
1318
|
-
const result = await handleApiCall(
|
|
1715
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
1716
|
+
const result = await handleApiCall(sockSdk.searchDependencies({
|
|
1319
1717
|
limit,
|
|
1320
1718
|
offset
|
|
1321
1719
|
}), 'Searching dependencies');
|
|
@@ -1828,12 +2226,12 @@ async function getAlertsMapFromPnpmLockfile(lockfile, options) {
|
|
|
1828
2226
|
}
|
|
1829
2227
|
const getText = () => `Looking up data for ${remaining} packages`;
|
|
1830
2228
|
spinner?.start(getText());
|
|
1831
|
-
const
|
|
2229
|
+
const sockSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
|
|
1832
2230
|
const toAlertsMapOptions = {
|
|
1833
2231
|
overrides: lockfile.overrides,
|
|
1834
2232
|
...options
|
|
1835
2233
|
};
|
|
1836
|
-
for await (const batchPackageFetchResult of
|
|
2234
|
+
for await (const batchPackageFetchResult of sockSdk.batchPackageStream({
|
|
1837
2235
|
alerts: 'true',
|
|
1838
2236
|
compact: 'true',
|
|
1839
2237
|
fixable: include.unfixable ? 'false' : 'true'
|
|
@@ -2432,15 +2830,15 @@ async function run$x(argv, importMeta, {
|
|
|
2432
2830
|
}
|
|
2433
2831
|
|
|
2434
2832
|
async function fetchPackageInfo(pkgName, pkgVersion, includeAllIssues) {
|
|
2435
|
-
const
|
|
2833
|
+
const sockSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
|
|
2436
2834
|
|
|
2437
2835
|
// Lazily access constants.spinner.
|
|
2438
2836
|
const {
|
|
2439
2837
|
spinner
|
|
2440
2838
|
} = constants;
|
|
2441
2839
|
spinner.start(pkgVersion === 'latest' ? `Looking up data for the latest version of ${pkgName}` : `Looking up data for version ${pkgVersion} of ${pkgName}`);
|
|
2442
|
-
const result = await handleApiCall(
|
|
2443
|
-
const scoreResult = await handleApiCall(
|
|
2840
|
+
const result = await handleApiCall(sockSdk.getIssuesByNPMPackage(pkgName, pkgVersion), 'looking up package');
|
|
2841
|
+
const scoreResult = await handleApiCall(sockSdk.getScoreByNPMPackage(pkgName, pkgVersion), 'looking up package score');
|
|
2444
2842
|
spinner.successAndStop('Data fetched');
|
|
2445
2843
|
if (result.success === false) {
|
|
2446
2844
|
return handleUnsuccessfulApiResponse('getIssuesByNPMPackage', result);
|
|
@@ -2655,18 +3053,18 @@ async function run$w(argv, importMeta, {
|
|
|
2655
3053
|
}
|
|
2656
3054
|
|
|
2657
3055
|
function applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy) {
|
|
2658
|
-
shadowNpmInject.
|
|
2659
|
-
shadowNpmInject.
|
|
2660
|
-
shadowNpmInject.
|
|
2661
|
-
shadowNpmInject.
|
|
3056
|
+
shadowNpmInject.updateConfigValue('enforcedOrgs', enforcedOrgs);
|
|
3057
|
+
shadowNpmInject.updateConfigValue('apiToken', apiToken);
|
|
3058
|
+
shadowNpmInject.updateConfigValue('apiBaseUrl', apiBaseUrl);
|
|
3059
|
+
shadowNpmInject.updateConfigValue('apiProxy', apiProxy);
|
|
2662
3060
|
}
|
|
2663
3061
|
|
|
2664
3062
|
const {
|
|
2665
3063
|
SOCKET_PUBLIC_API_TOKEN
|
|
2666
3064
|
} = constants;
|
|
2667
3065
|
async function attemptLogin(apiBaseUrl, apiProxy) {
|
|
2668
|
-
apiBaseUrl ??= shadowNpmInject.
|
|
2669
|
-
apiProxy ??= shadowNpmInject.
|
|
3066
|
+
apiBaseUrl ??= shadowNpmInject.getConfigValue('apiBaseUrl') ?? undefined;
|
|
3067
|
+
apiProxy ??= shadowNpmInject.getConfigValue('apiProxy') ?? undefined;
|
|
2670
3068
|
const apiToken = (await prompts.password({
|
|
2671
3069
|
message: `Enter your ${terminalLink('Socket.dev API key', 'https://docs.socket.dev/docs/api-keys')} (leave blank for a public key)`
|
|
2672
3070
|
})) || SOCKET_PUBLIC_API_TOKEN;
|
|
@@ -2722,7 +3120,7 @@ async function attemptLogin(apiBaseUrl, apiProxy) {
|
|
|
2722
3120
|
}
|
|
2723
3121
|
}
|
|
2724
3122
|
spinner.stop();
|
|
2725
|
-
const oldToken = shadowNpmInject.
|
|
3123
|
+
const oldToken = shadowNpmInject.getConfigValue('apiToken');
|
|
2726
3124
|
try {
|
|
2727
3125
|
applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy);
|
|
2728
3126
|
logger.logger.success(`API credentials ${oldToken ? 'updated' : 'set'}`);
|
|
@@ -2790,10 +3188,10 @@ async function run$v(argv, importMeta, {
|
|
|
2790
3188
|
}
|
|
2791
3189
|
|
|
2792
3190
|
function applyLogout() {
|
|
2793
|
-
shadowNpmInject.
|
|
2794
|
-
shadowNpmInject.
|
|
2795
|
-
shadowNpmInject.
|
|
2796
|
-
shadowNpmInject.
|
|
3191
|
+
shadowNpmInject.updateConfigValue('apiToken', null);
|
|
3192
|
+
shadowNpmInject.updateConfigValue('apiBaseUrl', null);
|
|
3193
|
+
shadowNpmInject.updateConfigValue('apiProxy', null);
|
|
3194
|
+
shadowNpmInject.updateConfigValue('enforcedOrgs', null);
|
|
2797
3195
|
}
|
|
2798
3196
|
|
|
2799
3197
|
function attemptLogout() {
|
|
@@ -4542,14 +4940,14 @@ async function fetchOrganization() {
|
|
|
4542
4940
|
return await fetchOrganizationWithToken(apiToken);
|
|
4543
4941
|
}
|
|
4544
4942
|
async function fetchOrganizationWithToken(apiToken) {
|
|
4545
|
-
const
|
|
4943
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
4546
4944
|
|
|
4547
4945
|
// Lazily access constants.spinner.
|
|
4548
4946
|
const {
|
|
4549
4947
|
spinner
|
|
4550
4948
|
} = constants;
|
|
4551
4949
|
spinner.start('Fetching organization list...');
|
|
4552
|
-
const result = await handleApiCall(
|
|
4950
|
+
const result = await handleApiCall(sockSdk.getOrganizations(), 'looking up organizations');
|
|
4553
4951
|
spinner.successAndStop('Received organization list response.');
|
|
4554
4952
|
if (!result.success) {
|
|
4555
4953
|
handleUnsuccessfulApiResponse('getOrganizations', result);
|
|
@@ -4679,9 +5077,9 @@ async function fetchSecurityPolicyWithToken(apiToken, orgSlug) {
|
|
|
4679
5077
|
const {
|
|
4680
5078
|
spinner
|
|
4681
5079
|
} = constants;
|
|
4682
|
-
const
|
|
5080
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
4683
5081
|
spinner.start('Fetching organization quota...');
|
|
4684
|
-
const result = await handleApiCall(
|
|
5082
|
+
const result = await handleApiCall(sockSdk.getOrgSecurityPolicy(orgSlug), 'looking up organization quota');
|
|
4685
5083
|
spinner?.successAndStop('Received organization quota response.');
|
|
4686
5084
|
if (!result.success) {
|
|
4687
5085
|
handleUnsuccessfulApiResponse('getOrgSecurityPolicy', result);
|
|
@@ -4824,9 +5222,9 @@ async function fetchQuotaWithToken(apiToken) {
|
|
|
4824
5222
|
const {
|
|
4825
5223
|
spinner
|
|
4826
5224
|
} = constants;
|
|
4827
|
-
const
|
|
5225
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
4828
5226
|
spinner.start('Fetching organization quota...');
|
|
4829
|
-
const result = await handleApiCall(
|
|
5227
|
+
const result = await handleApiCall(sockSdk.getQuota(), 'looking up organization quota');
|
|
4830
5228
|
spinner?.successAndStop('Recieved organization quota response.');
|
|
4831
5229
|
if (!result.success) {
|
|
4832
5230
|
handleUnsuccessfulApiResponse('getQuota', result);
|
|
@@ -4953,8 +5351,8 @@ async function fetchPurlsShallowScore(purls) {
|
|
|
4953
5351
|
spinner
|
|
4954
5352
|
} = constants;
|
|
4955
5353
|
spinner.start(`Requesting data ...`);
|
|
4956
|
-
const
|
|
4957
|
-
const result = await handleApiCall(
|
|
5354
|
+
const sockSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
|
|
5355
|
+
const result = await handleApiCall(sockSdk.batchPackageFetch({
|
|
4958
5356
|
alerts: 'true'
|
|
4959
5357
|
// compact: false,
|
|
4960
5358
|
// fixable: false,
|
|
@@ -5355,8 +5753,8 @@ async function createReport(socketConfig, inputPaths, {
|
|
|
5355
5753
|
const {
|
|
5356
5754
|
spinner
|
|
5357
5755
|
} = constants;
|
|
5358
|
-
const
|
|
5359
|
-
const supportedFiles = await
|
|
5756
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
5757
|
+
const supportedFiles = await sockSdk.getReportSupportedFiles().then(res => {
|
|
5360
5758
|
if (!res.success) handleUnsuccessfulApiResponse('getReportSupportedFiles', res);
|
|
5361
5759
|
return res.data;
|
|
5362
5760
|
}).catch(cause => {
|
|
@@ -5364,7 +5762,7 @@ async function createReport(socketConfig, inputPaths, {
|
|
|
5364
5762
|
cause
|
|
5365
5763
|
});
|
|
5366
5764
|
});
|
|
5367
|
-
const packagePaths = await shadowNpmPaths.
|
|
5765
|
+
const packagePaths = await shadowNpmPaths.getPackageFilesForScan(cwd, inputPaths, supportedFiles, socketConfig);
|
|
5368
5766
|
const packagePathsCount = packagePaths.length;
|
|
5369
5767
|
if (packagePathsCount && debug.isDebug()) {
|
|
5370
5768
|
for (const pkgPath of packagePaths) {
|
|
@@ -5376,7 +5774,7 @@ async function createReport(socketConfig, inputPaths, {
|
|
|
5376
5774
|
return undefined;
|
|
5377
5775
|
}
|
|
5378
5776
|
spinner.start(`Creating report with ${packagePathsCount} package ${words.pluralize('file', packagePathsCount)}`);
|
|
5379
|
-
const apiCall =
|
|
5777
|
+
const apiCall = sockSdk.createReportFromFilePaths(packagePaths, cwd, socketConfig?.issueRules);
|
|
5380
5778
|
const result = await handleApiCall(apiCall, 'creating report');
|
|
5381
5779
|
if (!result.success) {
|
|
5382
5780
|
handleUnsuccessfulApiResponse('createReport', result);
|
|
@@ -5387,8 +5785,8 @@ async function createReport(socketConfig, inputPaths, {
|
|
|
5387
5785
|
}
|
|
5388
5786
|
|
|
5389
5787
|
async function getSocketConfig(absoluteConfigPath) {
|
|
5390
|
-
const socketConfig = await config$
|
|
5391
|
-
if (cause && typeof cause === 'object' && cause instanceof config$
|
|
5788
|
+
const socketConfig = await config$H.readSocketConfig(absoluteConfigPath).catch(cause => {
|
|
5789
|
+
if (cause && typeof cause === 'object' && cause instanceof config$H.SocketValidationError) {
|
|
5392
5790
|
// Inspired by workbox-build:
|
|
5393
5791
|
// https://github.com/GoogleChrome/workbox/blob/95f97a207fd51efb3f8a653f6e3e58224183a778/packages/workbox-build/src/lib/validate-options.ts#L68-L71
|
|
5394
5792
|
const betterErrors = betterAjvErrors.betterAjvErrors({
|
|
@@ -5416,12 +5814,12 @@ async function fetchReportData$1(reportId, includeAllIssues, strict) {
|
|
|
5416
5814
|
} = constants;
|
|
5417
5815
|
spinner.log('Fetching report with ID ${reportId} (this could take a while)');
|
|
5418
5816
|
spinner.start(`Fetch started... (this could take a while)`);
|
|
5419
|
-
const
|
|
5817
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
5420
5818
|
let result;
|
|
5421
5819
|
for (let retry = 1; !result; ++retry) {
|
|
5422
5820
|
try {
|
|
5423
5821
|
// eslint-disable-next-line no-await-in-loop
|
|
5424
|
-
result = await handleApiCall(
|
|
5822
|
+
result = await handleApiCall(sockSdk.getReport(reportId), 'fetching report');
|
|
5425
5823
|
} catch (err) {
|
|
5426
5824
|
if (retry >= MAX_TIMEOUT_RETRY || !(err instanceof Error) || err.cause?.cause?.response?.statusCode !== HTTP_CODE_TIMEOUT) {
|
|
5427
5825
|
spinner.stop(`Failed to fetch report`);
|
|
@@ -5473,7 +5871,7 @@ function formatReportDataOutput(reportId, data, commandName, outputKind, strict,
|
|
|
5473
5871
|
}
|
|
5474
5872
|
}
|
|
5475
5873
|
|
|
5476
|
-
async function
|
|
5874
|
+
async function fetchScan(orgSlug, scanId) {
|
|
5477
5875
|
// Lazily access constants.spinner.
|
|
5478
5876
|
const {
|
|
5479
5877
|
spinner
|
|
@@ -5483,7 +5881,7 @@ async function getFullScan(orgSlug, fullScanId) {
|
|
|
5483
5881
|
throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
|
|
5484
5882
|
}
|
|
5485
5883
|
spinner.start('Fetching full-scan...');
|
|
5486
|
-
const response = await queryApi(`orgs/${orgSlug}/full-scans/${encodeURIComponent(
|
|
5884
|
+
const response = await queryApi(`orgs/${orgSlug}/full-scans/${encodeURIComponent(scanId)}`, apiToken);
|
|
5487
5885
|
spinner.stop('Fetch complete.');
|
|
5488
5886
|
if (!response.ok) {
|
|
5489
5887
|
const err = await handleApiError(response.status);
|
|
@@ -5512,7 +5910,7 @@ async function viewReport(reportId, {
|
|
|
5512
5910
|
strict
|
|
5513
5911
|
}) {
|
|
5514
5912
|
const result = await fetchReportData$1(reportId, all, strict);
|
|
5515
|
-
const artifacts = await
|
|
5913
|
+
const artifacts = await fetchScan('socketdev', reportId);
|
|
5516
5914
|
if (result) {
|
|
5517
5915
|
formatReportDataOutput(reportId, result, commandName, outputKind, strict, artifacts);
|
|
5518
5916
|
}
|
|
@@ -5713,9 +6111,9 @@ async function fetchCreateRepoWithToken(apiToken, {
|
|
|
5713
6111
|
const {
|
|
5714
6112
|
spinner
|
|
5715
6113
|
} = constants;
|
|
5716
|
-
const
|
|
6114
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
5717
6115
|
spinner.start('Sending request ot create a repository...');
|
|
5718
|
-
const result = await handleApiCall(
|
|
6116
|
+
const result = await handleApiCall(sockSdk.createOrgRepo(orgSlug, {
|
|
5719
6117
|
name: repoName,
|
|
5720
6118
|
description,
|
|
5721
6119
|
homepage,
|
|
@@ -5860,8 +6258,8 @@ async function deleteRepoWithToken(orgSlug, repoName, apiToken) {
|
|
|
5860
6258
|
spinner
|
|
5861
6259
|
} = constants;
|
|
5862
6260
|
spinner.start('Deleting repository...');
|
|
5863
|
-
const
|
|
5864
|
-
const result = await handleApiCall(
|
|
6261
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
6262
|
+
const result = await handleApiCall(sockSdk.deleteOrgRepo(orgSlug, repoName), 'deleting repository');
|
|
5865
6263
|
if (!result.success) {
|
|
5866
6264
|
handleUnsuccessfulApiResponse('deleteOrgRepo', result);
|
|
5867
6265
|
return;
|
|
@@ -5956,9 +6354,9 @@ async function fetchListReposWithToken(apiToken, {
|
|
|
5956
6354
|
const {
|
|
5957
6355
|
spinner
|
|
5958
6356
|
} = constants;
|
|
5959
|
-
const
|
|
6357
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
5960
6358
|
spinner.start('Fetching list of repositories...');
|
|
5961
|
-
const result = await handleApiCall(
|
|
6359
|
+
const result = await handleApiCall(sockSdk.getOrgRepoList(orgSlug, {
|
|
5962
6360
|
sort,
|
|
5963
6361
|
direction,
|
|
5964
6362
|
per_page: String(per_page),
|
|
@@ -6145,8 +6543,8 @@ async function fetchUpdateRepoWithToken(apiToken, {
|
|
|
6145
6543
|
spinner
|
|
6146
6544
|
} = constants;
|
|
6147
6545
|
spinner.start('Sending request to update a repository...');
|
|
6148
|
-
const
|
|
6149
|
-
const result = await handleApiCall(
|
|
6546
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
6547
|
+
const result = await handleApiCall(sockSdk.updateOrgRepo(orgSlug, repoName, {
|
|
6150
6548
|
orgSlug,
|
|
6151
6549
|
name: repoName,
|
|
6152
6550
|
description,
|
|
@@ -6293,9 +6691,9 @@ async function fetchViewRepoWithToken(orgSlug, repoName, apiToken) {
|
|
|
6293
6691
|
const {
|
|
6294
6692
|
spinner
|
|
6295
6693
|
} = constants;
|
|
6296
|
-
const
|
|
6694
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
6297
6695
|
spinner.start('Fetching repository data...');
|
|
6298
|
-
const result = await handleApiCall(
|
|
6696
|
+
const result = await handleApiCall(sockSdk.getOrgRepo(orgSlug, repoName), 'fetching repository');
|
|
6299
6697
|
spinner.successAndStop('Received response while fetched repository data.');
|
|
6300
6698
|
if (!result.success) {
|
|
6301
6699
|
handleUnsuccessfulApiResponse('getOrgRepo', result);
|
|
@@ -6449,8 +6847,106 @@ const cmdRepos = {
|
|
|
6449
6847
|
}
|
|
6450
6848
|
};
|
|
6451
6849
|
|
|
6452
|
-
async function
|
|
6453
|
-
const
|
|
6850
|
+
async function fetchCreateOrgFullScan(packagePaths, orgSlug, repoName, branchName, commitMessage, defaultBranch, pendingHead, tmp, cwd) {
|
|
6851
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
6852
|
+
|
|
6853
|
+
// Lazily access constants.spinner.
|
|
6854
|
+
const {
|
|
6855
|
+
spinner
|
|
6856
|
+
} = constants;
|
|
6857
|
+
spinner.start(`Creating a scan with ${packagePaths.length} packages...`);
|
|
6858
|
+
const result = await handleApiCall(sockSdk.createOrgFullScan(orgSlug, {
|
|
6859
|
+
repo: repoName,
|
|
6860
|
+
branch: branchName,
|
|
6861
|
+
commit_message: commitMessage,
|
|
6862
|
+
make_default_branch: String(defaultBranch),
|
|
6863
|
+
set_as_pending_head: String(pendingHead),
|
|
6864
|
+
tmp: String(tmp)
|
|
6865
|
+
}, packagePaths, cwd), 'Creating scan');
|
|
6866
|
+
spinner.successAndStop('Scan created successfully');
|
|
6867
|
+
if (!result.success) {
|
|
6868
|
+
handleUnsuccessfulApiResponse('CreateOrgFullScan', result);
|
|
6869
|
+
return;
|
|
6870
|
+
}
|
|
6871
|
+
return result.data;
|
|
6872
|
+
}
|
|
6873
|
+
|
|
6874
|
+
async function fetchSupportedScanFileNames() {
|
|
6875
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
6876
|
+
|
|
6877
|
+
// Lazily access constants.spinner.
|
|
6878
|
+
const {
|
|
6879
|
+
spinner
|
|
6880
|
+
} = constants;
|
|
6881
|
+
spinner.start('Requesting supported scan file types from API...');
|
|
6882
|
+
const result = await handleApiCall(sockSdk.getReportSupportedFiles(), 'fetching supported scan file types');
|
|
6883
|
+
spinner.successAndStop('Received response while fetched supported scan file types.');
|
|
6884
|
+
if (!result.success) {
|
|
6885
|
+
handleUnsuccessfulApiResponse('getReportSupportedFiles', result);
|
|
6886
|
+
return;
|
|
6887
|
+
}
|
|
6888
|
+
return result.data;
|
|
6889
|
+
}
|
|
6890
|
+
|
|
6891
|
+
async function outputCreateNewScan(data) {
|
|
6892
|
+
const link = colors.underline(colors.cyan(`${data.html_report_url}`));
|
|
6893
|
+
logger.logger.log(`Available at: ${link}`);
|
|
6894
|
+
const rl = readline.createInterface({
|
|
6895
|
+
input: process$1.stdin,
|
|
6896
|
+
output: process$1.stdout
|
|
6897
|
+
});
|
|
6898
|
+
const answer = await rl.question('Would you like to open it in your browser? (y/n)');
|
|
6899
|
+
if (answer.toLowerCase() === 'y') {
|
|
6900
|
+
await vendor.open(`${data.html_report_url}`);
|
|
6901
|
+
}
|
|
6902
|
+
rl.close();
|
|
6903
|
+
}
|
|
6904
|
+
|
|
6905
|
+
async function handleCreateNewScan({
|
|
6906
|
+
branchName,
|
|
6907
|
+
commitMessage,
|
|
6908
|
+
cwd,
|
|
6909
|
+
defaultBranch,
|
|
6910
|
+
orgSlug,
|
|
6911
|
+
pendingHead,
|
|
6912
|
+
readOnly,
|
|
6913
|
+
repoName,
|
|
6914
|
+
targets,
|
|
6915
|
+
tmp
|
|
6916
|
+
}) {
|
|
6917
|
+
const apiToken = shadowNpmInject.getDefaultToken();
|
|
6918
|
+
|
|
6919
|
+
// Note: you need an apiToken to request supportedScanFileNames from the API
|
|
6920
|
+
if (!apiToken) {
|
|
6921
|
+
throw new shadowNpmInject.AuthError('User must be authenticated to create and submit new scans. To log in, run the command `socket login` and enter your API key.');
|
|
6922
|
+
}
|
|
6923
|
+
const supportedFileNames = await fetchSupportedScanFileNames();
|
|
6924
|
+
if (!supportedFileNames) return;
|
|
6925
|
+
const packagePaths = await shadowNpmPaths.getPackageFilesForScan(cwd, targets, supportedFileNames
|
|
6926
|
+
// socketConfig
|
|
6927
|
+
);
|
|
6928
|
+
if (!packagePaths.length) {
|
|
6929
|
+
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
6930
|
+
// options or missing arguments.
|
|
6931
|
+
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
6932
|
+
process$1.exitCode = 2;
|
|
6933
|
+
logger.logger.fail(commonTags.stripIndents`
|
|
6934
|
+
${colors.bgRed(colors.white('Input error'))}: The TARGET did not contain any matching / supported files for a scan
|
|
6935
|
+
`);
|
|
6936
|
+
return;
|
|
6937
|
+
}
|
|
6938
|
+
if (readOnly) {
|
|
6939
|
+
logger.logger.log('[ReadOnly] Bailing now');
|
|
6940
|
+
return;
|
|
6941
|
+
}
|
|
6942
|
+
const data = await fetchCreateOrgFullScan(packagePaths, orgSlug, repoName, branchName, commitMessage, defaultBranch, pendingHead, tmp, cwd);
|
|
6943
|
+
if (!data) return;
|
|
6944
|
+
await outputCreateNewScan(data);
|
|
6945
|
+
}
|
|
6946
|
+
|
|
6947
|
+
async function suggestOrgSlug() {
|
|
6948
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
6949
|
+
const result = await handleApiCall(sockSdk.getOrganizations(), 'looking up organizations');
|
|
6454
6950
|
// Ignore a failed request here. It was not the primary goal of
|
|
6455
6951
|
// running this command and reporting it only leads to end-user confusion.
|
|
6456
6952
|
if (result.success) {
|
|
@@ -6471,13 +6967,17 @@ async function suggestOrgSlug(socketSdk) {
|
|
|
6471
6967
|
if (proceed) {
|
|
6472
6968
|
return proceed;
|
|
6473
6969
|
}
|
|
6970
|
+
} else {
|
|
6971
|
+
logger.logger.fail('Failed to lookup organization list from API, unable to suggest.');
|
|
6474
6972
|
}
|
|
6475
6973
|
}
|
|
6476
6974
|
|
|
6477
|
-
async function suggestRepoSlug(
|
|
6975
|
+
async function suggestRepoSlug(orgSlug) {
|
|
6976
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
6977
|
+
|
|
6478
6978
|
// Same as above, but if there's a repo with the same name as cwd then
|
|
6479
6979
|
// default the selection to that name.
|
|
6480
|
-
const result = await handleApiCall(
|
|
6980
|
+
const result = await handleApiCall(sockSdk.getOrgRepoList(orgSlug, {
|
|
6481
6981
|
orgSlug,
|
|
6482
6982
|
sort: 'name',
|
|
6483
6983
|
direction: 'asc',
|
|
@@ -6487,6 +6987,7 @@ async function suggestRepoSlug(socketSdk, orgSlug) {
|
|
|
6487
6987
|
perPage: '10',
|
|
6488
6988
|
page: '0'
|
|
6489
6989
|
}), 'looking up known repos');
|
|
6990
|
+
|
|
6490
6991
|
// Ignore a failed request here. It was not the primary goal of
|
|
6491
6992
|
// running this command and reporting it only leads to end-user confusion.
|
|
6492
6993
|
if (result.success) {
|
|
@@ -6494,7 +6995,7 @@ async function suggestRepoSlug(socketSdk, orgSlug) {
|
|
|
6494
6995
|
let cwdIsKnown = !!currentDirName && result.data.results.some(obj => obj.slug === currentDirName);
|
|
6495
6996
|
if (!cwdIsKnown && currentDirName) {
|
|
6496
6997
|
// Do an explicit request so we can assert that the cwd exists or not
|
|
6497
|
-
const result = await handleApiCall(
|
|
6998
|
+
const result = await handleApiCall(sockSdk.getOrgRepo(orgSlug, currentDirName), 'checking if current cwd is a known repo');
|
|
6498
6999
|
if (result.success) {
|
|
6499
7000
|
cwdIsKnown = true;
|
|
6500
7001
|
}
|
|
@@ -6533,203 +7034,64 @@ async function suggestRepoSlug(socketSdk, orgSlug) {
|
|
|
6533
7034
|
}
|
|
6534
7035
|
});
|
|
6535
7036
|
return {
|
|
6536
|
-
slug: repoName,
|
|
6537
|
-
defaultBranch: repoDefaultBranch
|
|
6538
|
-
};
|
|
6539
|
-
}
|
|
6540
|
-
}
|
|
6541
|
-
}
|
|
6542
|
-
function dirNameToSlug(name) {
|
|
6543
|
-
// Uses slug specs asserted by our servers
|
|
6544
|
-
// Note: this can lead to collisions; eg. slug for `x--y` and `x---y` is `x-y`
|
|
6545
|
-
return name.toLowerCase().replace(/[^[a-zA-Z0-9_.-]/g, '_').replace(/--+/g, '-').replace(/__+/g, '_').replace(/\.\.+/g, '.').replace(/[._-]+$/, '');
|
|
6546
|
-
}
|
|
6547
|
-
|
|
6548
|
-
async function suggestBranchSlug(repoDefaultBranch) {
|
|
6549
|
-
const spawnResult = spawn.spawnSync('git', ['branch', '--show-current']);
|
|
6550
|
-
const currentBranch = spawnResult.stdout.toString('utf8').trim();
|
|
6551
|
-
if (currentBranch && spawnResult.status === 0) {
|
|
6552
|
-
const proceed = await prompts.select({
|
|
6553
|
-
message: 'Use the current git branch as target branch name?',
|
|
6554
|
-
choices: [{
|
|
6555
|
-
name: `Yes [${currentBranch}]`,
|
|
6556
|
-
value: currentBranch,
|
|
6557
|
-
description: 'Use the current git branch for branch name'
|
|
6558
|
-
}, ...(repoDefaultBranch && repoDefaultBranch !== currentBranch ? [{
|
|
6559
|
-
name: `No, use the default branch [${repoDefaultBranch}]`,
|
|
6560
|
-
value: repoDefaultBranch,
|
|
6561
|
-
description: 'Use the default branch for target repo as the target branch name'
|
|
6562
|
-
}] : []), {
|
|
6563
|
-
name: 'No',
|
|
6564
|
-
value: '',
|
|
6565
|
-
description: 'Do not use the current git branch as name (will end in a no-op)'
|
|
6566
|
-
}].filter(Boolean)
|
|
6567
|
-
});
|
|
6568
|
-
if (proceed) {
|
|
6569
|
-
return proceed;
|
|
6570
|
-
}
|
|
6571
|
-
}
|
|
6572
|
-
}
|
|
6573
|
-
|
|
6574
|
-
async function suggestTarget() {
|
|
6575
|
-
// We could prefill this with sub-dirs of the current
|
|
6576
|
-
// dir ... but is that going to be useful?
|
|
6577
|
-
const proceed = await prompts.select({
|
|
6578
|
-
message: 'No TARGET given. Do you want to use the current directory?',
|
|
6579
|
-
choices: [{
|
|
6580
|
-
name: 'Yes',
|
|
6581
|
-
value: true,
|
|
6582
|
-
description: 'Target the current directory'
|
|
6583
|
-
}, {
|
|
6584
|
-
name: 'No',
|
|
6585
|
-
value: false,
|
|
6586
|
-
description: 'Do not use the current directory (this will end in a no-op)'
|
|
6587
|
-
}]
|
|
6588
|
-
});
|
|
6589
|
-
if (proceed) {
|
|
6590
|
-
return ['.'];
|
|
6591
|
-
}
|
|
6592
|
-
}
|
|
6593
|
-
|
|
6594
|
-
async function createFullScan({
|
|
6595
|
-
branchName,
|
|
6596
|
-
commitHash: _commitHash,
|
|
6597
|
-
commitMessage,
|
|
6598
|
-
committers: _committers,
|
|
6599
|
-
cwd,
|
|
6600
|
-
defaultBranch,
|
|
6601
|
-
orgSlug,
|
|
6602
|
-
pendingHead,
|
|
6603
|
-
pullRequest: _pullRequest,
|
|
6604
|
-
readOnly,
|
|
6605
|
-
repoName,
|
|
6606
|
-
targets,
|
|
6607
|
-
tmp
|
|
6608
|
-
}) {
|
|
6609
|
-
// Lazily access constants.spinner.
|
|
6610
|
-
const {
|
|
6611
|
-
spinner
|
|
6612
|
-
} = constants;
|
|
6613
|
-
const socketSdk = await shadowNpmInject.setupSdk();
|
|
6614
|
-
const supportedFiles = await socketSdk.getReportSupportedFiles().then(res => {
|
|
6615
|
-
if (!res.success) {
|
|
6616
|
-
handleUnsuccessfulApiResponse('getReportSupportedFiles', res);
|
|
6617
|
-
assert(false, 'handleUnsuccessfulApiResponse should unconditionally throw');
|
|
6618
|
-
}
|
|
6619
|
-
return res.data;
|
|
6620
|
-
}).catch(cause => {
|
|
6621
|
-
throw new Error('Failed getting supported files for report', {
|
|
6622
|
-
cause
|
|
6623
|
-
});
|
|
6624
|
-
});
|
|
6625
|
-
|
|
6626
|
-
// If we updated any inputs then we should print the command line to repeat
|
|
6627
|
-
// the command without requiring user input, as a suggestion.
|
|
6628
|
-
let updatedInput = false;
|
|
6629
|
-
if (!targets.length) {
|
|
6630
|
-
const received = await suggestTarget();
|
|
6631
|
-
targets = received ?? [];
|
|
6632
|
-
updatedInput = true;
|
|
6633
|
-
}
|
|
6634
|
-
|
|
6635
|
-
// // TODO: we'll probably use socket.json or something else soon...
|
|
6636
|
-
// const absoluteConfigPath = path.join(cwd, 'socket.yml')
|
|
6637
|
-
// const socketConfig = await getSocketConfig(absoluteConfigPath)
|
|
6638
|
-
|
|
6639
|
-
const packagePaths = await shadowNpmPaths.getPackageFilesFullScans(cwd, targets, supportedFiles
|
|
6640
|
-
// socketConfig
|
|
6641
|
-
);
|
|
6642
|
-
|
|
6643
|
-
// We're going to need an api token to suggest data because those suggestions
|
|
6644
|
-
// must come from data we already know. Don't error on missing api token yet.
|
|
6645
|
-
// If the api-token is not set, ignore it for the sake of suggestions.
|
|
6646
|
-
const apiToken = shadowNpmInject.getDefaultToken();
|
|
6647
|
-
|
|
6648
|
-
// If the current cwd is unknown and is used as a repo slug anyways, we will
|
|
6649
|
-
// first need to register the slug before we can use it.
|
|
6650
|
-
let repoDefaultBranch = '';
|
|
6651
|
-
if (apiToken) {
|
|
6652
|
-
if (!orgSlug) {
|
|
6653
|
-
const suggestion = await suggestOrgSlug(socketSdk);
|
|
6654
|
-
if (suggestion) orgSlug = suggestion;
|
|
6655
|
-
updatedInput = true;
|
|
6656
|
-
}
|
|
6657
|
-
|
|
6658
|
-
// (Don't bother asking for the rest if we didn't get an org slug above)
|
|
6659
|
-
if (orgSlug && !repoName) {
|
|
6660
|
-
const suggestion = await suggestRepoSlug(socketSdk, orgSlug);
|
|
6661
|
-
if (suggestion) {
|
|
6662
|
-
repoDefaultBranch = suggestion.defaultBranch;
|
|
6663
|
-
repoName = suggestion.slug;
|
|
6664
|
-
}
|
|
6665
|
-
updatedInput = true;
|
|
6666
|
-
}
|
|
6667
|
-
|
|
6668
|
-
// (Don't bother asking for the rest if we didn't get an org/repo above)
|
|
6669
|
-
if (orgSlug && repoName && !branchName) {
|
|
6670
|
-
const suggestion = await suggestBranchSlug(repoDefaultBranch);
|
|
6671
|
-
if (suggestion) branchName = suggestion;
|
|
6672
|
-
updatedInput = true;
|
|
7037
|
+
slug: repoName,
|
|
7038
|
+
defaultBranch: repoDefaultBranch
|
|
7039
|
+
};
|
|
6673
7040
|
}
|
|
7041
|
+
} else {
|
|
7042
|
+
logger.logger.fail('Failed to lookup repo list from API, unable to suggest.');
|
|
6674
7043
|
}
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
|
|
6682
|
-
|
|
6683
|
-
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6684
|
-
|
|
6685
|
-
- Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6686
|
-
|
|
6687
|
-
- Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6688
|
-
|
|
6689
|
-
- At least one TARGET (e.g. \`.\` or \`./package.json\`) ${!packagePaths.length ? colors.red(targets.length > 0 ? '(TARGET' + (targets.length ? 's' : '') + ' contained no matching/supported files!)' : '(missing)') : colors.green('(ok)')}
|
|
7044
|
+
}
|
|
7045
|
+
function dirNameToSlug(name) {
|
|
7046
|
+
// Uses slug specs asserted by our servers
|
|
7047
|
+
// Note: this can lead to collisions; eg. slug for `x--y` and `x---y` is `x-y`
|
|
7048
|
+
return name.toLowerCase().replace(/[^[a-zA-Z0-9_.-]/g, '_').replace(/--+/g, '-').replace(/__+/g, '_').replace(/\.\.+/g, '.').replace(/[._-]+$/, '');
|
|
7049
|
+
}
|
|
6690
7050
|
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
set_as_pending_head: String(pendingHead),
|
|
6715
|
-
tmp: String(tmp)
|
|
6716
|
-
}, packagePaths, cwd), 'Creating scan');
|
|
6717
|
-
if (!result.success) {
|
|
6718
|
-
handleUnsuccessfulApiResponse('CreateOrgFullScan', result);
|
|
6719
|
-
return;
|
|
7051
|
+
async function suggestBranchSlug(repoDefaultBranch) {
|
|
7052
|
+
const spawnResult = spawn.spawnSync('git', ['branch', '--show-current']);
|
|
7053
|
+
const currentBranch = spawnResult.stdout.toString('utf8').trim();
|
|
7054
|
+
if (currentBranch && spawnResult.status === 0) {
|
|
7055
|
+
const proceed = await prompts.select({
|
|
7056
|
+
message: 'Use the current git branch as target branch name?',
|
|
7057
|
+
choices: [{
|
|
7058
|
+
name: `Yes [${currentBranch}]`,
|
|
7059
|
+
value: currentBranch,
|
|
7060
|
+
description: 'Use the current git branch for branch name'
|
|
7061
|
+
}, ...(repoDefaultBranch && repoDefaultBranch !== currentBranch ? [{
|
|
7062
|
+
name: `No, use the default branch [${repoDefaultBranch}]`,
|
|
7063
|
+
value: repoDefaultBranch,
|
|
7064
|
+
description: 'Use the default branch for target repo as the target branch name'
|
|
7065
|
+
}] : []), {
|
|
7066
|
+
name: 'No',
|
|
7067
|
+
value: '',
|
|
7068
|
+
description: 'Do not use the current git branch as name (will end in a no-op)'
|
|
7069
|
+
}].filter(Boolean)
|
|
7070
|
+
});
|
|
7071
|
+
if (proceed) {
|
|
7072
|
+
return proceed;
|
|
7073
|
+
}
|
|
6720
7074
|
}
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
|
|
7075
|
+
}
|
|
7076
|
+
|
|
7077
|
+
async function suggestTarget() {
|
|
7078
|
+
// We could prefill this with sub-dirs of the current
|
|
7079
|
+
// dir ... but is that going to be useful?
|
|
7080
|
+
const proceed = await prompts.select({
|
|
7081
|
+
message: 'No TARGET given. Do you want to use the current directory?',
|
|
7082
|
+
choices: [{
|
|
7083
|
+
name: 'Yes',
|
|
7084
|
+
value: true,
|
|
7085
|
+
description: 'Target the current directory'
|
|
7086
|
+
}, {
|
|
7087
|
+
name: 'No',
|
|
7088
|
+
value: false,
|
|
7089
|
+
description: 'Do not use the current directory (this will end in a no-op)'
|
|
7090
|
+
}]
|
|
6727
7091
|
});
|
|
6728
|
-
|
|
6729
|
-
|
|
6730
|
-
await vendor.open(`${result.data.html_report_url}`);
|
|
7092
|
+
if (proceed) {
|
|
7093
|
+
return ['.'];
|
|
6731
7094
|
}
|
|
6732
|
-
rl.close();
|
|
6733
7095
|
}
|
|
6734
7096
|
|
|
6735
7097
|
const {
|
|
@@ -6853,18 +7215,66 @@ async function run$7(argv, importMeta, {
|
|
|
6853
7215
|
importMeta,
|
|
6854
7216
|
parentName
|
|
6855
7217
|
});
|
|
6856
|
-
const [orgSlug = '', ...targets] = cli.input;
|
|
6857
|
-
const cwd = cli.flags['cwd'] && cli.flags['cwd'] !== 'process.cwd()' ? String(cli.flags['cwd']) : process$1.cwd();
|
|
6858
7218
|
const {
|
|
7219
|
+
cwd: cwdOverride,
|
|
7220
|
+
dryRun
|
|
7221
|
+
} = cli.flags;
|
|
7222
|
+
const cwd = cwdOverride && cwdOverride !== 'process.cwd()' ? String(cwdOverride) : process$1.cwd();
|
|
7223
|
+
let {
|
|
6859
7224
|
branch: branchName,
|
|
6860
7225
|
repo: repoName
|
|
6861
7226
|
} = cli.flags;
|
|
6862
|
-
|
|
7227
|
+
let [orgSlug = '', ...targets] = cli.input;
|
|
6863
7228
|
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
7229
|
+
// We're going to need an api token to suggest data because those suggestions
|
|
7230
|
+
// must come from data we already know. Don't error on missing api token yet.
|
|
7231
|
+
// If the api-token is not set, ignore it for the sake of suggestions.
|
|
7232
|
+
const apiToken = shadowNpmInject.getDefaultToken();
|
|
7233
|
+
|
|
7234
|
+
// If we updated any inputs then we should print the command line to repeat
|
|
7235
|
+
// the command without requiring user input, as a suggestion.
|
|
7236
|
+
let updatedInput = false;
|
|
7237
|
+
if (!targets.length && !dryRun) {
|
|
7238
|
+
const received = await suggestTarget();
|
|
7239
|
+
targets = received ?? [];
|
|
7240
|
+
updatedInput = true;
|
|
7241
|
+
}
|
|
7242
|
+
|
|
7243
|
+
// If the current cwd is unknown and is used as a repo slug anyways, we will
|
|
7244
|
+
// first need to register the slug before we can use it.
|
|
7245
|
+
let repoDefaultBranch = '';
|
|
7246
|
+
// Only do suggestions with an apiToken and when not in dryRun mode
|
|
7247
|
+
if (apiToken && !dryRun) {
|
|
7248
|
+
if (!orgSlug) {
|
|
7249
|
+
const suggestion = await suggestOrgSlug();
|
|
7250
|
+
if (suggestion) orgSlug = suggestion;
|
|
7251
|
+
updatedInput = true;
|
|
7252
|
+
}
|
|
7253
|
+
|
|
7254
|
+
// (Don't bother asking for the rest if we didn't get an org slug above)
|
|
7255
|
+
if (orgSlug && !repoName) {
|
|
7256
|
+
const suggestion = await suggestRepoSlug(orgSlug);
|
|
7257
|
+
if (suggestion) {
|
|
7258
|
+
repoDefaultBranch = suggestion.defaultBranch;
|
|
7259
|
+
repoName = suggestion.slug;
|
|
7260
|
+
}
|
|
7261
|
+
updatedInput = true;
|
|
7262
|
+
}
|
|
7263
|
+
|
|
7264
|
+
// (Don't bother asking for the rest if we didn't get an org/repo above)
|
|
7265
|
+
if (orgSlug && repoName && !branchName) {
|
|
7266
|
+
const suggestion = await suggestBranchSlug(repoDefaultBranch);
|
|
7267
|
+
if (suggestion) branchName = suggestion;
|
|
7268
|
+
updatedInput = true;
|
|
7269
|
+
}
|
|
7270
|
+
}
|
|
7271
|
+
if (updatedInput && repoName && branchName && orgSlug && targets?.length) {
|
|
7272
|
+
logger.logger.error('Note: You can invoke this command next time to skip the interactive questions:');
|
|
7273
|
+
logger.logger.error('```');
|
|
7274
|
+
logger.logger.error(` socket scan create [other flags...] --repo ${repoName} --branch ${branchName} ${orgSlug} ${targets.join(' ')}`);
|
|
7275
|
+
logger.logger.error('```\n');
|
|
7276
|
+
}
|
|
7277
|
+
if (!orgSlug || !repoName || !branchName || !targets.length) {
|
|
6868
7278
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
6869
7279
|
// options or missing arguments.
|
|
6870
7280
|
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
@@ -6878,28 +7288,25 @@ async function run$7(argv, importMeta, {
|
|
|
6878
7288
|
|
|
6879
7289
|
- Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6880
7290
|
|
|
6881
|
-
- At least one TARGET (e.g. \`.\` or \`./package.json\`) ${!targets.length ? '(missing)' : colors.green('(ok)')}
|
|
7291
|
+
- At least one TARGET (e.g. \`.\` or \`./package.json\`) ${!targets.length ? colors.red('(missing)') : colors.green('(ok)')}
|
|
6882
7292
|
|
|
6883
|
-
|
|
7293
|
+
${!apiToken ? 'Note: was unable to make suggestions because no API Token was found; this would make the command fail regardless' : ''}
|
|
6884
7294
|
`);
|
|
6885
7295
|
return;
|
|
6886
7296
|
}
|
|
6887
7297
|
|
|
6888
7298
|
// Note exiting earlier to skirt a hidden auth requirement
|
|
6889
|
-
if (
|
|
7299
|
+
if (dryRun) {
|
|
6890
7300
|
logger.logger.log(DRY_RUN_BAIL_TEXT$7);
|
|
6891
7301
|
return;
|
|
6892
7302
|
}
|
|
6893
|
-
await
|
|
7303
|
+
await handleCreateNewScan({
|
|
6894
7304
|
branchName: branchName,
|
|
6895
|
-
commitHash: cli.flags['commitHash'] ?? '',
|
|
6896
7305
|
commitMessage: cli.flags['commitMessage'] ?? '',
|
|
6897
|
-
committers: cli.flags['committers'] ?? '',
|
|
6898
7306
|
cwd,
|
|
6899
7307
|
defaultBranch: Boolean(cli.flags['defaultBranch']),
|
|
6900
7308
|
orgSlug,
|
|
6901
7309
|
pendingHead: Boolean(cli.flags['pendingHead']),
|
|
6902
|
-
pullRequest: cli.flags['pullRequest'] ?? undefined,
|
|
6903
7310
|
readOnly: Boolean(cli.flags['readOnly']),
|
|
6904
7311
|
repoName: repoName,
|
|
6905
7312
|
targets,
|
|
@@ -6907,26 +7314,37 @@ async function run$7(argv, importMeta, {
|
|
|
6907
7314
|
});
|
|
6908
7315
|
}
|
|
6909
7316
|
|
|
6910
|
-
async function
|
|
7317
|
+
async function fetchDeleteOrgFullScan(orgSlug, scanId) {
|
|
6911
7318
|
const apiToken = shadowNpmInject.getDefaultToken();
|
|
6912
7319
|
if (!apiToken) {
|
|
6913
7320
|
throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
|
|
6914
7321
|
}
|
|
6915
|
-
await
|
|
7322
|
+
await fetchDeleteOrgFullScanWithToken(apiToken, orgSlug, scanId);
|
|
6916
7323
|
}
|
|
6917
|
-
async function
|
|
7324
|
+
async function fetchDeleteOrgFullScanWithToken(apiToken, orgSlug, scanId) {
|
|
6918
7325
|
// Lazily access constants.spinner.
|
|
6919
7326
|
const {
|
|
6920
7327
|
spinner
|
|
6921
7328
|
} = constants;
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
const result = await handleApiCall(
|
|
7329
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
7330
|
+
spinner.start('Requesting the scan to be deleted...');
|
|
7331
|
+
const result = await handleApiCall(sockSdk.deleteOrgFullScan(orgSlug, scanId), 'Deleting scan');
|
|
7332
|
+
spinner.successAndStop('Received response for deleting a scan.');
|
|
6925
7333
|
if (!result.success) {
|
|
6926
7334
|
handleUnsuccessfulApiResponse('deleteOrgFullScan', result);
|
|
6927
7335
|
return;
|
|
6928
7336
|
}
|
|
6929
|
-
|
|
7337
|
+
return result.data;
|
|
7338
|
+
}
|
|
7339
|
+
|
|
7340
|
+
async function outputDeleteScan(_data) {
|
|
7341
|
+
logger.logger.success('Scan deleted successfully');
|
|
7342
|
+
}
|
|
7343
|
+
|
|
7344
|
+
async function handleDeleteScan(orgSlug, scanId) {
|
|
7345
|
+
const data = await fetchDeleteOrgFullScan(orgSlug, scanId);
|
|
7346
|
+
if (!data) return;
|
|
7347
|
+
await outputDeleteScan();
|
|
6930
7348
|
}
|
|
6931
7349
|
|
|
6932
7350
|
const {
|
|
@@ -6965,8 +7383,8 @@ async function run$6(argv, importMeta, {
|
|
|
6965
7383
|
importMeta,
|
|
6966
7384
|
parentName
|
|
6967
7385
|
});
|
|
6968
|
-
const [orgSlug = '',
|
|
6969
|
-
if (!orgSlug || !
|
|
7386
|
+
const [orgSlug = '', scanId = ''] = cli.input;
|
|
7387
|
+
if (!orgSlug || !scanId) {
|
|
6970
7388
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
6971
7389
|
// options or missing arguments.
|
|
6972
7390
|
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
@@ -6975,22 +7393,20 @@ async function run$6(argv, importMeta, {
|
|
|
6975
7393
|
|
|
6976
7394
|
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6977
7395
|
|
|
6978
|
-
- Full Scan ID to delete as second argument ${!
|
|
7396
|
+
- Full Scan ID to delete as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
|
|
6979
7397
|
return;
|
|
6980
7398
|
}
|
|
6981
7399
|
if (cli.flags['dryRun']) {
|
|
6982
7400
|
logger.logger.log(DRY_RUN_BAIL_TEXT$6);
|
|
6983
7401
|
return;
|
|
6984
7402
|
}
|
|
6985
|
-
await
|
|
7403
|
+
await handleDeleteScan(orgSlug, scanId);
|
|
6986
7404
|
}
|
|
6987
7405
|
|
|
6988
|
-
|
|
6989
|
-
async function listFullScans({
|
|
7406
|
+
async function fetchListScans({
|
|
6990
7407
|
direction,
|
|
6991
7408
|
from_time,
|
|
6992
7409
|
orgSlug,
|
|
6993
|
-
outputKind,
|
|
6994
7410
|
page,
|
|
6995
7411
|
per_page,
|
|
6996
7412
|
sort
|
|
@@ -6999,23 +7415,19 @@ async function listFullScans({
|
|
|
6999
7415
|
if (!apiToken) {
|
|
7000
7416
|
throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
|
|
7001
7417
|
}
|
|
7002
|
-
await
|
|
7003
|
-
apiToken,
|
|
7418
|
+
await fetchListScansWithToken(apiToken, {
|
|
7004
7419
|
direction,
|
|
7005
7420
|
from_time,
|
|
7006
7421
|
orgSlug,
|
|
7007
|
-
outputKind,
|
|
7008
7422
|
page,
|
|
7009
7423
|
per_page,
|
|
7010
7424
|
sort
|
|
7011
7425
|
});
|
|
7012
7426
|
}
|
|
7013
|
-
async function
|
|
7014
|
-
apiToken,
|
|
7427
|
+
async function fetchListScansWithToken(apiToken, {
|
|
7015
7428
|
direction,
|
|
7016
7429
|
from_time,
|
|
7017
7430
|
orgSlug,
|
|
7018
|
-
outputKind,
|
|
7019
7431
|
page,
|
|
7020
7432
|
per_page,
|
|
7021
7433
|
sort
|
|
@@ -7024,22 +7436,27 @@ async function listFullScansWithToken({
|
|
|
7024
7436
|
const {
|
|
7025
7437
|
spinner
|
|
7026
7438
|
} = constants;
|
|
7439
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
7027
7440
|
spinner.start('Fetching list of scans...');
|
|
7028
|
-
const
|
|
7029
|
-
const result = await handleApiCall(socketSdk.getOrgFullScanList(orgSlug, {
|
|
7441
|
+
const result = await handleApiCall(sockSdk.getOrgFullScanList(orgSlug, {
|
|
7030
7442
|
sort,
|
|
7031
7443
|
direction,
|
|
7032
7444
|
per_page: String(per_page),
|
|
7033
7445
|
page: String(page),
|
|
7034
7446
|
from: from_time
|
|
7035
7447
|
}), 'Listing scans');
|
|
7448
|
+
spinner.successAndStop(`Received response for list of scans.`);
|
|
7036
7449
|
if (!result.success) {
|
|
7037
7450
|
handleUnsuccessfulApiResponse('getOrgFullScanList', result);
|
|
7038
7451
|
return;
|
|
7039
7452
|
}
|
|
7040
|
-
|
|
7453
|
+
return result.data;
|
|
7454
|
+
}
|
|
7455
|
+
|
|
7456
|
+
// @ts-ignore
|
|
7457
|
+
async function outputListScans(data, outputKind) {
|
|
7041
7458
|
if (outputKind === 'json') {
|
|
7042
|
-
logger.logger.log(
|
|
7459
|
+
logger.logger.log(data);
|
|
7043
7460
|
return;
|
|
7044
7461
|
}
|
|
7045
7462
|
const options = {
|
|
@@ -7057,7 +7474,7 @@ async function listFullScansWithToken({
|
|
|
7057
7474
|
name: colors.magenta('Created at')
|
|
7058
7475
|
}]
|
|
7059
7476
|
};
|
|
7060
|
-
const formattedResults =
|
|
7477
|
+
const formattedResults = data.results.map(d => {
|
|
7061
7478
|
return {
|
|
7062
7479
|
id: d.id,
|
|
7063
7480
|
report_url: colors.underline(`${d.html_report_url}`),
|
|
@@ -7072,6 +7489,27 @@ async function listFullScansWithToken({
|
|
|
7072
7489
|
logger.logger.log(chalkTable(options, formattedResults));
|
|
7073
7490
|
}
|
|
7074
7491
|
|
|
7492
|
+
async function handleListScans({
|
|
7493
|
+
direction,
|
|
7494
|
+
from_time,
|
|
7495
|
+
orgSlug,
|
|
7496
|
+
outputKind,
|
|
7497
|
+
page,
|
|
7498
|
+
per_page,
|
|
7499
|
+
sort
|
|
7500
|
+
}) {
|
|
7501
|
+
const data = await fetchListScans({
|
|
7502
|
+
direction,
|
|
7503
|
+
from_time,
|
|
7504
|
+
orgSlug,
|
|
7505
|
+
page,
|
|
7506
|
+
per_page,
|
|
7507
|
+
sort
|
|
7508
|
+
});
|
|
7509
|
+
if (!data) return;
|
|
7510
|
+
await outputListScans(data, outputKind);
|
|
7511
|
+
}
|
|
7512
|
+
|
|
7075
7513
|
const {
|
|
7076
7514
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$5
|
|
7077
7515
|
} = constants;
|
|
@@ -7159,7 +7597,7 @@ async function run$5(argv, importMeta, {
|
|
|
7159
7597
|
logger.logger.log(DRY_RUN_BAIL_TEXT$5);
|
|
7160
7598
|
return;
|
|
7161
7599
|
}
|
|
7162
|
-
await
|
|
7600
|
+
await handleListScans({
|
|
7163
7601
|
direction: String(cli.flags['direction'] || ''),
|
|
7164
7602
|
from_time: String(cli.flags['fromTime'] || ''),
|
|
7165
7603
|
orgSlug,
|
|
@@ -7170,46 +7608,56 @@ async function run$5(argv, importMeta, {
|
|
|
7170
7608
|
});
|
|
7171
7609
|
}
|
|
7172
7610
|
|
|
7173
|
-
async function
|
|
7611
|
+
async function fetchScanMetadata(orgSlug, scanId) {
|
|
7174
7612
|
const apiToken = shadowNpmInject.getDefaultToken();
|
|
7175
7613
|
if (!apiToken) {
|
|
7176
7614
|
throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
|
|
7177
7615
|
}
|
|
7178
|
-
await
|
|
7616
|
+
await fetchScanMetadataWithToken(apiToken, orgSlug, scanId);
|
|
7179
7617
|
}
|
|
7180
|
-
async function
|
|
7618
|
+
async function fetchScanMetadataWithToken(apiToken, orgSlug, scanId) {
|
|
7181
7619
|
// Lazily access constants.spinner.
|
|
7182
7620
|
const {
|
|
7183
7621
|
spinner
|
|
7184
7622
|
} = constants;
|
|
7623
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
7185
7624
|
spinner.start('Fetching meta data for a full scan...');
|
|
7186
|
-
const
|
|
7187
|
-
|
|
7625
|
+
const result = await handleApiCall(sockSdk.getOrgFullScanMetadata(orgSlug, scanId), 'Listing scans');
|
|
7626
|
+
spinner.successAndStop('Received response for scan meta data.');
|
|
7188
7627
|
if (!result.success) {
|
|
7189
7628
|
handleUnsuccessfulApiResponse('getOrgFullScanMetadata', result);
|
|
7190
7629
|
return;
|
|
7191
7630
|
}
|
|
7192
|
-
|
|
7631
|
+
return result.data;
|
|
7632
|
+
}
|
|
7633
|
+
|
|
7634
|
+
async function outputScanMetadata(data, scanId, outputKind) {
|
|
7193
7635
|
if (outputKind === 'json') {
|
|
7194
|
-
logger.logger.log(
|
|
7636
|
+
logger.logger.log(data);
|
|
7195
7637
|
} else {
|
|
7196
7638
|
// Markdown = print
|
|
7197
7639
|
if (outputKind === 'markdown') {
|
|
7198
7640
|
logger.logger.log('# Scan meta data\n');
|
|
7199
7641
|
}
|
|
7200
7642
|
logger.logger.log(`Scan ID: ${scanId}\n`);
|
|
7201
|
-
for (const [key, value] of Object.entries(
|
|
7643
|
+
for (const [key, value] of Object.entries(data)) {
|
|
7202
7644
|
if (['id', 'updated_at', 'organization_id', 'repository_id', 'commit_hash', 'html_report_url'].includes(key)) continue;
|
|
7203
7645
|
logger.logger.log(`- ${key}:`, value);
|
|
7204
7646
|
}
|
|
7205
7647
|
if (outputKind === 'markdown') {
|
|
7206
|
-
logger.logger.log(`\nYou can view this report at: [${
|
|
7648
|
+
logger.logger.log(`\nYou can view this report at: [${data.html_report_url}](${data.html_report_url})\n`);
|
|
7207
7649
|
} else {
|
|
7208
|
-
logger.logger.log(`\nYou can view this report at: ${
|
|
7650
|
+
logger.logger.log(`\nYou can view this report at: ${data.html_report_url}]\n`);
|
|
7209
7651
|
}
|
|
7210
7652
|
}
|
|
7211
7653
|
}
|
|
7212
7654
|
|
|
7655
|
+
async function handleOrgScanMetadata(orgSlug, scanId, outputKind) {
|
|
7656
|
+
const data = await fetchScanMetadata(orgSlug, scanId);
|
|
7657
|
+
if (!data) return;
|
|
7658
|
+
await outputScanMetadata(data, scanId, outputKind);
|
|
7659
|
+
}
|
|
7660
|
+
|
|
7213
7661
|
const {
|
|
7214
7662
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$4
|
|
7215
7663
|
} = constants;
|
|
@@ -7246,8 +7694,8 @@ async function run$4(argv, importMeta, {
|
|
|
7246
7694
|
importMeta,
|
|
7247
7695
|
parentName
|
|
7248
7696
|
});
|
|
7249
|
-
const [orgSlug = '',
|
|
7250
|
-
if (!orgSlug || !
|
|
7697
|
+
const [orgSlug = '', scanId = ''] = cli.input;
|
|
7698
|
+
if (!orgSlug || !scanId) {
|
|
7251
7699
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
7252
7700
|
// options or missing arguments.
|
|
7253
7701
|
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
@@ -7256,14 +7704,14 @@ async function run$4(argv, importMeta, {
|
|
|
7256
7704
|
|
|
7257
7705
|
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7258
7706
|
|
|
7259
|
-
- Full Scan ID to inspect as second argument ${!
|
|
7707
|
+
- Full Scan ID to inspect as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
|
|
7260
7708
|
return;
|
|
7261
7709
|
}
|
|
7262
7710
|
if (cli.flags['dryRun']) {
|
|
7263
7711
|
logger.logger.log(DRY_RUN_BAIL_TEXT$4);
|
|
7264
7712
|
return;
|
|
7265
7713
|
}
|
|
7266
|
-
await
|
|
7714
|
+
await handleOrgScanMetadata(orgSlug, scanId, cli.flags['json'] ? 'json' : cli.flags['markdown'] ? 'markdown' : 'print');
|
|
7267
7715
|
}
|
|
7268
7716
|
|
|
7269
7717
|
/**
|
|
@@ -7271,7 +7719,7 @@ async function run$4(argv, importMeta, {
|
|
|
7271
7719
|
* full scan ID.
|
|
7272
7720
|
* It can optionally only fetch the security or license side of things.
|
|
7273
7721
|
*/
|
|
7274
|
-
async function fetchReportData(orgSlug,
|
|
7722
|
+
async function fetchReportData(orgSlug, scanId,
|
|
7275
7723
|
// includeLicensePolicy: boolean,
|
|
7276
7724
|
includeSecurityPolicy) {
|
|
7277
7725
|
let haveScan = false;
|
|
@@ -7308,14 +7756,14 @@ includeSecurityPolicy) {
|
|
|
7308
7756
|
throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
|
|
7309
7757
|
}
|
|
7310
7758
|
updateProgress();
|
|
7311
|
-
const
|
|
7759
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
7312
7760
|
|
|
7313
7761
|
// @ts-ignore
|
|
7314
7762
|
const [scan,
|
|
7315
7763
|
// licensePolicyMaybe,
|
|
7316
7764
|
securityPolicyMaybe] = await Promise.all([(async () => {
|
|
7317
7765
|
try {
|
|
7318
|
-
const response = await queryApi(`orgs/${orgSlug}/full-scans/${encodeURIComponent(
|
|
7766
|
+
const response = await queryApi(`orgs/${orgSlug}/full-scans/${encodeURIComponent(scanId)}`, apiToken);
|
|
7319
7767
|
haveScan = true;
|
|
7320
7768
|
updateProgress();
|
|
7321
7769
|
if (!response.ok) {
|
|
@@ -7341,7 +7789,7 @@ includeSecurityPolicy) {
|
|
|
7341
7789
|
})(),
|
|
7342
7790
|
// includeLicensePolicy &&
|
|
7343
7791
|
// (async () => {
|
|
7344
|
-
// const r = await
|
|
7792
|
+
// const r = await sockSdk.getOrgSecurityPolicy(orgSlug)
|
|
7345
7793
|
// haveLicensePolicy = true
|
|
7346
7794
|
// updateProgress()
|
|
7347
7795
|
// return await handleApiCall(
|
|
@@ -7350,7 +7798,7 @@ includeSecurityPolicy) {
|
|
|
7350
7798
|
// )
|
|
7351
7799
|
// })(),
|
|
7352
7800
|
includeSecurityPolicy && (async () => {
|
|
7353
|
-
const r = await
|
|
7801
|
+
const r = await sockSdk.getOrgSecurityPolicy(orgSlug);
|
|
7354
7802
|
haveSecurityPolicy = true;
|
|
7355
7803
|
updateProgress();
|
|
7356
7804
|
return await handleApiCall(r, "looking up organization's security policy");
|
|
@@ -7596,40 +8044,31 @@ function* walkNestedMap(map, keys = []) {
|
|
|
7596
8044
|
}
|
|
7597
8045
|
}
|
|
7598
8046
|
|
|
7599
|
-
async function
|
|
8047
|
+
async function outputScanReport(scan,
|
|
8048
|
+
// licensePolicy: undefined | SocketSdkReturnType<'getOrgSecurityPolicy'>,
|
|
8049
|
+
securityPolicy, {
|
|
7600
8050
|
filePath,
|
|
7601
8051
|
fold,
|
|
7602
|
-
fullScanId,
|
|
7603
8052
|
includeLicensePolicy,
|
|
7604
8053
|
includeSecurityPolicy,
|
|
7605
8054
|
orgSlug,
|
|
7606
8055
|
outputKind,
|
|
7607
8056
|
reportLevel,
|
|
8057
|
+
scanId,
|
|
7608
8058
|
short
|
|
7609
8059
|
}) {
|
|
7610
|
-
logger.logger.error('output:', outputKind, ', file:', filePath, ', fold:', fold, ', reportLevel:', reportLevel);
|
|
7611
8060
|
if (!includeSecurityPolicy) {
|
|
8061
|
+
process.exitCode = 1;
|
|
7612
8062
|
return; // caller should assert
|
|
7613
8063
|
}
|
|
7614
|
-
const {
|
|
7615
|
-
// licensePolicy,
|
|
7616
|
-
ok,
|
|
7617
|
-
scan,
|
|
7618
|
-
securityPolicy
|
|
7619
|
-
} = await fetchReportData(orgSlug, fullScanId,
|
|
7620
|
-
// includeLicensePolicy
|
|
7621
|
-
includeSecurityPolicy);
|
|
7622
|
-
if (!ok) {
|
|
7623
|
-
return;
|
|
7624
|
-
}
|
|
7625
8064
|
const scanReport = generateReport(scan, undefined,
|
|
7626
8065
|
// licensePolicy,
|
|
7627
8066
|
securityPolicy, {
|
|
7628
8067
|
orgSlug,
|
|
7629
|
-
scanId
|
|
8068
|
+
scanId,
|
|
7630
8069
|
fold,
|
|
7631
|
-
|
|
7632
|
-
|
|
8070
|
+
reportLevel,
|
|
8071
|
+
short
|
|
7633
8072
|
});
|
|
7634
8073
|
if (!scanReport.healthy) {
|
|
7635
8074
|
process.exitCode = 1;
|
|
@@ -7716,6 +8155,43 @@ ${!report.alerts.size ? '' : mdTable(flatData, ['Policy', 'Alert Type', 'Package
|
|
|
7716
8155
|
return md;
|
|
7717
8156
|
}
|
|
7718
8157
|
|
|
8158
|
+
async function handleScanReport({
|
|
8159
|
+
filePath,
|
|
8160
|
+
fold,
|
|
8161
|
+
includeLicensePolicy,
|
|
8162
|
+
includeSecurityPolicy,
|
|
8163
|
+
orgSlug,
|
|
8164
|
+
outputKind,
|
|
8165
|
+
reportLevel,
|
|
8166
|
+
scanId,
|
|
8167
|
+
short
|
|
8168
|
+
}) {
|
|
8169
|
+
if (!includeSecurityPolicy) {
|
|
8170
|
+
process.exitCode = 1;
|
|
8171
|
+
return; // caller should assert
|
|
8172
|
+
}
|
|
8173
|
+
const {
|
|
8174
|
+
// licensePolicy,
|
|
8175
|
+
ok,
|
|
8176
|
+
scan,
|
|
8177
|
+
securityPolicy
|
|
8178
|
+
} = await fetchReportData(orgSlug, scanId,
|
|
8179
|
+
// includeLicensePolicy
|
|
8180
|
+
includeSecurityPolicy);
|
|
8181
|
+
if (!ok) return;
|
|
8182
|
+
await outputScanReport(scan, securityPolicy, {
|
|
8183
|
+
filePath,
|
|
8184
|
+
fold,
|
|
8185
|
+
scanId: scanId,
|
|
8186
|
+
includeLicensePolicy,
|
|
8187
|
+
includeSecurityPolicy,
|
|
8188
|
+
orgSlug,
|
|
8189
|
+
outputKind,
|
|
8190
|
+
reportLevel,
|
|
8191
|
+
short
|
|
8192
|
+
});
|
|
8193
|
+
}
|
|
8194
|
+
|
|
7719
8195
|
const {
|
|
7720
8196
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$3
|
|
7721
8197
|
} = constants;
|
|
@@ -7802,8 +8278,8 @@ async function run$3(argv, importMeta, {
|
|
|
7802
8278
|
reportLevel = 'warn',
|
|
7803
8279
|
security
|
|
7804
8280
|
} = cli.flags;
|
|
7805
|
-
const [orgSlug = '',
|
|
7806
|
-
if (!orgSlug || !
|
|
8281
|
+
const [orgSlug = '', scanId = '', file = '-'] = cli.input;
|
|
8282
|
+
if (!orgSlug || !scanId ||
|
|
7807
8283
|
// (!license && !security) ||
|
|
7808
8284
|
json && markdown) {
|
|
7809
8285
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
@@ -7815,7 +8291,7 @@ async function run$3(argv, importMeta, {
|
|
|
7815
8291
|
|
|
7816
8292
|
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7817
8293
|
|
|
7818
|
-
- Full Scan ID to fetch as second argument ${!
|
|
8294
|
+
- Full Scan ID to fetch as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7819
8295
|
|
|
7820
8296
|
- Not both the --json and --markdown flags ${json && markdown ? colors.red('(pick one!)') : colors.green('(ok)')}
|
|
7821
8297
|
`
|
|
@@ -7827,9 +8303,9 @@ async function run$3(argv, importMeta, {
|
|
|
7827
8303
|
logger.logger.log(DRY_RUN_BAIL_TEXT$3);
|
|
7828
8304
|
return;
|
|
7829
8305
|
}
|
|
7830
|
-
await
|
|
8306
|
+
await handleScanReport({
|
|
7831
8307
|
orgSlug,
|
|
7832
|
-
|
|
8308
|
+
scanId: scanId,
|
|
7833
8309
|
includeLicensePolicy: false,
|
|
7834
8310
|
// !!license,
|
|
7835
8311
|
includeSecurityPolicy: typeof security === 'boolean' ? security : true,
|
|
@@ -7841,29 +8317,7 @@ async function run$3(argv, importMeta, {
|
|
|
7841
8317
|
});
|
|
7842
8318
|
}
|
|
7843
8319
|
|
|
7844
|
-
async function
|
|
7845
|
-
// Lazily access constants.spinner.
|
|
7846
|
-
const {
|
|
7847
|
-
spinner
|
|
7848
|
-
} = constants;
|
|
7849
|
-
const apiToken = shadowNpmInject.getDefaultToken();
|
|
7850
|
-
if (!apiToken) {
|
|
7851
|
-
throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
|
|
7852
|
-
}
|
|
7853
|
-
spinner.start('Fetching scan...');
|
|
7854
|
-
const socketSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
7855
|
-
const data = await handleApiCall(socketSdk.getOrgFullScan(orgSlug, fullScanId, file === '-' ? undefined : file), 'Fetching a scan');
|
|
7856
|
-
if (!data?.success) {
|
|
7857
|
-
handleUnsuccessfulApiResponse('getOrgFullScan', data);
|
|
7858
|
-
return;
|
|
7859
|
-
}
|
|
7860
|
-
spinner?.successAndStop(file ? `Full scan details written to ${file}` : 'stdout');
|
|
7861
|
-
return data;
|
|
7862
|
-
}
|
|
7863
|
-
|
|
7864
|
-
async function viewFullScan(orgSlug, fullScanId, filePath) {
|
|
7865
|
-
const artifacts = await getFullScan(orgSlug, fullScanId);
|
|
7866
|
-
if (!artifacts) return;
|
|
8320
|
+
async function outputScanView(artifacts, orgSlug, scanId, filePath) {
|
|
7867
8321
|
const display = artifacts.map(art => {
|
|
7868
8322
|
const author = Array.isArray(art.author) ? `${art.author[0]}${art.author.length > 1 ? ' et.al.' : ''}` : art.author;
|
|
7869
8323
|
return {
|
|
@@ -7880,11 +8334,11 @@ async function viewFullScan(orgSlug, fullScanId, filePath) {
|
|
|
7880
8334
|
|
|
7881
8335
|
These are the artifacts and their scores found.
|
|
7882
8336
|
|
|
7883
|
-
|
|
8337
|
+
Scan ID: ${scanId}
|
|
7884
8338
|
|
|
7885
8339
|
${md}
|
|
7886
8340
|
|
|
7887
|
-
View this report at: https://socket.dev/dashboard/org/${orgSlug}/sbom/${
|
|
8341
|
+
View this report at: https://socket.dev/dashboard/org/${orgSlug}/sbom/${scanId}
|
|
7888
8342
|
`.trim() + '\n';
|
|
7889
8343
|
if (filePath && filePath !== '-') {
|
|
7890
8344
|
try {
|
|
@@ -7900,6 +8354,32 @@ View this report at: https://socket.dev/dashboard/org/${orgSlug}/sbom/${fullScan
|
|
|
7900
8354
|
}
|
|
7901
8355
|
}
|
|
7902
8356
|
|
|
8357
|
+
async function handleScanView(orgSlug, scanId, filePath) {
|
|
8358
|
+
const data = await fetchScan(orgSlug, scanId);
|
|
8359
|
+
if (!data) return;
|
|
8360
|
+
await outputScanView(data, orgSlug, scanId, filePath);
|
|
8361
|
+
}
|
|
8362
|
+
|
|
8363
|
+
async function streamScan(orgSlug, scanId, file) {
|
|
8364
|
+
// Lazily access constants.spinner.
|
|
8365
|
+
const {
|
|
8366
|
+
spinner
|
|
8367
|
+
} = constants;
|
|
8368
|
+
const apiToken = shadowNpmInject.getDefaultToken();
|
|
8369
|
+
if (!apiToken) {
|
|
8370
|
+
throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
|
|
8371
|
+
}
|
|
8372
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
8373
|
+
spinner.start('Fetching scan...');
|
|
8374
|
+
const data = await handleApiCall(sockSdk.getOrgFullScan(orgSlug, scanId, file === '-' ? undefined : file), 'Fetching a scan');
|
|
8375
|
+
spinner?.successAndStop(file ? `Full scan details written to ${file}` : 'stdout');
|
|
8376
|
+
if (!data?.success) {
|
|
8377
|
+
handleUnsuccessfulApiResponse('getOrgFullScan', data);
|
|
8378
|
+
return;
|
|
8379
|
+
}
|
|
8380
|
+
return data;
|
|
8381
|
+
}
|
|
8382
|
+
|
|
7903
8383
|
const {
|
|
7904
8384
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$2
|
|
7905
8385
|
} = constants;
|
|
@@ -7938,8 +8418,8 @@ async function run$2(argv, importMeta, {
|
|
|
7938
8418
|
importMeta,
|
|
7939
8419
|
parentName
|
|
7940
8420
|
});
|
|
7941
|
-
const [orgSlug = '',
|
|
7942
|
-
if (!orgSlug || !
|
|
8421
|
+
const [orgSlug = '', scanId = '', file = '-'] = cli.input;
|
|
8422
|
+
if (!orgSlug || !scanId) {
|
|
7943
8423
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
7944
8424
|
// options or missing arguments.
|
|
7945
8425
|
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
@@ -7949,7 +8429,7 @@ async function run$2(argv, importMeta, {
|
|
|
7949
8429
|
|
|
7950
8430
|
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7951
8431
|
|
|
7952
|
-
- Full Scan ID to fetch as second argument ${!
|
|
8432
|
+
- Full Scan ID to fetch as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7953
8433
|
`);
|
|
7954
8434
|
return;
|
|
7955
8435
|
}
|
|
@@ -7958,9 +8438,9 @@ async function run$2(argv, importMeta, {
|
|
|
7958
8438
|
return;
|
|
7959
8439
|
}
|
|
7960
8440
|
if (cli.flags['json']) {
|
|
7961
|
-
await
|
|
8441
|
+
await streamScan(orgSlug, scanId, file);
|
|
7962
8442
|
} else {
|
|
7963
|
-
await
|
|
8443
|
+
await handleScanView(orgSlug, scanId, file);
|
|
7964
8444
|
}
|
|
7965
8445
|
}
|
|
7966
8446
|
|
|
@@ -8456,12 +8936,13 @@ void (async () => {
|
|
|
8456
8936
|
await vendor.updater({
|
|
8457
8937
|
name: SOCKET_CLI_BIN_NAME,
|
|
8458
8938
|
// The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_VERSION']".
|
|
8459
|
-
version: "0.14.
|
|
8939
|
+
version: "0.14.67",
|
|
8460
8940
|
ttl: 86_400_000 /* 24 hours in milliseconds */
|
|
8461
8941
|
});
|
|
8462
8942
|
try {
|
|
8463
8943
|
await meowWithSubcommands({
|
|
8464
8944
|
cdxgen: cmdCdxgen,
|
|
8945
|
+
config: cmdConfig,
|
|
8465
8946
|
fix: cmdFix,
|
|
8466
8947
|
info: cmdInfo,
|
|
8467
8948
|
login: cmdLogin,
|
|
@@ -8523,5 +9004,5 @@ void (async () => {
|
|
|
8523
9004
|
await shadowNpmInject.captureException(e);
|
|
8524
9005
|
}
|
|
8525
9006
|
})();
|
|
8526
|
-
//# debugId=
|
|
9007
|
+
//# debugId=199d20b5-2692-44b6-b880-34650eeaae46
|
|
8527
9008
|
//# sourceMappingURL=cli.js.map
|