@socketsecurity/cli 0.14.65 → 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 -2
- package/dist/constants.js +10 -6
- package/dist/constants.js.map +1 -1
- package/dist/module-sync/cli.js +1038 -556
- 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 +136 -114
- 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/module-sync/socket-package-alert.d.ts +1 -1
- package/dist/require/cli.js +1038 -556
- package/dist/require/cli.js.map +1 -1
- package/package.json +13 -13
- package/dist/module-sync/settings.d.ts +0 -15
package/dist/require/cli.js
CHANGED
|
@@ -55,18 +55,18 @@ 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'));
|
|
63
62
|
var readline$1 = require('node:readline');
|
|
64
63
|
|
|
65
|
-
function handleUnsuccessfulApiResponse(_name,
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
64
|
+
function handleUnsuccessfulApiResponse(_name, sockSdkError) {
|
|
65
|
+
const message = sockSdkError.error || 'No error message returned';
|
|
66
|
+
const {
|
|
67
|
+
status
|
|
68
|
+
} = sockSdkError;
|
|
69
|
+
if (status === 401 || status === 403) {
|
|
70
70
|
// Lazily access constants.spinner.
|
|
71
71
|
const {
|
|
72
72
|
spinner
|
|
@@ -88,7 +88,7 @@ async function handleApiCall(value, description) {
|
|
|
88
88
|
}
|
|
89
89
|
return result;
|
|
90
90
|
}
|
|
91
|
-
async function
|
|
91
|
+
async function handleApiError(code) {
|
|
92
92
|
if (code === 400) {
|
|
93
93
|
return 'One of the options passed might be incorrect.';
|
|
94
94
|
} else if (code === 403) {
|
|
@@ -102,22 +102,22 @@ function getLastFiveOfApiToken(token) {
|
|
|
102
102
|
|
|
103
103
|
// The API server that should be used for operations.
|
|
104
104
|
function getDefaultApiBaseUrl() {
|
|
105
|
-
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');
|
|
106
106
|
return strings.isNonEmptyString(baseUrl) ? baseUrl : undefined;
|
|
107
107
|
}
|
|
108
|
-
async function
|
|
108
|
+
async function queryApi(path, apiToken) {
|
|
109
109
|
const API_V0_URL = getDefaultApiBaseUrl();
|
|
110
110
|
return await fetch(`${API_V0_URL}/${path}`, {
|
|
111
111
|
method: 'GET',
|
|
112
112
|
headers: {
|
|
113
|
-
Authorization: `Basic ${btoa(`${apiToken}
|
|
113
|
+
Authorization: `Basic ${btoa(`${apiToken}:`)}`
|
|
114
114
|
}
|
|
115
115
|
});
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
async function fetchOrgAnalyticsData(time, spinner, apiToken) {
|
|
119
|
-
const
|
|
120
|
-
const result = await handleApiCall(
|
|
119
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
120
|
+
const result = await handleApiCall(sockSdk.getOrgAnalytics(time.toString()), 'fetching analytics data');
|
|
121
121
|
if (result.success === false) {
|
|
122
122
|
handleUnsuccessfulApiResponse('getOrgAnalytics', result);
|
|
123
123
|
return undefined;
|
|
@@ -131,8 +131,8 @@ async function fetchOrgAnalyticsData(time, spinner, apiToken) {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
async function fetchRepoAnalyticsData(repo, time, spinner, apiToken) {
|
|
134
|
-
const
|
|
135
|
-
const result = await handleApiCall(
|
|
134
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
135
|
+
const result = await handleApiCall(sockSdk.getRepoAnalytics(repo, time.toString()), 'fetching analytics data');
|
|
136
136
|
if (result.success === false) {
|
|
137
137
|
handleUnsuccessfulApiResponse('getRepoAnalytics', result);
|
|
138
138
|
return undefined;
|
|
@@ -652,9 +652,9 @@ function emitBanner(name) {
|
|
|
652
652
|
}
|
|
653
653
|
function getAsciiHeader(command) {
|
|
654
654
|
const cliVersion = // The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_VERSION_HASH']".
|
|
655
|
-
"0.14.
|
|
655
|
+
"0.14.67:a2db5d2:39ede5c0:pub";
|
|
656
656
|
const nodeVersion = process.version;
|
|
657
|
-
const apiToken = shadowNpmInject.
|
|
657
|
+
const apiToken = shadowNpmInject.getConfigValue('apiToken');
|
|
658
658
|
const shownToken = apiToken ? getLastFiveOfApiToken(apiToken) : 'no';
|
|
659
659
|
const relCwd = path.normalizePath(process.cwd().replace(new RegExp(`^${regexps.escapeRegExp(constants.homePath)}(?:${path$1.sep}|$)`, 'i'), '~/'));
|
|
660
660
|
const body = `
|
|
@@ -666,9 +666,9 @@ function getAsciiHeader(command) {
|
|
|
666
666
|
}
|
|
667
667
|
|
|
668
668
|
const {
|
|
669
|
-
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
669
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$F
|
|
670
670
|
} = constants;
|
|
671
|
-
const config$
|
|
671
|
+
const config$G = {
|
|
672
672
|
commandName: 'analytics',
|
|
673
673
|
description: `Look up analytics data`,
|
|
674
674
|
hidden: false,
|
|
@@ -719,16 +719,16 @@ const config$C = {
|
|
|
719
719
|
`
|
|
720
720
|
};
|
|
721
721
|
const cmdAnalytics = {
|
|
722
|
-
description: config$
|
|
723
|
-
hidden: config$
|
|
724
|
-
run: run$
|
|
722
|
+
description: config$G.description,
|
|
723
|
+
hidden: config$G.hidden,
|
|
724
|
+
run: run$G
|
|
725
725
|
};
|
|
726
|
-
async function run$
|
|
726
|
+
async function run$G(argv, importMeta, {
|
|
727
727
|
parentName
|
|
728
728
|
}) {
|
|
729
729
|
const cli = meowOrExit({
|
|
730
730
|
argv,
|
|
731
|
-
config: config$
|
|
731
|
+
config: config$G,
|
|
732
732
|
importMeta,
|
|
733
733
|
parentName
|
|
734
734
|
});
|
|
@@ -765,7 +765,7 @@ async function run$C(argv, importMeta, {
|
|
|
765
765
|
return;
|
|
766
766
|
}
|
|
767
767
|
if (cli.flags['dryRun']) {
|
|
768
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
768
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$F);
|
|
769
769
|
return;
|
|
770
770
|
}
|
|
771
771
|
return await displayAnalytics({
|
|
@@ -808,8 +808,8 @@ async function fetchAuditLogWithToken(apiToken, {
|
|
|
808
808
|
spinner
|
|
809
809
|
} = constants;
|
|
810
810
|
spinner.start(`Looking up audit log for ${orgSlug}`);
|
|
811
|
-
const
|
|
812
|
-
const result = await handleApiCall(
|
|
811
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
812
|
+
const result = await handleApiCall(sockSdk.getAuditLogEvents(orgSlug, {
|
|
813
813
|
// I'm not sure this is used at all.
|
|
814
814
|
outputJson: String(outputKind === 'json'),
|
|
815
815
|
// I'm not sure this is used at all.
|
|
@@ -952,9 +952,9 @@ async function handleAuditLog({
|
|
|
952
952
|
}
|
|
953
953
|
|
|
954
954
|
const {
|
|
955
|
-
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
955
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$E
|
|
956
956
|
} = constants;
|
|
957
|
-
const config$
|
|
957
|
+
const config$F = {
|
|
958
958
|
commandName: 'audit-log',
|
|
959
959
|
description: 'Look up the audit log for an organization',
|
|
960
960
|
hidden: false,
|
|
@@ -995,16 +995,16 @@ const config$B = {
|
|
|
995
995
|
`
|
|
996
996
|
};
|
|
997
997
|
const cmdAuditLog = {
|
|
998
|
-
description: config$
|
|
999
|
-
hidden: config$
|
|
1000
|
-
run: run$
|
|
998
|
+
description: config$F.description,
|
|
999
|
+
hidden: config$F.hidden,
|
|
1000
|
+
run: run$F
|
|
1001
1001
|
};
|
|
1002
|
-
async function run$
|
|
1002
|
+
async function run$F(argv, importMeta, {
|
|
1003
1003
|
parentName
|
|
1004
1004
|
}) {
|
|
1005
1005
|
const cli = meowOrExit({
|
|
1006
1006
|
argv,
|
|
1007
|
-
config: config$
|
|
1007
|
+
config: config$F,
|
|
1008
1008
|
importMeta,
|
|
1009
1009
|
parentName
|
|
1010
1010
|
});
|
|
@@ -1029,7 +1029,7 @@ async function run$B(argv, importMeta, {
|
|
|
1029
1029
|
return;
|
|
1030
1030
|
}
|
|
1031
1031
|
if (cli.flags['dryRun']) {
|
|
1032
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
1032
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$E);
|
|
1033
1033
|
return;
|
|
1034
1034
|
}
|
|
1035
1035
|
await handleAuditLog({
|
|
@@ -1146,7 +1146,7 @@ function isHelpFlag(cmdArg) {
|
|
|
1146
1146
|
|
|
1147
1147
|
// import { meowOrExit } from '../../utils/meow-with-subcommands'
|
|
1148
1148
|
const {
|
|
1149
|
-
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
1149
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$D
|
|
1150
1150
|
} = constants;
|
|
1151
1151
|
|
|
1152
1152
|
// TODO: convert yargs to meow. Or convert all the other things to yargs.
|
|
@@ -1223,7 +1223,7 @@ const yargsConfig = {
|
|
|
1223
1223
|
'yes'],
|
|
1224
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']
|
|
1225
1225
|
};
|
|
1226
|
-
const config$
|
|
1226
|
+
const config$E = {
|
|
1227
1227
|
commandName: 'cdxgen',
|
|
1228
1228
|
description: 'Create an SBOM with CycloneDX generator (cdxgen)',
|
|
1229
1229
|
hidden: false,
|
|
@@ -1239,18 +1239,18 @@ const config$A = {
|
|
|
1239
1239
|
`
|
|
1240
1240
|
};
|
|
1241
1241
|
const cmdCdxgen = {
|
|
1242
|
-
description: config$
|
|
1243
|
-
hidden: config$
|
|
1244
|
-
run: run$
|
|
1242
|
+
description: config$E.description,
|
|
1243
|
+
hidden: config$E.hidden,
|
|
1244
|
+
run: run$E
|
|
1245
1245
|
};
|
|
1246
|
-
async function run$
|
|
1246
|
+
async function run$E(argv, importMeta, {
|
|
1247
1247
|
parentName
|
|
1248
1248
|
}) {
|
|
1249
1249
|
const cli = meowOrExit({
|
|
1250
1250
|
allowUnknownFlags: true,
|
|
1251
1251
|
// Don't let meow take over --help.
|
|
1252
1252
|
argv: argv.filter(a => !isHelpFlag(a)),
|
|
1253
|
-
config: config$
|
|
1253
|
+
config: config$E,
|
|
1254
1254
|
importMeta,
|
|
1255
1255
|
parentName
|
|
1256
1256
|
});
|
|
@@ -1282,7 +1282,7 @@ async function run$A(argv, importMeta, {
|
|
|
1282
1282
|
return;
|
|
1283
1283
|
}
|
|
1284
1284
|
if (cli.flags['dryRun']) {
|
|
1285
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
1285
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$D);
|
|
1286
1286
|
return;
|
|
1287
1287
|
}
|
|
1288
1288
|
if (yargv.output === undefined) {
|
|
@@ -1291,212 +1291,611 @@ async function run$A(argv, importMeta, {
|
|
|
1291
1291
|
await runCycloneDX(yargv);
|
|
1292
1292
|
}
|
|
1293
1293
|
|
|
1294
|
-
async function
|
|
1295
|
-
limit,
|
|
1296
|
-
offset
|
|
1297
|
-
}) {
|
|
1298
|
-
const apiToken = shadowNpmInject.getDefaultToken();
|
|
1299
|
-
if (!apiToken) {
|
|
1300
|
-
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.');
|
|
1301
|
-
}
|
|
1302
|
-
return await fetchDependenciesWithToken(apiToken, {
|
|
1303
|
-
limit,
|
|
1304
|
-
offset
|
|
1305
|
-
});
|
|
1306
|
-
}
|
|
1307
|
-
async function fetchDependenciesWithToken(apiToken, {
|
|
1308
|
-
limit,
|
|
1309
|
-
offset
|
|
1310
|
-
}) {
|
|
1311
|
-
// Lazily access constants.spinner.
|
|
1312
|
-
const {
|
|
1313
|
-
spinner
|
|
1314
|
-
} = constants;
|
|
1315
|
-
spinner.start('Fetching organization dependencies...');
|
|
1316
|
-
const socketSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
1317
|
-
const result = await handleApiCall(socketSdk.searchDependencies({
|
|
1318
|
-
limit,
|
|
1319
|
-
offset
|
|
1320
|
-
}), 'Searching dependencies');
|
|
1321
|
-
spinner?.successAndStop('Received organization dependencies response.');
|
|
1322
|
-
if (!result.success) {
|
|
1323
|
-
handleUnsuccessfulApiResponse('searchDependencies', result);
|
|
1324
|
-
return;
|
|
1325
|
-
}
|
|
1326
|
-
return result.data;
|
|
1327
|
-
}
|
|
1328
|
-
|
|
1329
|
-
// @ts-ignore
|
|
1330
|
-
async function outputDependencies(data, {
|
|
1331
|
-
limit,
|
|
1332
|
-
offset,
|
|
1333
|
-
outputKind
|
|
1334
|
-
}) {
|
|
1294
|
+
async function outputConfigGet(key, value, outputKind) {
|
|
1335
1295
|
if (outputKind === 'json') {
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
logger.logger.log(
|
|
1345
|
-
|
|
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}`);
|
|
1346
1309
|
}
|
|
1347
|
-
logger.logger.log('Request details: Offset:', offset, ', limit:', limit, ', is there more data after this?', data.end ? 'no' : 'yes');
|
|
1348
|
-
const options = {
|
|
1349
|
-
columns: [{
|
|
1350
|
-
field: 'namespace',
|
|
1351
|
-
name: colors.cyan('Namespace')
|
|
1352
|
-
}, {
|
|
1353
|
-
field: 'name',
|
|
1354
|
-
name: colors.cyan('Name')
|
|
1355
|
-
}, {
|
|
1356
|
-
field: 'version',
|
|
1357
|
-
name: colors.cyan('Version')
|
|
1358
|
-
}, {
|
|
1359
|
-
field: 'repository',
|
|
1360
|
-
name: colors.cyan('Repository')
|
|
1361
|
-
}, {
|
|
1362
|
-
field: 'branch',
|
|
1363
|
-
name: colors.cyan('Branch')
|
|
1364
|
-
}, {
|
|
1365
|
-
field: 'type',
|
|
1366
|
-
name: colors.cyan('Type')
|
|
1367
|
-
}, {
|
|
1368
|
-
field: 'direct',
|
|
1369
|
-
name: colors.cyan('Direct')
|
|
1370
|
-
}]
|
|
1371
|
-
};
|
|
1372
|
-
logger.logger.log(chalkTable(options, data.rows));
|
|
1373
1310
|
}
|
|
1374
1311
|
|
|
1375
|
-
async function
|
|
1376
|
-
|
|
1377
|
-
offset,
|
|
1312
|
+
async function handleConfigGet({
|
|
1313
|
+
key,
|
|
1378
1314
|
outputKind
|
|
1379
1315
|
}) {
|
|
1380
|
-
const
|
|
1381
|
-
|
|
1382
|
-
offset
|
|
1383
|
-
});
|
|
1384
|
-
if (!data) return;
|
|
1385
|
-
await outputDependencies(data, {
|
|
1386
|
-
limit,
|
|
1387
|
-
offset,
|
|
1388
|
-
outputKind
|
|
1389
|
-
});
|
|
1316
|
+
const value = shadowNpmInject.getConfigValue(key);
|
|
1317
|
+
await outputConfigGet(key, value, outputKind);
|
|
1390
1318
|
}
|
|
1391
1319
|
|
|
1392
1320
|
const {
|
|
1393
|
-
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
1321
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$C
|
|
1394
1322
|
} = constants;
|
|
1395
|
-
const config$
|
|
1396
|
-
commandName: '
|
|
1397
|
-
description: '
|
|
1323
|
+
const config$D = {
|
|
1324
|
+
commandName: 'get',
|
|
1325
|
+
description: 'Get the value of a local CLI config item',
|
|
1398
1326
|
hidden: false,
|
|
1399
1327
|
flags: {
|
|
1400
1328
|
...commonFlags,
|
|
1401
|
-
limit: {
|
|
1402
|
-
type: 'number',
|
|
1403
|
-
shortFlag: 'l',
|
|
1404
|
-
default: 50,
|
|
1405
|
-
description: 'Maximum number of dependencies returned'
|
|
1406
|
-
},
|
|
1407
|
-
offset: {
|
|
1408
|
-
type: 'number',
|
|
1409
|
-
shortFlag: 'o',
|
|
1410
|
-
default: 0,
|
|
1411
|
-
description: 'Page number'
|
|
1412
|
-
},
|
|
1413
1329
|
...outputFlags
|
|
1414
1330
|
},
|
|
1415
1331
|
help: (command, config) => `
|
|
1416
1332
|
Usage
|
|
1417
|
-
${command}
|
|
1333
|
+
$ ${command} <org slug>
|
|
1418
1334
|
|
|
1419
1335
|
Options
|
|
1420
1336
|
${getFlagListOutput(config.flags, 6)}
|
|
1421
1337
|
|
|
1338
|
+
Keys:
|
|
1339
|
+
|
|
1340
|
+
${Array.from(shadowNpmInject.supportedConfigKeys.entries()).map(([key, desc]) => ` - ${key} -- ${desc}`).join('\n')}
|
|
1341
|
+
|
|
1422
1342
|
Examples
|
|
1423
|
-
${command}
|
|
1343
|
+
$ ${command} FakeOrg --repoName=test-repo
|
|
1424
1344
|
`
|
|
1425
1345
|
};
|
|
1426
|
-
const
|
|
1427
|
-
description: config$
|
|
1428
|
-
hidden: config$
|
|
1429
|
-
run: run$
|
|
1346
|
+
const cmdConfigGet = {
|
|
1347
|
+
description: config$D.description,
|
|
1348
|
+
hidden: config$D.hidden,
|
|
1349
|
+
run: run$D
|
|
1430
1350
|
};
|
|
1431
|
-
async function run$
|
|
1351
|
+
async function run$D(argv, importMeta, {
|
|
1432
1352
|
parentName
|
|
1433
1353
|
}) {
|
|
1434
1354
|
const cli = meowOrExit({
|
|
1435
1355
|
argv,
|
|
1436
|
-
config: config$
|
|
1356
|
+
config: config$D,
|
|
1437
1357
|
importMeta,
|
|
1438
1358
|
parentName
|
|
1439
1359
|
});
|
|
1440
1360
|
const {
|
|
1441
1361
|
json,
|
|
1442
|
-
|
|
1443
|
-
markdown,
|
|
1444
|
-
offset
|
|
1362
|
+
markdown
|
|
1445
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
|
+
}
|
|
1446
1376
|
if (cli.flags['dryRun']) {
|
|
1447
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
1377
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$C);
|
|
1448
1378
|
return;
|
|
1449
1379
|
}
|
|
1450
|
-
await
|
|
1451
|
-
|
|
1452
|
-
offset: Number(offset || 0) || 0,
|
|
1380
|
+
await handleConfigGet({
|
|
1381
|
+
key: key,
|
|
1453
1382
|
outputKind: json ? 'json' : markdown ? 'markdown' : 'text'
|
|
1454
1383
|
});
|
|
1455
1384
|
}
|
|
1456
1385
|
|
|
1457
|
-
async function
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
orgSlug
|
|
1386
|
+
async function outputConfigList({
|
|
1387
|
+
full,
|
|
1388
|
+
outputKind
|
|
1461
1389
|
}) {
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
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
|
+
}
|
|
1465
1421
|
}
|
|
1466
|
-
return await fetchDiffScanWithToken(apiToken, {
|
|
1467
|
-
after,
|
|
1468
|
-
before,
|
|
1469
|
-
orgSlug
|
|
1470
|
-
});
|
|
1471
1422
|
}
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
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
|
|
1476
1462
|
}) {
|
|
1477
|
-
|
|
1463
|
+
const cli = meowOrExit({
|
|
1464
|
+
argv,
|
|
1465
|
+
config: config$C,
|
|
1466
|
+
importMeta,
|
|
1467
|
+
parentName
|
|
1468
|
+
});
|
|
1478
1469
|
const {
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
const err = await handleAPIError(response.status);
|
|
1486
|
-
spinner.errorAndStop(`${colors.bgRed(colors.white(response.statusText))}: ${err}`);
|
|
1470
|
+
full,
|
|
1471
|
+
json,
|
|
1472
|
+
markdown
|
|
1473
|
+
} = cli.flags;
|
|
1474
|
+
if (cli.flags['dryRun']) {
|
|
1475
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$B);
|
|
1487
1476
|
return;
|
|
1488
1477
|
}
|
|
1489
|
-
|
|
1490
|
-
|
|
1478
|
+
await outputConfigList({
|
|
1479
|
+
full: !!full,
|
|
1480
|
+
outputKind: json ? 'json' : markdown ? 'markdown' : 'text'
|
|
1481
|
+
});
|
|
1491
1482
|
}
|
|
1492
1483
|
|
|
1493
|
-
async function
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
}
|
|
1498
|
-
|
|
1499
|
-
|
|
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
|
+
|
|
1693
|
+
async function fetchDependencies({
|
|
1694
|
+
limit,
|
|
1695
|
+
offset
|
|
1696
|
+
}) {
|
|
1697
|
+
const apiToken = shadowNpmInject.getDefaultToken();
|
|
1698
|
+
if (!apiToken) {
|
|
1699
|
+
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.');
|
|
1700
|
+
}
|
|
1701
|
+
return await fetchDependenciesWithToken(apiToken, {
|
|
1702
|
+
limit,
|
|
1703
|
+
offset
|
|
1704
|
+
});
|
|
1705
|
+
}
|
|
1706
|
+
async function fetchDependenciesWithToken(apiToken, {
|
|
1707
|
+
limit,
|
|
1708
|
+
offset
|
|
1709
|
+
}) {
|
|
1710
|
+
// Lazily access constants.spinner.
|
|
1711
|
+
const {
|
|
1712
|
+
spinner
|
|
1713
|
+
} = constants;
|
|
1714
|
+
spinner.start('Fetching organization dependencies...');
|
|
1715
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
1716
|
+
const result = await handleApiCall(sockSdk.searchDependencies({
|
|
1717
|
+
limit,
|
|
1718
|
+
offset
|
|
1719
|
+
}), 'Searching dependencies');
|
|
1720
|
+
spinner?.successAndStop('Received organization dependencies response.');
|
|
1721
|
+
if (!result.success) {
|
|
1722
|
+
handleUnsuccessfulApiResponse('searchDependencies', result);
|
|
1723
|
+
return;
|
|
1724
|
+
}
|
|
1725
|
+
return result.data;
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
// @ts-ignore
|
|
1729
|
+
async function outputDependencies(data, {
|
|
1730
|
+
limit,
|
|
1731
|
+
offset,
|
|
1732
|
+
outputKind
|
|
1733
|
+
}) {
|
|
1734
|
+
if (outputKind === 'json') {
|
|
1735
|
+
let json;
|
|
1736
|
+
try {
|
|
1737
|
+
json = JSON.stringify(data, null, 2);
|
|
1738
|
+
} catch (e) {
|
|
1739
|
+
process.exitCode = 1;
|
|
1740
|
+
logger.logger.fail('There was a problem converting the data to JSON, please try without the `--json` flag');
|
|
1741
|
+
return;
|
|
1742
|
+
}
|
|
1743
|
+
logger.logger.log(json);
|
|
1744
|
+
return;
|
|
1745
|
+
}
|
|
1746
|
+
logger.logger.log('Request details: Offset:', offset, ', limit:', limit, ', is there more data after this?', data.end ? 'no' : 'yes');
|
|
1747
|
+
const options = {
|
|
1748
|
+
columns: [{
|
|
1749
|
+
field: 'namespace',
|
|
1750
|
+
name: colors.cyan('Namespace')
|
|
1751
|
+
}, {
|
|
1752
|
+
field: 'name',
|
|
1753
|
+
name: colors.cyan('Name')
|
|
1754
|
+
}, {
|
|
1755
|
+
field: 'version',
|
|
1756
|
+
name: colors.cyan('Version')
|
|
1757
|
+
}, {
|
|
1758
|
+
field: 'repository',
|
|
1759
|
+
name: colors.cyan('Repository')
|
|
1760
|
+
}, {
|
|
1761
|
+
field: 'branch',
|
|
1762
|
+
name: colors.cyan('Branch')
|
|
1763
|
+
}, {
|
|
1764
|
+
field: 'type',
|
|
1765
|
+
name: colors.cyan('Type')
|
|
1766
|
+
}, {
|
|
1767
|
+
field: 'direct',
|
|
1768
|
+
name: colors.cyan('Direct')
|
|
1769
|
+
}]
|
|
1770
|
+
};
|
|
1771
|
+
logger.logger.log(chalkTable(options, data.rows));
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1774
|
+
async function handleDependencies({
|
|
1775
|
+
limit,
|
|
1776
|
+
offset,
|
|
1777
|
+
outputKind
|
|
1778
|
+
}) {
|
|
1779
|
+
const data = await fetchDependencies({
|
|
1780
|
+
limit,
|
|
1781
|
+
offset
|
|
1782
|
+
});
|
|
1783
|
+
if (!data) return;
|
|
1784
|
+
await outputDependencies(data, {
|
|
1785
|
+
limit,
|
|
1786
|
+
offset,
|
|
1787
|
+
outputKind
|
|
1788
|
+
});
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
const {
|
|
1792
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$y
|
|
1793
|
+
} = constants;
|
|
1794
|
+
const config$z = {
|
|
1795
|
+
commandName: 'dependencies',
|
|
1796
|
+
description: 'Search for any dependency that is being used in your organization',
|
|
1797
|
+
hidden: false,
|
|
1798
|
+
flags: {
|
|
1799
|
+
...commonFlags,
|
|
1800
|
+
limit: {
|
|
1801
|
+
type: 'number',
|
|
1802
|
+
shortFlag: 'l',
|
|
1803
|
+
default: 50,
|
|
1804
|
+
description: 'Maximum number of dependencies returned'
|
|
1805
|
+
},
|
|
1806
|
+
offset: {
|
|
1807
|
+
type: 'number',
|
|
1808
|
+
shortFlag: 'o',
|
|
1809
|
+
default: 0,
|
|
1810
|
+
description: 'Page number'
|
|
1811
|
+
},
|
|
1812
|
+
...outputFlags
|
|
1813
|
+
},
|
|
1814
|
+
help: (command, config) => `
|
|
1815
|
+
Usage
|
|
1816
|
+
${command}
|
|
1817
|
+
|
|
1818
|
+
Options
|
|
1819
|
+
${getFlagListOutput(config.flags, 6)}
|
|
1820
|
+
|
|
1821
|
+
Examples
|
|
1822
|
+
${command} --limit 20 --offset 10
|
|
1823
|
+
`
|
|
1824
|
+
};
|
|
1825
|
+
const cmdScanCreate$1 = {
|
|
1826
|
+
description: config$z.description,
|
|
1827
|
+
hidden: config$z.hidden,
|
|
1828
|
+
run: run$z
|
|
1829
|
+
};
|
|
1830
|
+
async function run$z(argv, importMeta, {
|
|
1831
|
+
parentName
|
|
1832
|
+
}) {
|
|
1833
|
+
const cli = meowOrExit({
|
|
1834
|
+
argv,
|
|
1835
|
+
config: config$z,
|
|
1836
|
+
importMeta,
|
|
1837
|
+
parentName
|
|
1838
|
+
});
|
|
1839
|
+
const {
|
|
1840
|
+
json,
|
|
1841
|
+
limit,
|
|
1842
|
+
markdown,
|
|
1843
|
+
offset
|
|
1844
|
+
} = cli.flags;
|
|
1845
|
+
if (cli.flags['dryRun']) {
|
|
1846
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$y);
|
|
1847
|
+
return;
|
|
1848
|
+
}
|
|
1849
|
+
await handleDependencies({
|
|
1850
|
+
limit: Number(limit || 0) || 0,
|
|
1851
|
+
offset: Number(offset || 0) || 0,
|
|
1852
|
+
outputKind: json ? 'json' : markdown ? 'markdown' : 'text'
|
|
1853
|
+
});
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
async function fetchDiffScan({
|
|
1857
|
+
after,
|
|
1858
|
+
before,
|
|
1859
|
+
orgSlug
|
|
1860
|
+
}) {
|
|
1861
|
+
const apiToken = shadowNpmInject.getDefaultToken();
|
|
1862
|
+
if (!apiToken) {
|
|
1863
|
+
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.');
|
|
1864
|
+
}
|
|
1865
|
+
return await fetchDiffScanWithToken(apiToken, {
|
|
1866
|
+
after,
|
|
1867
|
+
before,
|
|
1868
|
+
orgSlug
|
|
1869
|
+
});
|
|
1870
|
+
}
|
|
1871
|
+
async function fetchDiffScanWithToken(apiToken, {
|
|
1872
|
+
after,
|
|
1873
|
+
before,
|
|
1874
|
+
orgSlug
|
|
1875
|
+
}) {
|
|
1876
|
+
// Lazily access constants.spinner.
|
|
1877
|
+
const {
|
|
1878
|
+
spinner
|
|
1879
|
+
} = constants;
|
|
1880
|
+
spinner.start('Fetching diff-scan...');
|
|
1881
|
+
const response = await queryApi(`orgs/${orgSlug}/full-scans/diff?before=${encodeURIComponent(before)}&after=${encodeURIComponent(after)}`, apiToken);
|
|
1882
|
+
spinner?.successAndStop('Received diff-scan response');
|
|
1883
|
+
if (!response.ok) {
|
|
1884
|
+
const err = await handleApiError(response.status);
|
|
1885
|
+
spinner.errorAndStop(`${colors.bgRed(colors.white(response.statusText))}: ${err}`);
|
|
1886
|
+
return;
|
|
1887
|
+
}
|
|
1888
|
+
const result = await handleApiCall(await response.json(), 'Deserializing json');
|
|
1889
|
+
return result;
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1892
|
+
async function outputDiffScan(result, {
|
|
1893
|
+
depth,
|
|
1894
|
+
file,
|
|
1895
|
+
outputKind
|
|
1896
|
+
}) {
|
|
1897
|
+
const dashboardUrl = result.diff_report_url;
|
|
1898
|
+
const dashboardMessage = dashboardUrl ? `\n View this diff scan in the Socket dashboard: ${colors.cyan(dashboardUrl)}` : '';
|
|
1500
1899
|
|
|
1501
1900
|
// When forcing json, or dumping to file, serialize to string such that it
|
|
1502
1901
|
// won't get truncated. The only way to dump the full raw JSON to stdout is
|
|
@@ -1827,12 +2226,12 @@ async function getAlertsMapFromPnpmLockfile(lockfile, options) {
|
|
|
1827
2226
|
}
|
|
1828
2227
|
const getText = () => `Looking up data for ${remaining} packages`;
|
|
1829
2228
|
spinner?.start(getText());
|
|
1830
|
-
const
|
|
2229
|
+
const sockSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
|
|
1831
2230
|
const toAlertsMapOptions = {
|
|
1832
2231
|
overrides: lockfile.overrides,
|
|
1833
2232
|
...options
|
|
1834
2233
|
};
|
|
1835
|
-
for await (const batchPackageFetchResult of
|
|
2234
|
+
for await (const batchPackageFetchResult of sockSdk.batchPackageStream({
|
|
1836
2235
|
alerts: 'true',
|
|
1837
2236
|
compact: 'true',
|
|
1838
2237
|
fixable: include.unfixable ? 'false' : 'true'
|
|
@@ -2431,15 +2830,15 @@ async function run$x(argv, importMeta, {
|
|
|
2431
2830
|
}
|
|
2432
2831
|
|
|
2433
2832
|
async function fetchPackageInfo(pkgName, pkgVersion, includeAllIssues) {
|
|
2434
|
-
const
|
|
2833
|
+
const sockSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
|
|
2435
2834
|
|
|
2436
2835
|
// Lazily access constants.spinner.
|
|
2437
2836
|
const {
|
|
2438
2837
|
spinner
|
|
2439
2838
|
} = constants;
|
|
2440
2839
|
spinner.start(pkgVersion === 'latest' ? `Looking up data for the latest version of ${pkgName}` : `Looking up data for version ${pkgVersion} of ${pkgName}`);
|
|
2441
|
-
const result = await handleApiCall(
|
|
2442
|
-
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');
|
|
2443
2842
|
spinner.successAndStop('Data fetched');
|
|
2444
2843
|
if (result.success === false) {
|
|
2445
2844
|
return handleUnsuccessfulApiResponse('getIssuesByNPMPackage', result);
|
|
@@ -2467,7 +2866,7 @@ function formatScore$1(score) {
|
|
|
2467
2866
|
return colors.red(`${score}`);
|
|
2468
2867
|
}
|
|
2469
2868
|
function outputPackageIssuesDetails(packageData, outputMarkdown) {
|
|
2470
|
-
const issueDetails = packageData.filter(d => d.value?.severity === shadowNpmInject.
|
|
2869
|
+
const issueDetails = packageData.filter(d => d.value?.severity === shadowNpmInject.ALERT_SEVERITY.critical || d.value?.severity === shadowNpmInject.ALERT_SEVERITY.high);
|
|
2471
2870
|
const uniqueIssueDetails = issueDetails.reduce((acc, issue) => {
|
|
2472
2871
|
const {
|
|
2473
2872
|
type
|
|
@@ -2654,18 +3053,18 @@ async function run$w(argv, importMeta, {
|
|
|
2654
3053
|
}
|
|
2655
3054
|
|
|
2656
3055
|
function applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy) {
|
|
2657
|
-
shadowNpmInject.
|
|
2658
|
-
shadowNpmInject.
|
|
2659
|
-
shadowNpmInject.
|
|
2660
|
-
shadowNpmInject.
|
|
3056
|
+
shadowNpmInject.updateConfigValue('enforcedOrgs', enforcedOrgs);
|
|
3057
|
+
shadowNpmInject.updateConfigValue('apiToken', apiToken);
|
|
3058
|
+
shadowNpmInject.updateConfigValue('apiBaseUrl', apiBaseUrl);
|
|
3059
|
+
shadowNpmInject.updateConfigValue('apiProxy', apiProxy);
|
|
2661
3060
|
}
|
|
2662
3061
|
|
|
2663
3062
|
const {
|
|
2664
3063
|
SOCKET_PUBLIC_API_TOKEN
|
|
2665
3064
|
} = constants;
|
|
2666
3065
|
async function attemptLogin(apiBaseUrl, apiProxy) {
|
|
2667
|
-
apiBaseUrl ??= shadowNpmInject.
|
|
2668
|
-
apiProxy ??= shadowNpmInject.
|
|
3066
|
+
apiBaseUrl ??= shadowNpmInject.getConfigValue('apiBaseUrl') ?? undefined;
|
|
3067
|
+
apiProxy ??= shadowNpmInject.getConfigValue('apiProxy') ?? undefined;
|
|
2669
3068
|
const apiToken = (await prompts.password({
|
|
2670
3069
|
message: `Enter your ${terminalLink('Socket.dev API key', 'https://docs.socket.dev/docs/api-keys')} (leave blank for a public key)`
|
|
2671
3070
|
})) || SOCKET_PUBLIC_API_TOKEN;
|
|
@@ -2721,7 +3120,7 @@ async function attemptLogin(apiBaseUrl, apiProxy) {
|
|
|
2721
3120
|
}
|
|
2722
3121
|
}
|
|
2723
3122
|
spinner.stop();
|
|
2724
|
-
const oldToken = shadowNpmInject.
|
|
3123
|
+
const oldToken = shadowNpmInject.getConfigValue('apiToken');
|
|
2725
3124
|
try {
|
|
2726
3125
|
applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy);
|
|
2727
3126
|
logger.logger.success(`API credentials ${oldToken ? 'updated' : 'set'}`);
|
|
@@ -2789,10 +3188,10 @@ async function run$v(argv, importMeta, {
|
|
|
2789
3188
|
}
|
|
2790
3189
|
|
|
2791
3190
|
function applyLogout() {
|
|
2792
|
-
shadowNpmInject.
|
|
2793
|
-
shadowNpmInject.
|
|
2794
|
-
shadowNpmInject.
|
|
2795
|
-
shadowNpmInject.
|
|
3191
|
+
shadowNpmInject.updateConfigValue('apiToken', null);
|
|
3192
|
+
shadowNpmInject.updateConfigValue('apiBaseUrl', null);
|
|
3193
|
+
shadowNpmInject.updateConfigValue('apiProxy', null);
|
|
3194
|
+
shadowNpmInject.updateConfigValue('enforcedOrgs', null);
|
|
2796
3195
|
}
|
|
2797
3196
|
|
|
2798
3197
|
function attemptLogout() {
|
|
@@ -4541,14 +4940,14 @@ async function fetchOrganization() {
|
|
|
4541
4940
|
return await fetchOrganizationWithToken(apiToken);
|
|
4542
4941
|
}
|
|
4543
4942
|
async function fetchOrganizationWithToken(apiToken) {
|
|
4544
|
-
const
|
|
4943
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
4545
4944
|
|
|
4546
4945
|
// Lazily access constants.spinner.
|
|
4547
4946
|
const {
|
|
4548
4947
|
spinner
|
|
4549
4948
|
} = constants;
|
|
4550
4949
|
spinner.start('Fetching organization list...');
|
|
4551
|
-
const result = await handleApiCall(
|
|
4950
|
+
const result = await handleApiCall(sockSdk.getOrganizations(), 'looking up organizations');
|
|
4552
4951
|
spinner.successAndStop('Received organization list response.');
|
|
4553
4952
|
if (!result.success) {
|
|
4554
4953
|
handleUnsuccessfulApiResponse('getOrganizations', result);
|
|
@@ -4678,9 +5077,9 @@ async function fetchSecurityPolicyWithToken(apiToken, orgSlug) {
|
|
|
4678
5077
|
const {
|
|
4679
5078
|
spinner
|
|
4680
5079
|
} = constants;
|
|
4681
|
-
const
|
|
5080
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
4682
5081
|
spinner.start('Fetching organization quota...');
|
|
4683
|
-
const result = await handleApiCall(
|
|
5082
|
+
const result = await handleApiCall(sockSdk.getOrgSecurityPolicy(orgSlug), 'looking up organization quota');
|
|
4684
5083
|
spinner?.successAndStop('Received organization quota response.');
|
|
4685
5084
|
if (!result.success) {
|
|
4686
5085
|
handleUnsuccessfulApiResponse('getOrgSecurityPolicy', result);
|
|
@@ -4823,9 +5222,9 @@ async function fetchQuotaWithToken(apiToken) {
|
|
|
4823
5222
|
const {
|
|
4824
5223
|
spinner
|
|
4825
5224
|
} = constants;
|
|
4826
|
-
const
|
|
5225
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
4827
5226
|
spinner.start('Fetching organization quota...');
|
|
4828
|
-
const result = await handleApiCall(
|
|
5227
|
+
const result = await handleApiCall(sockSdk.getQuota(), 'looking up organization quota');
|
|
4829
5228
|
spinner?.successAndStop('Recieved organization quota response.');
|
|
4830
5229
|
if (!result.success) {
|
|
4831
5230
|
handleUnsuccessfulApiResponse('getQuota', result);
|
|
@@ -4952,8 +5351,8 @@ async function fetchPurlsShallowScore(purls) {
|
|
|
4952
5351
|
spinner
|
|
4953
5352
|
} = constants;
|
|
4954
5353
|
spinner.start(`Requesting data ...`);
|
|
4955
|
-
const
|
|
4956
|
-
const result = await handleApiCall(
|
|
5354
|
+
const sockSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
|
|
5355
|
+
const result = await handleApiCall(sockSdk.batchPackageFetch({
|
|
4957
5356
|
alerts: 'true'
|
|
4958
5357
|
// compact: false,
|
|
4959
5358
|
// fixable: false,
|
|
@@ -5354,8 +5753,8 @@ async function createReport(socketConfig, inputPaths, {
|
|
|
5354
5753
|
const {
|
|
5355
5754
|
spinner
|
|
5356
5755
|
} = constants;
|
|
5357
|
-
const
|
|
5358
|
-
const supportedFiles = await
|
|
5756
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
5757
|
+
const supportedFiles = await sockSdk.getReportSupportedFiles().then(res => {
|
|
5359
5758
|
if (!res.success) handleUnsuccessfulApiResponse('getReportSupportedFiles', res);
|
|
5360
5759
|
return res.data;
|
|
5361
5760
|
}).catch(cause => {
|
|
@@ -5363,7 +5762,7 @@ async function createReport(socketConfig, inputPaths, {
|
|
|
5363
5762
|
cause
|
|
5364
5763
|
});
|
|
5365
5764
|
});
|
|
5366
|
-
const packagePaths = await shadowNpmPaths.
|
|
5765
|
+
const packagePaths = await shadowNpmPaths.getPackageFilesForScan(cwd, inputPaths, supportedFiles, socketConfig);
|
|
5367
5766
|
const packagePathsCount = packagePaths.length;
|
|
5368
5767
|
if (packagePathsCount && debug.isDebug()) {
|
|
5369
5768
|
for (const pkgPath of packagePaths) {
|
|
@@ -5375,7 +5774,7 @@ async function createReport(socketConfig, inputPaths, {
|
|
|
5375
5774
|
return undefined;
|
|
5376
5775
|
}
|
|
5377
5776
|
spinner.start(`Creating report with ${packagePathsCount} package ${words.pluralize('file', packagePathsCount)}`);
|
|
5378
|
-
const apiCall =
|
|
5777
|
+
const apiCall = sockSdk.createReportFromFilePaths(packagePaths, cwd, socketConfig?.issueRules);
|
|
5379
5778
|
const result = await handleApiCall(apiCall, 'creating report');
|
|
5380
5779
|
if (!result.success) {
|
|
5381
5780
|
handleUnsuccessfulApiResponse('createReport', result);
|
|
@@ -5386,8 +5785,8 @@ async function createReport(socketConfig, inputPaths, {
|
|
|
5386
5785
|
}
|
|
5387
5786
|
|
|
5388
5787
|
async function getSocketConfig(absoluteConfigPath) {
|
|
5389
|
-
const socketConfig = await config$
|
|
5390
|
-
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) {
|
|
5391
5790
|
// Inspired by workbox-build:
|
|
5392
5791
|
// https://github.com/GoogleChrome/workbox/blob/95f97a207fd51efb3f8a653f6e3e58224183a778/packages/workbox-build/src/lib/validate-options.ts#L68-L71
|
|
5393
5792
|
const betterErrors = betterAjvErrors.betterAjvErrors({
|
|
@@ -5415,12 +5814,12 @@ async function fetchReportData$1(reportId, includeAllIssues, strict) {
|
|
|
5415
5814
|
} = constants;
|
|
5416
5815
|
spinner.log('Fetching report with ID ${reportId} (this could take a while)');
|
|
5417
5816
|
spinner.start(`Fetch started... (this could take a while)`);
|
|
5418
|
-
const
|
|
5817
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
5419
5818
|
let result;
|
|
5420
5819
|
for (let retry = 1; !result; ++retry) {
|
|
5421
5820
|
try {
|
|
5422
5821
|
// eslint-disable-next-line no-await-in-loop
|
|
5423
|
-
result = await handleApiCall(
|
|
5822
|
+
result = await handleApiCall(sockSdk.getReport(reportId), 'fetching report');
|
|
5424
5823
|
} catch (err) {
|
|
5425
5824
|
if (retry >= MAX_TIMEOUT_RETRY || !(err instanceof Error) || err.cause?.cause?.response?.statusCode !== HTTP_CODE_TIMEOUT) {
|
|
5426
5825
|
spinner.stop(`Failed to fetch report`);
|
|
@@ -5472,7 +5871,7 @@ function formatReportDataOutput(reportId, data, commandName, outputKind, strict,
|
|
|
5472
5871
|
}
|
|
5473
5872
|
}
|
|
5474
5873
|
|
|
5475
|
-
async function
|
|
5874
|
+
async function fetchScan(orgSlug, scanId) {
|
|
5476
5875
|
// Lazily access constants.spinner.
|
|
5477
5876
|
const {
|
|
5478
5877
|
spinner
|
|
@@ -5482,10 +5881,10 @@ async function getFullScan(orgSlug, fullScanId) {
|
|
|
5482
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.');
|
|
5483
5882
|
}
|
|
5484
5883
|
spinner.start('Fetching full-scan...');
|
|
5485
|
-
const response = await
|
|
5884
|
+
const response = await queryApi(`orgs/${orgSlug}/full-scans/${encodeURIComponent(scanId)}`, apiToken);
|
|
5486
5885
|
spinner.stop('Fetch complete.');
|
|
5487
5886
|
if (!response.ok) {
|
|
5488
|
-
const err = await
|
|
5887
|
+
const err = await handleApiError(response.status);
|
|
5489
5888
|
logger.logger.fail(`${colors.bgRed(colors.white(response.statusText))}: Fetch error: ${err}`);
|
|
5490
5889
|
return;
|
|
5491
5890
|
}
|
|
@@ -5511,7 +5910,7 @@ async function viewReport(reportId, {
|
|
|
5511
5910
|
strict
|
|
5512
5911
|
}) {
|
|
5513
5912
|
const result = await fetchReportData$1(reportId, all, strict);
|
|
5514
|
-
const artifacts = await
|
|
5913
|
+
const artifacts = await fetchScan('socketdev', reportId);
|
|
5515
5914
|
if (result) {
|
|
5516
5915
|
formatReportDataOutput(reportId, result, commandName, outputKind, strict, artifacts);
|
|
5517
5916
|
}
|
|
@@ -5712,9 +6111,9 @@ async function fetchCreateRepoWithToken(apiToken, {
|
|
|
5712
6111
|
const {
|
|
5713
6112
|
spinner
|
|
5714
6113
|
} = constants;
|
|
5715
|
-
const
|
|
6114
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
5716
6115
|
spinner.start('Sending request ot create a repository...');
|
|
5717
|
-
const result = await handleApiCall(
|
|
6116
|
+
const result = await handleApiCall(sockSdk.createOrgRepo(orgSlug, {
|
|
5718
6117
|
name: repoName,
|
|
5719
6118
|
description,
|
|
5720
6119
|
homepage,
|
|
@@ -5859,8 +6258,8 @@ async function deleteRepoWithToken(orgSlug, repoName, apiToken) {
|
|
|
5859
6258
|
spinner
|
|
5860
6259
|
} = constants;
|
|
5861
6260
|
spinner.start('Deleting repository...');
|
|
5862
|
-
const
|
|
5863
|
-
const result = await handleApiCall(
|
|
6261
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
6262
|
+
const result = await handleApiCall(sockSdk.deleteOrgRepo(orgSlug, repoName), 'deleting repository');
|
|
5864
6263
|
if (!result.success) {
|
|
5865
6264
|
handleUnsuccessfulApiResponse('deleteOrgRepo', result);
|
|
5866
6265
|
return;
|
|
@@ -5955,9 +6354,9 @@ async function fetchListReposWithToken(apiToken, {
|
|
|
5955
6354
|
const {
|
|
5956
6355
|
spinner
|
|
5957
6356
|
} = constants;
|
|
5958
|
-
const
|
|
6357
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
5959
6358
|
spinner.start('Fetching list of repositories...');
|
|
5960
|
-
const result = await handleApiCall(
|
|
6359
|
+
const result = await handleApiCall(sockSdk.getOrgRepoList(orgSlug, {
|
|
5961
6360
|
sort,
|
|
5962
6361
|
direction,
|
|
5963
6362
|
per_page: String(per_page),
|
|
@@ -6144,8 +6543,8 @@ async function fetchUpdateRepoWithToken(apiToken, {
|
|
|
6144
6543
|
spinner
|
|
6145
6544
|
} = constants;
|
|
6146
6545
|
spinner.start('Sending request to update a repository...');
|
|
6147
|
-
const
|
|
6148
|
-
const result = await handleApiCall(
|
|
6546
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
6547
|
+
const result = await handleApiCall(sockSdk.updateOrgRepo(orgSlug, repoName, {
|
|
6149
6548
|
orgSlug,
|
|
6150
6549
|
name: repoName,
|
|
6151
6550
|
description,
|
|
@@ -6292,9 +6691,9 @@ async function fetchViewRepoWithToken(orgSlug, repoName, apiToken) {
|
|
|
6292
6691
|
const {
|
|
6293
6692
|
spinner
|
|
6294
6693
|
} = constants;
|
|
6295
|
-
const
|
|
6694
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
6296
6695
|
spinner.start('Fetching repository data...');
|
|
6297
|
-
const result = await handleApiCall(
|
|
6696
|
+
const result = await handleApiCall(sockSdk.getOrgRepo(orgSlug, repoName), 'fetching repository');
|
|
6298
6697
|
spinner.successAndStop('Received response while fetched repository data.');
|
|
6299
6698
|
if (!result.success) {
|
|
6300
6699
|
handleUnsuccessfulApiResponse('getOrgRepo', result);
|
|
@@ -6448,8 +6847,106 @@ const cmdRepos = {
|
|
|
6448
6847
|
}
|
|
6449
6848
|
};
|
|
6450
6849
|
|
|
6451
|
-
async function
|
|
6452
|
-
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');
|
|
6453
6950
|
// Ignore a failed request here. It was not the primary goal of
|
|
6454
6951
|
// running this command and reporting it only leads to end-user confusion.
|
|
6455
6952
|
if (result.success) {
|
|
@@ -6470,13 +6967,17 @@ async function suggestOrgSlug(socketSdk) {
|
|
|
6470
6967
|
if (proceed) {
|
|
6471
6968
|
return proceed;
|
|
6472
6969
|
}
|
|
6970
|
+
} else {
|
|
6971
|
+
logger.logger.fail('Failed to lookup organization list from API, unable to suggest.');
|
|
6473
6972
|
}
|
|
6474
6973
|
}
|
|
6475
6974
|
|
|
6476
|
-
async function suggestRepoSlug(
|
|
6975
|
+
async function suggestRepoSlug(orgSlug) {
|
|
6976
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
6977
|
+
|
|
6477
6978
|
// Same as above, but if there's a repo with the same name as cwd then
|
|
6478
6979
|
// default the selection to that name.
|
|
6479
|
-
const result = await handleApiCall(
|
|
6980
|
+
const result = await handleApiCall(sockSdk.getOrgRepoList(orgSlug, {
|
|
6480
6981
|
orgSlug,
|
|
6481
6982
|
sort: 'name',
|
|
6482
6983
|
direction: 'asc',
|
|
@@ -6486,6 +6987,7 @@ async function suggestRepoSlug(socketSdk, orgSlug) {
|
|
|
6486
6987
|
perPage: '10',
|
|
6487
6988
|
page: '0'
|
|
6488
6989
|
}), 'looking up known repos');
|
|
6990
|
+
|
|
6489
6991
|
// Ignore a failed request here. It was not the primary goal of
|
|
6490
6992
|
// running this command and reporting it only leads to end-user confusion.
|
|
6491
6993
|
if (result.success) {
|
|
@@ -6493,7 +6995,7 @@ async function suggestRepoSlug(socketSdk, orgSlug) {
|
|
|
6493
6995
|
let cwdIsKnown = !!currentDirName && result.data.results.some(obj => obj.slug === currentDirName);
|
|
6494
6996
|
if (!cwdIsKnown && currentDirName) {
|
|
6495
6997
|
// Do an explicit request so we can assert that the cwd exists or not
|
|
6496
|
-
const result = await handleApiCall(
|
|
6998
|
+
const result = await handleApiCall(sockSdk.getOrgRepo(orgSlug, currentDirName), 'checking if current cwd is a known repo');
|
|
6497
6999
|
if (result.success) {
|
|
6498
7000
|
cwdIsKnown = true;
|
|
6499
7001
|
}
|
|
@@ -6532,203 +7034,64 @@ async function suggestRepoSlug(socketSdk, orgSlug) {
|
|
|
6532
7034
|
}
|
|
6533
7035
|
});
|
|
6534
7036
|
return {
|
|
6535
|
-
slug: repoName,
|
|
6536
|
-
defaultBranch: repoDefaultBranch
|
|
6537
|
-
};
|
|
6538
|
-
}
|
|
6539
|
-
}
|
|
6540
|
-
}
|
|
6541
|
-
function dirNameToSlug(name) {
|
|
6542
|
-
// Uses slug specs asserted by our servers
|
|
6543
|
-
// Note: this can lead to collisions; eg. slug for `x--y` and `x---y` is `x-y`
|
|
6544
|
-
return name.toLowerCase().replace(/[^[a-zA-Z0-9_.-]/g, '_').replace(/--+/g, '-').replace(/__+/g, '_').replace(/\.\.+/g, '.').replace(/[._-]+$/, '');
|
|
6545
|
-
}
|
|
6546
|
-
|
|
6547
|
-
async function suggestBranchSlug(repoDefaultBranch) {
|
|
6548
|
-
const spawnResult = spawn.spawnSync('git', ['branch', '--show-current']);
|
|
6549
|
-
const currentBranch = spawnResult.stdout.toString('utf8').trim();
|
|
6550
|
-
if (currentBranch && spawnResult.status === 0) {
|
|
6551
|
-
const proceed = await prompts.select({
|
|
6552
|
-
message: 'Use the current git branch as target branch name?',
|
|
6553
|
-
choices: [{
|
|
6554
|
-
name: `Yes [${currentBranch}]`,
|
|
6555
|
-
value: currentBranch,
|
|
6556
|
-
description: 'Use the current git branch for branch name'
|
|
6557
|
-
}, ...(repoDefaultBranch && repoDefaultBranch !== currentBranch ? [{
|
|
6558
|
-
name: `No, use the default branch [${repoDefaultBranch}]`,
|
|
6559
|
-
value: repoDefaultBranch,
|
|
6560
|
-
description: 'Use the default branch for target repo as the target branch name'
|
|
6561
|
-
}] : []), {
|
|
6562
|
-
name: 'No',
|
|
6563
|
-
value: '',
|
|
6564
|
-
description: 'Do not use the current git branch as name (will end in a no-op)'
|
|
6565
|
-
}].filter(Boolean)
|
|
6566
|
-
});
|
|
6567
|
-
if (proceed) {
|
|
6568
|
-
return proceed;
|
|
6569
|
-
}
|
|
6570
|
-
}
|
|
6571
|
-
}
|
|
6572
|
-
|
|
6573
|
-
async function suggestTarget() {
|
|
6574
|
-
// We could prefill this with sub-dirs of the current
|
|
6575
|
-
// dir ... but is that going to be useful?
|
|
6576
|
-
const proceed = await prompts.select({
|
|
6577
|
-
message: 'No TARGET given. Do you want to use the current directory?',
|
|
6578
|
-
choices: [{
|
|
6579
|
-
name: 'Yes',
|
|
6580
|
-
value: true,
|
|
6581
|
-
description: 'Target the current directory'
|
|
6582
|
-
}, {
|
|
6583
|
-
name: 'No',
|
|
6584
|
-
value: false,
|
|
6585
|
-
description: 'Do not use the current directory (this will end in a no-op)'
|
|
6586
|
-
}]
|
|
6587
|
-
});
|
|
6588
|
-
if (proceed) {
|
|
6589
|
-
return ['.'];
|
|
6590
|
-
}
|
|
6591
|
-
}
|
|
6592
|
-
|
|
6593
|
-
async function createFullScan({
|
|
6594
|
-
branchName,
|
|
6595
|
-
commitHash: _commitHash,
|
|
6596
|
-
commitMessage,
|
|
6597
|
-
committers: _committers,
|
|
6598
|
-
cwd,
|
|
6599
|
-
defaultBranch,
|
|
6600
|
-
orgSlug,
|
|
6601
|
-
pendingHead,
|
|
6602
|
-
pullRequest: _pullRequest,
|
|
6603
|
-
readOnly,
|
|
6604
|
-
repoName,
|
|
6605
|
-
targets,
|
|
6606
|
-
tmp
|
|
6607
|
-
}) {
|
|
6608
|
-
// Lazily access constants.spinner.
|
|
6609
|
-
const {
|
|
6610
|
-
spinner
|
|
6611
|
-
} = constants;
|
|
6612
|
-
const socketSdk = await shadowNpmInject.setupSdk();
|
|
6613
|
-
const supportedFiles = await socketSdk.getReportSupportedFiles().then(res => {
|
|
6614
|
-
if (!res.success) {
|
|
6615
|
-
handleUnsuccessfulApiResponse('getReportSupportedFiles', res);
|
|
6616
|
-
assert(false, 'handleUnsuccessfulApiResponse should unconditionally throw');
|
|
6617
|
-
}
|
|
6618
|
-
return res.data;
|
|
6619
|
-
}).catch(cause => {
|
|
6620
|
-
throw new Error('Failed getting supported files for report', {
|
|
6621
|
-
cause
|
|
6622
|
-
});
|
|
6623
|
-
});
|
|
6624
|
-
|
|
6625
|
-
// If we updated any inputs then we should print the command line to repeat
|
|
6626
|
-
// the command without requiring user input, as a suggestion.
|
|
6627
|
-
let updatedInput = false;
|
|
6628
|
-
if (!targets.length) {
|
|
6629
|
-
const received = await suggestTarget();
|
|
6630
|
-
targets = received ?? [];
|
|
6631
|
-
updatedInput = true;
|
|
6632
|
-
}
|
|
6633
|
-
|
|
6634
|
-
// // TODO: we'll probably use socket.json or something else soon...
|
|
6635
|
-
// const absoluteConfigPath = path.join(cwd, 'socket.yml')
|
|
6636
|
-
// const socketConfig = await getSocketConfig(absoluteConfigPath)
|
|
6637
|
-
|
|
6638
|
-
const packagePaths = await shadowNpmPaths.getPackageFilesFullScans(cwd, targets, supportedFiles
|
|
6639
|
-
// socketConfig
|
|
6640
|
-
);
|
|
6641
|
-
|
|
6642
|
-
// We're going to need an api token to suggest data because those suggestions
|
|
6643
|
-
// must come from data we already know. Don't error on missing api token yet.
|
|
6644
|
-
// If the api-token is not set, ignore it for the sake of suggestions.
|
|
6645
|
-
const apiToken = shadowNpmInject.getDefaultToken();
|
|
6646
|
-
|
|
6647
|
-
// If the current cwd is unknown and is used as a repo slug anyways, we will
|
|
6648
|
-
// first need to register the slug before we can use it.
|
|
6649
|
-
let repoDefaultBranch = '';
|
|
6650
|
-
if (apiToken) {
|
|
6651
|
-
if (!orgSlug) {
|
|
6652
|
-
const suggestion = await suggestOrgSlug(socketSdk);
|
|
6653
|
-
if (suggestion) orgSlug = suggestion;
|
|
6654
|
-
updatedInput = true;
|
|
6655
|
-
}
|
|
6656
|
-
|
|
6657
|
-
// (Don't bother asking for the rest if we didn't get an org slug above)
|
|
6658
|
-
if (orgSlug && !repoName) {
|
|
6659
|
-
const suggestion = await suggestRepoSlug(socketSdk, orgSlug);
|
|
6660
|
-
if (suggestion) {
|
|
6661
|
-
repoDefaultBranch = suggestion.defaultBranch;
|
|
6662
|
-
repoName = suggestion.slug;
|
|
6663
|
-
}
|
|
6664
|
-
updatedInput = true;
|
|
6665
|
-
}
|
|
6666
|
-
|
|
6667
|
-
// (Don't bother asking for the rest if we didn't get an org/repo above)
|
|
6668
|
-
if (orgSlug && repoName && !branchName) {
|
|
6669
|
-
const suggestion = await suggestBranchSlug(repoDefaultBranch);
|
|
6670
|
-
if (suggestion) branchName = suggestion;
|
|
6671
|
-
updatedInput = true;
|
|
7037
|
+
slug: repoName,
|
|
7038
|
+
defaultBranch: repoDefaultBranch
|
|
7039
|
+
};
|
|
6672
7040
|
}
|
|
7041
|
+
} else {
|
|
7042
|
+
logger.logger.fail('Failed to lookup repo list from API, unable to suggest.');
|
|
6673
7043
|
}
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
|
|
6681
|
-
|
|
6682
|
-
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6683
|
-
|
|
6684
|
-
- Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6685
|
-
|
|
6686
|
-
- Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6687
|
-
|
|
6688
|
-
- 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
|
+
}
|
|
6689
7050
|
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
set_as_pending_head: String(pendingHead),
|
|
6714
|
-
tmp: String(tmp)
|
|
6715
|
-
}, packagePaths, cwd), 'Creating scan');
|
|
6716
|
-
if (!result.success) {
|
|
6717
|
-
handleUnsuccessfulApiResponse('CreateOrgFullScan', result);
|
|
6718
|
-
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
|
+
}
|
|
6719
7074
|
}
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
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
|
+
}]
|
|
6726
7091
|
});
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
await vendor.open(`${result.data.html_report_url}`);
|
|
7092
|
+
if (proceed) {
|
|
7093
|
+
return ['.'];
|
|
6730
7094
|
}
|
|
6731
|
-
rl.close();
|
|
6732
7095
|
}
|
|
6733
7096
|
|
|
6734
7097
|
const {
|
|
@@ -6852,18 +7215,66 @@ async function run$7(argv, importMeta, {
|
|
|
6852
7215
|
importMeta,
|
|
6853
7216
|
parentName
|
|
6854
7217
|
});
|
|
6855
|
-
const [orgSlug = '', ...targets] = cli.input;
|
|
6856
|
-
const cwd = cli.flags['cwd'] && cli.flags['cwd'] !== 'process.cwd()' ? String(cli.flags['cwd']) : process$1.cwd();
|
|
6857
7218
|
const {
|
|
7219
|
+
cwd: cwdOverride,
|
|
7220
|
+
dryRun
|
|
7221
|
+
} = cli.flags;
|
|
7222
|
+
const cwd = cwdOverride && cwdOverride !== 'process.cwd()' ? String(cwdOverride) : process$1.cwd();
|
|
7223
|
+
let {
|
|
6858
7224
|
branch: branchName,
|
|
6859
7225
|
repo: repoName
|
|
6860
7226
|
} = cli.flags;
|
|
6861
|
-
|
|
7227
|
+
let [orgSlug = '', ...targets] = cli.input;
|
|
6862
7228
|
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
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) {
|
|
6867
7278
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
6868
7279
|
// options or missing arguments.
|
|
6869
7280
|
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
@@ -6877,28 +7288,25 @@ async function run$7(argv, importMeta, {
|
|
|
6877
7288
|
|
|
6878
7289
|
- Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6879
7290
|
|
|
6880
|
-
- 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)')}
|
|
6881
7292
|
|
|
6882
|
-
|
|
7293
|
+
${!apiToken ? 'Note: was unable to make suggestions because no API Token was found; this would make the command fail regardless' : ''}
|
|
6883
7294
|
`);
|
|
6884
7295
|
return;
|
|
6885
7296
|
}
|
|
6886
7297
|
|
|
6887
7298
|
// Note exiting earlier to skirt a hidden auth requirement
|
|
6888
|
-
if (
|
|
7299
|
+
if (dryRun) {
|
|
6889
7300
|
logger.logger.log(DRY_RUN_BAIL_TEXT$7);
|
|
6890
7301
|
return;
|
|
6891
7302
|
}
|
|
6892
|
-
await
|
|
7303
|
+
await handleCreateNewScan({
|
|
6893
7304
|
branchName: branchName,
|
|
6894
|
-
commitHash: cli.flags['commitHash'] ?? '',
|
|
6895
7305
|
commitMessage: cli.flags['commitMessage'] ?? '',
|
|
6896
|
-
committers: cli.flags['committers'] ?? '',
|
|
6897
7306
|
cwd,
|
|
6898
7307
|
defaultBranch: Boolean(cli.flags['defaultBranch']),
|
|
6899
7308
|
orgSlug,
|
|
6900
7309
|
pendingHead: Boolean(cli.flags['pendingHead']),
|
|
6901
|
-
pullRequest: cli.flags['pullRequest'] ?? undefined,
|
|
6902
7310
|
readOnly: Boolean(cli.flags['readOnly']),
|
|
6903
7311
|
repoName: repoName,
|
|
6904
7312
|
targets,
|
|
@@ -6906,26 +7314,37 @@ async function run$7(argv, importMeta, {
|
|
|
6906
7314
|
});
|
|
6907
7315
|
}
|
|
6908
7316
|
|
|
6909
|
-
async function
|
|
7317
|
+
async function fetchDeleteOrgFullScan(orgSlug, scanId) {
|
|
6910
7318
|
const apiToken = shadowNpmInject.getDefaultToken();
|
|
6911
7319
|
if (!apiToken) {
|
|
6912
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.');
|
|
6913
7321
|
}
|
|
6914
|
-
await
|
|
7322
|
+
await fetchDeleteOrgFullScanWithToken(apiToken, orgSlug, scanId);
|
|
6915
7323
|
}
|
|
6916
|
-
async function
|
|
7324
|
+
async function fetchDeleteOrgFullScanWithToken(apiToken, orgSlug, scanId) {
|
|
6917
7325
|
// Lazily access constants.spinner.
|
|
6918
7326
|
const {
|
|
6919
7327
|
spinner
|
|
6920
7328
|
} = constants;
|
|
6921
|
-
|
|
6922
|
-
|
|
6923
|
-
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.');
|
|
6924
7333
|
if (!result.success) {
|
|
6925
7334
|
handleUnsuccessfulApiResponse('deleteOrgFullScan', result);
|
|
6926
7335
|
return;
|
|
6927
7336
|
}
|
|
6928
|
-
|
|
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();
|
|
6929
7348
|
}
|
|
6930
7349
|
|
|
6931
7350
|
const {
|
|
@@ -6964,8 +7383,8 @@ async function run$6(argv, importMeta, {
|
|
|
6964
7383
|
importMeta,
|
|
6965
7384
|
parentName
|
|
6966
7385
|
});
|
|
6967
|
-
const [orgSlug = '',
|
|
6968
|
-
if (!orgSlug || !
|
|
7386
|
+
const [orgSlug = '', scanId = ''] = cli.input;
|
|
7387
|
+
if (!orgSlug || !scanId) {
|
|
6969
7388
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
6970
7389
|
// options or missing arguments.
|
|
6971
7390
|
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
@@ -6974,22 +7393,20 @@ async function run$6(argv, importMeta, {
|
|
|
6974
7393
|
|
|
6975
7394
|
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6976
7395
|
|
|
6977
|
-
- Full Scan ID to delete as second argument ${!
|
|
7396
|
+
- Full Scan ID to delete as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
|
|
6978
7397
|
return;
|
|
6979
7398
|
}
|
|
6980
7399
|
if (cli.flags['dryRun']) {
|
|
6981
7400
|
logger.logger.log(DRY_RUN_BAIL_TEXT$6);
|
|
6982
7401
|
return;
|
|
6983
7402
|
}
|
|
6984
|
-
await
|
|
7403
|
+
await handleDeleteScan(orgSlug, scanId);
|
|
6985
7404
|
}
|
|
6986
7405
|
|
|
6987
|
-
|
|
6988
|
-
async function listFullScans({
|
|
7406
|
+
async function fetchListScans({
|
|
6989
7407
|
direction,
|
|
6990
7408
|
from_time,
|
|
6991
7409
|
orgSlug,
|
|
6992
|
-
outputKind,
|
|
6993
7410
|
page,
|
|
6994
7411
|
per_page,
|
|
6995
7412
|
sort
|
|
@@ -6998,23 +7415,19 @@ async function listFullScans({
|
|
|
6998
7415
|
if (!apiToken) {
|
|
6999
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.');
|
|
7000
7417
|
}
|
|
7001
|
-
await
|
|
7002
|
-
apiToken,
|
|
7418
|
+
await fetchListScansWithToken(apiToken, {
|
|
7003
7419
|
direction,
|
|
7004
7420
|
from_time,
|
|
7005
7421
|
orgSlug,
|
|
7006
|
-
outputKind,
|
|
7007
7422
|
page,
|
|
7008
7423
|
per_page,
|
|
7009
7424
|
sort
|
|
7010
7425
|
});
|
|
7011
7426
|
}
|
|
7012
|
-
async function
|
|
7013
|
-
apiToken,
|
|
7427
|
+
async function fetchListScansWithToken(apiToken, {
|
|
7014
7428
|
direction,
|
|
7015
7429
|
from_time,
|
|
7016
7430
|
orgSlug,
|
|
7017
|
-
outputKind,
|
|
7018
7431
|
page,
|
|
7019
7432
|
per_page,
|
|
7020
7433
|
sort
|
|
@@ -7023,22 +7436,27 @@ async function listFullScansWithToken({
|
|
|
7023
7436
|
const {
|
|
7024
7437
|
spinner
|
|
7025
7438
|
} = constants;
|
|
7439
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
7026
7440
|
spinner.start('Fetching list of scans...');
|
|
7027
|
-
const
|
|
7028
|
-
const result = await handleApiCall(socketSdk.getOrgFullScanList(orgSlug, {
|
|
7441
|
+
const result = await handleApiCall(sockSdk.getOrgFullScanList(orgSlug, {
|
|
7029
7442
|
sort,
|
|
7030
7443
|
direction,
|
|
7031
7444
|
per_page: String(per_page),
|
|
7032
7445
|
page: String(page),
|
|
7033
7446
|
from: from_time
|
|
7034
7447
|
}), 'Listing scans');
|
|
7448
|
+
spinner.successAndStop(`Received response for list of scans.`);
|
|
7035
7449
|
if (!result.success) {
|
|
7036
7450
|
handleUnsuccessfulApiResponse('getOrgFullScanList', result);
|
|
7037
7451
|
return;
|
|
7038
7452
|
}
|
|
7039
|
-
|
|
7453
|
+
return result.data;
|
|
7454
|
+
}
|
|
7455
|
+
|
|
7456
|
+
// @ts-ignore
|
|
7457
|
+
async function outputListScans(data, outputKind) {
|
|
7040
7458
|
if (outputKind === 'json') {
|
|
7041
|
-
logger.logger.log(
|
|
7459
|
+
logger.logger.log(data);
|
|
7042
7460
|
return;
|
|
7043
7461
|
}
|
|
7044
7462
|
const options = {
|
|
@@ -7056,7 +7474,7 @@ async function listFullScansWithToken({
|
|
|
7056
7474
|
name: colors.magenta('Created at')
|
|
7057
7475
|
}]
|
|
7058
7476
|
};
|
|
7059
|
-
const formattedResults =
|
|
7477
|
+
const formattedResults = data.results.map(d => {
|
|
7060
7478
|
return {
|
|
7061
7479
|
id: d.id,
|
|
7062
7480
|
report_url: colors.underline(`${d.html_report_url}`),
|
|
@@ -7071,6 +7489,27 @@ async function listFullScansWithToken({
|
|
|
7071
7489
|
logger.logger.log(chalkTable(options, formattedResults));
|
|
7072
7490
|
}
|
|
7073
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
|
+
|
|
7074
7513
|
const {
|
|
7075
7514
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$5
|
|
7076
7515
|
} = constants;
|
|
@@ -7158,7 +7597,7 @@ async function run$5(argv, importMeta, {
|
|
|
7158
7597
|
logger.logger.log(DRY_RUN_BAIL_TEXT$5);
|
|
7159
7598
|
return;
|
|
7160
7599
|
}
|
|
7161
|
-
await
|
|
7600
|
+
await handleListScans({
|
|
7162
7601
|
direction: String(cli.flags['direction'] || ''),
|
|
7163
7602
|
from_time: String(cli.flags['fromTime'] || ''),
|
|
7164
7603
|
orgSlug,
|
|
@@ -7169,46 +7608,56 @@ async function run$5(argv, importMeta, {
|
|
|
7169
7608
|
});
|
|
7170
7609
|
}
|
|
7171
7610
|
|
|
7172
|
-
async function
|
|
7611
|
+
async function fetchScanMetadata(orgSlug, scanId) {
|
|
7173
7612
|
const apiToken = shadowNpmInject.getDefaultToken();
|
|
7174
7613
|
if (!apiToken) {
|
|
7175
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.');
|
|
7176
7615
|
}
|
|
7177
|
-
await
|
|
7616
|
+
await fetchScanMetadataWithToken(apiToken, orgSlug, scanId);
|
|
7178
7617
|
}
|
|
7179
|
-
async function
|
|
7618
|
+
async function fetchScanMetadataWithToken(apiToken, orgSlug, scanId) {
|
|
7180
7619
|
// Lazily access constants.spinner.
|
|
7181
7620
|
const {
|
|
7182
7621
|
spinner
|
|
7183
7622
|
} = constants;
|
|
7623
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
7184
7624
|
spinner.start('Fetching meta data for a full scan...');
|
|
7185
|
-
const
|
|
7186
|
-
|
|
7625
|
+
const result = await handleApiCall(sockSdk.getOrgFullScanMetadata(orgSlug, scanId), 'Listing scans');
|
|
7626
|
+
spinner.successAndStop('Received response for scan meta data.');
|
|
7187
7627
|
if (!result.success) {
|
|
7188
7628
|
handleUnsuccessfulApiResponse('getOrgFullScanMetadata', result);
|
|
7189
7629
|
return;
|
|
7190
7630
|
}
|
|
7191
|
-
|
|
7631
|
+
return result.data;
|
|
7632
|
+
}
|
|
7633
|
+
|
|
7634
|
+
async function outputScanMetadata(data, scanId, outputKind) {
|
|
7192
7635
|
if (outputKind === 'json') {
|
|
7193
|
-
logger.logger.log(
|
|
7636
|
+
logger.logger.log(data);
|
|
7194
7637
|
} else {
|
|
7195
7638
|
// Markdown = print
|
|
7196
7639
|
if (outputKind === 'markdown') {
|
|
7197
7640
|
logger.logger.log('# Scan meta data\n');
|
|
7198
7641
|
}
|
|
7199
7642
|
logger.logger.log(`Scan ID: ${scanId}\n`);
|
|
7200
|
-
for (const [key, value] of Object.entries(
|
|
7643
|
+
for (const [key, value] of Object.entries(data)) {
|
|
7201
7644
|
if (['id', 'updated_at', 'organization_id', 'repository_id', 'commit_hash', 'html_report_url'].includes(key)) continue;
|
|
7202
7645
|
logger.logger.log(`- ${key}:`, value);
|
|
7203
7646
|
}
|
|
7204
7647
|
if (outputKind === 'markdown') {
|
|
7205
|
-
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`);
|
|
7206
7649
|
} else {
|
|
7207
|
-
logger.logger.log(`\nYou can view this report at: ${
|
|
7650
|
+
logger.logger.log(`\nYou can view this report at: ${data.html_report_url}]\n`);
|
|
7208
7651
|
}
|
|
7209
7652
|
}
|
|
7210
7653
|
}
|
|
7211
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
|
+
|
|
7212
7661
|
const {
|
|
7213
7662
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$4
|
|
7214
7663
|
} = constants;
|
|
@@ -7245,8 +7694,8 @@ async function run$4(argv, importMeta, {
|
|
|
7245
7694
|
importMeta,
|
|
7246
7695
|
parentName
|
|
7247
7696
|
});
|
|
7248
|
-
const [orgSlug = '',
|
|
7249
|
-
if (!orgSlug || !
|
|
7697
|
+
const [orgSlug = '', scanId = ''] = cli.input;
|
|
7698
|
+
if (!orgSlug || !scanId) {
|
|
7250
7699
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
7251
7700
|
// options or missing arguments.
|
|
7252
7701
|
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
@@ -7255,14 +7704,14 @@ async function run$4(argv, importMeta, {
|
|
|
7255
7704
|
|
|
7256
7705
|
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7257
7706
|
|
|
7258
|
-
- Full Scan ID to inspect as second argument ${!
|
|
7707
|
+
- Full Scan ID to inspect as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
|
|
7259
7708
|
return;
|
|
7260
7709
|
}
|
|
7261
7710
|
if (cli.flags['dryRun']) {
|
|
7262
7711
|
logger.logger.log(DRY_RUN_BAIL_TEXT$4);
|
|
7263
7712
|
return;
|
|
7264
7713
|
}
|
|
7265
|
-
await
|
|
7714
|
+
await handleOrgScanMetadata(orgSlug, scanId, cli.flags['json'] ? 'json' : cli.flags['markdown'] ? 'markdown' : 'print');
|
|
7266
7715
|
}
|
|
7267
7716
|
|
|
7268
7717
|
/**
|
|
@@ -7270,7 +7719,7 @@ async function run$4(argv, importMeta, {
|
|
|
7270
7719
|
* full scan ID.
|
|
7271
7720
|
* It can optionally only fetch the security or license side of things.
|
|
7272
7721
|
*/
|
|
7273
|
-
async function fetchReportData(orgSlug,
|
|
7722
|
+
async function fetchReportData(orgSlug, scanId,
|
|
7274
7723
|
// includeLicensePolicy: boolean,
|
|
7275
7724
|
includeSecurityPolicy) {
|
|
7276
7725
|
let haveScan = false;
|
|
@@ -7307,18 +7756,18 @@ includeSecurityPolicy) {
|
|
|
7307
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.');
|
|
7308
7757
|
}
|
|
7309
7758
|
updateProgress();
|
|
7310
|
-
const
|
|
7759
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
7311
7760
|
|
|
7312
7761
|
// @ts-ignore
|
|
7313
7762
|
const [scan,
|
|
7314
7763
|
// licensePolicyMaybe,
|
|
7315
7764
|
securityPolicyMaybe] = await Promise.all([(async () => {
|
|
7316
7765
|
try {
|
|
7317
|
-
const response = await
|
|
7766
|
+
const response = await queryApi(`orgs/${orgSlug}/full-scans/${encodeURIComponent(scanId)}`, apiToken);
|
|
7318
7767
|
haveScan = true;
|
|
7319
7768
|
updateProgress();
|
|
7320
7769
|
if (!response.ok) {
|
|
7321
|
-
const err = await
|
|
7770
|
+
const err = await handleApiError(response.status);
|
|
7322
7771
|
logger.logger.fail(`${colors.bgRed(colors.white(response.statusText))}: Fetch error: ${err}`);
|
|
7323
7772
|
return undefined;
|
|
7324
7773
|
}
|
|
@@ -7340,7 +7789,7 @@ includeSecurityPolicy) {
|
|
|
7340
7789
|
})(),
|
|
7341
7790
|
// includeLicensePolicy &&
|
|
7342
7791
|
// (async () => {
|
|
7343
|
-
// const r = await
|
|
7792
|
+
// const r = await sockSdk.getOrgSecurityPolicy(orgSlug)
|
|
7344
7793
|
// haveLicensePolicy = true
|
|
7345
7794
|
// updateProgress()
|
|
7346
7795
|
// return await handleApiCall(
|
|
@@ -7349,7 +7798,7 @@ includeSecurityPolicy) {
|
|
|
7349
7798
|
// )
|
|
7350
7799
|
// })(),
|
|
7351
7800
|
includeSecurityPolicy && (async () => {
|
|
7352
|
-
const r = await
|
|
7801
|
+
const r = await sockSdk.getOrgSecurityPolicy(orgSlug);
|
|
7353
7802
|
haveSecurityPolicy = true;
|
|
7354
7803
|
updateProgress();
|
|
7355
7804
|
return await handleApiCall(r, "looking up organization's security policy");
|
|
@@ -7595,40 +8044,31 @@ function* walkNestedMap(map, keys = []) {
|
|
|
7595
8044
|
}
|
|
7596
8045
|
}
|
|
7597
8046
|
|
|
7598
|
-
async function
|
|
8047
|
+
async function outputScanReport(scan,
|
|
8048
|
+
// licensePolicy: undefined | SocketSdkReturnType<'getOrgSecurityPolicy'>,
|
|
8049
|
+
securityPolicy, {
|
|
7599
8050
|
filePath,
|
|
7600
8051
|
fold,
|
|
7601
|
-
fullScanId,
|
|
7602
8052
|
includeLicensePolicy,
|
|
7603
8053
|
includeSecurityPolicy,
|
|
7604
8054
|
orgSlug,
|
|
7605
8055
|
outputKind,
|
|
7606
8056
|
reportLevel,
|
|
8057
|
+
scanId,
|
|
7607
8058
|
short
|
|
7608
8059
|
}) {
|
|
7609
|
-
logger.logger.error('output:', outputKind, ', file:', filePath, ', fold:', fold, ', reportLevel:', reportLevel);
|
|
7610
8060
|
if (!includeSecurityPolicy) {
|
|
8061
|
+
process.exitCode = 1;
|
|
7611
8062
|
return; // caller should assert
|
|
7612
8063
|
}
|
|
7613
|
-
const {
|
|
7614
|
-
// licensePolicy,
|
|
7615
|
-
ok,
|
|
7616
|
-
scan,
|
|
7617
|
-
securityPolicy
|
|
7618
|
-
} = await fetchReportData(orgSlug, fullScanId,
|
|
7619
|
-
// includeLicensePolicy
|
|
7620
|
-
includeSecurityPolicy);
|
|
7621
|
-
if (!ok) {
|
|
7622
|
-
return;
|
|
7623
|
-
}
|
|
7624
8064
|
const scanReport = generateReport(scan, undefined,
|
|
7625
8065
|
// licensePolicy,
|
|
7626
8066
|
securityPolicy, {
|
|
7627
8067
|
orgSlug,
|
|
7628
|
-
scanId
|
|
8068
|
+
scanId,
|
|
7629
8069
|
fold,
|
|
7630
|
-
|
|
7631
|
-
|
|
8070
|
+
reportLevel,
|
|
8071
|
+
short
|
|
7632
8072
|
});
|
|
7633
8073
|
if (!scanReport.healthy) {
|
|
7634
8074
|
process.exitCode = 1;
|
|
@@ -7715,6 +8155,43 @@ ${!report.alerts.size ? '' : mdTable(flatData, ['Policy', 'Alert Type', 'Package
|
|
|
7715
8155
|
return md;
|
|
7716
8156
|
}
|
|
7717
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
|
+
|
|
7718
8195
|
const {
|
|
7719
8196
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$3
|
|
7720
8197
|
} = constants;
|
|
@@ -7801,8 +8278,8 @@ async function run$3(argv, importMeta, {
|
|
|
7801
8278
|
reportLevel = 'warn',
|
|
7802
8279
|
security
|
|
7803
8280
|
} = cli.flags;
|
|
7804
|
-
const [orgSlug = '',
|
|
7805
|
-
if (!orgSlug || !
|
|
8281
|
+
const [orgSlug = '', scanId = '', file = '-'] = cli.input;
|
|
8282
|
+
if (!orgSlug || !scanId ||
|
|
7806
8283
|
// (!license && !security) ||
|
|
7807
8284
|
json && markdown) {
|
|
7808
8285
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
@@ -7814,7 +8291,7 @@ async function run$3(argv, importMeta, {
|
|
|
7814
8291
|
|
|
7815
8292
|
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7816
8293
|
|
|
7817
|
-
- Full Scan ID to fetch as second argument ${!
|
|
8294
|
+
- Full Scan ID to fetch as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7818
8295
|
|
|
7819
8296
|
- Not both the --json and --markdown flags ${json && markdown ? colors.red('(pick one!)') : colors.green('(ok)')}
|
|
7820
8297
|
`
|
|
@@ -7826,9 +8303,9 @@ async function run$3(argv, importMeta, {
|
|
|
7826
8303
|
logger.logger.log(DRY_RUN_BAIL_TEXT$3);
|
|
7827
8304
|
return;
|
|
7828
8305
|
}
|
|
7829
|
-
await
|
|
8306
|
+
await handleScanReport({
|
|
7830
8307
|
orgSlug,
|
|
7831
|
-
|
|
8308
|
+
scanId: scanId,
|
|
7832
8309
|
includeLicensePolicy: false,
|
|
7833
8310
|
// !!license,
|
|
7834
8311
|
includeSecurityPolicy: typeof security === 'boolean' ? security : true,
|
|
@@ -7840,29 +8317,7 @@ async function run$3(argv, importMeta, {
|
|
|
7840
8317
|
});
|
|
7841
8318
|
}
|
|
7842
8319
|
|
|
7843
|
-
async function
|
|
7844
|
-
// Lazily access constants.spinner.
|
|
7845
|
-
const {
|
|
7846
|
-
spinner
|
|
7847
|
-
} = constants;
|
|
7848
|
-
const apiToken = shadowNpmInject.getDefaultToken();
|
|
7849
|
-
if (!apiToken) {
|
|
7850
|
-
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.');
|
|
7851
|
-
}
|
|
7852
|
-
spinner.start('Fetching scan...');
|
|
7853
|
-
const socketSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
7854
|
-
const data = await handleApiCall(socketSdk.getOrgFullScan(orgSlug, fullScanId, file === '-' ? undefined : file), 'Fetching a scan');
|
|
7855
|
-
if (!data?.success) {
|
|
7856
|
-
handleUnsuccessfulApiResponse('getOrgFullScan', data);
|
|
7857
|
-
return;
|
|
7858
|
-
}
|
|
7859
|
-
spinner?.successAndStop(file ? `Full scan details written to ${file}` : 'stdout');
|
|
7860
|
-
return data;
|
|
7861
|
-
}
|
|
7862
|
-
|
|
7863
|
-
async function viewFullScan(orgSlug, fullScanId, filePath) {
|
|
7864
|
-
const artifacts = await getFullScan(orgSlug, fullScanId);
|
|
7865
|
-
if (!artifacts) return;
|
|
8320
|
+
async function outputScanView(artifacts, orgSlug, scanId, filePath) {
|
|
7866
8321
|
const display = artifacts.map(art => {
|
|
7867
8322
|
const author = Array.isArray(art.author) ? `${art.author[0]}${art.author.length > 1 ? ' et.al.' : ''}` : art.author;
|
|
7868
8323
|
return {
|
|
@@ -7879,11 +8334,11 @@ async function viewFullScan(orgSlug, fullScanId, filePath) {
|
|
|
7879
8334
|
|
|
7880
8335
|
These are the artifacts and their scores found.
|
|
7881
8336
|
|
|
7882
|
-
|
|
8337
|
+
Scan ID: ${scanId}
|
|
7883
8338
|
|
|
7884
8339
|
${md}
|
|
7885
8340
|
|
|
7886
|
-
View this report at: https://socket.dev/dashboard/org/${orgSlug}/sbom/${
|
|
8341
|
+
View this report at: https://socket.dev/dashboard/org/${orgSlug}/sbom/${scanId}
|
|
7887
8342
|
`.trim() + '\n';
|
|
7888
8343
|
if (filePath && filePath !== '-') {
|
|
7889
8344
|
try {
|
|
@@ -7899,6 +8354,32 @@ View this report at: https://socket.dev/dashboard/org/${orgSlug}/sbom/${fullScan
|
|
|
7899
8354
|
}
|
|
7900
8355
|
}
|
|
7901
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
|
+
|
|
7902
8383
|
const {
|
|
7903
8384
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$2
|
|
7904
8385
|
} = constants;
|
|
@@ -7937,8 +8418,8 @@ async function run$2(argv, importMeta, {
|
|
|
7937
8418
|
importMeta,
|
|
7938
8419
|
parentName
|
|
7939
8420
|
});
|
|
7940
|
-
const [orgSlug = '',
|
|
7941
|
-
if (!orgSlug || !
|
|
8421
|
+
const [orgSlug = '', scanId = '', file = '-'] = cli.input;
|
|
8422
|
+
if (!orgSlug || !scanId) {
|
|
7942
8423
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
7943
8424
|
// options or missing arguments.
|
|
7944
8425
|
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
@@ -7948,7 +8429,7 @@ async function run$2(argv, importMeta, {
|
|
|
7948
8429
|
|
|
7949
8430
|
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7950
8431
|
|
|
7951
|
-
- Full Scan ID to fetch as second argument ${!
|
|
8432
|
+
- Full Scan ID to fetch as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7952
8433
|
`);
|
|
7953
8434
|
return;
|
|
7954
8435
|
}
|
|
@@ -7957,9 +8438,9 @@ async function run$2(argv, importMeta, {
|
|
|
7957
8438
|
return;
|
|
7958
8439
|
}
|
|
7959
8440
|
if (cli.flags['json']) {
|
|
7960
|
-
await
|
|
8441
|
+
await streamScan(orgSlug, scanId, file);
|
|
7961
8442
|
} else {
|
|
7962
|
-
await
|
|
8443
|
+
await handleScanView(orgSlug, scanId, file);
|
|
7963
8444
|
}
|
|
7964
8445
|
}
|
|
7965
8446
|
|
|
@@ -8032,7 +8513,7 @@ async function getThreatFeedWithToken({
|
|
|
8032
8513
|
} = constants;
|
|
8033
8514
|
const queryParams = new URLSearchParams([['direction', direction], ['ecosystem', ecosystem], ['filter', filter], ['page', page], ['per_page', String(perPage)]]);
|
|
8034
8515
|
spinner.start('Fetching Threat Feed data...');
|
|
8035
|
-
const response = await
|
|
8516
|
+
const response = await queryApi(`threat-feed?${queryParams}`, apiToken);
|
|
8036
8517
|
const data = await response.json();
|
|
8037
8518
|
spinner.stop('Threat feed data fetched');
|
|
8038
8519
|
if (outputKind === 'json') {
|
|
@@ -8455,12 +8936,13 @@ void (async () => {
|
|
|
8455
8936
|
await vendor.updater({
|
|
8456
8937
|
name: SOCKET_CLI_BIN_NAME,
|
|
8457
8938
|
// The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_VERSION']".
|
|
8458
|
-
version: "0.14.
|
|
8939
|
+
version: "0.14.67",
|
|
8459
8940
|
ttl: 86_400_000 /* 24 hours in milliseconds */
|
|
8460
8941
|
});
|
|
8461
8942
|
try {
|
|
8462
8943
|
await meowWithSubcommands({
|
|
8463
8944
|
cdxgen: cmdCdxgen,
|
|
8945
|
+
config: cmdConfig,
|
|
8464
8946
|
fix: cmdFix,
|
|
8465
8947
|
info: cmdInfo,
|
|
8466
8948
|
login: cmdLogin,
|
|
@@ -8522,5 +9004,5 @@ void (async () => {
|
|
|
8522
9004
|
await shadowNpmInject.captureException(e);
|
|
8523
9005
|
}
|
|
8524
9006
|
})();
|
|
8525
|
-
//# debugId=
|
|
9007
|
+
//# debugId=199d20b5-2692-44b6-b880-34650eeaae46
|
|
8526
9008
|
//# sourceMappingURL=cli.js.map
|