@socketsecurity/cli-with-sentry 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/instrument-with-sentry.js +2 -2
- package/dist/instrument-with-sentry.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/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 +14 -14
- package/dist/module-sync/fs.d.ts +0 -22
- 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:df42d424: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'
|
|
@@ -2433,15 +2832,15 @@ async function run$x(argv, importMeta, {
|
|
|
2433
2832
|
}
|
|
2434
2833
|
|
|
2435
2834
|
async function fetchPackageInfo(pkgName, pkgVersion, includeAllIssues) {
|
|
2436
|
-
const
|
|
2835
|
+
const sockSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
|
|
2437
2836
|
|
|
2438
2837
|
// Lazily access constants.spinner.
|
|
2439
2838
|
const {
|
|
2440
2839
|
spinner
|
|
2441
2840
|
} = constants;
|
|
2442
2841
|
spinner.start(pkgVersion === 'latest' ? `Looking up data for the latest version of ${pkgName}` : `Looking up data for version ${pkgVersion} of ${pkgName}`);
|
|
2443
|
-
const result = await handleApiCall(
|
|
2444
|
-
const scoreResult = await handleApiCall(
|
|
2842
|
+
const result = await handleApiCall(sockSdk.getIssuesByNPMPackage(pkgName, pkgVersion), 'looking up package');
|
|
2843
|
+
const scoreResult = await handleApiCall(sockSdk.getScoreByNPMPackage(pkgName, pkgVersion), 'looking up package score');
|
|
2445
2844
|
spinner.successAndStop('Data fetched');
|
|
2446
2845
|
if (result.success === false) {
|
|
2447
2846
|
return handleUnsuccessfulApiResponse('getIssuesByNPMPackage', result);
|
|
@@ -2469,7 +2868,7 @@ function formatScore$1(score) {
|
|
|
2469
2868
|
return colors.red(`${score}`);
|
|
2470
2869
|
}
|
|
2471
2870
|
function outputPackageIssuesDetails(packageData, outputMarkdown) {
|
|
2472
|
-
const issueDetails = packageData.filter(d => d.value?.severity === shadowNpmInject.
|
|
2871
|
+
const issueDetails = packageData.filter(d => d.value?.severity === shadowNpmInject.ALERT_SEVERITY.critical || d.value?.severity === shadowNpmInject.ALERT_SEVERITY.high);
|
|
2473
2872
|
const uniqueIssueDetails = issueDetails.reduce((acc, issue) => {
|
|
2474
2873
|
const {
|
|
2475
2874
|
type
|
|
@@ -2656,18 +3055,18 @@ async function run$w(argv, importMeta, {
|
|
|
2656
3055
|
}
|
|
2657
3056
|
|
|
2658
3057
|
function applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy) {
|
|
2659
|
-
shadowNpmInject.
|
|
2660
|
-
shadowNpmInject.
|
|
2661
|
-
shadowNpmInject.
|
|
2662
|
-
shadowNpmInject.
|
|
3058
|
+
shadowNpmInject.updateConfigValue('enforcedOrgs', enforcedOrgs);
|
|
3059
|
+
shadowNpmInject.updateConfigValue('apiToken', apiToken);
|
|
3060
|
+
shadowNpmInject.updateConfigValue('apiBaseUrl', apiBaseUrl);
|
|
3061
|
+
shadowNpmInject.updateConfigValue('apiProxy', apiProxy);
|
|
2663
3062
|
}
|
|
2664
3063
|
|
|
2665
3064
|
const {
|
|
2666
3065
|
SOCKET_PUBLIC_API_TOKEN
|
|
2667
3066
|
} = constants;
|
|
2668
3067
|
async function attemptLogin(apiBaseUrl, apiProxy) {
|
|
2669
|
-
apiBaseUrl ??= shadowNpmInject.
|
|
2670
|
-
apiProxy ??= shadowNpmInject.
|
|
3068
|
+
apiBaseUrl ??= shadowNpmInject.getConfigValue('apiBaseUrl') ?? undefined;
|
|
3069
|
+
apiProxy ??= shadowNpmInject.getConfigValue('apiProxy') ?? undefined;
|
|
2671
3070
|
const apiToken = (await prompts.password({
|
|
2672
3071
|
message: `Enter your ${terminalLink('Socket.dev API key', 'https://docs.socket.dev/docs/api-keys')} (leave blank for a public key)`
|
|
2673
3072
|
})) || SOCKET_PUBLIC_API_TOKEN;
|
|
@@ -2723,7 +3122,7 @@ async function attemptLogin(apiBaseUrl, apiProxy) {
|
|
|
2723
3122
|
}
|
|
2724
3123
|
}
|
|
2725
3124
|
spinner.stop();
|
|
2726
|
-
const oldToken = shadowNpmInject.
|
|
3125
|
+
const oldToken = shadowNpmInject.getConfigValue('apiToken');
|
|
2727
3126
|
try {
|
|
2728
3127
|
applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy);
|
|
2729
3128
|
logger.logger.success(`API credentials ${oldToken ? 'updated' : 'set'}`);
|
|
@@ -2791,10 +3190,10 @@ async function run$v(argv, importMeta, {
|
|
|
2791
3190
|
}
|
|
2792
3191
|
|
|
2793
3192
|
function applyLogout() {
|
|
2794
|
-
shadowNpmInject.
|
|
2795
|
-
shadowNpmInject.
|
|
2796
|
-
shadowNpmInject.
|
|
2797
|
-
shadowNpmInject.
|
|
3193
|
+
shadowNpmInject.updateConfigValue('apiToken', null);
|
|
3194
|
+
shadowNpmInject.updateConfigValue('apiBaseUrl', null);
|
|
3195
|
+
shadowNpmInject.updateConfigValue('apiProxy', null);
|
|
3196
|
+
shadowNpmInject.updateConfigValue('enforcedOrgs', null);
|
|
2798
3197
|
}
|
|
2799
3198
|
|
|
2800
3199
|
function attemptLogout() {
|
|
@@ -4543,14 +4942,14 @@ async function fetchOrganization() {
|
|
|
4543
4942
|
return await fetchOrganizationWithToken(apiToken);
|
|
4544
4943
|
}
|
|
4545
4944
|
async function fetchOrganizationWithToken(apiToken) {
|
|
4546
|
-
const
|
|
4945
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
4547
4946
|
|
|
4548
4947
|
// Lazily access constants.spinner.
|
|
4549
4948
|
const {
|
|
4550
4949
|
spinner
|
|
4551
4950
|
} = constants;
|
|
4552
4951
|
spinner.start('Fetching organization list...');
|
|
4553
|
-
const result = await handleApiCall(
|
|
4952
|
+
const result = await handleApiCall(sockSdk.getOrganizations(), 'looking up organizations');
|
|
4554
4953
|
spinner.successAndStop('Received organization list response.');
|
|
4555
4954
|
if (!result.success) {
|
|
4556
4955
|
handleUnsuccessfulApiResponse('getOrganizations', result);
|
|
@@ -4680,9 +5079,9 @@ async function fetchSecurityPolicyWithToken(apiToken, orgSlug) {
|
|
|
4680
5079
|
const {
|
|
4681
5080
|
spinner
|
|
4682
5081
|
} = constants;
|
|
4683
|
-
const
|
|
5082
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
4684
5083
|
spinner.start('Fetching organization quota...');
|
|
4685
|
-
const result = await handleApiCall(
|
|
5084
|
+
const result = await handleApiCall(sockSdk.getOrgSecurityPolicy(orgSlug), 'looking up organization quota');
|
|
4686
5085
|
spinner?.successAndStop('Received organization quota response.');
|
|
4687
5086
|
if (!result.success) {
|
|
4688
5087
|
handleUnsuccessfulApiResponse('getOrgSecurityPolicy', result);
|
|
@@ -4825,9 +5224,9 @@ async function fetchQuotaWithToken(apiToken) {
|
|
|
4825
5224
|
const {
|
|
4826
5225
|
spinner
|
|
4827
5226
|
} = constants;
|
|
4828
|
-
const
|
|
5227
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
4829
5228
|
spinner.start('Fetching organization quota...');
|
|
4830
|
-
const result = await handleApiCall(
|
|
5229
|
+
const result = await handleApiCall(sockSdk.getQuota(), 'looking up organization quota');
|
|
4831
5230
|
spinner?.successAndStop('Recieved organization quota response.');
|
|
4832
5231
|
if (!result.success) {
|
|
4833
5232
|
handleUnsuccessfulApiResponse('getQuota', result);
|
|
@@ -4954,8 +5353,8 @@ async function fetchPurlsShallowScore(purls) {
|
|
|
4954
5353
|
spinner
|
|
4955
5354
|
} = constants;
|
|
4956
5355
|
spinner.start(`Requesting data ...`);
|
|
4957
|
-
const
|
|
4958
|
-
const result = await handleApiCall(
|
|
5356
|
+
const sockSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
|
|
5357
|
+
const result = await handleApiCall(sockSdk.batchPackageFetch({
|
|
4959
5358
|
alerts: 'true'
|
|
4960
5359
|
// compact: false,
|
|
4961
5360
|
// fixable: false,
|
|
@@ -5356,8 +5755,8 @@ async function createReport(socketConfig, inputPaths, {
|
|
|
5356
5755
|
const {
|
|
5357
5756
|
spinner
|
|
5358
5757
|
} = constants;
|
|
5359
|
-
const
|
|
5360
|
-
const supportedFiles = await
|
|
5758
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
5759
|
+
const supportedFiles = await sockSdk.getReportSupportedFiles().then(res => {
|
|
5361
5760
|
if (!res.success) handleUnsuccessfulApiResponse('getReportSupportedFiles', res);
|
|
5362
5761
|
return res.data;
|
|
5363
5762
|
}).catch(cause => {
|
|
@@ -5365,7 +5764,7 @@ async function createReport(socketConfig, inputPaths, {
|
|
|
5365
5764
|
cause
|
|
5366
5765
|
});
|
|
5367
5766
|
});
|
|
5368
|
-
const packagePaths = await shadowNpmPaths.
|
|
5767
|
+
const packagePaths = await shadowNpmPaths.getPackageFilesForScan(cwd, inputPaths, supportedFiles, socketConfig);
|
|
5369
5768
|
const packagePathsCount = packagePaths.length;
|
|
5370
5769
|
if (packagePathsCount && debug.isDebug()) {
|
|
5371
5770
|
for (const pkgPath of packagePaths) {
|
|
@@ -5377,7 +5776,7 @@ async function createReport(socketConfig, inputPaths, {
|
|
|
5377
5776
|
return undefined;
|
|
5378
5777
|
}
|
|
5379
5778
|
spinner.start(`Creating report with ${packagePathsCount} package ${words.pluralize('file', packagePathsCount)}`);
|
|
5380
|
-
const apiCall =
|
|
5779
|
+
const apiCall = sockSdk.createReportFromFilePaths(packagePaths, cwd, socketConfig?.issueRules);
|
|
5381
5780
|
const result = await handleApiCall(apiCall, 'creating report');
|
|
5382
5781
|
if (!result.success) {
|
|
5383
5782
|
handleUnsuccessfulApiResponse('createReport', result);
|
|
@@ -5388,8 +5787,8 @@ async function createReport(socketConfig, inputPaths, {
|
|
|
5388
5787
|
}
|
|
5389
5788
|
|
|
5390
5789
|
async function getSocketConfig(absoluteConfigPath) {
|
|
5391
|
-
const socketConfig = await config$
|
|
5392
|
-
if (cause && typeof cause === 'object' && cause instanceof config$
|
|
5790
|
+
const socketConfig = await config$H.readSocketConfig(absoluteConfigPath).catch(cause => {
|
|
5791
|
+
if (cause && typeof cause === 'object' && cause instanceof config$H.SocketValidationError) {
|
|
5393
5792
|
// Inspired by workbox-build:
|
|
5394
5793
|
// https://github.com/GoogleChrome/workbox/blob/95f97a207fd51efb3f8a653f6e3e58224183a778/packages/workbox-build/src/lib/validate-options.ts#L68-L71
|
|
5395
5794
|
const betterErrors = betterAjvErrors.betterAjvErrors({
|
|
@@ -5417,12 +5816,12 @@ async function fetchReportData$1(reportId, includeAllIssues, strict) {
|
|
|
5417
5816
|
} = constants;
|
|
5418
5817
|
spinner.log('Fetching report with ID ${reportId} (this could take a while)');
|
|
5419
5818
|
spinner.start(`Fetch started... (this could take a while)`);
|
|
5420
|
-
const
|
|
5819
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
5421
5820
|
let result;
|
|
5422
5821
|
for (let retry = 1; !result; ++retry) {
|
|
5423
5822
|
try {
|
|
5424
5823
|
// eslint-disable-next-line no-await-in-loop
|
|
5425
|
-
result = await handleApiCall(
|
|
5824
|
+
result = await handleApiCall(sockSdk.getReport(reportId), 'fetching report');
|
|
5426
5825
|
} catch (err) {
|
|
5427
5826
|
if (retry >= MAX_TIMEOUT_RETRY || !(err instanceof Error) || err.cause?.cause?.response?.statusCode !== HTTP_CODE_TIMEOUT) {
|
|
5428
5827
|
spinner.stop(`Failed to fetch report`);
|
|
@@ -5474,7 +5873,7 @@ function formatReportDataOutput(reportId, data, commandName, outputKind, strict,
|
|
|
5474
5873
|
}
|
|
5475
5874
|
}
|
|
5476
5875
|
|
|
5477
|
-
async function
|
|
5876
|
+
async function fetchScan(orgSlug, scanId) {
|
|
5478
5877
|
// Lazily access constants.spinner.
|
|
5479
5878
|
const {
|
|
5480
5879
|
spinner
|
|
@@ -5484,10 +5883,10 @@ async function getFullScan(orgSlug, fullScanId) {
|
|
|
5484
5883
|
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.');
|
|
5485
5884
|
}
|
|
5486
5885
|
spinner.start('Fetching full-scan...');
|
|
5487
|
-
const response = await
|
|
5886
|
+
const response = await queryApi(`orgs/${orgSlug}/full-scans/${encodeURIComponent(scanId)}`, apiToken);
|
|
5488
5887
|
spinner.stop('Fetch complete.');
|
|
5489
5888
|
if (!response.ok) {
|
|
5490
|
-
const err = await
|
|
5889
|
+
const err = await handleApiError(response.status);
|
|
5491
5890
|
logger.logger.fail(`${colors.bgRed(colors.white(response.statusText))}: Fetch error: ${err}`);
|
|
5492
5891
|
return;
|
|
5493
5892
|
}
|
|
@@ -5513,7 +5912,7 @@ async function viewReport(reportId, {
|
|
|
5513
5912
|
strict
|
|
5514
5913
|
}) {
|
|
5515
5914
|
const result = await fetchReportData$1(reportId, all, strict);
|
|
5516
|
-
const artifacts = await
|
|
5915
|
+
const artifacts = await fetchScan('socketdev', reportId);
|
|
5517
5916
|
if (result) {
|
|
5518
5917
|
formatReportDataOutput(reportId, result, commandName, outputKind, strict, artifacts);
|
|
5519
5918
|
}
|
|
@@ -5714,9 +6113,9 @@ async function fetchCreateRepoWithToken(apiToken, {
|
|
|
5714
6113
|
const {
|
|
5715
6114
|
spinner
|
|
5716
6115
|
} = constants;
|
|
5717
|
-
const
|
|
6116
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
5718
6117
|
spinner.start('Sending request ot create a repository...');
|
|
5719
|
-
const result = await handleApiCall(
|
|
6118
|
+
const result = await handleApiCall(sockSdk.createOrgRepo(orgSlug, {
|
|
5720
6119
|
name: repoName,
|
|
5721
6120
|
description,
|
|
5722
6121
|
homepage,
|
|
@@ -5861,8 +6260,8 @@ async function deleteRepoWithToken(orgSlug, repoName, apiToken) {
|
|
|
5861
6260
|
spinner
|
|
5862
6261
|
} = constants;
|
|
5863
6262
|
spinner.start('Deleting repository...');
|
|
5864
|
-
const
|
|
5865
|
-
const result = await handleApiCall(
|
|
6263
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
6264
|
+
const result = await handleApiCall(sockSdk.deleteOrgRepo(orgSlug, repoName), 'deleting repository');
|
|
5866
6265
|
if (!result.success) {
|
|
5867
6266
|
handleUnsuccessfulApiResponse('deleteOrgRepo', result);
|
|
5868
6267
|
return;
|
|
@@ -5957,9 +6356,9 @@ async function fetchListReposWithToken(apiToken, {
|
|
|
5957
6356
|
const {
|
|
5958
6357
|
spinner
|
|
5959
6358
|
} = constants;
|
|
5960
|
-
const
|
|
6359
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
5961
6360
|
spinner.start('Fetching list of repositories...');
|
|
5962
|
-
const result = await handleApiCall(
|
|
6361
|
+
const result = await handleApiCall(sockSdk.getOrgRepoList(orgSlug, {
|
|
5963
6362
|
sort,
|
|
5964
6363
|
direction,
|
|
5965
6364
|
per_page: String(per_page),
|
|
@@ -6146,8 +6545,8 @@ async function fetchUpdateRepoWithToken(apiToken, {
|
|
|
6146
6545
|
spinner
|
|
6147
6546
|
} = constants;
|
|
6148
6547
|
spinner.start('Sending request to update a repository...');
|
|
6149
|
-
const
|
|
6150
|
-
const result = await handleApiCall(
|
|
6548
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
6549
|
+
const result = await handleApiCall(sockSdk.updateOrgRepo(orgSlug, repoName, {
|
|
6151
6550
|
orgSlug,
|
|
6152
6551
|
name: repoName,
|
|
6153
6552
|
description,
|
|
@@ -6294,9 +6693,9 @@ async function fetchViewRepoWithToken(orgSlug, repoName, apiToken) {
|
|
|
6294
6693
|
const {
|
|
6295
6694
|
spinner
|
|
6296
6695
|
} = constants;
|
|
6297
|
-
const
|
|
6696
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
6298
6697
|
spinner.start('Fetching repository data...');
|
|
6299
|
-
const result = await handleApiCall(
|
|
6698
|
+
const result = await handleApiCall(sockSdk.getOrgRepo(orgSlug, repoName), 'fetching repository');
|
|
6300
6699
|
spinner.successAndStop('Received response while fetched repository data.');
|
|
6301
6700
|
if (!result.success) {
|
|
6302
6701
|
handleUnsuccessfulApiResponse('getOrgRepo', result);
|
|
@@ -6450,8 +6849,106 @@ const cmdRepos = {
|
|
|
6450
6849
|
}
|
|
6451
6850
|
};
|
|
6452
6851
|
|
|
6453
|
-
async function
|
|
6454
|
-
const
|
|
6852
|
+
async function fetchCreateOrgFullScan(packagePaths, orgSlug, repoName, branchName, commitMessage, defaultBranch, pendingHead, tmp, cwd) {
|
|
6853
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
6854
|
+
|
|
6855
|
+
// Lazily access constants.spinner.
|
|
6856
|
+
const {
|
|
6857
|
+
spinner
|
|
6858
|
+
} = constants;
|
|
6859
|
+
spinner.start(`Creating a scan with ${packagePaths.length} packages...`);
|
|
6860
|
+
const result = await handleApiCall(sockSdk.createOrgFullScan(orgSlug, {
|
|
6861
|
+
repo: repoName,
|
|
6862
|
+
branch: branchName,
|
|
6863
|
+
commit_message: commitMessage,
|
|
6864
|
+
make_default_branch: String(defaultBranch),
|
|
6865
|
+
set_as_pending_head: String(pendingHead),
|
|
6866
|
+
tmp: String(tmp)
|
|
6867
|
+
}, packagePaths, cwd), 'Creating scan');
|
|
6868
|
+
spinner.successAndStop('Scan created successfully');
|
|
6869
|
+
if (!result.success) {
|
|
6870
|
+
handleUnsuccessfulApiResponse('CreateOrgFullScan', result);
|
|
6871
|
+
return;
|
|
6872
|
+
}
|
|
6873
|
+
return result.data;
|
|
6874
|
+
}
|
|
6875
|
+
|
|
6876
|
+
async function fetchSupportedScanFileNames() {
|
|
6877
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
6878
|
+
|
|
6879
|
+
// Lazily access constants.spinner.
|
|
6880
|
+
const {
|
|
6881
|
+
spinner
|
|
6882
|
+
} = constants;
|
|
6883
|
+
spinner.start('Requesting supported scan file types from API...');
|
|
6884
|
+
const result = await handleApiCall(sockSdk.getReportSupportedFiles(), 'fetching supported scan file types');
|
|
6885
|
+
spinner.successAndStop('Received response while fetched supported scan file types.');
|
|
6886
|
+
if (!result.success) {
|
|
6887
|
+
handleUnsuccessfulApiResponse('getReportSupportedFiles', result);
|
|
6888
|
+
return;
|
|
6889
|
+
}
|
|
6890
|
+
return result.data;
|
|
6891
|
+
}
|
|
6892
|
+
|
|
6893
|
+
async function outputCreateNewScan(data) {
|
|
6894
|
+
const link = colors.underline(colors.cyan(`${data.html_report_url}`));
|
|
6895
|
+
logger.logger.log(`Available at: ${link}`);
|
|
6896
|
+
const rl = readline.createInterface({
|
|
6897
|
+
input: process$1.stdin,
|
|
6898
|
+
output: process$1.stdout
|
|
6899
|
+
});
|
|
6900
|
+
const answer = await rl.question('Would you like to open it in your browser? (y/n)');
|
|
6901
|
+
if (answer.toLowerCase() === 'y') {
|
|
6902
|
+
await vendor.open(`${data.html_report_url}`);
|
|
6903
|
+
}
|
|
6904
|
+
rl.close();
|
|
6905
|
+
}
|
|
6906
|
+
|
|
6907
|
+
async function handleCreateNewScan({
|
|
6908
|
+
branchName,
|
|
6909
|
+
commitMessage,
|
|
6910
|
+
cwd,
|
|
6911
|
+
defaultBranch,
|
|
6912
|
+
orgSlug,
|
|
6913
|
+
pendingHead,
|
|
6914
|
+
readOnly,
|
|
6915
|
+
repoName,
|
|
6916
|
+
targets,
|
|
6917
|
+
tmp
|
|
6918
|
+
}) {
|
|
6919
|
+
const apiToken = shadowNpmInject.getDefaultToken();
|
|
6920
|
+
|
|
6921
|
+
// Note: you need an apiToken to request supportedScanFileNames from the API
|
|
6922
|
+
if (!apiToken) {
|
|
6923
|
+
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.');
|
|
6924
|
+
}
|
|
6925
|
+
const supportedFileNames = await fetchSupportedScanFileNames();
|
|
6926
|
+
if (!supportedFileNames) return;
|
|
6927
|
+
const packagePaths = await shadowNpmPaths.getPackageFilesForScan(cwd, targets, supportedFileNames
|
|
6928
|
+
// socketConfig
|
|
6929
|
+
);
|
|
6930
|
+
if (!packagePaths.length) {
|
|
6931
|
+
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
6932
|
+
// options or missing arguments.
|
|
6933
|
+
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
6934
|
+
process$1.exitCode = 2;
|
|
6935
|
+
logger.logger.fail(commonTags.stripIndents`
|
|
6936
|
+
${colors.bgRed(colors.white('Input error'))}: The TARGET did not contain any matching / supported files for a scan
|
|
6937
|
+
`);
|
|
6938
|
+
return;
|
|
6939
|
+
}
|
|
6940
|
+
if (readOnly) {
|
|
6941
|
+
logger.logger.log('[ReadOnly] Bailing now');
|
|
6942
|
+
return;
|
|
6943
|
+
}
|
|
6944
|
+
const data = await fetchCreateOrgFullScan(packagePaths, orgSlug, repoName, branchName, commitMessage, defaultBranch, pendingHead, tmp, cwd);
|
|
6945
|
+
if (!data) return;
|
|
6946
|
+
await outputCreateNewScan(data);
|
|
6947
|
+
}
|
|
6948
|
+
|
|
6949
|
+
async function suggestOrgSlug() {
|
|
6950
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
6951
|
+
const result = await handleApiCall(sockSdk.getOrganizations(), 'looking up organizations');
|
|
6455
6952
|
// Ignore a failed request here. It was not the primary goal of
|
|
6456
6953
|
// running this command and reporting it only leads to end-user confusion.
|
|
6457
6954
|
if (result.success) {
|
|
@@ -6472,13 +6969,17 @@ async function suggestOrgSlug(socketSdk) {
|
|
|
6472
6969
|
if (proceed) {
|
|
6473
6970
|
return proceed;
|
|
6474
6971
|
}
|
|
6972
|
+
} else {
|
|
6973
|
+
logger.logger.fail('Failed to lookup organization list from API, unable to suggest.');
|
|
6475
6974
|
}
|
|
6476
6975
|
}
|
|
6477
6976
|
|
|
6478
|
-
async function suggestRepoSlug(
|
|
6977
|
+
async function suggestRepoSlug(orgSlug) {
|
|
6978
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
6979
|
+
|
|
6479
6980
|
// Same as above, but if there's a repo with the same name as cwd then
|
|
6480
6981
|
// default the selection to that name.
|
|
6481
|
-
const result = await handleApiCall(
|
|
6982
|
+
const result = await handleApiCall(sockSdk.getOrgRepoList(orgSlug, {
|
|
6482
6983
|
orgSlug,
|
|
6483
6984
|
sort: 'name',
|
|
6484
6985
|
direction: 'asc',
|
|
@@ -6488,6 +6989,7 @@ async function suggestRepoSlug(socketSdk, orgSlug) {
|
|
|
6488
6989
|
perPage: '10',
|
|
6489
6990
|
page: '0'
|
|
6490
6991
|
}), 'looking up known repos');
|
|
6992
|
+
|
|
6491
6993
|
// Ignore a failed request here. It was not the primary goal of
|
|
6492
6994
|
// running this command and reporting it only leads to end-user confusion.
|
|
6493
6995
|
if (result.success) {
|
|
@@ -6495,7 +6997,7 @@ async function suggestRepoSlug(socketSdk, orgSlug) {
|
|
|
6495
6997
|
let cwdIsKnown = !!currentDirName && result.data.results.some(obj => obj.slug === currentDirName);
|
|
6496
6998
|
if (!cwdIsKnown && currentDirName) {
|
|
6497
6999
|
// Do an explicit request so we can assert that the cwd exists or not
|
|
6498
|
-
const result = await handleApiCall(
|
|
7000
|
+
const result = await handleApiCall(sockSdk.getOrgRepo(orgSlug, currentDirName), 'checking if current cwd is a known repo');
|
|
6499
7001
|
if (result.success) {
|
|
6500
7002
|
cwdIsKnown = true;
|
|
6501
7003
|
}
|
|
@@ -6534,203 +7036,64 @@ async function suggestRepoSlug(socketSdk, orgSlug) {
|
|
|
6534
7036
|
}
|
|
6535
7037
|
});
|
|
6536
7038
|
return {
|
|
6537
|
-
slug: repoName,
|
|
6538
|
-
defaultBranch: repoDefaultBranch
|
|
6539
|
-
};
|
|
6540
|
-
}
|
|
6541
|
-
}
|
|
6542
|
-
}
|
|
6543
|
-
function dirNameToSlug(name) {
|
|
6544
|
-
// Uses slug specs asserted by our servers
|
|
6545
|
-
// Note: this can lead to collisions; eg. slug for `x--y` and `x---y` is `x-y`
|
|
6546
|
-
return name.toLowerCase().replace(/[^[a-zA-Z0-9_.-]/g, '_').replace(/--+/g, '-').replace(/__+/g, '_').replace(/\.\.+/g, '.').replace(/[._-]+$/, '');
|
|
6547
|
-
}
|
|
6548
|
-
|
|
6549
|
-
async function suggestBranchSlug(repoDefaultBranch) {
|
|
6550
|
-
const spawnResult = spawn.spawnSync('git', ['branch', '--show-current']);
|
|
6551
|
-
const currentBranch = spawnResult.stdout.toString('utf8').trim();
|
|
6552
|
-
if (currentBranch && spawnResult.status === 0) {
|
|
6553
|
-
const proceed = await prompts.select({
|
|
6554
|
-
message: 'Use the current git branch as target branch name?',
|
|
6555
|
-
choices: [{
|
|
6556
|
-
name: `Yes [${currentBranch}]`,
|
|
6557
|
-
value: currentBranch,
|
|
6558
|
-
description: 'Use the current git branch for branch name'
|
|
6559
|
-
}, ...(repoDefaultBranch && repoDefaultBranch !== currentBranch ? [{
|
|
6560
|
-
name: `No, use the default branch [${repoDefaultBranch}]`,
|
|
6561
|
-
value: repoDefaultBranch,
|
|
6562
|
-
description: 'Use the default branch for target repo as the target branch name'
|
|
6563
|
-
}] : []), {
|
|
6564
|
-
name: 'No',
|
|
6565
|
-
value: '',
|
|
6566
|
-
description: 'Do not use the current git branch as name (will end in a no-op)'
|
|
6567
|
-
}].filter(Boolean)
|
|
6568
|
-
});
|
|
6569
|
-
if (proceed) {
|
|
6570
|
-
return proceed;
|
|
6571
|
-
}
|
|
6572
|
-
}
|
|
6573
|
-
}
|
|
6574
|
-
|
|
6575
|
-
async function suggestTarget() {
|
|
6576
|
-
// We could prefill this with sub-dirs of the current
|
|
6577
|
-
// dir ... but is that going to be useful?
|
|
6578
|
-
const proceed = await prompts.select({
|
|
6579
|
-
message: 'No TARGET given. Do you want to use the current directory?',
|
|
6580
|
-
choices: [{
|
|
6581
|
-
name: 'Yes',
|
|
6582
|
-
value: true,
|
|
6583
|
-
description: 'Target the current directory'
|
|
6584
|
-
}, {
|
|
6585
|
-
name: 'No',
|
|
6586
|
-
value: false,
|
|
6587
|
-
description: 'Do not use the current directory (this will end in a no-op)'
|
|
6588
|
-
}]
|
|
6589
|
-
});
|
|
6590
|
-
if (proceed) {
|
|
6591
|
-
return ['.'];
|
|
6592
|
-
}
|
|
6593
|
-
}
|
|
6594
|
-
|
|
6595
|
-
async function createFullScan({
|
|
6596
|
-
branchName,
|
|
6597
|
-
commitHash: _commitHash,
|
|
6598
|
-
commitMessage,
|
|
6599
|
-
committers: _committers,
|
|
6600
|
-
cwd,
|
|
6601
|
-
defaultBranch,
|
|
6602
|
-
orgSlug,
|
|
6603
|
-
pendingHead,
|
|
6604
|
-
pullRequest: _pullRequest,
|
|
6605
|
-
readOnly,
|
|
6606
|
-
repoName,
|
|
6607
|
-
targets,
|
|
6608
|
-
tmp
|
|
6609
|
-
}) {
|
|
6610
|
-
// Lazily access constants.spinner.
|
|
6611
|
-
const {
|
|
6612
|
-
spinner
|
|
6613
|
-
} = constants;
|
|
6614
|
-
const socketSdk = await shadowNpmInject.setupSdk();
|
|
6615
|
-
const supportedFiles = await socketSdk.getReportSupportedFiles().then(res => {
|
|
6616
|
-
if (!res.success) {
|
|
6617
|
-
handleUnsuccessfulApiResponse('getReportSupportedFiles', res);
|
|
6618
|
-
assert(false, 'handleUnsuccessfulApiResponse should unconditionally throw');
|
|
6619
|
-
}
|
|
6620
|
-
return res.data;
|
|
6621
|
-
}).catch(cause => {
|
|
6622
|
-
throw new Error('Failed getting supported files for report', {
|
|
6623
|
-
cause
|
|
6624
|
-
});
|
|
6625
|
-
});
|
|
6626
|
-
|
|
6627
|
-
// If we updated any inputs then we should print the command line to repeat
|
|
6628
|
-
// the command without requiring user input, as a suggestion.
|
|
6629
|
-
let updatedInput = false;
|
|
6630
|
-
if (!targets.length) {
|
|
6631
|
-
const received = await suggestTarget();
|
|
6632
|
-
targets = received ?? [];
|
|
6633
|
-
updatedInput = true;
|
|
6634
|
-
}
|
|
6635
|
-
|
|
6636
|
-
// // TODO: we'll probably use socket.json or something else soon...
|
|
6637
|
-
// const absoluteConfigPath = path.join(cwd, 'socket.yml')
|
|
6638
|
-
// const socketConfig = await getSocketConfig(absoluteConfigPath)
|
|
6639
|
-
|
|
6640
|
-
const packagePaths = await shadowNpmPaths.getPackageFilesFullScans(cwd, targets, supportedFiles
|
|
6641
|
-
// socketConfig
|
|
6642
|
-
);
|
|
6643
|
-
|
|
6644
|
-
// We're going to need an api token to suggest data because those suggestions
|
|
6645
|
-
// must come from data we already know. Don't error on missing api token yet.
|
|
6646
|
-
// If the api-token is not set, ignore it for the sake of suggestions.
|
|
6647
|
-
const apiToken = shadowNpmInject.getDefaultToken();
|
|
6648
|
-
|
|
6649
|
-
// If the current cwd is unknown and is used as a repo slug anyways, we will
|
|
6650
|
-
// first need to register the slug before we can use it.
|
|
6651
|
-
let repoDefaultBranch = '';
|
|
6652
|
-
if (apiToken) {
|
|
6653
|
-
if (!orgSlug) {
|
|
6654
|
-
const suggestion = await suggestOrgSlug(socketSdk);
|
|
6655
|
-
if (suggestion) orgSlug = suggestion;
|
|
6656
|
-
updatedInput = true;
|
|
6657
|
-
}
|
|
6658
|
-
|
|
6659
|
-
// (Don't bother asking for the rest if we didn't get an org slug above)
|
|
6660
|
-
if (orgSlug && !repoName) {
|
|
6661
|
-
const suggestion = await suggestRepoSlug(socketSdk, orgSlug);
|
|
6662
|
-
if (suggestion) {
|
|
6663
|
-
repoDefaultBranch = suggestion.defaultBranch;
|
|
6664
|
-
repoName = suggestion.slug;
|
|
6665
|
-
}
|
|
6666
|
-
updatedInput = true;
|
|
6667
|
-
}
|
|
6668
|
-
|
|
6669
|
-
// (Don't bother asking for the rest if we didn't get an org/repo above)
|
|
6670
|
-
if (orgSlug && repoName && !branchName) {
|
|
6671
|
-
const suggestion = await suggestBranchSlug(repoDefaultBranch);
|
|
6672
|
-
if (suggestion) branchName = suggestion;
|
|
6673
|
-
updatedInput = true;
|
|
7039
|
+
slug: repoName,
|
|
7040
|
+
defaultBranch: repoDefaultBranch
|
|
7041
|
+
};
|
|
6674
7042
|
}
|
|
7043
|
+
} else {
|
|
7044
|
+
logger.logger.fail('Failed to lookup repo list from API, unable to suggest.');
|
|
6675
7045
|
}
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
|
|
6683
|
-
|
|
6684
|
-
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6685
|
-
|
|
6686
|
-
- Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6687
|
-
|
|
6688
|
-
- Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6689
|
-
|
|
6690
|
-
- 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)')}
|
|
7046
|
+
}
|
|
7047
|
+
function dirNameToSlug(name) {
|
|
7048
|
+
// Uses slug specs asserted by our servers
|
|
7049
|
+
// Note: this can lead to collisions; eg. slug for `x--y` and `x---y` is `x-y`
|
|
7050
|
+
return name.toLowerCase().replace(/[^[a-zA-Z0-9_.-]/g, '_').replace(/--+/g, '-').replace(/__+/g, '_').replace(/\.\.+/g, '.').replace(/[._-]+$/, '');
|
|
7051
|
+
}
|
|
6691
7052
|
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
set_as_pending_head: String(pendingHead),
|
|
6716
|
-
tmp: String(tmp)
|
|
6717
|
-
}, packagePaths, cwd), 'Creating scan');
|
|
6718
|
-
if (!result.success) {
|
|
6719
|
-
handleUnsuccessfulApiResponse('CreateOrgFullScan', result);
|
|
6720
|
-
return;
|
|
7053
|
+
async function suggestBranchSlug(repoDefaultBranch) {
|
|
7054
|
+
const spawnResult = spawn.spawnSync('git', ['branch', '--show-current']);
|
|
7055
|
+
const currentBranch = spawnResult.stdout.toString('utf8').trim();
|
|
7056
|
+
if (currentBranch && spawnResult.status === 0) {
|
|
7057
|
+
const proceed = await prompts.select({
|
|
7058
|
+
message: 'Use the current git branch as target branch name?',
|
|
7059
|
+
choices: [{
|
|
7060
|
+
name: `Yes [${currentBranch}]`,
|
|
7061
|
+
value: currentBranch,
|
|
7062
|
+
description: 'Use the current git branch for branch name'
|
|
7063
|
+
}, ...(repoDefaultBranch && repoDefaultBranch !== currentBranch ? [{
|
|
7064
|
+
name: `No, use the default branch [${repoDefaultBranch}]`,
|
|
7065
|
+
value: repoDefaultBranch,
|
|
7066
|
+
description: 'Use the default branch for target repo as the target branch name'
|
|
7067
|
+
}] : []), {
|
|
7068
|
+
name: 'No',
|
|
7069
|
+
value: '',
|
|
7070
|
+
description: 'Do not use the current git branch as name (will end in a no-op)'
|
|
7071
|
+
}].filter(Boolean)
|
|
7072
|
+
});
|
|
7073
|
+
if (proceed) {
|
|
7074
|
+
return proceed;
|
|
7075
|
+
}
|
|
6721
7076
|
}
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
7077
|
+
}
|
|
7078
|
+
|
|
7079
|
+
async function suggestTarget() {
|
|
7080
|
+
// We could prefill this with sub-dirs of the current
|
|
7081
|
+
// dir ... but is that going to be useful?
|
|
7082
|
+
const proceed = await prompts.select({
|
|
7083
|
+
message: 'No TARGET given. Do you want to use the current directory?',
|
|
7084
|
+
choices: [{
|
|
7085
|
+
name: 'Yes',
|
|
7086
|
+
value: true,
|
|
7087
|
+
description: 'Target the current directory'
|
|
7088
|
+
}, {
|
|
7089
|
+
name: 'No',
|
|
7090
|
+
value: false,
|
|
7091
|
+
description: 'Do not use the current directory (this will end in a no-op)'
|
|
7092
|
+
}]
|
|
6728
7093
|
});
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
await vendor.open(`${result.data.html_report_url}`);
|
|
7094
|
+
if (proceed) {
|
|
7095
|
+
return ['.'];
|
|
6732
7096
|
}
|
|
6733
|
-
rl.close();
|
|
6734
7097
|
}
|
|
6735
7098
|
|
|
6736
7099
|
const {
|
|
@@ -6854,18 +7217,66 @@ async function run$7(argv, importMeta, {
|
|
|
6854
7217
|
importMeta,
|
|
6855
7218
|
parentName
|
|
6856
7219
|
});
|
|
6857
|
-
const [orgSlug = '', ...targets] = cli.input;
|
|
6858
|
-
const cwd = cli.flags['cwd'] && cli.flags['cwd'] !== 'process.cwd()' ? String(cli.flags['cwd']) : process$1.cwd();
|
|
6859
7220
|
const {
|
|
7221
|
+
cwd: cwdOverride,
|
|
7222
|
+
dryRun
|
|
7223
|
+
} = cli.flags;
|
|
7224
|
+
const cwd = cwdOverride && cwdOverride !== 'process.cwd()' ? String(cwdOverride) : process$1.cwd();
|
|
7225
|
+
let {
|
|
6860
7226
|
branch: branchName,
|
|
6861
7227
|
repo: repoName
|
|
6862
7228
|
} = cli.flags;
|
|
6863
|
-
|
|
7229
|
+
let [orgSlug = '', ...targets] = cli.input;
|
|
6864
7230
|
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
7231
|
+
// We're going to need an api token to suggest data because those suggestions
|
|
7232
|
+
// must come from data we already know. Don't error on missing api token yet.
|
|
7233
|
+
// If the api-token is not set, ignore it for the sake of suggestions.
|
|
7234
|
+
const apiToken = shadowNpmInject.getDefaultToken();
|
|
7235
|
+
|
|
7236
|
+
// If we updated any inputs then we should print the command line to repeat
|
|
7237
|
+
// the command without requiring user input, as a suggestion.
|
|
7238
|
+
let updatedInput = false;
|
|
7239
|
+
if (!targets.length && !dryRun) {
|
|
7240
|
+
const received = await suggestTarget();
|
|
7241
|
+
targets = received ?? [];
|
|
7242
|
+
updatedInput = true;
|
|
7243
|
+
}
|
|
7244
|
+
|
|
7245
|
+
// If the current cwd is unknown and is used as a repo slug anyways, we will
|
|
7246
|
+
// first need to register the slug before we can use it.
|
|
7247
|
+
let repoDefaultBranch = '';
|
|
7248
|
+
// Only do suggestions with an apiToken and when not in dryRun mode
|
|
7249
|
+
if (apiToken && !dryRun) {
|
|
7250
|
+
if (!orgSlug) {
|
|
7251
|
+
const suggestion = await suggestOrgSlug();
|
|
7252
|
+
if (suggestion) orgSlug = suggestion;
|
|
7253
|
+
updatedInput = true;
|
|
7254
|
+
}
|
|
7255
|
+
|
|
7256
|
+
// (Don't bother asking for the rest if we didn't get an org slug above)
|
|
7257
|
+
if (orgSlug && !repoName) {
|
|
7258
|
+
const suggestion = await suggestRepoSlug(orgSlug);
|
|
7259
|
+
if (suggestion) {
|
|
7260
|
+
repoDefaultBranch = suggestion.defaultBranch;
|
|
7261
|
+
repoName = suggestion.slug;
|
|
7262
|
+
}
|
|
7263
|
+
updatedInput = true;
|
|
7264
|
+
}
|
|
7265
|
+
|
|
7266
|
+
// (Don't bother asking for the rest if we didn't get an org/repo above)
|
|
7267
|
+
if (orgSlug && repoName && !branchName) {
|
|
7268
|
+
const suggestion = await suggestBranchSlug(repoDefaultBranch);
|
|
7269
|
+
if (suggestion) branchName = suggestion;
|
|
7270
|
+
updatedInput = true;
|
|
7271
|
+
}
|
|
7272
|
+
}
|
|
7273
|
+
if (updatedInput && repoName && branchName && orgSlug && targets?.length) {
|
|
7274
|
+
logger.logger.error('Note: You can invoke this command next time to skip the interactive questions:');
|
|
7275
|
+
logger.logger.error('```');
|
|
7276
|
+
logger.logger.error(` socket scan create [other flags...] --repo ${repoName} --branch ${branchName} ${orgSlug} ${targets.join(' ')}`);
|
|
7277
|
+
logger.logger.error('```\n');
|
|
7278
|
+
}
|
|
7279
|
+
if (!orgSlug || !repoName || !branchName || !targets.length) {
|
|
6869
7280
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
6870
7281
|
// options or missing arguments.
|
|
6871
7282
|
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
@@ -6879,28 +7290,25 @@ async function run$7(argv, importMeta, {
|
|
|
6879
7290
|
|
|
6880
7291
|
- Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6881
7292
|
|
|
6882
|
-
- At least one TARGET (e.g. \`.\` or \`./package.json\`) ${!targets.length ? '(missing)' : colors.green('(ok)')}
|
|
7293
|
+
- At least one TARGET (e.g. \`.\` or \`./package.json\`) ${!targets.length ? colors.red('(missing)') : colors.green('(ok)')}
|
|
6883
7294
|
|
|
6884
|
-
|
|
7295
|
+
${!apiToken ? 'Note: was unable to make suggestions because no API Token was found; this would make the command fail regardless' : ''}
|
|
6885
7296
|
`);
|
|
6886
7297
|
return;
|
|
6887
7298
|
}
|
|
6888
7299
|
|
|
6889
7300
|
// Note exiting earlier to skirt a hidden auth requirement
|
|
6890
|
-
if (
|
|
7301
|
+
if (dryRun) {
|
|
6891
7302
|
logger.logger.log(DRY_RUN_BAIL_TEXT$7);
|
|
6892
7303
|
return;
|
|
6893
7304
|
}
|
|
6894
|
-
await
|
|
7305
|
+
await handleCreateNewScan({
|
|
6895
7306
|
branchName: branchName,
|
|
6896
|
-
commitHash: cli.flags['commitHash'] ?? '',
|
|
6897
7307
|
commitMessage: cli.flags['commitMessage'] ?? '',
|
|
6898
|
-
committers: cli.flags['committers'] ?? '',
|
|
6899
7308
|
cwd,
|
|
6900
7309
|
defaultBranch: Boolean(cli.flags['defaultBranch']),
|
|
6901
7310
|
orgSlug,
|
|
6902
7311
|
pendingHead: Boolean(cli.flags['pendingHead']),
|
|
6903
|
-
pullRequest: cli.flags['pullRequest'] ?? undefined,
|
|
6904
7312
|
readOnly: Boolean(cli.flags['readOnly']),
|
|
6905
7313
|
repoName: repoName,
|
|
6906
7314
|
targets,
|
|
@@ -6908,26 +7316,37 @@ async function run$7(argv, importMeta, {
|
|
|
6908
7316
|
});
|
|
6909
7317
|
}
|
|
6910
7318
|
|
|
6911
|
-
async function
|
|
7319
|
+
async function fetchDeleteOrgFullScan(orgSlug, scanId) {
|
|
6912
7320
|
const apiToken = shadowNpmInject.getDefaultToken();
|
|
6913
7321
|
if (!apiToken) {
|
|
6914
7322
|
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.');
|
|
6915
7323
|
}
|
|
6916
|
-
await
|
|
7324
|
+
await fetchDeleteOrgFullScanWithToken(apiToken, orgSlug, scanId);
|
|
6917
7325
|
}
|
|
6918
|
-
async function
|
|
7326
|
+
async function fetchDeleteOrgFullScanWithToken(apiToken, orgSlug, scanId) {
|
|
6919
7327
|
// Lazily access constants.spinner.
|
|
6920
7328
|
const {
|
|
6921
7329
|
spinner
|
|
6922
7330
|
} = constants;
|
|
6923
|
-
|
|
6924
|
-
|
|
6925
|
-
const result = await handleApiCall(
|
|
7331
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
7332
|
+
spinner.start('Requesting the scan to be deleted...');
|
|
7333
|
+
const result = await handleApiCall(sockSdk.deleteOrgFullScan(orgSlug, scanId), 'Deleting scan');
|
|
7334
|
+
spinner.successAndStop('Received response for deleting a scan.');
|
|
6926
7335
|
if (!result.success) {
|
|
6927
7336
|
handleUnsuccessfulApiResponse('deleteOrgFullScan', result);
|
|
6928
7337
|
return;
|
|
6929
7338
|
}
|
|
6930
|
-
|
|
7339
|
+
return result.data;
|
|
7340
|
+
}
|
|
7341
|
+
|
|
7342
|
+
async function outputDeleteScan(_data) {
|
|
7343
|
+
logger.logger.success('Scan deleted successfully');
|
|
7344
|
+
}
|
|
7345
|
+
|
|
7346
|
+
async function handleDeleteScan(orgSlug, scanId) {
|
|
7347
|
+
const data = await fetchDeleteOrgFullScan(orgSlug, scanId);
|
|
7348
|
+
if (!data) return;
|
|
7349
|
+
await outputDeleteScan();
|
|
6931
7350
|
}
|
|
6932
7351
|
|
|
6933
7352
|
const {
|
|
@@ -6966,8 +7385,8 @@ async function run$6(argv, importMeta, {
|
|
|
6966
7385
|
importMeta,
|
|
6967
7386
|
parentName
|
|
6968
7387
|
});
|
|
6969
|
-
const [orgSlug = '',
|
|
6970
|
-
if (!orgSlug || !
|
|
7388
|
+
const [orgSlug = '', scanId = ''] = cli.input;
|
|
7389
|
+
if (!orgSlug || !scanId) {
|
|
6971
7390
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
6972
7391
|
// options or missing arguments.
|
|
6973
7392
|
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
@@ -6976,22 +7395,20 @@ async function run$6(argv, importMeta, {
|
|
|
6976
7395
|
|
|
6977
7396
|
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6978
7397
|
|
|
6979
|
-
- Full Scan ID to delete as second argument ${!
|
|
7398
|
+
- Full Scan ID to delete as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
|
|
6980
7399
|
return;
|
|
6981
7400
|
}
|
|
6982
7401
|
if (cli.flags['dryRun']) {
|
|
6983
7402
|
logger.logger.log(DRY_RUN_BAIL_TEXT$6);
|
|
6984
7403
|
return;
|
|
6985
7404
|
}
|
|
6986
|
-
await
|
|
7405
|
+
await handleDeleteScan(orgSlug, scanId);
|
|
6987
7406
|
}
|
|
6988
7407
|
|
|
6989
|
-
|
|
6990
|
-
async function listFullScans({
|
|
7408
|
+
async function fetchListScans({
|
|
6991
7409
|
direction,
|
|
6992
7410
|
from_time,
|
|
6993
7411
|
orgSlug,
|
|
6994
|
-
outputKind,
|
|
6995
7412
|
page,
|
|
6996
7413
|
per_page,
|
|
6997
7414
|
sort
|
|
@@ -7000,23 +7417,19 @@ async function listFullScans({
|
|
|
7000
7417
|
if (!apiToken) {
|
|
7001
7418
|
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.');
|
|
7002
7419
|
}
|
|
7003
|
-
await
|
|
7004
|
-
apiToken,
|
|
7420
|
+
await fetchListScansWithToken(apiToken, {
|
|
7005
7421
|
direction,
|
|
7006
7422
|
from_time,
|
|
7007
7423
|
orgSlug,
|
|
7008
|
-
outputKind,
|
|
7009
7424
|
page,
|
|
7010
7425
|
per_page,
|
|
7011
7426
|
sort
|
|
7012
7427
|
});
|
|
7013
7428
|
}
|
|
7014
|
-
async function
|
|
7015
|
-
apiToken,
|
|
7429
|
+
async function fetchListScansWithToken(apiToken, {
|
|
7016
7430
|
direction,
|
|
7017
7431
|
from_time,
|
|
7018
7432
|
orgSlug,
|
|
7019
|
-
outputKind,
|
|
7020
7433
|
page,
|
|
7021
7434
|
per_page,
|
|
7022
7435
|
sort
|
|
@@ -7025,22 +7438,27 @@ async function listFullScansWithToken({
|
|
|
7025
7438
|
const {
|
|
7026
7439
|
spinner
|
|
7027
7440
|
} = constants;
|
|
7441
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
7028
7442
|
spinner.start('Fetching list of scans...');
|
|
7029
|
-
const
|
|
7030
|
-
const result = await handleApiCall(socketSdk.getOrgFullScanList(orgSlug, {
|
|
7443
|
+
const result = await handleApiCall(sockSdk.getOrgFullScanList(orgSlug, {
|
|
7031
7444
|
sort,
|
|
7032
7445
|
direction,
|
|
7033
7446
|
per_page: String(per_page),
|
|
7034
7447
|
page: String(page),
|
|
7035
7448
|
from: from_time
|
|
7036
7449
|
}), 'Listing scans');
|
|
7450
|
+
spinner.successAndStop(`Received response for list of scans.`);
|
|
7037
7451
|
if (!result.success) {
|
|
7038
7452
|
handleUnsuccessfulApiResponse('getOrgFullScanList', result);
|
|
7039
7453
|
return;
|
|
7040
7454
|
}
|
|
7041
|
-
|
|
7455
|
+
return result.data;
|
|
7456
|
+
}
|
|
7457
|
+
|
|
7458
|
+
// @ts-ignore
|
|
7459
|
+
async function outputListScans(data, outputKind) {
|
|
7042
7460
|
if (outputKind === 'json') {
|
|
7043
|
-
logger.logger.log(
|
|
7461
|
+
logger.logger.log(data);
|
|
7044
7462
|
return;
|
|
7045
7463
|
}
|
|
7046
7464
|
const options = {
|
|
@@ -7058,7 +7476,7 @@ async function listFullScansWithToken({
|
|
|
7058
7476
|
name: colors.magenta('Created at')
|
|
7059
7477
|
}]
|
|
7060
7478
|
};
|
|
7061
|
-
const formattedResults =
|
|
7479
|
+
const formattedResults = data.results.map(d => {
|
|
7062
7480
|
return {
|
|
7063
7481
|
id: d.id,
|
|
7064
7482
|
report_url: colors.underline(`${d.html_report_url}`),
|
|
@@ -7073,6 +7491,27 @@ async function listFullScansWithToken({
|
|
|
7073
7491
|
logger.logger.log(chalkTable(options, formattedResults));
|
|
7074
7492
|
}
|
|
7075
7493
|
|
|
7494
|
+
async function handleListScans({
|
|
7495
|
+
direction,
|
|
7496
|
+
from_time,
|
|
7497
|
+
orgSlug,
|
|
7498
|
+
outputKind,
|
|
7499
|
+
page,
|
|
7500
|
+
per_page,
|
|
7501
|
+
sort
|
|
7502
|
+
}) {
|
|
7503
|
+
const data = await fetchListScans({
|
|
7504
|
+
direction,
|
|
7505
|
+
from_time,
|
|
7506
|
+
orgSlug,
|
|
7507
|
+
page,
|
|
7508
|
+
per_page,
|
|
7509
|
+
sort
|
|
7510
|
+
});
|
|
7511
|
+
if (!data) return;
|
|
7512
|
+
await outputListScans(data, outputKind);
|
|
7513
|
+
}
|
|
7514
|
+
|
|
7076
7515
|
const {
|
|
7077
7516
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$5
|
|
7078
7517
|
} = constants;
|
|
@@ -7160,7 +7599,7 @@ async function run$5(argv, importMeta, {
|
|
|
7160
7599
|
logger.logger.log(DRY_RUN_BAIL_TEXT$5);
|
|
7161
7600
|
return;
|
|
7162
7601
|
}
|
|
7163
|
-
await
|
|
7602
|
+
await handleListScans({
|
|
7164
7603
|
direction: String(cli.flags['direction'] || ''),
|
|
7165
7604
|
from_time: String(cli.flags['fromTime'] || ''),
|
|
7166
7605
|
orgSlug,
|
|
@@ -7171,46 +7610,56 @@ async function run$5(argv, importMeta, {
|
|
|
7171
7610
|
});
|
|
7172
7611
|
}
|
|
7173
7612
|
|
|
7174
|
-
async function
|
|
7613
|
+
async function fetchScanMetadata(orgSlug, scanId) {
|
|
7175
7614
|
const apiToken = shadowNpmInject.getDefaultToken();
|
|
7176
7615
|
if (!apiToken) {
|
|
7177
7616
|
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.');
|
|
7178
7617
|
}
|
|
7179
|
-
await
|
|
7618
|
+
await fetchScanMetadataWithToken(apiToken, orgSlug, scanId);
|
|
7180
7619
|
}
|
|
7181
|
-
async function
|
|
7620
|
+
async function fetchScanMetadataWithToken(apiToken, orgSlug, scanId) {
|
|
7182
7621
|
// Lazily access constants.spinner.
|
|
7183
7622
|
const {
|
|
7184
7623
|
spinner
|
|
7185
7624
|
} = constants;
|
|
7625
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
7186
7626
|
spinner.start('Fetching meta data for a full scan...');
|
|
7187
|
-
const
|
|
7188
|
-
|
|
7627
|
+
const result = await handleApiCall(sockSdk.getOrgFullScanMetadata(orgSlug, scanId), 'Listing scans');
|
|
7628
|
+
spinner.successAndStop('Received response for scan meta data.');
|
|
7189
7629
|
if (!result.success) {
|
|
7190
7630
|
handleUnsuccessfulApiResponse('getOrgFullScanMetadata', result);
|
|
7191
7631
|
return;
|
|
7192
7632
|
}
|
|
7193
|
-
|
|
7633
|
+
return result.data;
|
|
7634
|
+
}
|
|
7635
|
+
|
|
7636
|
+
async function outputScanMetadata(data, scanId, outputKind) {
|
|
7194
7637
|
if (outputKind === 'json') {
|
|
7195
|
-
logger.logger.log(
|
|
7638
|
+
logger.logger.log(data);
|
|
7196
7639
|
} else {
|
|
7197
7640
|
// Markdown = print
|
|
7198
7641
|
if (outputKind === 'markdown') {
|
|
7199
7642
|
logger.logger.log('# Scan meta data\n');
|
|
7200
7643
|
}
|
|
7201
7644
|
logger.logger.log(`Scan ID: ${scanId}\n`);
|
|
7202
|
-
for (const [key, value] of Object.entries(
|
|
7645
|
+
for (const [key, value] of Object.entries(data)) {
|
|
7203
7646
|
if (['id', 'updated_at', 'organization_id', 'repository_id', 'commit_hash', 'html_report_url'].includes(key)) continue;
|
|
7204
7647
|
logger.logger.log(`- ${key}:`, value);
|
|
7205
7648
|
}
|
|
7206
7649
|
if (outputKind === 'markdown') {
|
|
7207
|
-
logger.logger.log(`\nYou can view this report at: [${
|
|
7650
|
+
logger.logger.log(`\nYou can view this report at: [${data.html_report_url}](${data.html_report_url})\n`);
|
|
7208
7651
|
} else {
|
|
7209
|
-
logger.logger.log(`\nYou can view this report at: ${
|
|
7652
|
+
logger.logger.log(`\nYou can view this report at: ${data.html_report_url}]\n`);
|
|
7210
7653
|
}
|
|
7211
7654
|
}
|
|
7212
7655
|
}
|
|
7213
7656
|
|
|
7657
|
+
async function handleOrgScanMetadata(orgSlug, scanId, outputKind) {
|
|
7658
|
+
const data = await fetchScanMetadata(orgSlug, scanId);
|
|
7659
|
+
if (!data) return;
|
|
7660
|
+
await outputScanMetadata(data, scanId, outputKind);
|
|
7661
|
+
}
|
|
7662
|
+
|
|
7214
7663
|
const {
|
|
7215
7664
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$4
|
|
7216
7665
|
} = constants;
|
|
@@ -7247,8 +7696,8 @@ async function run$4(argv, importMeta, {
|
|
|
7247
7696
|
importMeta,
|
|
7248
7697
|
parentName
|
|
7249
7698
|
});
|
|
7250
|
-
const [orgSlug = '',
|
|
7251
|
-
if (!orgSlug || !
|
|
7699
|
+
const [orgSlug = '', scanId = ''] = cli.input;
|
|
7700
|
+
if (!orgSlug || !scanId) {
|
|
7252
7701
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
7253
7702
|
// options or missing arguments.
|
|
7254
7703
|
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
@@ -7257,14 +7706,14 @@ async function run$4(argv, importMeta, {
|
|
|
7257
7706
|
|
|
7258
7707
|
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7259
7708
|
|
|
7260
|
-
- Full Scan ID to inspect as second argument ${!
|
|
7709
|
+
- Full Scan ID to inspect as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
|
|
7261
7710
|
return;
|
|
7262
7711
|
}
|
|
7263
7712
|
if (cli.flags['dryRun']) {
|
|
7264
7713
|
logger.logger.log(DRY_RUN_BAIL_TEXT$4);
|
|
7265
7714
|
return;
|
|
7266
7715
|
}
|
|
7267
|
-
await
|
|
7716
|
+
await handleOrgScanMetadata(orgSlug, scanId, cli.flags['json'] ? 'json' : cli.flags['markdown'] ? 'markdown' : 'print');
|
|
7268
7717
|
}
|
|
7269
7718
|
|
|
7270
7719
|
/**
|
|
@@ -7272,7 +7721,7 @@ async function run$4(argv, importMeta, {
|
|
|
7272
7721
|
* full scan ID.
|
|
7273
7722
|
* It can optionally only fetch the security or license side of things.
|
|
7274
7723
|
*/
|
|
7275
|
-
async function fetchReportData(orgSlug,
|
|
7724
|
+
async function fetchReportData(orgSlug, scanId,
|
|
7276
7725
|
// includeLicensePolicy: boolean,
|
|
7277
7726
|
includeSecurityPolicy) {
|
|
7278
7727
|
let haveScan = false;
|
|
@@ -7309,18 +7758,18 @@ includeSecurityPolicy) {
|
|
|
7309
7758
|
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.');
|
|
7310
7759
|
}
|
|
7311
7760
|
updateProgress();
|
|
7312
|
-
const
|
|
7761
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
7313
7762
|
|
|
7314
7763
|
// @ts-ignore
|
|
7315
7764
|
const [scan,
|
|
7316
7765
|
// licensePolicyMaybe,
|
|
7317
7766
|
securityPolicyMaybe] = await Promise.all([(async () => {
|
|
7318
7767
|
try {
|
|
7319
|
-
const response = await
|
|
7768
|
+
const response = await queryApi(`orgs/${orgSlug}/full-scans/${encodeURIComponent(scanId)}`, apiToken);
|
|
7320
7769
|
haveScan = true;
|
|
7321
7770
|
updateProgress();
|
|
7322
7771
|
if (!response.ok) {
|
|
7323
|
-
const err = await
|
|
7772
|
+
const err = await handleApiError(response.status);
|
|
7324
7773
|
logger.logger.fail(`${colors.bgRed(colors.white(response.statusText))}: Fetch error: ${err}`);
|
|
7325
7774
|
return undefined;
|
|
7326
7775
|
}
|
|
@@ -7342,7 +7791,7 @@ includeSecurityPolicy) {
|
|
|
7342
7791
|
})(),
|
|
7343
7792
|
// includeLicensePolicy &&
|
|
7344
7793
|
// (async () => {
|
|
7345
|
-
// const r = await
|
|
7794
|
+
// const r = await sockSdk.getOrgSecurityPolicy(orgSlug)
|
|
7346
7795
|
// haveLicensePolicy = true
|
|
7347
7796
|
// updateProgress()
|
|
7348
7797
|
// return await handleApiCall(
|
|
@@ -7351,7 +7800,7 @@ includeSecurityPolicy) {
|
|
|
7351
7800
|
// )
|
|
7352
7801
|
// })(),
|
|
7353
7802
|
includeSecurityPolicy && (async () => {
|
|
7354
|
-
const r = await
|
|
7803
|
+
const r = await sockSdk.getOrgSecurityPolicy(orgSlug);
|
|
7355
7804
|
haveSecurityPolicy = true;
|
|
7356
7805
|
updateProgress();
|
|
7357
7806
|
return await handleApiCall(r, "looking up organization's security policy");
|
|
@@ -7597,40 +8046,31 @@ function* walkNestedMap(map, keys = []) {
|
|
|
7597
8046
|
}
|
|
7598
8047
|
}
|
|
7599
8048
|
|
|
7600
|
-
async function
|
|
8049
|
+
async function outputScanReport(scan,
|
|
8050
|
+
// licensePolicy: undefined | SocketSdkReturnType<'getOrgSecurityPolicy'>,
|
|
8051
|
+
securityPolicy, {
|
|
7601
8052
|
filePath,
|
|
7602
8053
|
fold,
|
|
7603
|
-
fullScanId,
|
|
7604
8054
|
includeLicensePolicy,
|
|
7605
8055
|
includeSecurityPolicy,
|
|
7606
8056
|
orgSlug,
|
|
7607
8057
|
outputKind,
|
|
7608
8058
|
reportLevel,
|
|
8059
|
+
scanId,
|
|
7609
8060
|
short
|
|
7610
8061
|
}) {
|
|
7611
|
-
logger.logger.error('output:', outputKind, ', file:', filePath, ', fold:', fold, ', reportLevel:', reportLevel);
|
|
7612
8062
|
if (!includeSecurityPolicy) {
|
|
8063
|
+
process.exitCode = 1;
|
|
7613
8064
|
return; // caller should assert
|
|
7614
8065
|
}
|
|
7615
|
-
const {
|
|
7616
|
-
// licensePolicy,
|
|
7617
|
-
ok,
|
|
7618
|
-
scan,
|
|
7619
|
-
securityPolicy
|
|
7620
|
-
} = await fetchReportData(orgSlug, fullScanId,
|
|
7621
|
-
// includeLicensePolicy
|
|
7622
|
-
includeSecurityPolicy);
|
|
7623
|
-
if (!ok) {
|
|
7624
|
-
return;
|
|
7625
|
-
}
|
|
7626
8066
|
const scanReport = generateReport(scan, undefined,
|
|
7627
8067
|
// licensePolicy,
|
|
7628
8068
|
securityPolicy, {
|
|
7629
8069
|
orgSlug,
|
|
7630
|
-
scanId
|
|
8070
|
+
scanId,
|
|
7631
8071
|
fold,
|
|
7632
|
-
|
|
7633
|
-
|
|
8072
|
+
reportLevel,
|
|
8073
|
+
short
|
|
7634
8074
|
});
|
|
7635
8075
|
if (!scanReport.healthy) {
|
|
7636
8076
|
process.exitCode = 1;
|
|
@@ -7717,6 +8157,43 @@ ${!report.alerts.size ? '' : mdTable(flatData, ['Policy', 'Alert Type', 'Package
|
|
|
7717
8157
|
return md;
|
|
7718
8158
|
}
|
|
7719
8159
|
|
|
8160
|
+
async function handleScanReport({
|
|
8161
|
+
filePath,
|
|
8162
|
+
fold,
|
|
8163
|
+
includeLicensePolicy,
|
|
8164
|
+
includeSecurityPolicy,
|
|
8165
|
+
orgSlug,
|
|
8166
|
+
outputKind,
|
|
8167
|
+
reportLevel,
|
|
8168
|
+
scanId,
|
|
8169
|
+
short
|
|
8170
|
+
}) {
|
|
8171
|
+
if (!includeSecurityPolicy) {
|
|
8172
|
+
process.exitCode = 1;
|
|
8173
|
+
return; // caller should assert
|
|
8174
|
+
}
|
|
8175
|
+
const {
|
|
8176
|
+
// licensePolicy,
|
|
8177
|
+
ok,
|
|
8178
|
+
scan,
|
|
8179
|
+
securityPolicy
|
|
8180
|
+
} = await fetchReportData(orgSlug, scanId,
|
|
8181
|
+
// includeLicensePolicy
|
|
8182
|
+
includeSecurityPolicy);
|
|
8183
|
+
if (!ok) return;
|
|
8184
|
+
await outputScanReport(scan, securityPolicy, {
|
|
8185
|
+
filePath,
|
|
8186
|
+
fold,
|
|
8187
|
+
scanId: scanId,
|
|
8188
|
+
includeLicensePolicy,
|
|
8189
|
+
includeSecurityPolicy,
|
|
8190
|
+
orgSlug,
|
|
8191
|
+
outputKind,
|
|
8192
|
+
reportLevel,
|
|
8193
|
+
short
|
|
8194
|
+
});
|
|
8195
|
+
}
|
|
8196
|
+
|
|
7720
8197
|
const {
|
|
7721
8198
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$3
|
|
7722
8199
|
} = constants;
|
|
@@ -7803,8 +8280,8 @@ async function run$3(argv, importMeta, {
|
|
|
7803
8280
|
reportLevel = 'warn',
|
|
7804
8281
|
security
|
|
7805
8282
|
} = cli.flags;
|
|
7806
|
-
const [orgSlug = '',
|
|
7807
|
-
if (!orgSlug || !
|
|
8283
|
+
const [orgSlug = '', scanId = '', file = '-'] = cli.input;
|
|
8284
|
+
if (!orgSlug || !scanId ||
|
|
7808
8285
|
// (!license && !security) ||
|
|
7809
8286
|
json && markdown) {
|
|
7810
8287
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
@@ -7816,7 +8293,7 @@ async function run$3(argv, importMeta, {
|
|
|
7816
8293
|
|
|
7817
8294
|
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7818
8295
|
|
|
7819
|
-
- Full Scan ID to fetch as second argument ${!
|
|
8296
|
+
- Full Scan ID to fetch as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7820
8297
|
|
|
7821
8298
|
- Not both the --json and --markdown flags ${json && markdown ? colors.red('(pick one!)') : colors.green('(ok)')}
|
|
7822
8299
|
`
|
|
@@ -7828,9 +8305,9 @@ async function run$3(argv, importMeta, {
|
|
|
7828
8305
|
logger.logger.log(DRY_RUN_BAIL_TEXT$3);
|
|
7829
8306
|
return;
|
|
7830
8307
|
}
|
|
7831
|
-
await
|
|
8308
|
+
await handleScanReport({
|
|
7832
8309
|
orgSlug,
|
|
7833
|
-
|
|
8310
|
+
scanId: scanId,
|
|
7834
8311
|
includeLicensePolicy: false,
|
|
7835
8312
|
// !!license,
|
|
7836
8313
|
includeSecurityPolicy: typeof security === 'boolean' ? security : true,
|
|
@@ -7842,29 +8319,7 @@ async function run$3(argv, importMeta, {
|
|
|
7842
8319
|
});
|
|
7843
8320
|
}
|
|
7844
8321
|
|
|
7845
|
-
async function
|
|
7846
|
-
// Lazily access constants.spinner.
|
|
7847
|
-
const {
|
|
7848
|
-
spinner
|
|
7849
|
-
} = constants;
|
|
7850
|
-
const apiToken = shadowNpmInject.getDefaultToken();
|
|
7851
|
-
if (!apiToken) {
|
|
7852
|
-
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.');
|
|
7853
|
-
}
|
|
7854
|
-
spinner.start('Fetching scan...');
|
|
7855
|
-
const socketSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
7856
|
-
const data = await handleApiCall(socketSdk.getOrgFullScan(orgSlug, fullScanId, file === '-' ? undefined : file), 'Fetching a scan');
|
|
7857
|
-
if (!data?.success) {
|
|
7858
|
-
handleUnsuccessfulApiResponse('getOrgFullScan', data);
|
|
7859
|
-
return;
|
|
7860
|
-
}
|
|
7861
|
-
spinner?.successAndStop(file ? `Full scan details written to ${file}` : 'stdout');
|
|
7862
|
-
return data;
|
|
7863
|
-
}
|
|
7864
|
-
|
|
7865
|
-
async function viewFullScan(orgSlug, fullScanId, filePath) {
|
|
7866
|
-
const artifacts = await getFullScan(orgSlug, fullScanId);
|
|
7867
|
-
if (!artifacts) return;
|
|
8322
|
+
async function outputScanView(artifacts, orgSlug, scanId, filePath) {
|
|
7868
8323
|
const display = artifacts.map(art => {
|
|
7869
8324
|
const author = Array.isArray(art.author) ? `${art.author[0]}${art.author.length > 1 ? ' et.al.' : ''}` : art.author;
|
|
7870
8325
|
return {
|
|
@@ -7881,11 +8336,11 @@ async function viewFullScan(orgSlug, fullScanId, filePath) {
|
|
|
7881
8336
|
|
|
7882
8337
|
These are the artifacts and their scores found.
|
|
7883
8338
|
|
|
7884
|
-
|
|
8339
|
+
Scan ID: ${scanId}
|
|
7885
8340
|
|
|
7886
8341
|
${md}
|
|
7887
8342
|
|
|
7888
|
-
View this report at: https://socket.dev/dashboard/org/${orgSlug}/sbom/${
|
|
8343
|
+
View this report at: https://socket.dev/dashboard/org/${orgSlug}/sbom/${scanId}
|
|
7889
8344
|
`.trim() + '\n';
|
|
7890
8345
|
if (filePath && filePath !== '-') {
|
|
7891
8346
|
try {
|
|
@@ -7901,6 +8356,32 @@ View this report at: https://socket.dev/dashboard/org/${orgSlug}/sbom/${fullScan
|
|
|
7901
8356
|
}
|
|
7902
8357
|
}
|
|
7903
8358
|
|
|
8359
|
+
async function handleScanView(orgSlug, scanId, filePath) {
|
|
8360
|
+
const data = await fetchScan(orgSlug, scanId);
|
|
8361
|
+
if (!data) return;
|
|
8362
|
+
await outputScanView(data, orgSlug, scanId, filePath);
|
|
8363
|
+
}
|
|
8364
|
+
|
|
8365
|
+
async function streamScan(orgSlug, scanId, file) {
|
|
8366
|
+
// Lazily access constants.spinner.
|
|
8367
|
+
const {
|
|
8368
|
+
spinner
|
|
8369
|
+
} = constants;
|
|
8370
|
+
const apiToken = shadowNpmInject.getDefaultToken();
|
|
8371
|
+
if (!apiToken) {
|
|
8372
|
+
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.');
|
|
8373
|
+
}
|
|
8374
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
8375
|
+
spinner.start('Fetching scan...');
|
|
8376
|
+
const data = await handleApiCall(sockSdk.getOrgFullScan(orgSlug, scanId, file === '-' ? undefined : file), 'Fetching a scan');
|
|
8377
|
+
spinner?.successAndStop(file ? `Full scan details written to ${file}` : 'stdout');
|
|
8378
|
+
if (!data?.success) {
|
|
8379
|
+
handleUnsuccessfulApiResponse('getOrgFullScan', data);
|
|
8380
|
+
return;
|
|
8381
|
+
}
|
|
8382
|
+
return data;
|
|
8383
|
+
}
|
|
8384
|
+
|
|
7904
8385
|
const {
|
|
7905
8386
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$2
|
|
7906
8387
|
} = constants;
|
|
@@ -7939,8 +8420,8 @@ async function run$2(argv, importMeta, {
|
|
|
7939
8420
|
importMeta,
|
|
7940
8421
|
parentName
|
|
7941
8422
|
});
|
|
7942
|
-
const [orgSlug = '',
|
|
7943
|
-
if (!orgSlug || !
|
|
8423
|
+
const [orgSlug = '', scanId = '', file = '-'] = cli.input;
|
|
8424
|
+
if (!orgSlug || !scanId) {
|
|
7944
8425
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
7945
8426
|
// options or missing arguments.
|
|
7946
8427
|
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
@@ -7950,7 +8431,7 @@ async function run$2(argv, importMeta, {
|
|
|
7950
8431
|
|
|
7951
8432
|
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7952
8433
|
|
|
7953
|
-
- Full Scan ID to fetch as second argument ${!
|
|
8434
|
+
- Full Scan ID to fetch as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7954
8435
|
`);
|
|
7955
8436
|
return;
|
|
7956
8437
|
}
|
|
@@ -7959,9 +8440,9 @@ async function run$2(argv, importMeta, {
|
|
|
7959
8440
|
return;
|
|
7960
8441
|
}
|
|
7961
8442
|
if (cli.flags['json']) {
|
|
7962
|
-
await
|
|
8443
|
+
await streamScan(orgSlug, scanId, file);
|
|
7963
8444
|
} else {
|
|
7964
|
-
await
|
|
8445
|
+
await handleScanView(orgSlug, scanId, file);
|
|
7965
8446
|
}
|
|
7966
8447
|
}
|
|
7967
8448
|
|
|
@@ -8034,7 +8515,7 @@ async function getThreatFeedWithToken({
|
|
|
8034
8515
|
} = constants;
|
|
8035
8516
|
const queryParams = new URLSearchParams([['direction', direction], ['ecosystem', ecosystem], ['filter', filter], ['page', page], ['per_page', String(perPage)]]);
|
|
8036
8517
|
spinner.start('Fetching Threat Feed data...');
|
|
8037
|
-
const response = await
|
|
8518
|
+
const response = await queryApi(`threat-feed?${queryParams}`, apiToken);
|
|
8038
8519
|
const data = await response.json();
|
|
8039
8520
|
spinner.stop('Threat feed data fetched');
|
|
8040
8521
|
if (outputKind === 'json') {
|
|
@@ -8457,12 +8938,13 @@ void (async () => {
|
|
|
8457
8938
|
await vendor.updater({
|
|
8458
8939
|
name: SOCKET_CLI_BIN_NAME,
|
|
8459
8940
|
// The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_VERSION']".
|
|
8460
|
-
version: "0.14.
|
|
8941
|
+
version: "0.14.67",
|
|
8461
8942
|
ttl: 86_400_000 /* 24 hours in milliseconds */
|
|
8462
8943
|
});
|
|
8463
8944
|
try {
|
|
8464
8945
|
await meowWithSubcommands({
|
|
8465
8946
|
cdxgen: cmdCdxgen,
|
|
8947
|
+
config: cmdConfig,
|
|
8466
8948
|
fix: cmdFix,
|
|
8467
8949
|
info: cmdInfo,
|
|
8468
8950
|
login: cmdLogin,
|
|
@@ -8524,5 +9006,5 @@ void (async () => {
|
|
|
8524
9006
|
await shadowNpmInject.captureException(e);
|
|
8525
9007
|
}
|
|
8526
9008
|
})();
|
|
8527
|
-
//# debugId=
|
|
9009
|
+
//# debugId=85506a12-36b6-49a2-b249-50b4dfcf2be6
|
|
8528
9010
|
//# sourceMappingURL=cli.js.map
|