@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/module-sync/cli.js
CHANGED
|
@@ -56,19 +56,19 @@ var tinyglobby = _socketInterop(require('tinyglobby'));
|
|
|
56
56
|
var promises = require('@socketsecurity/registry/lib/promises');
|
|
57
57
|
var yaml = _socketInterop(require('yaml'));
|
|
58
58
|
var betterAjvErrors = _socketInterop(require('@apideck/better-ajv-errors'));
|
|
59
|
-
var config$
|
|
60
|
-
var assert = require('node:assert');
|
|
59
|
+
var config$H = require('@socketsecurity/config');
|
|
61
60
|
var readline = require('node:readline/promises');
|
|
62
61
|
var open = _socketInterop(require('open'));
|
|
63
62
|
var BoxWidget = _socketInterop(require('blessed/lib/widgets/box'));
|
|
64
63
|
var TableWidget = _socketInterop(require('blessed-contrib/lib/widget/table'));
|
|
65
64
|
var readline$1 = require('node:readline');
|
|
66
65
|
|
|
67
|
-
function handleUnsuccessfulApiResponse(_name,
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
function handleUnsuccessfulApiResponse(_name, sockSdkError) {
|
|
67
|
+
const message = sockSdkError.error || 'No error message returned';
|
|
68
|
+
const {
|
|
69
|
+
status
|
|
70
|
+
} = sockSdkError;
|
|
71
|
+
if (status === 401 || status === 403) {
|
|
72
72
|
// Lazily access constants.spinner.
|
|
73
73
|
const {
|
|
74
74
|
spinner
|
|
@@ -90,7 +90,7 @@ async function handleApiCall(value, description) {
|
|
|
90
90
|
}
|
|
91
91
|
return result;
|
|
92
92
|
}
|
|
93
|
-
async function
|
|
93
|
+
async function handleApiError(code) {
|
|
94
94
|
if (code === 400) {
|
|
95
95
|
return 'One of the options passed might be incorrect.';
|
|
96
96
|
} else if (code === 403) {
|
|
@@ -104,22 +104,22 @@ function getLastFiveOfApiToken(token) {
|
|
|
104
104
|
|
|
105
105
|
// The API server that should be used for operations.
|
|
106
106
|
function getDefaultApiBaseUrl() {
|
|
107
|
-
const baseUrl = process$1.env['SOCKET_SECURITY_API_BASE_URL'] || shadowNpmInject.
|
|
107
|
+
const baseUrl = process$1.env['SOCKET_SECURITY_API_BASE_URL'] || shadowNpmInject.getConfigValue('apiBaseUrl');
|
|
108
108
|
return strings.isNonEmptyString(baseUrl) ? baseUrl : undefined;
|
|
109
109
|
}
|
|
110
|
-
async function
|
|
110
|
+
async function queryApi(path, apiToken) {
|
|
111
111
|
const API_V0_URL = getDefaultApiBaseUrl();
|
|
112
112
|
return await fetch(`${API_V0_URL}/${path}`, {
|
|
113
113
|
method: 'GET',
|
|
114
114
|
headers: {
|
|
115
|
-
Authorization: `Basic ${btoa(`${apiToken}
|
|
115
|
+
Authorization: `Basic ${btoa(`${apiToken}:`)}`
|
|
116
116
|
}
|
|
117
117
|
});
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
async function fetchOrgAnalyticsData(time, spinner, apiToken) {
|
|
121
|
-
const
|
|
122
|
-
const result = await handleApiCall(
|
|
121
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
122
|
+
const result = await handleApiCall(sockSdk.getOrgAnalytics(time.toString()), 'fetching analytics data');
|
|
123
123
|
if (result.success === false) {
|
|
124
124
|
handleUnsuccessfulApiResponse('getOrgAnalytics', result);
|
|
125
125
|
return undefined;
|
|
@@ -133,8 +133,8 @@ async function fetchOrgAnalyticsData(time, spinner, apiToken) {
|
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
async function fetchRepoAnalyticsData(repo, time, spinner, apiToken) {
|
|
136
|
-
const
|
|
137
|
-
const result = await handleApiCall(
|
|
136
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
137
|
+
const result = await handleApiCall(sockSdk.getRepoAnalytics(repo, time.toString()), 'fetching analytics data');
|
|
138
138
|
if (result.success === false) {
|
|
139
139
|
handleUnsuccessfulApiResponse('getRepoAnalytics', result);
|
|
140
140
|
return undefined;
|
|
@@ -654,9 +654,9 @@ function emitBanner(name) {
|
|
|
654
654
|
}
|
|
655
655
|
function getAsciiHeader(command) {
|
|
656
656
|
const cliVersion = // The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_VERSION_HASH']".
|
|
657
|
-
"0.14.
|
|
657
|
+
"0.14.67:a2db5d2:df42d424:pub";
|
|
658
658
|
const nodeVersion = process.version;
|
|
659
|
-
const apiToken = shadowNpmInject.
|
|
659
|
+
const apiToken = shadowNpmInject.getConfigValue('apiToken');
|
|
660
660
|
const shownToken = apiToken ? getLastFiveOfApiToken(apiToken) : 'no';
|
|
661
661
|
const relCwd = path.normalizePath(process.cwd().replace(new RegExp(`^${regexps.escapeRegExp(constants.homePath)}(?:${path$1.sep}|$)`, 'i'), '~/'));
|
|
662
662
|
const body = `
|
|
@@ -668,9 +668,9 @@ function getAsciiHeader(command) {
|
|
|
668
668
|
}
|
|
669
669
|
|
|
670
670
|
const {
|
|
671
|
-
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
671
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$F
|
|
672
672
|
} = constants;
|
|
673
|
-
const config$
|
|
673
|
+
const config$G = {
|
|
674
674
|
commandName: 'analytics',
|
|
675
675
|
description: `Look up analytics data`,
|
|
676
676
|
hidden: false,
|
|
@@ -721,16 +721,16 @@ const config$C = {
|
|
|
721
721
|
`
|
|
722
722
|
};
|
|
723
723
|
const cmdAnalytics = {
|
|
724
|
-
description: config$
|
|
725
|
-
hidden: config$
|
|
726
|
-
run: run$
|
|
724
|
+
description: config$G.description,
|
|
725
|
+
hidden: config$G.hidden,
|
|
726
|
+
run: run$G
|
|
727
727
|
};
|
|
728
|
-
async function run$
|
|
728
|
+
async function run$G(argv, importMeta, {
|
|
729
729
|
parentName
|
|
730
730
|
}) {
|
|
731
731
|
const cli = meowOrExit({
|
|
732
732
|
argv,
|
|
733
|
-
config: config$
|
|
733
|
+
config: config$G,
|
|
734
734
|
importMeta,
|
|
735
735
|
parentName
|
|
736
736
|
});
|
|
@@ -767,7 +767,7 @@ async function run$C(argv, importMeta, {
|
|
|
767
767
|
return;
|
|
768
768
|
}
|
|
769
769
|
if (cli.flags['dryRun']) {
|
|
770
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
770
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$F);
|
|
771
771
|
return;
|
|
772
772
|
}
|
|
773
773
|
return await displayAnalytics({
|
|
@@ -810,8 +810,8 @@ async function fetchAuditLogWithToken(apiToken, {
|
|
|
810
810
|
spinner
|
|
811
811
|
} = constants;
|
|
812
812
|
spinner.start(`Looking up audit log for ${orgSlug}`);
|
|
813
|
-
const
|
|
814
|
-
const result = await handleApiCall(
|
|
813
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
814
|
+
const result = await handleApiCall(sockSdk.getAuditLogEvents(orgSlug, {
|
|
815
815
|
// I'm not sure this is used at all.
|
|
816
816
|
outputJson: String(outputKind === 'json'),
|
|
817
817
|
// I'm not sure this is used at all.
|
|
@@ -954,9 +954,9 @@ async function handleAuditLog({
|
|
|
954
954
|
}
|
|
955
955
|
|
|
956
956
|
const {
|
|
957
|
-
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
957
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$E
|
|
958
958
|
} = constants;
|
|
959
|
-
const config$
|
|
959
|
+
const config$F = {
|
|
960
960
|
commandName: 'audit-log',
|
|
961
961
|
description: 'Look up the audit log for an organization',
|
|
962
962
|
hidden: false,
|
|
@@ -997,16 +997,16 @@ const config$B = {
|
|
|
997
997
|
`
|
|
998
998
|
};
|
|
999
999
|
const cmdAuditLog = {
|
|
1000
|
-
description: config$
|
|
1001
|
-
hidden: config$
|
|
1002
|
-
run: run$
|
|
1000
|
+
description: config$F.description,
|
|
1001
|
+
hidden: config$F.hidden,
|
|
1002
|
+
run: run$F
|
|
1003
1003
|
};
|
|
1004
|
-
async function run$
|
|
1004
|
+
async function run$F(argv, importMeta, {
|
|
1005
1005
|
parentName
|
|
1006
1006
|
}) {
|
|
1007
1007
|
const cli = meowOrExit({
|
|
1008
1008
|
argv,
|
|
1009
|
-
config: config$
|
|
1009
|
+
config: config$F,
|
|
1010
1010
|
importMeta,
|
|
1011
1011
|
parentName
|
|
1012
1012
|
});
|
|
@@ -1031,7 +1031,7 @@ async function run$B(argv, importMeta, {
|
|
|
1031
1031
|
return;
|
|
1032
1032
|
}
|
|
1033
1033
|
if (cli.flags['dryRun']) {
|
|
1034
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
1034
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$E);
|
|
1035
1035
|
return;
|
|
1036
1036
|
}
|
|
1037
1037
|
await handleAuditLog({
|
|
@@ -1148,7 +1148,7 @@ function isHelpFlag(cmdArg) {
|
|
|
1148
1148
|
|
|
1149
1149
|
// import { meowOrExit } from '../../utils/meow-with-subcommands'
|
|
1150
1150
|
const {
|
|
1151
|
-
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
1151
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$D
|
|
1152
1152
|
} = constants;
|
|
1153
1153
|
|
|
1154
1154
|
// TODO: convert yargs to meow. Or convert all the other things to yargs.
|
|
@@ -1225,7 +1225,7 @@ const yargsConfig = {
|
|
|
1225
1225
|
'yes'],
|
|
1226
1226
|
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']
|
|
1227
1227
|
};
|
|
1228
|
-
const config$
|
|
1228
|
+
const config$E = {
|
|
1229
1229
|
commandName: 'cdxgen',
|
|
1230
1230
|
description: 'Create an SBOM with CycloneDX generator (cdxgen)',
|
|
1231
1231
|
hidden: false,
|
|
@@ -1241,18 +1241,18 @@ const config$A = {
|
|
|
1241
1241
|
`
|
|
1242
1242
|
};
|
|
1243
1243
|
const cmdCdxgen = {
|
|
1244
|
-
description: config$
|
|
1245
|
-
hidden: config$
|
|
1246
|
-
run: run$
|
|
1244
|
+
description: config$E.description,
|
|
1245
|
+
hidden: config$E.hidden,
|
|
1246
|
+
run: run$E
|
|
1247
1247
|
};
|
|
1248
|
-
async function run$
|
|
1248
|
+
async function run$E(argv, importMeta, {
|
|
1249
1249
|
parentName
|
|
1250
1250
|
}) {
|
|
1251
1251
|
const cli = meowOrExit({
|
|
1252
1252
|
allowUnknownFlags: true,
|
|
1253
1253
|
// Don't let meow take over --help.
|
|
1254
1254
|
argv: argv.filter(a => !isHelpFlag(a)),
|
|
1255
|
-
config: config$
|
|
1255
|
+
config: config$E,
|
|
1256
1256
|
importMeta,
|
|
1257
1257
|
parentName
|
|
1258
1258
|
});
|
|
@@ -1284,7 +1284,7 @@ async function run$A(argv, importMeta, {
|
|
|
1284
1284
|
return;
|
|
1285
1285
|
}
|
|
1286
1286
|
if (cli.flags['dryRun']) {
|
|
1287
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
1287
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$D);
|
|
1288
1288
|
return;
|
|
1289
1289
|
}
|
|
1290
1290
|
if (yargv.output === undefined) {
|
|
@@ -1293,212 +1293,611 @@ async function run$A(argv, importMeta, {
|
|
|
1293
1293
|
await runCycloneDX(yargv);
|
|
1294
1294
|
}
|
|
1295
1295
|
|
|
1296
|
-
async function
|
|
1297
|
-
limit,
|
|
1298
|
-
offset
|
|
1299
|
-
}) {
|
|
1300
|
-
const apiToken = shadowNpmInject.getDefaultToken();
|
|
1301
|
-
if (!apiToken) {
|
|
1302
|
-
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.');
|
|
1303
|
-
}
|
|
1304
|
-
return await fetchDependenciesWithToken(apiToken, {
|
|
1305
|
-
limit,
|
|
1306
|
-
offset
|
|
1307
|
-
});
|
|
1308
|
-
}
|
|
1309
|
-
async function fetchDependenciesWithToken(apiToken, {
|
|
1310
|
-
limit,
|
|
1311
|
-
offset
|
|
1312
|
-
}) {
|
|
1313
|
-
// Lazily access constants.spinner.
|
|
1314
|
-
const {
|
|
1315
|
-
spinner
|
|
1316
|
-
} = constants;
|
|
1317
|
-
spinner.start('Fetching organization dependencies...');
|
|
1318
|
-
const socketSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
1319
|
-
const result = await handleApiCall(socketSdk.searchDependencies({
|
|
1320
|
-
limit,
|
|
1321
|
-
offset
|
|
1322
|
-
}), 'Searching dependencies');
|
|
1323
|
-
spinner?.successAndStop('Received organization dependencies response.');
|
|
1324
|
-
if (!result.success) {
|
|
1325
|
-
handleUnsuccessfulApiResponse('searchDependencies', result);
|
|
1326
|
-
return;
|
|
1327
|
-
}
|
|
1328
|
-
return result.data;
|
|
1329
|
-
}
|
|
1330
|
-
|
|
1331
|
-
// @ts-ignore
|
|
1332
|
-
async function outputDependencies(data, {
|
|
1333
|
-
limit,
|
|
1334
|
-
offset,
|
|
1335
|
-
outputKind
|
|
1336
|
-
}) {
|
|
1296
|
+
async function outputConfigGet(key, value, outputKind) {
|
|
1337
1297
|
if (outputKind === 'json') {
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
logger.logger.log(
|
|
1347
|
-
|
|
1298
|
+
logger.logger.log(JSON.stringify({
|
|
1299
|
+
success: true,
|
|
1300
|
+
result: {
|
|
1301
|
+
key,
|
|
1302
|
+
value
|
|
1303
|
+
}
|
|
1304
|
+
}));
|
|
1305
|
+
} else if (outputKind === 'markdown') {
|
|
1306
|
+
logger.logger.log(`# Config Value`);
|
|
1307
|
+
logger.logger.log('');
|
|
1308
|
+
logger.logger.log(`Config key '${key}' has value '${value}`);
|
|
1309
|
+
} else {
|
|
1310
|
+
logger.logger.log(`${key}: ${value}`);
|
|
1348
1311
|
}
|
|
1349
|
-
logger.logger.log('Request details: Offset:', offset, ', limit:', limit, ', is there more data after this?', data.end ? 'no' : 'yes');
|
|
1350
|
-
const options = {
|
|
1351
|
-
columns: [{
|
|
1352
|
-
field: 'namespace',
|
|
1353
|
-
name: colors.cyan('Namespace')
|
|
1354
|
-
}, {
|
|
1355
|
-
field: 'name',
|
|
1356
|
-
name: colors.cyan('Name')
|
|
1357
|
-
}, {
|
|
1358
|
-
field: 'version',
|
|
1359
|
-
name: colors.cyan('Version')
|
|
1360
|
-
}, {
|
|
1361
|
-
field: 'repository',
|
|
1362
|
-
name: colors.cyan('Repository')
|
|
1363
|
-
}, {
|
|
1364
|
-
field: 'branch',
|
|
1365
|
-
name: colors.cyan('Branch')
|
|
1366
|
-
}, {
|
|
1367
|
-
field: 'type',
|
|
1368
|
-
name: colors.cyan('Type')
|
|
1369
|
-
}, {
|
|
1370
|
-
field: 'direct',
|
|
1371
|
-
name: colors.cyan('Direct')
|
|
1372
|
-
}]
|
|
1373
|
-
};
|
|
1374
|
-
logger.logger.log(chalkTable(options, data.rows));
|
|
1375
1312
|
}
|
|
1376
1313
|
|
|
1377
|
-
async function
|
|
1378
|
-
|
|
1379
|
-
offset,
|
|
1314
|
+
async function handleConfigGet({
|
|
1315
|
+
key,
|
|
1380
1316
|
outputKind
|
|
1381
1317
|
}) {
|
|
1382
|
-
const
|
|
1383
|
-
|
|
1384
|
-
offset
|
|
1385
|
-
});
|
|
1386
|
-
if (!data) return;
|
|
1387
|
-
await outputDependencies(data, {
|
|
1388
|
-
limit,
|
|
1389
|
-
offset,
|
|
1390
|
-
outputKind
|
|
1391
|
-
});
|
|
1318
|
+
const value = shadowNpmInject.getConfigValue(key);
|
|
1319
|
+
await outputConfigGet(key, value, outputKind);
|
|
1392
1320
|
}
|
|
1393
1321
|
|
|
1394
1322
|
const {
|
|
1395
|
-
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$
|
|
1323
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$C
|
|
1396
1324
|
} = constants;
|
|
1397
|
-
const config$
|
|
1398
|
-
commandName: '
|
|
1399
|
-
description: '
|
|
1325
|
+
const config$D = {
|
|
1326
|
+
commandName: 'get',
|
|
1327
|
+
description: 'Get the value of a local CLI config item',
|
|
1400
1328
|
hidden: false,
|
|
1401
1329
|
flags: {
|
|
1402
1330
|
...commonFlags,
|
|
1403
|
-
limit: {
|
|
1404
|
-
type: 'number',
|
|
1405
|
-
shortFlag: 'l',
|
|
1406
|
-
default: 50,
|
|
1407
|
-
description: 'Maximum number of dependencies returned'
|
|
1408
|
-
},
|
|
1409
|
-
offset: {
|
|
1410
|
-
type: 'number',
|
|
1411
|
-
shortFlag: 'o',
|
|
1412
|
-
default: 0,
|
|
1413
|
-
description: 'Page number'
|
|
1414
|
-
},
|
|
1415
1331
|
...outputFlags
|
|
1416
1332
|
},
|
|
1417
1333
|
help: (command, config) => `
|
|
1418
1334
|
Usage
|
|
1419
|
-
${command}
|
|
1335
|
+
$ ${command} <org slug>
|
|
1420
1336
|
|
|
1421
1337
|
Options
|
|
1422
1338
|
${getFlagListOutput(config.flags, 6)}
|
|
1423
1339
|
|
|
1340
|
+
Keys:
|
|
1341
|
+
|
|
1342
|
+
${Array.from(shadowNpmInject.supportedConfigKeys.entries()).map(([key, desc]) => ` - ${key} -- ${desc}`).join('\n')}
|
|
1343
|
+
|
|
1424
1344
|
Examples
|
|
1425
|
-
${command}
|
|
1345
|
+
$ ${command} FakeOrg --repoName=test-repo
|
|
1426
1346
|
`
|
|
1427
1347
|
};
|
|
1428
|
-
const
|
|
1429
|
-
description: config$
|
|
1430
|
-
hidden: config$
|
|
1431
|
-
run: run$
|
|
1348
|
+
const cmdConfigGet = {
|
|
1349
|
+
description: config$D.description,
|
|
1350
|
+
hidden: config$D.hidden,
|
|
1351
|
+
run: run$D
|
|
1432
1352
|
};
|
|
1433
|
-
async function run$
|
|
1353
|
+
async function run$D(argv, importMeta, {
|
|
1434
1354
|
parentName
|
|
1435
1355
|
}) {
|
|
1436
1356
|
const cli = meowOrExit({
|
|
1437
1357
|
argv,
|
|
1438
|
-
config: config$
|
|
1358
|
+
config: config$D,
|
|
1439
1359
|
importMeta,
|
|
1440
1360
|
parentName
|
|
1441
1361
|
});
|
|
1442
1362
|
const {
|
|
1443
1363
|
json,
|
|
1444
|
-
|
|
1445
|
-
markdown,
|
|
1446
|
-
offset
|
|
1364
|
+
markdown
|
|
1447
1365
|
} = cli.flags;
|
|
1366
|
+
const [key = ''] = cli.input;
|
|
1367
|
+
if (!shadowNpmInject.supportedConfigKeys.has(key) && key !== 'test') {
|
|
1368
|
+
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
1369
|
+
// options or missing arguments.
|
|
1370
|
+
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
1371
|
+
process.exitCode = 2;
|
|
1372
|
+
logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
|
|
1373
|
+
|
|
1374
|
+
- Config key should be the first arg ${!key ? colors.red('(missing!)') : !shadowNpmInject.supportedConfigKeys.has(key) ? colors.red('(invalid config key!)') : colors.green('(ok)')}
|
|
1375
|
+
`);
|
|
1376
|
+
return;
|
|
1377
|
+
}
|
|
1448
1378
|
if (cli.flags['dryRun']) {
|
|
1449
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$
|
|
1379
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$C);
|
|
1450
1380
|
return;
|
|
1451
1381
|
}
|
|
1452
|
-
await
|
|
1453
|
-
|
|
1454
|
-
offset: Number(offset || 0) || 0,
|
|
1382
|
+
await handleConfigGet({
|
|
1383
|
+
key: key,
|
|
1455
1384
|
outputKind: json ? 'json' : markdown ? 'markdown' : 'text'
|
|
1456
1385
|
});
|
|
1457
1386
|
}
|
|
1458
1387
|
|
|
1459
|
-
async function
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
orgSlug
|
|
1388
|
+
async function outputConfigList({
|
|
1389
|
+
full,
|
|
1390
|
+
outputKind
|
|
1463
1391
|
}) {
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1392
|
+
if (outputKind === 'json') {
|
|
1393
|
+
const obj = {};
|
|
1394
|
+
for (const key of shadowNpmInject.supportedConfigKeys.keys()) {
|
|
1395
|
+
let value = shadowNpmInject.getConfigValue(key);
|
|
1396
|
+
if (!full && shadowNpmInject.sensitiveConfigKeys.has(key)) {
|
|
1397
|
+
value = '********';
|
|
1398
|
+
}
|
|
1399
|
+
if (full || value !== undefined) {
|
|
1400
|
+
obj[key] = value ?? '<none>';
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
logger.logger.log(JSON.stringify({
|
|
1404
|
+
success: true,
|
|
1405
|
+
full,
|
|
1406
|
+
config: obj
|
|
1407
|
+
}, null, 2));
|
|
1408
|
+
} else {
|
|
1409
|
+
const maxWidth = Array.from(shadowNpmInject.supportedConfigKeys.keys()).reduce((a, b) => Math.max(a, b.length), 0);
|
|
1410
|
+
logger.logger.log('# Local CLI Config');
|
|
1411
|
+
logger.logger.log('');
|
|
1412
|
+
logger.logger.log(`This is the local CLI config (full=${!!full}):`);
|
|
1413
|
+
logger.logger.log('');
|
|
1414
|
+
for (const key of shadowNpmInject.supportedConfigKeys.keys()) {
|
|
1415
|
+
let value = shadowNpmInject.getConfigValue(key);
|
|
1416
|
+
if (!full && shadowNpmInject.sensitiveConfigKeys.has(key)) {
|
|
1417
|
+
value = '********';
|
|
1418
|
+
}
|
|
1419
|
+
if (full || value !== undefined) {
|
|
1420
|
+
logger.logger.log(`- ${key}:${' '.repeat(Math.max(0, maxWidth - key.length + 3))} ${Array.isArray(value) ? value.join(', ') || '<none>' : value ?? '<none>'}`);
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1467
1423
|
}
|
|
1468
|
-
return await fetchDiffScanWithToken(apiToken, {
|
|
1469
|
-
after,
|
|
1470
|
-
before,
|
|
1471
|
-
orgSlug
|
|
1472
|
-
});
|
|
1473
1424
|
}
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1425
|
+
|
|
1426
|
+
const {
|
|
1427
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$B
|
|
1428
|
+
} = constants;
|
|
1429
|
+
const config$C = {
|
|
1430
|
+
commandName: 'list',
|
|
1431
|
+
description: 'Show all local CLI config items and their values',
|
|
1432
|
+
hidden: false,
|
|
1433
|
+
flags: {
|
|
1434
|
+
...commonFlags,
|
|
1435
|
+
...outputFlags,
|
|
1436
|
+
full: {
|
|
1437
|
+
type: 'boolean',
|
|
1438
|
+
default: false,
|
|
1439
|
+
description: 'Show full tokens in plaintext (unsafe)'
|
|
1440
|
+
}
|
|
1441
|
+
},
|
|
1442
|
+
help: (command, config) => `
|
|
1443
|
+
Usage
|
|
1444
|
+
$ ${command} <org slug>
|
|
1445
|
+
|
|
1446
|
+
Options
|
|
1447
|
+
${getFlagListOutput(config.flags, 6)}
|
|
1448
|
+
|
|
1449
|
+
Keys:
|
|
1450
|
+
|
|
1451
|
+
${Array.from(shadowNpmInject.supportedConfigKeys.entries()).map(([key, desc]) => ` - ${key} -- ${desc}`).join('\n')}
|
|
1452
|
+
|
|
1453
|
+
Examples
|
|
1454
|
+
$ ${command} FakeOrg --repoName=test-repo
|
|
1455
|
+
`
|
|
1456
|
+
};
|
|
1457
|
+
const cmdConfigList = {
|
|
1458
|
+
description: config$C.description,
|
|
1459
|
+
hidden: config$C.hidden,
|
|
1460
|
+
run: run$C
|
|
1461
|
+
};
|
|
1462
|
+
async function run$C(argv, importMeta, {
|
|
1463
|
+
parentName
|
|
1478
1464
|
}) {
|
|
1479
|
-
|
|
1465
|
+
const cli = meowOrExit({
|
|
1466
|
+
argv,
|
|
1467
|
+
config: config$C,
|
|
1468
|
+
importMeta,
|
|
1469
|
+
parentName
|
|
1470
|
+
});
|
|
1480
1471
|
const {
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
const err = await handleAPIError(response.status);
|
|
1488
|
-
spinner.errorAndStop(`${colors.bgRed(colors.white(response.statusText))}: ${err}`);
|
|
1472
|
+
full,
|
|
1473
|
+
json,
|
|
1474
|
+
markdown
|
|
1475
|
+
} = cli.flags;
|
|
1476
|
+
if (cli.flags['dryRun']) {
|
|
1477
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$B);
|
|
1489
1478
|
return;
|
|
1490
1479
|
}
|
|
1491
|
-
|
|
1492
|
-
|
|
1480
|
+
await outputConfigList({
|
|
1481
|
+
full: !!full,
|
|
1482
|
+
outputKind: json ? 'json' : markdown ? 'markdown' : 'text'
|
|
1483
|
+
});
|
|
1493
1484
|
}
|
|
1494
1485
|
|
|
1495
|
-
async function
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
}
|
|
1500
|
-
|
|
1501
|
-
|
|
1486
|
+
async function outputConfigSet(key, _value, outputKind) {
|
|
1487
|
+
if (outputKind === 'json') {
|
|
1488
|
+
logger.logger.log(JSON.stringify({
|
|
1489
|
+
success: true,
|
|
1490
|
+
message: `Config key '${key}' was updated`
|
|
1491
|
+
}));
|
|
1492
|
+
} else if (outputKind === 'markdown') {
|
|
1493
|
+
logger.logger.log(`# Update config`);
|
|
1494
|
+
logger.logger.log('');
|
|
1495
|
+
logger.logger.log(`Config key '${key}' was updated`);
|
|
1496
|
+
} else {
|
|
1497
|
+
logger.logger.log(`OK`);
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
async function handleConfigSet({
|
|
1502
|
+
key,
|
|
1503
|
+
outputKind,
|
|
1504
|
+
value
|
|
1505
|
+
}) {
|
|
1506
|
+
shadowNpmInject.updateConfigValue(key, value);
|
|
1507
|
+
await outputConfigSet(key, value, outputKind);
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
const {
|
|
1511
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$A
|
|
1512
|
+
} = constants;
|
|
1513
|
+
const config$B = {
|
|
1514
|
+
commandName: 'set',
|
|
1515
|
+
description: 'Update the value of a local CLI config item',
|
|
1516
|
+
hidden: false,
|
|
1517
|
+
flags: {
|
|
1518
|
+
...commonFlags,
|
|
1519
|
+
...outputFlags
|
|
1520
|
+
},
|
|
1521
|
+
help: (command, config) => `
|
|
1522
|
+
Usage
|
|
1523
|
+
$ ${command} <key> <value>
|
|
1524
|
+
|
|
1525
|
+
Options
|
|
1526
|
+
${getFlagListOutput(config.flags, 6)}
|
|
1527
|
+
|
|
1528
|
+
This is a crude way of updating the local configuration for this CLI tool.
|
|
1529
|
+
|
|
1530
|
+
Note that updating a value here is nothing more than updating a key/value
|
|
1531
|
+
store entry. No validation is happening. The server may reject your config.
|
|
1532
|
+
|
|
1533
|
+
Keys:
|
|
1534
|
+
|
|
1535
|
+
${Array.from(shadowNpmInject.supportedConfigKeys.entries()).map(([key, desc]) => ` - ${key} -- ${desc}`).join('\n')}
|
|
1536
|
+
|
|
1537
|
+
Examples
|
|
1538
|
+
$ ${command} apiProxy https://example.com
|
|
1539
|
+
`
|
|
1540
|
+
};
|
|
1541
|
+
const cmdConfigSet = {
|
|
1542
|
+
description: config$B.description,
|
|
1543
|
+
hidden: config$B.hidden,
|
|
1544
|
+
run: run$B
|
|
1545
|
+
};
|
|
1546
|
+
async function run$B(argv, importMeta, {
|
|
1547
|
+
parentName
|
|
1548
|
+
}) {
|
|
1549
|
+
const cli = meowOrExit({
|
|
1550
|
+
argv,
|
|
1551
|
+
config: config$B,
|
|
1552
|
+
importMeta,
|
|
1553
|
+
parentName
|
|
1554
|
+
});
|
|
1555
|
+
const {
|
|
1556
|
+
json,
|
|
1557
|
+
markdown
|
|
1558
|
+
} = cli.flags;
|
|
1559
|
+
const [key = '', ...rest] = cli.input;
|
|
1560
|
+
const value = rest.join(' ');
|
|
1561
|
+
if (!shadowNpmInject.supportedConfigKeys.has(key) && key !== 'test' || !value) {
|
|
1562
|
+
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
1563
|
+
// options or missing arguments.
|
|
1564
|
+
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
1565
|
+
process.exitCode = 2;
|
|
1566
|
+
logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
|
|
1567
|
+
|
|
1568
|
+
- Config key should be the first arg ${!key ? colors.red('(missing!)') : !shadowNpmInject.supportedConfigKeys.has(key) ? colors.red('(invalid config key!)') : colors.green('(ok)')}
|
|
1569
|
+
|
|
1570
|
+
- Key value should be the remaining args (use \`del\` to unset a value) ${!value ? colors.red('(missing!)') : colors.green('(ok)')}`);
|
|
1571
|
+
return;
|
|
1572
|
+
}
|
|
1573
|
+
if (cli.flags['dryRun']) {
|
|
1574
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$A);
|
|
1575
|
+
return;
|
|
1576
|
+
}
|
|
1577
|
+
await handleConfigSet({
|
|
1578
|
+
key: key,
|
|
1579
|
+
outputKind: json ? 'json' : markdown ? 'markdown' : 'text',
|
|
1580
|
+
value
|
|
1581
|
+
});
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
async function outputConfigUnset(key, outputKind) {
|
|
1585
|
+
if (outputKind === 'json') {
|
|
1586
|
+
logger.logger.log(JSON.stringify({
|
|
1587
|
+
success: true,
|
|
1588
|
+
message: `Config key '${key}' was unset`
|
|
1589
|
+
}));
|
|
1590
|
+
} else if (outputKind === 'markdown') {
|
|
1591
|
+
logger.logger.log(`# Update config`);
|
|
1592
|
+
logger.logger.log('');
|
|
1593
|
+
logger.logger.log(`Config key '${key}' was unset`);
|
|
1594
|
+
} else {
|
|
1595
|
+
logger.logger.log(`OK`);
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
async function handleConfigUnset({
|
|
1600
|
+
key,
|
|
1601
|
+
outputKind
|
|
1602
|
+
}) {
|
|
1603
|
+
shadowNpmInject.updateConfigValue(key, undefined);
|
|
1604
|
+
await outputConfigUnset(key, outputKind);
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
const {
|
|
1608
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$z
|
|
1609
|
+
} = constants;
|
|
1610
|
+
const config$A = {
|
|
1611
|
+
commandName: 'unset',
|
|
1612
|
+
description: 'Clear the value of a local CLI config item',
|
|
1613
|
+
hidden: false,
|
|
1614
|
+
flags: {
|
|
1615
|
+
...commonFlags,
|
|
1616
|
+
...outputFlags
|
|
1617
|
+
},
|
|
1618
|
+
help: (command, config) => `
|
|
1619
|
+
Usage
|
|
1620
|
+
$ ${command} <org slug>
|
|
1621
|
+
|
|
1622
|
+
Options
|
|
1623
|
+
${getFlagListOutput(config.flags, 6)}
|
|
1624
|
+
|
|
1625
|
+
Keys:
|
|
1626
|
+
|
|
1627
|
+
${Array.from(shadowNpmInject.supportedConfigKeys.entries()).map(([key, desc]) => ` - ${key} -- ${desc}`).join('\n')}
|
|
1628
|
+
|
|
1629
|
+
Examples
|
|
1630
|
+
$ ${command} FakeOrg --repoName=test-repo
|
|
1631
|
+
`
|
|
1632
|
+
};
|
|
1633
|
+
const cmdConfigUnset = {
|
|
1634
|
+
description: config$A.description,
|
|
1635
|
+
hidden: config$A.hidden,
|
|
1636
|
+
run: run$A
|
|
1637
|
+
};
|
|
1638
|
+
async function run$A(argv, importMeta, {
|
|
1639
|
+
parentName
|
|
1640
|
+
}) {
|
|
1641
|
+
const cli = meowOrExit({
|
|
1642
|
+
argv,
|
|
1643
|
+
config: config$A,
|
|
1644
|
+
importMeta,
|
|
1645
|
+
parentName
|
|
1646
|
+
});
|
|
1647
|
+
const {
|
|
1648
|
+
json,
|
|
1649
|
+
markdown
|
|
1650
|
+
} = cli.flags;
|
|
1651
|
+
const [key = ''] = cli.input;
|
|
1652
|
+
if (!shadowNpmInject.supportedConfigKeys.has(key) && key !== 'test') {
|
|
1653
|
+
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
1654
|
+
// options or missing arguments.
|
|
1655
|
+
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
1656
|
+
process.exitCode = 2;
|
|
1657
|
+
logger.logger.fail(commonTags.stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
|
|
1658
|
+
|
|
1659
|
+
- Config key should be the first arg ${!key ? colors.red('(missing!)') : !shadowNpmInject.supportedConfigKeys.has(key) ? colors.red('(invalid config key!)') : colors.green('(ok)')}
|
|
1660
|
+
`);
|
|
1661
|
+
return;
|
|
1662
|
+
}
|
|
1663
|
+
if (cli.flags['dryRun']) {
|
|
1664
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$z);
|
|
1665
|
+
return;
|
|
1666
|
+
}
|
|
1667
|
+
await handleConfigUnset({
|
|
1668
|
+
key: key,
|
|
1669
|
+
outputKind: json ? 'json' : markdown ? 'markdown' : 'text'
|
|
1670
|
+
});
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
const description$7 = 'Commands related to the local CLI configuration';
|
|
1674
|
+
const cmdConfig = {
|
|
1675
|
+
description: description$7,
|
|
1676
|
+
hidden: true,
|
|
1677
|
+
// [beta]
|
|
1678
|
+
async run(argv, importMeta, {
|
|
1679
|
+
parentName
|
|
1680
|
+
}) {
|
|
1681
|
+
await meowWithSubcommands({
|
|
1682
|
+
unset: cmdConfigUnset,
|
|
1683
|
+
get: cmdConfigGet,
|
|
1684
|
+
list: cmdConfigList,
|
|
1685
|
+
set: cmdConfigSet
|
|
1686
|
+
}, {
|
|
1687
|
+
argv,
|
|
1688
|
+
description: description$7,
|
|
1689
|
+
importMeta,
|
|
1690
|
+
name: `${parentName} config`
|
|
1691
|
+
});
|
|
1692
|
+
}
|
|
1693
|
+
};
|
|
1694
|
+
|
|
1695
|
+
async function fetchDependencies({
|
|
1696
|
+
limit,
|
|
1697
|
+
offset
|
|
1698
|
+
}) {
|
|
1699
|
+
const apiToken = shadowNpmInject.getDefaultToken();
|
|
1700
|
+
if (!apiToken) {
|
|
1701
|
+
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.');
|
|
1702
|
+
}
|
|
1703
|
+
return await fetchDependenciesWithToken(apiToken, {
|
|
1704
|
+
limit,
|
|
1705
|
+
offset
|
|
1706
|
+
});
|
|
1707
|
+
}
|
|
1708
|
+
async function fetchDependenciesWithToken(apiToken, {
|
|
1709
|
+
limit,
|
|
1710
|
+
offset
|
|
1711
|
+
}) {
|
|
1712
|
+
// Lazily access constants.spinner.
|
|
1713
|
+
const {
|
|
1714
|
+
spinner
|
|
1715
|
+
} = constants;
|
|
1716
|
+
spinner.start('Fetching organization dependencies...');
|
|
1717
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
1718
|
+
const result = await handleApiCall(sockSdk.searchDependencies({
|
|
1719
|
+
limit,
|
|
1720
|
+
offset
|
|
1721
|
+
}), 'Searching dependencies');
|
|
1722
|
+
spinner?.successAndStop('Received organization dependencies response.');
|
|
1723
|
+
if (!result.success) {
|
|
1724
|
+
handleUnsuccessfulApiResponse('searchDependencies', result);
|
|
1725
|
+
return;
|
|
1726
|
+
}
|
|
1727
|
+
return result.data;
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1730
|
+
// @ts-ignore
|
|
1731
|
+
async function outputDependencies(data, {
|
|
1732
|
+
limit,
|
|
1733
|
+
offset,
|
|
1734
|
+
outputKind
|
|
1735
|
+
}) {
|
|
1736
|
+
if (outputKind === 'json') {
|
|
1737
|
+
let json;
|
|
1738
|
+
try {
|
|
1739
|
+
json = JSON.stringify(data, null, 2);
|
|
1740
|
+
} catch (e) {
|
|
1741
|
+
process.exitCode = 1;
|
|
1742
|
+
logger.logger.fail('There was a problem converting the data to JSON, please try without the `--json` flag');
|
|
1743
|
+
return;
|
|
1744
|
+
}
|
|
1745
|
+
logger.logger.log(json);
|
|
1746
|
+
return;
|
|
1747
|
+
}
|
|
1748
|
+
logger.logger.log('Request details: Offset:', offset, ', limit:', limit, ', is there more data after this?', data.end ? 'no' : 'yes');
|
|
1749
|
+
const options = {
|
|
1750
|
+
columns: [{
|
|
1751
|
+
field: 'namespace',
|
|
1752
|
+
name: colors.cyan('Namespace')
|
|
1753
|
+
}, {
|
|
1754
|
+
field: 'name',
|
|
1755
|
+
name: colors.cyan('Name')
|
|
1756
|
+
}, {
|
|
1757
|
+
field: 'version',
|
|
1758
|
+
name: colors.cyan('Version')
|
|
1759
|
+
}, {
|
|
1760
|
+
field: 'repository',
|
|
1761
|
+
name: colors.cyan('Repository')
|
|
1762
|
+
}, {
|
|
1763
|
+
field: 'branch',
|
|
1764
|
+
name: colors.cyan('Branch')
|
|
1765
|
+
}, {
|
|
1766
|
+
field: 'type',
|
|
1767
|
+
name: colors.cyan('Type')
|
|
1768
|
+
}, {
|
|
1769
|
+
field: 'direct',
|
|
1770
|
+
name: colors.cyan('Direct')
|
|
1771
|
+
}]
|
|
1772
|
+
};
|
|
1773
|
+
logger.logger.log(chalkTable(options, data.rows));
|
|
1774
|
+
}
|
|
1775
|
+
|
|
1776
|
+
async function handleDependencies({
|
|
1777
|
+
limit,
|
|
1778
|
+
offset,
|
|
1779
|
+
outputKind
|
|
1780
|
+
}) {
|
|
1781
|
+
const data = await fetchDependencies({
|
|
1782
|
+
limit,
|
|
1783
|
+
offset
|
|
1784
|
+
});
|
|
1785
|
+
if (!data) return;
|
|
1786
|
+
await outputDependencies(data, {
|
|
1787
|
+
limit,
|
|
1788
|
+
offset,
|
|
1789
|
+
outputKind
|
|
1790
|
+
});
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
const {
|
|
1794
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$y
|
|
1795
|
+
} = constants;
|
|
1796
|
+
const config$z = {
|
|
1797
|
+
commandName: 'dependencies',
|
|
1798
|
+
description: 'Search for any dependency that is being used in your organization',
|
|
1799
|
+
hidden: false,
|
|
1800
|
+
flags: {
|
|
1801
|
+
...commonFlags,
|
|
1802
|
+
limit: {
|
|
1803
|
+
type: 'number',
|
|
1804
|
+
shortFlag: 'l',
|
|
1805
|
+
default: 50,
|
|
1806
|
+
description: 'Maximum number of dependencies returned'
|
|
1807
|
+
},
|
|
1808
|
+
offset: {
|
|
1809
|
+
type: 'number',
|
|
1810
|
+
shortFlag: 'o',
|
|
1811
|
+
default: 0,
|
|
1812
|
+
description: 'Page number'
|
|
1813
|
+
},
|
|
1814
|
+
...outputFlags
|
|
1815
|
+
},
|
|
1816
|
+
help: (command, config) => `
|
|
1817
|
+
Usage
|
|
1818
|
+
${command}
|
|
1819
|
+
|
|
1820
|
+
Options
|
|
1821
|
+
${getFlagListOutput(config.flags, 6)}
|
|
1822
|
+
|
|
1823
|
+
Examples
|
|
1824
|
+
${command} --limit 20 --offset 10
|
|
1825
|
+
`
|
|
1826
|
+
};
|
|
1827
|
+
const cmdScanCreate$1 = {
|
|
1828
|
+
description: config$z.description,
|
|
1829
|
+
hidden: config$z.hidden,
|
|
1830
|
+
run: run$z
|
|
1831
|
+
};
|
|
1832
|
+
async function run$z(argv, importMeta, {
|
|
1833
|
+
parentName
|
|
1834
|
+
}) {
|
|
1835
|
+
const cli = meowOrExit({
|
|
1836
|
+
argv,
|
|
1837
|
+
config: config$z,
|
|
1838
|
+
importMeta,
|
|
1839
|
+
parentName
|
|
1840
|
+
});
|
|
1841
|
+
const {
|
|
1842
|
+
json,
|
|
1843
|
+
limit,
|
|
1844
|
+
markdown,
|
|
1845
|
+
offset
|
|
1846
|
+
} = cli.flags;
|
|
1847
|
+
if (cli.flags['dryRun']) {
|
|
1848
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$y);
|
|
1849
|
+
return;
|
|
1850
|
+
}
|
|
1851
|
+
await handleDependencies({
|
|
1852
|
+
limit: Number(limit || 0) || 0,
|
|
1853
|
+
offset: Number(offset || 0) || 0,
|
|
1854
|
+
outputKind: json ? 'json' : markdown ? 'markdown' : 'text'
|
|
1855
|
+
});
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
async function fetchDiffScan({
|
|
1859
|
+
after,
|
|
1860
|
+
before,
|
|
1861
|
+
orgSlug
|
|
1862
|
+
}) {
|
|
1863
|
+
const apiToken = shadowNpmInject.getDefaultToken();
|
|
1864
|
+
if (!apiToken) {
|
|
1865
|
+
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.');
|
|
1866
|
+
}
|
|
1867
|
+
return await fetchDiffScanWithToken(apiToken, {
|
|
1868
|
+
after,
|
|
1869
|
+
before,
|
|
1870
|
+
orgSlug
|
|
1871
|
+
});
|
|
1872
|
+
}
|
|
1873
|
+
async function fetchDiffScanWithToken(apiToken, {
|
|
1874
|
+
after,
|
|
1875
|
+
before,
|
|
1876
|
+
orgSlug
|
|
1877
|
+
}) {
|
|
1878
|
+
// Lazily access constants.spinner.
|
|
1879
|
+
const {
|
|
1880
|
+
spinner
|
|
1881
|
+
} = constants;
|
|
1882
|
+
spinner.start('Fetching diff-scan...');
|
|
1883
|
+
const response = await queryApi(`orgs/${orgSlug}/full-scans/diff?before=${encodeURIComponent(before)}&after=${encodeURIComponent(after)}`, apiToken);
|
|
1884
|
+
spinner?.successAndStop('Received diff-scan response');
|
|
1885
|
+
if (!response.ok) {
|
|
1886
|
+
const err = await handleApiError(response.status);
|
|
1887
|
+
spinner.errorAndStop(`${colors.bgRed(colors.white(response.statusText))}: ${err}`);
|
|
1888
|
+
return;
|
|
1889
|
+
}
|
|
1890
|
+
const result = await handleApiCall(await response.json(), 'Deserializing json');
|
|
1891
|
+
return result;
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1894
|
+
async function outputDiffScan(result, {
|
|
1895
|
+
depth,
|
|
1896
|
+
file,
|
|
1897
|
+
outputKind
|
|
1898
|
+
}) {
|
|
1899
|
+
const dashboardUrl = result.diff_report_url;
|
|
1900
|
+
const dashboardMessage = dashboardUrl ? `\n View this diff scan in the Socket dashboard: ${colors.cyan(dashboardUrl)}` : '';
|
|
1502
1901
|
|
|
1503
1902
|
// When forcing json, or dumping to file, serialize to string such that it
|
|
1504
1903
|
// won't get truncated. The only way to dump the full raw JSON to stdout is
|
|
@@ -1829,12 +2228,12 @@ async function getAlertsMapFromPnpmLockfile(lockfile, options) {
|
|
|
1829
2228
|
}
|
|
1830
2229
|
const getText = () => `Looking up data for ${remaining} packages`;
|
|
1831
2230
|
spinner?.start(getText());
|
|
1832
|
-
const
|
|
2231
|
+
const sockSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
|
|
1833
2232
|
const toAlertsMapOptions = {
|
|
1834
2233
|
overrides: lockfile.overrides,
|
|
1835
2234
|
...options
|
|
1836
2235
|
};
|
|
1837
|
-
for await (const batchPackageFetchResult of
|
|
2236
|
+
for await (const batchPackageFetchResult of sockSdk.batchPackageStream({
|
|
1838
2237
|
alerts: 'true',
|
|
1839
2238
|
compact: 'true',
|
|
1840
2239
|
fixable: include.unfixable ? 'false' : 'true'
|
|
@@ -2435,15 +2834,15 @@ async function run$x(argv, importMeta, {
|
|
|
2435
2834
|
}
|
|
2436
2835
|
|
|
2437
2836
|
async function fetchPackageInfo(pkgName, pkgVersion, includeAllIssues) {
|
|
2438
|
-
const
|
|
2837
|
+
const sockSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
|
|
2439
2838
|
|
|
2440
2839
|
// Lazily access constants.spinner.
|
|
2441
2840
|
const {
|
|
2442
2841
|
spinner
|
|
2443
2842
|
} = constants;
|
|
2444
2843
|
spinner.start(pkgVersion === 'latest' ? `Looking up data for the latest version of ${pkgName}` : `Looking up data for version ${pkgVersion} of ${pkgName}`);
|
|
2445
|
-
const result = await handleApiCall(
|
|
2446
|
-
const scoreResult = await handleApiCall(
|
|
2844
|
+
const result = await handleApiCall(sockSdk.getIssuesByNPMPackage(pkgName, pkgVersion), 'looking up package');
|
|
2845
|
+
const scoreResult = await handleApiCall(sockSdk.getScoreByNPMPackage(pkgName, pkgVersion), 'looking up package score');
|
|
2447
2846
|
spinner.successAndStop('Data fetched');
|
|
2448
2847
|
if (result.success === false) {
|
|
2449
2848
|
return handleUnsuccessfulApiResponse('getIssuesByNPMPackage', result);
|
|
@@ -2471,7 +2870,7 @@ function formatScore$1(score) {
|
|
|
2471
2870
|
return colors.red(`${score}`);
|
|
2472
2871
|
}
|
|
2473
2872
|
function outputPackageIssuesDetails(packageData, outputMarkdown) {
|
|
2474
|
-
const issueDetails = packageData.filter(d => d.value?.severity === shadowNpmInject.
|
|
2873
|
+
const issueDetails = packageData.filter(d => d.value?.severity === shadowNpmInject.ALERT_SEVERITY.critical || d.value?.severity === shadowNpmInject.ALERT_SEVERITY.high);
|
|
2475
2874
|
const uniqueIssueDetails = issueDetails.reduce((acc, issue) => {
|
|
2476
2875
|
const {
|
|
2477
2876
|
type
|
|
@@ -2658,18 +3057,18 @@ async function run$w(argv, importMeta, {
|
|
|
2658
3057
|
}
|
|
2659
3058
|
|
|
2660
3059
|
function applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy) {
|
|
2661
|
-
shadowNpmInject.
|
|
2662
|
-
shadowNpmInject.
|
|
2663
|
-
shadowNpmInject.
|
|
2664
|
-
shadowNpmInject.
|
|
3060
|
+
shadowNpmInject.updateConfigValue('enforcedOrgs', enforcedOrgs);
|
|
3061
|
+
shadowNpmInject.updateConfigValue('apiToken', apiToken);
|
|
3062
|
+
shadowNpmInject.updateConfigValue('apiBaseUrl', apiBaseUrl);
|
|
3063
|
+
shadowNpmInject.updateConfigValue('apiProxy', apiProxy);
|
|
2665
3064
|
}
|
|
2666
3065
|
|
|
2667
3066
|
const {
|
|
2668
3067
|
SOCKET_PUBLIC_API_TOKEN
|
|
2669
3068
|
} = constants;
|
|
2670
3069
|
async function attemptLogin(apiBaseUrl, apiProxy) {
|
|
2671
|
-
apiBaseUrl ??= shadowNpmInject.
|
|
2672
|
-
apiProxy ??= shadowNpmInject.
|
|
3070
|
+
apiBaseUrl ??= shadowNpmInject.getConfigValue('apiBaseUrl') ?? undefined;
|
|
3071
|
+
apiProxy ??= shadowNpmInject.getConfigValue('apiProxy') ?? undefined;
|
|
2673
3072
|
const apiToken = (await prompts.password({
|
|
2674
3073
|
message: `Enter your ${terminalLink('Socket.dev API key', 'https://docs.socket.dev/docs/api-keys')} (leave blank for a public key)`
|
|
2675
3074
|
})) || SOCKET_PUBLIC_API_TOKEN;
|
|
@@ -2725,7 +3124,7 @@ async function attemptLogin(apiBaseUrl, apiProxy) {
|
|
|
2725
3124
|
}
|
|
2726
3125
|
}
|
|
2727
3126
|
spinner.stop();
|
|
2728
|
-
const oldToken = shadowNpmInject.
|
|
3127
|
+
const oldToken = shadowNpmInject.getConfigValue('apiToken');
|
|
2729
3128
|
try {
|
|
2730
3129
|
applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy);
|
|
2731
3130
|
logger.logger.success(`API credentials ${oldToken ? 'updated' : 'set'}`);
|
|
@@ -2793,10 +3192,10 @@ async function run$v(argv, importMeta, {
|
|
|
2793
3192
|
}
|
|
2794
3193
|
|
|
2795
3194
|
function applyLogout() {
|
|
2796
|
-
shadowNpmInject.
|
|
2797
|
-
shadowNpmInject.
|
|
2798
|
-
shadowNpmInject.
|
|
2799
|
-
shadowNpmInject.
|
|
3195
|
+
shadowNpmInject.updateConfigValue('apiToken', null);
|
|
3196
|
+
shadowNpmInject.updateConfigValue('apiBaseUrl', null);
|
|
3197
|
+
shadowNpmInject.updateConfigValue('apiProxy', null);
|
|
3198
|
+
shadowNpmInject.updateConfigValue('enforcedOrgs', null);
|
|
2800
3199
|
}
|
|
2801
3200
|
|
|
2802
3201
|
function attemptLogout() {
|
|
@@ -4545,14 +4944,14 @@ async function fetchOrganization() {
|
|
|
4545
4944
|
return await fetchOrganizationWithToken(apiToken);
|
|
4546
4945
|
}
|
|
4547
4946
|
async function fetchOrganizationWithToken(apiToken) {
|
|
4548
|
-
const
|
|
4947
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
4549
4948
|
|
|
4550
4949
|
// Lazily access constants.spinner.
|
|
4551
4950
|
const {
|
|
4552
4951
|
spinner
|
|
4553
4952
|
} = constants;
|
|
4554
4953
|
spinner.start('Fetching organization list...');
|
|
4555
|
-
const result = await handleApiCall(
|
|
4954
|
+
const result = await handleApiCall(sockSdk.getOrganizations(), 'looking up organizations');
|
|
4556
4955
|
spinner.successAndStop('Received organization list response.');
|
|
4557
4956
|
if (!result.success) {
|
|
4558
4957
|
handleUnsuccessfulApiResponse('getOrganizations', result);
|
|
@@ -4682,9 +5081,9 @@ async function fetchSecurityPolicyWithToken(apiToken, orgSlug) {
|
|
|
4682
5081
|
const {
|
|
4683
5082
|
spinner
|
|
4684
5083
|
} = constants;
|
|
4685
|
-
const
|
|
5084
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
4686
5085
|
spinner.start('Fetching organization quota...');
|
|
4687
|
-
const result = await handleApiCall(
|
|
5086
|
+
const result = await handleApiCall(sockSdk.getOrgSecurityPolicy(orgSlug), 'looking up organization quota');
|
|
4688
5087
|
spinner?.successAndStop('Received organization quota response.');
|
|
4689
5088
|
if (!result.success) {
|
|
4690
5089
|
handleUnsuccessfulApiResponse('getOrgSecurityPolicy', result);
|
|
@@ -4827,9 +5226,9 @@ async function fetchQuotaWithToken(apiToken) {
|
|
|
4827
5226
|
const {
|
|
4828
5227
|
spinner
|
|
4829
5228
|
} = constants;
|
|
4830
|
-
const
|
|
5229
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
4831
5230
|
spinner.start('Fetching organization quota...');
|
|
4832
|
-
const result = await handleApiCall(
|
|
5231
|
+
const result = await handleApiCall(sockSdk.getQuota(), 'looking up organization quota');
|
|
4833
5232
|
spinner?.successAndStop('Recieved organization quota response.');
|
|
4834
5233
|
if (!result.success) {
|
|
4835
5234
|
handleUnsuccessfulApiResponse('getQuota', result);
|
|
@@ -4956,8 +5355,8 @@ async function fetchPurlsShallowScore(purls) {
|
|
|
4956
5355
|
spinner
|
|
4957
5356
|
} = constants;
|
|
4958
5357
|
spinner.start(`Requesting data ...`);
|
|
4959
|
-
const
|
|
4960
|
-
const result = await handleApiCall(
|
|
5358
|
+
const sockSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
|
|
5359
|
+
const result = await handleApiCall(sockSdk.batchPackageFetch({
|
|
4961
5360
|
alerts: 'true'
|
|
4962
5361
|
// compact: false,
|
|
4963
5362
|
// fixable: false,
|
|
@@ -5358,8 +5757,8 @@ async function createReport(socketConfig, inputPaths, {
|
|
|
5358
5757
|
const {
|
|
5359
5758
|
spinner
|
|
5360
5759
|
} = constants;
|
|
5361
|
-
const
|
|
5362
|
-
const supportedFiles = await
|
|
5760
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
5761
|
+
const supportedFiles = await sockSdk.getReportSupportedFiles().then(res => {
|
|
5363
5762
|
if (!res.success) handleUnsuccessfulApiResponse('getReportSupportedFiles', res);
|
|
5364
5763
|
return res.data;
|
|
5365
5764
|
}).catch(cause => {
|
|
@@ -5367,7 +5766,7 @@ async function createReport(socketConfig, inputPaths, {
|
|
|
5367
5766
|
cause
|
|
5368
5767
|
});
|
|
5369
5768
|
});
|
|
5370
|
-
const packagePaths = await shadowNpmPaths.
|
|
5769
|
+
const packagePaths = await shadowNpmPaths.getPackageFilesForScan(cwd, inputPaths, supportedFiles, socketConfig);
|
|
5371
5770
|
const packagePathsCount = packagePaths.length;
|
|
5372
5771
|
if (packagePathsCount && debug.isDebug()) {
|
|
5373
5772
|
for (const pkgPath of packagePaths) {
|
|
@@ -5379,7 +5778,7 @@ async function createReport(socketConfig, inputPaths, {
|
|
|
5379
5778
|
return undefined;
|
|
5380
5779
|
}
|
|
5381
5780
|
spinner.start(`Creating report with ${packagePathsCount} package ${words.pluralize('file', packagePathsCount)}`);
|
|
5382
|
-
const apiCall =
|
|
5781
|
+
const apiCall = sockSdk.createReportFromFilePaths(packagePaths, cwd, socketConfig?.issueRules);
|
|
5383
5782
|
const result = await handleApiCall(apiCall, 'creating report');
|
|
5384
5783
|
if (!result.success) {
|
|
5385
5784
|
handleUnsuccessfulApiResponse('createReport', result);
|
|
@@ -5390,8 +5789,8 @@ async function createReport(socketConfig, inputPaths, {
|
|
|
5390
5789
|
}
|
|
5391
5790
|
|
|
5392
5791
|
async function getSocketConfig(absoluteConfigPath) {
|
|
5393
|
-
const socketConfig = await config$
|
|
5394
|
-
if (cause && typeof cause === 'object' && cause instanceof config$
|
|
5792
|
+
const socketConfig = await config$H.readSocketConfig(absoluteConfigPath).catch(cause => {
|
|
5793
|
+
if (cause && typeof cause === 'object' && cause instanceof config$H.SocketValidationError) {
|
|
5395
5794
|
// Inspired by workbox-build:
|
|
5396
5795
|
// https://github.com/GoogleChrome/workbox/blob/95f97a207fd51efb3f8a653f6e3e58224183a778/packages/workbox-build/src/lib/validate-options.ts#L68-L71
|
|
5397
5796
|
const betterErrors = betterAjvErrors.betterAjvErrors({
|
|
@@ -5419,12 +5818,12 @@ async function fetchReportData$1(reportId, includeAllIssues, strict) {
|
|
|
5419
5818
|
} = constants;
|
|
5420
5819
|
spinner.log('Fetching report with ID ${reportId} (this could take a while)');
|
|
5421
5820
|
spinner.start(`Fetch started... (this could take a while)`);
|
|
5422
|
-
const
|
|
5821
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
5423
5822
|
let result;
|
|
5424
5823
|
for (let retry = 1; !result; ++retry) {
|
|
5425
5824
|
try {
|
|
5426
5825
|
// eslint-disable-next-line no-await-in-loop
|
|
5427
|
-
result = await handleApiCall(
|
|
5826
|
+
result = await handleApiCall(sockSdk.getReport(reportId), 'fetching report');
|
|
5428
5827
|
} catch (err) {
|
|
5429
5828
|
if (retry >= MAX_TIMEOUT_RETRY || !(err instanceof Error) || err.cause?.cause?.response?.statusCode !== HTTP_CODE_TIMEOUT) {
|
|
5430
5829
|
spinner.stop(`Failed to fetch report`);
|
|
@@ -5476,7 +5875,7 @@ function formatReportDataOutput(reportId, data, commandName, outputKind, strict,
|
|
|
5476
5875
|
}
|
|
5477
5876
|
}
|
|
5478
5877
|
|
|
5479
|
-
async function
|
|
5878
|
+
async function fetchScan(orgSlug, scanId) {
|
|
5480
5879
|
// Lazily access constants.spinner.
|
|
5481
5880
|
const {
|
|
5482
5881
|
spinner
|
|
@@ -5486,10 +5885,10 @@ async function getFullScan(orgSlug, fullScanId) {
|
|
|
5486
5885
|
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.');
|
|
5487
5886
|
}
|
|
5488
5887
|
spinner.start('Fetching full-scan...');
|
|
5489
|
-
const response = await
|
|
5888
|
+
const response = await queryApi(`orgs/${orgSlug}/full-scans/${encodeURIComponent(scanId)}`, apiToken);
|
|
5490
5889
|
spinner.stop('Fetch complete.');
|
|
5491
5890
|
if (!response.ok) {
|
|
5492
|
-
const err = await
|
|
5891
|
+
const err = await handleApiError(response.status);
|
|
5493
5892
|
logger.logger.fail(`${colors.bgRed(colors.white(response.statusText))}: Fetch error: ${err}`);
|
|
5494
5893
|
return;
|
|
5495
5894
|
}
|
|
@@ -5515,7 +5914,7 @@ async function viewReport(reportId, {
|
|
|
5515
5914
|
strict
|
|
5516
5915
|
}) {
|
|
5517
5916
|
const result = await fetchReportData$1(reportId, all, strict);
|
|
5518
|
-
const artifacts = await
|
|
5917
|
+
const artifacts = await fetchScan('socketdev', reportId);
|
|
5519
5918
|
if (result) {
|
|
5520
5919
|
formatReportDataOutput(reportId, result, commandName, outputKind, strict, artifacts);
|
|
5521
5920
|
}
|
|
@@ -5716,9 +6115,9 @@ async function fetchCreateRepoWithToken(apiToken, {
|
|
|
5716
6115
|
const {
|
|
5717
6116
|
spinner
|
|
5718
6117
|
} = constants;
|
|
5719
|
-
const
|
|
6118
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
5720
6119
|
spinner.start('Sending request ot create a repository...');
|
|
5721
|
-
const result = await handleApiCall(
|
|
6120
|
+
const result = await handleApiCall(sockSdk.createOrgRepo(orgSlug, {
|
|
5722
6121
|
name: repoName,
|
|
5723
6122
|
description,
|
|
5724
6123
|
homepage,
|
|
@@ -5863,8 +6262,8 @@ async function deleteRepoWithToken(orgSlug, repoName, apiToken) {
|
|
|
5863
6262
|
spinner
|
|
5864
6263
|
} = constants;
|
|
5865
6264
|
spinner.start('Deleting repository...');
|
|
5866
|
-
const
|
|
5867
|
-
const result = await handleApiCall(
|
|
6265
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
6266
|
+
const result = await handleApiCall(sockSdk.deleteOrgRepo(orgSlug, repoName), 'deleting repository');
|
|
5868
6267
|
if (!result.success) {
|
|
5869
6268
|
handleUnsuccessfulApiResponse('deleteOrgRepo', result);
|
|
5870
6269
|
return;
|
|
@@ -5959,9 +6358,9 @@ async function fetchListReposWithToken(apiToken, {
|
|
|
5959
6358
|
const {
|
|
5960
6359
|
spinner
|
|
5961
6360
|
} = constants;
|
|
5962
|
-
const
|
|
6361
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
5963
6362
|
spinner.start('Fetching list of repositories...');
|
|
5964
|
-
const result = await handleApiCall(
|
|
6363
|
+
const result = await handleApiCall(sockSdk.getOrgRepoList(orgSlug, {
|
|
5965
6364
|
sort,
|
|
5966
6365
|
direction,
|
|
5967
6366
|
per_page: String(per_page),
|
|
@@ -6148,8 +6547,8 @@ async function fetchUpdateRepoWithToken(apiToken, {
|
|
|
6148
6547
|
spinner
|
|
6149
6548
|
} = constants;
|
|
6150
6549
|
spinner.start('Sending request to update a repository...');
|
|
6151
|
-
const
|
|
6152
|
-
const result = await handleApiCall(
|
|
6550
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
6551
|
+
const result = await handleApiCall(sockSdk.updateOrgRepo(orgSlug, repoName, {
|
|
6153
6552
|
orgSlug,
|
|
6154
6553
|
name: repoName,
|
|
6155
6554
|
description,
|
|
@@ -6296,9 +6695,9 @@ async function fetchViewRepoWithToken(orgSlug, repoName, apiToken) {
|
|
|
6296
6695
|
const {
|
|
6297
6696
|
spinner
|
|
6298
6697
|
} = constants;
|
|
6299
|
-
const
|
|
6698
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
6300
6699
|
spinner.start('Fetching repository data...');
|
|
6301
|
-
const result = await handleApiCall(
|
|
6700
|
+
const result = await handleApiCall(sockSdk.getOrgRepo(orgSlug, repoName), 'fetching repository');
|
|
6302
6701
|
spinner.successAndStop('Received response while fetched repository data.');
|
|
6303
6702
|
if (!result.success) {
|
|
6304
6703
|
handleUnsuccessfulApiResponse('getOrgRepo', result);
|
|
@@ -6452,8 +6851,106 @@ const cmdRepos = {
|
|
|
6452
6851
|
}
|
|
6453
6852
|
};
|
|
6454
6853
|
|
|
6455
|
-
async function
|
|
6456
|
-
const
|
|
6854
|
+
async function fetchCreateOrgFullScan(packagePaths, orgSlug, repoName, branchName, commitMessage, defaultBranch, pendingHead, tmp, cwd) {
|
|
6855
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
6856
|
+
|
|
6857
|
+
// Lazily access constants.spinner.
|
|
6858
|
+
const {
|
|
6859
|
+
spinner
|
|
6860
|
+
} = constants;
|
|
6861
|
+
spinner.start(`Creating a scan with ${packagePaths.length} packages...`);
|
|
6862
|
+
const result = await handleApiCall(sockSdk.createOrgFullScan(orgSlug, {
|
|
6863
|
+
repo: repoName,
|
|
6864
|
+
branch: branchName,
|
|
6865
|
+
commit_message: commitMessage,
|
|
6866
|
+
make_default_branch: String(defaultBranch),
|
|
6867
|
+
set_as_pending_head: String(pendingHead),
|
|
6868
|
+
tmp: String(tmp)
|
|
6869
|
+
}, packagePaths, cwd), 'Creating scan');
|
|
6870
|
+
spinner.successAndStop('Scan created successfully');
|
|
6871
|
+
if (!result.success) {
|
|
6872
|
+
handleUnsuccessfulApiResponse('CreateOrgFullScan', result);
|
|
6873
|
+
return;
|
|
6874
|
+
}
|
|
6875
|
+
return result.data;
|
|
6876
|
+
}
|
|
6877
|
+
|
|
6878
|
+
async function fetchSupportedScanFileNames() {
|
|
6879
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
6880
|
+
|
|
6881
|
+
// Lazily access constants.spinner.
|
|
6882
|
+
const {
|
|
6883
|
+
spinner
|
|
6884
|
+
} = constants;
|
|
6885
|
+
spinner.start('Requesting supported scan file types from API...');
|
|
6886
|
+
const result = await handleApiCall(sockSdk.getReportSupportedFiles(), 'fetching supported scan file types');
|
|
6887
|
+
spinner.successAndStop('Received response while fetched supported scan file types.');
|
|
6888
|
+
if (!result.success) {
|
|
6889
|
+
handleUnsuccessfulApiResponse('getReportSupportedFiles', result);
|
|
6890
|
+
return;
|
|
6891
|
+
}
|
|
6892
|
+
return result.data;
|
|
6893
|
+
}
|
|
6894
|
+
|
|
6895
|
+
async function outputCreateNewScan(data) {
|
|
6896
|
+
const link = colors.underline(colors.cyan(`${data.html_report_url}`));
|
|
6897
|
+
logger.logger.log(`Available at: ${link}`);
|
|
6898
|
+
const rl = readline.createInterface({
|
|
6899
|
+
input: process$1.stdin,
|
|
6900
|
+
output: process$1.stdout
|
|
6901
|
+
});
|
|
6902
|
+
const answer = await rl.question('Would you like to open it in your browser? (y/n)');
|
|
6903
|
+
if (answer.toLowerCase() === 'y') {
|
|
6904
|
+
await open(`${data.html_report_url}`);
|
|
6905
|
+
}
|
|
6906
|
+
rl.close();
|
|
6907
|
+
}
|
|
6908
|
+
|
|
6909
|
+
async function handleCreateNewScan({
|
|
6910
|
+
branchName,
|
|
6911
|
+
commitMessage,
|
|
6912
|
+
cwd,
|
|
6913
|
+
defaultBranch,
|
|
6914
|
+
orgSlug,
|
|
6915
|
+
pendingHead,
|
|
6916
|
+
readOnly,
|
|
6917
|
+
repoName,
|
|
6918
|
+
targets,
|
|
6919
|
+
tmp
|
|
6920
|
+
}) {
|
|
6921
|
+
const apiToken = shadowNpmInject.getDefaultToken();
|
|
6922
|
+
|
|
6923
|
+
// Note: you need an apiToken to request supportedScanFileNames from the API
|
|
6924
|
+
if (!apiToken) {
|
|
6925
|
+
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.');
|
|
6926
|
+
}
|
|
6927
|
+
const supportedFileNames = await fetchSupportedScanFileNames();
|
|
6928
|
+
if (!supportedFileNames) return;
|
|
6929
|
+
const packagePaths = await shadowNpmPaths.getPackageFilesForScan(cwd, targets, supportedFileNames
|
|
6930
|
+
// socketConfig
|
|
6931
|
+
);
|
|
6932
|
+
if (!packagePaths.length) {
|
|
6933
|
+
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
6934
|
+
// options or missing arguments.
|
|
6935
|
+
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
6936
|
+
process$1.exitCode = 2;
|
|
6937
|
+
logger.logger.fail(commonTags.stripIndents`
|
|
6938
|
+
${colors.bgRed(colors.white('Input error'))}: The TARGET did not contain any matching / supported files for a scan
|
|
6939
|
+
`);
|
|
6940
|
+
return;
|
|
6941
|
+
}
|
|
6942
|
+
if (readOnly) {
|
|
6943
|
+
logger.logger.log('[ReadOnly] Bailing now');
|
|
6944
|
+
return;
|
|
6945
|
+
}
|
|
6946
|
+
const data = await fetchCreateOrgFullScan(packagePaths, orgSlug, repoName, branchName, commitMessage, defaultBranch, pendingHead, tmp, cwd);
|
|
6947
|
+
if (!data) return;
|
|
6948
|
+
await outputCreateNewScan(data);
|
|
6949
|
+
}
|
|
6950
|
+
|
|
6951
|
+
async function suggestOrgSlug() {
|
|
6952
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
6953
|
+
const result = await handleApiCall(sockSdk.getOrganizations(), 'looking up organizations');
|
|
6457
6954
|
// Ignore a failed request here. It was not the primary goal of
|
|
6458
6955
|
// running this command and reporting it only leads to end-user confusion.
|
|
6459
6956
|
if (result.success) {
|
|
@@ -6474,13 +6971,17 @@ async function suggestOrgSlug(socketSdk) {
|
|
|
6474
6971
|
if (proceed) {
|
|
6475
6972
|
return proceed;
|
|
6476
6973
|
}
|
|
6974
|
+
} else {
|
|
6975
|
+
logger.logger.fail('Failed to lookup organization list from API, unable to suggest.');
|
|
6477
6976
|
}
|
|
6478
6977
|
}
|
|
6479
6978
|
|
|
6480
|
-
async function suggestRepoSlug(
|
|
6979
|
+
async function suggestRepoSlug(orgSlug) {
|
|
6980
|
+
const sockSdk = await shadowNpmInject.setupSdk();
|
|
6981
|
+
|
|
6481
6982
|
// Same as above, but if there's a repo with the same name as cwd then
|
|
6482
6983
|
// default the selection to that name.
|
|
6483
|
-
const result = await handleApiCall(
|
|
6984
|
+
const result = await handleApiCall(sockSdk.getOrgRepoList(orgSlug, {
|
|
6484
6985
|
orgSlug,
|
|
6485
6986
|
sort: 'name',
|
|
6486
6987
|
direction: 'asc',
|
|
@@ -6490,6 +6991,7 @@ async function suggestRepoSlug(socketSdk, orgSlug) {
|
|
|
6490
6991
|
perPage: '10',
|
|
6491
6992
|
page: '0'
|
|
6492
6993
|
}), 'looking up known repos');
|
|
6994
|
+
|
|
6493
6995
|
// Ignore a failed request here. It was not the primary goal of
|
|
6494
6996
|
// running this command and reporting it only leads to end-user confusion.
|
|
6495
6997
|
if (result.success) {
|
|
@@ -6497,7 +6999,7 @@ async function suggestRepoSlug(socketSdk, orgSlug) {
|
|
|
6497
6999
|
let cwdIsKnown = !!currentDirName && result.data.results.some(obj => obj.slug === currentDirName);
|
|
6498
7000
|
if (!cwdIsKnown && currentDirName) {
|
|
6499
7001
|
// Do an explicit request so we can assert that the cwd exists or not
|
|
6500
|
-
const result = await handleApiCall(
|
|
7002
|
+
const result = await handleApiCall(sockSdk.getOrgRepo(orgSlug, currentDirName), 'checking if current cwd is a known repo');
|
|
6501
7003
|
if (result.success) {
|
|
6502
7004
|
cwdIsKnown = true;
|
|
6503
7005
|
}
|
|
@@ -6536,203 +7038,64 @@ async function suggestRepoSlug(socketSdk, orgSlug) {
|
|
|
6536
7038
|
}
|
|
6537
7039
|
});
|
|
6538
7040
|
return {
|
|
6539
|
-
slug: repoName,
|
|
6540
|
-
defaultBranch: repoDefaultBranch
|
|
6541
|
-
};
|
|
6542
|
-
}
|
|
6543
|
-
}
|
|
6544
|
-
}
|
|
6545
|
-
function dirNameToSlug(name) {
|
|
6546
|
-
// Uses slug specs asserted by our servers
|
|
6547
|
-
// Note: this can lead to collisions; eg. slug for `x--y` and `x---y` is `x-y`
|
|
6548
|
-
return name.toLowerCase().replace(/[^[a-zA-Z0-9_.-]/g, '_').replace(/--+/g, '-').replace(/__+/g, '_').replace(/\.\.+/g, '.').replace(/[._-]+$/, '');
|
|
6549
|
-
}
|
|
6550
|
-
|
|
6551
|
-
async function suggestBranchSlug(repoDefaultBranch) {
|
|
6552
|
-
const spawnResult = spawn.spawnSync('git', ['branch', '--show-current']);
|
|
6553
|
-
const currentBranch = spawnResult.stdout.toString('utf8').trim();
|
|
6554
|
-
if (currentBranch && spawnResult.status === 0) {
|
|
6555
|
-
const proceed = await prompts.select({
|
|
6556
|
-
message: 'Use the current git branch as target branch name?',
|
|
6557
|
-
choices: [{
|
|
6558
|
-
name: `Yes [${currentBranch}]`,
|
|
6559
|
-
value: currentBranch,
|
|
6560
|
-
description: 'Use the current git branch for branch name'
|
|
6561
|
-
}, ...(repoDefaultBranch && repoDefaultBranch !== currentBranch ? [{
|
|
6562
|
-
name: `No, use the default branch [${repoDefaultBranch}]`,
|
|
6563
|
-
value: repoDefaultBranch,
|
|
6564
|
-
description: 'Use the default branch for target repo as the target branch name'
|
|
6565
|
-
}] : []), {
|
|
6566
|
-
name: 'No',
|
|
6567
|
-
value: '',
|
|
6568
|
-
description: 'Do not use the current git branch as name (will end in a no-op)'
|
|
6569
|
-
}].filter(Boolean)
|
|
6570
|
-
});
|
|
6571
|
-
if (proceed) {
|
|
6572
|
-
return proceed;
|
|
6573
|
-
}
|
|
6574
|
-
}
|
|
6575
|
-
}
|
|
6576
|
-
|
|
6577
|
-
async function suggestTarget() {
|
|
6578
|
-
// We could prefill this with sub-dirs of the current
|
|
6579
|
-
// dir ... but is that going to be useful?
|
|
6580
|
-
const proceed = await prompts.select({
|
|
6581
|
-
message: 'No TARGET given. Do you want to use the current directory?',
|
|
6582
|
-
choices: [{
|
|
6583
|
-
name: 'Yes',
|
|
6584
|
-
value: true,
|
|
6585
|
-
description: 'Target the current directory'
|
|
6586
|
-
}, {
|
|
6587
|
-
name: 'No',
|
|
6588
|
-
value: false,
|
|
6589
|
-
description: 'Do not use the current directory (this will end in a no-op)'
|
|
6590
|
-
}]
|
|
6591
|
-
});
|
|
6592
|
-
if (proceed) {
|
|
6593
|
-
return ['.'];
|
|
6594
|
-
}
|
|
6595
|
-
}
|
|
6596
|
-
|
|
6597
|
-
async function createFullScan({
|
|
6598
|
-
branchName,
|
|
6599
|
-
commitHash: _commitHash,
|
|
6600
|
-
commitMessage,
|
|
6601
|
-
committers: _committers,
|
|
6602
|
-
cwd,
|
|
6603
|
-
defaultBranch,
|
|
6604
|
-
orgSlug,
|
|
6605
|
-
pendingHead,
|
|
6606
|
-
pullRequest: _pullRequest,
|
|
6607
|
-
readOnly,
|
|
6608
|
-
repoName,
|
|
6609
|
-
targets,
|
|
6610
|
-
tmp
|
|
6611
|
-
}) {
|
|
6612
|
-
// Lazily access constants.spinner.
|
|
6613
|
-
const {
|
|
6614
|
-
spinner
|
|
6615
|
-
} = constants;
|
|
6616
|
-
const socketSdk = await shadowNpmInject.setupSdk();
|
|
6617
|
-
const supportedFiles = await socketSdk.getReportSupportedFiles().then(res => {
|
|
6618
|
-
if (!res.success) {
|
|
6619
|
-
handleUnsuccessfulApiResponse('getReportSupportedFiles', res);
|
|
6620
|
-
assert(false, 'handleUnsuccessfulApiResponse should unconditionally throw');
|
|
6621
|
-
}
|
|
6622
|
-
return res.data;
|
|
6623
|
-
}).catch(cause => {
|
|
6624
|
-
throw new Error('Failed getting supported files for report', {
|
|
6625
|
-
cause
|
|
6626
|
-
});
|
|
6627
|
-
});
|
|
6628
|
-
|
|
6629
|
-
// If we updated any inputs then we should print the command line to repeat
|
|
6630
|
-
// the command without requiring user input, as a suggestion.
|
|
6631
|
-
let updatedInput = false;
|
|
6632
|
-
if (!targets.length) {
|
|
6633
|
-
const received = await suggestTarget();
|
|
6634
|
-
targets = received ?? [];
|
|
6635
|
-
updatedInput = true;
|
|
6636
|
-
}
|
|
6637
|
-
|
|
6638
|
-
// // TODO: we'll probably use socket.json or something else soon...
|
|
6639
|
-
// const absoluteConfigPath = path.join(cwd, 'socket.yml')
|
|
6640
|
-
// const socketConfig = await getSocketConfig(absoluteConfigPath)
|
|
6641
|
-
|
|
6642
|
-
const packagePaths = await shadowNpmPaths.getPackageFilesFullScans(cwd, targets, supportedFiles
|
|
6643
|
-
// socketConfig
|
|
6644
|
-
);
|
|
6645
|
-
|
|
6646
|
-
// We're going to need an api token to suggest data because those suggestions
|
|
6647
|
-
// must come from data we already know. Don't error on missing api token yet.
|
|
6648
|
-
// If the api-token is not set, ignore it for the sake of suggestions.
|
|
6649
|
-
const apiToken = shadowNpmInject.getDefaultToken();
|
|
6650
|
-
|
|
6651
|
-
// If the current cwd is unknown and is used as a repo slug anyways, we will
|
|
6652
|
-
// first need to register the slug before we can use it.
|
|
6653
|
-
let repoDefaultBranch = '';
|
|
6654
|
-
if (apiToken) {
|
|
6655
|
-
if (!orgSlug) {
|
|
6656
|
-
const suggestion = await suggestOrgSlug(socketSdk);
|
|
6657
|
-
if (suggestion) orgSlug = suggestion;
|
|
6658
|
-
updatedInput = true;
|
|
6659
|
-
}
|
|
6660
|
-
|
|
6661
|
-
// (Don't bother asking for the rest if we didn't get an org slug above)
|
|
6662
|
-
if (orgSlug && !repoName) {
|
|
6663
|
-
const suggestion = await suggestRepoSlug(socketSdk, orgSlug);
|
|
6664
|
-
if (suggestion) {
|
|
6665
|
-
repoDefaultBranch = suggestion.defaultBranch;
|
|
6666
|
-
repoName = suggestion.slug;
|
|
6667
|
-
}
|
|
6668
|
-
updatedInput = true;
|
|
6669
|
-
}
|
|
6670
|
-
|
|
6671
|
-
// (Don't bother asking for the rest if we didn't get an org/repo above)
|
|
6672
|
-
if (orgSlug && repoName && !branchName) {
|
|
6673
|
-
const suggestion = await suggestBranchSlug(repoDefaultBranch);
|
|
6674
|
-
if (suggestion) branchName = suggestion;
|
|
6675
|
-
updatedInput = true;
|
|
7041
|
+
slug: repoName,
|
|
7042
|
+
defaultBranch: repoDefaultBranch
|
|
7043
|
+
};
|
|
6676
7044
|
}
|
|
7045
|
+
} else {
|
|
7046
|
+
logger.logger.fail('Failed to lookup repo list from API, unable to suggest.');
|
|
6677
7047
|
}
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
|
|
6685
|
-
|
|
6686
|
-
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6687
|
-
|
|
6688
|
-
- Repository name using --repo ${!repoName ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6689
|
-
|
|
6690
|
-
- Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6691
|
-
|
|
6692
|
-
- 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)')}
|
|
7048
|
+
}
|
|
7049
|
+
function dirNameToSlug(name) {
|
|
7050
|
+
// Uses slug specs asserted by our servers
|
|
7051
|
+
// Note: this can lead to collisions; eg. slug for `x--y` and `x---y` is `x-y`
|
|
7052
|
+
return name.toLowerCase().replace(/[^[a-zA-Z0-9_.-]/g, '_').replace(/--+/g, '-').replace(/__+/g, '_').replace(/\.\.+/g, '.').replace(/[._-]+$/, '');
|
|
7053
|
+
}
|
|
6693
7054
|
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
set_as_pending_head: String(pendingHead),
|
|
6718
|
-
tmp: String(tmp)
|
|
6719
|
-
}, packagePaths, cwd), 'Creating scan');
|
|
6720
|
-
if (!result.success) {
|
|
6721
|
-
handleUnsuccessfulApiResponse('CreateOrgFullScan', result);
|
|
6722
|
-
return;
|
|
7055
|
+
async function suggestBranchSlug(repoDefaultBranch) {
|
|
7056
|
+
const spawnResult = spawn.spawnSync('git', ['branch', '--show-current']);
|
|
7057
|
+
const currentBranch = spawnResult.stdout.toString('utf8').trim();
|
|
7058
|
+
if (currentBranch && spawnResult.status === 0) {
|
|
7059
|
+
const proceed = await prompts.select({
|
|
7060
|
+
message: 'Use the current git branch as target branch name?',
|
|
7061
|
+
choices: [{
|
|
7062
|
+
name: `Yes [${currentBranch}]`,
|
|
7063
|
+
value: currentBranch,
|
|
7064
|
+
description: 'Use the current git branch for branch name'
|
|
7065
|
+
}, ...(repoDefaultBranch && repoDefaultBranch !== currentBranch ? [{
|
|
7066
|
+
name: `No, use the default branch [${repoDefaultBranch}]`,
|
|
7067
|
+
value: repoDefaultBranch,
|
|
7068
|
+
description: 'Use the default branch for target repo as the target branch name'
|
|
7069
|
+
}] : []), {
|
|
7070
|
+
name: 'No',
|
|
7071
|
+
value: '',
|
|
7072
|
+
description: 'Do not use the current git branch as name (will end in a no-op)'
|
|
7073
|
+
}].filter(Boolean)
|
|
7074
|
+
});
|
|
7075
|
+
if (proceed) {
|
|
7076
|
+
return proceed;
|
|
7077
|
+
}
|
|
6723
7078
|
}
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
|
|
7079
|
+
}
|
|
7080
|
+
|
|
7081
|
+
async function suggestTarget() {
|
|
7082
|
+
// We could prefill this with sub-dirs of the current
|
|
7083
|
+
// dir ... but is that going to be useful?
|
|
7084
|
+
const proceed = await prompts.select({
|
|
7085
|
+
message: 'No TARGET given. Do you want to use the current directory?',
|
|
7086
|
+
choices: [{
|
|
7087
|
+
name: 'Yes',
|
|
7088
|
+
value: true,
|
|
7089
|
+
description: 'Target the current directory'
|
|
7090
|
+
}, {
|
|
7091
|
+
name: 'No',
|
|
7092
|
+
value: false,
|
|
7093
|
+
description: 'Do not use the current directory (this will end in a no-op)'
|
|
7094
|
+
}]
|
|
6730
7095
|
});
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
await open(`${result.data.html_report_url}`);
|
|
7096
|
+
if (proceed) {
|
|
7097
|
+
return ['.'];
|
|
6734
7098
|
}
|
|
6735
|
-
rl.close();
|
|
6736
7099
|
}
|
|
6737
7100
|
|
|
6738
7101
|
const {
|
|
@@ -6856,18 +7219,66 @@ async function run$7(argv, importMeta, {
|
|
|
6856
7219
|
importMeta,
|
|
6857
7220
|
parentName
|
|
6858
7221
|
});
|
|
6859
|
-
const [orgSlug = '', ...targets] = cli.input;
|
|
6860
|
-
const cwd = cli.flags['cwd'] && cli.flags['cwd'] !== 'process.cwd()' ? String(cli.flags['cwd']) : process$1.cwd();
|
|
6861
7222
|
const {
|
|
7223
|
+
cwd: cwdOverride,
|
|
7224
|
+
dryRun
|
|
7225
|
+
} = cli.flags;
|
|
7226
|
+
const cwd = cwdOverride && cwdOverride !== 'process.cwd()' ? String(cwdOverride) : process$1.cwd();
|
|
7227
|
+
let {
|
|
6862
7228
|
branch: branchName,
|
|
6863
7229
|
repo: repoName
|
|
6864
7230
|
} = cli.flags;
|
|
6865
|
-
|
|
7231
|
+
let [orgSlug = '', ...targets] = cli.input;
|
|
6866
7232
|
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
7233
|
+
// We're going to need an api token to suggest data because those suggestions
|
|
7234
|
+
// must come from data we already know. Don't error on missing api token yet.
|
|
7235
|
+
// If the api-token is not set, ignore it for the sake of suggestions.
|
|
7236
|
+
const apiToken = shadowNpmInject.getDefaultToken();
|
|
7237
|
+
|
|
7238
|
+
// If we updated any inputs then we should print the command line to repeat
|
|
7239
|
+
// the command without requiring user input, as a suggestion.
|
|
7240
|
+
let updatedInput = false;
|
|
7241
|
+
if (!targets.length && !dryRun) {
|
|
7242
|
+
const received = await suggestTarget();
|
|
7243
|
+
targets = received ?? [];
|
|
7244
|
+
updatedInput = true;
|
|
7245
|
+
}
|
|
7246
|
+
|
|
7247
|
+
// If the current cwd is unknown and is used as a repo slug anyways, we will
|
|
7248
|
+
// first need to register the slug before we can use it.
|
|
7249
|
+
let repoDefaultBranch = '';
|
|
7250
|
+
// Only do suggestions with an apiToken and when not in dryRun mode
|
|
7251
|
+
if (apiToken && !dryRun) {
|
|
7252
|
+
if (!orgSlug) {
|
|
7253
|
+
const suggestion = await suggestOrgSlug();
|
|
7254
|
+
if (suggestion) orgSlug = suggestion;
|
|
7255
|
+
updatedInput = true;
|
|
7256
|
+
}
|
|
7257
|
+
|
|
7258
|
+
// (Don't bother asking for the rest if we didn't get an org slug above)
|
|
7259
|
+
if (orgSlug && !repoName) {
|
|
7260
|
+
const suggestion = await suggestRepoSlug(orgSlug);
|
|
7261
|
+
if (suggestion) {
|
|
7262
|
+
repoDefaultBranch = suggestion.defaultBranch;
|
|
7263
|
+
repoName = suggestion.slug;
|
|
7264
|
+
}
|
|
7265
|
+
updatedInput = true;
|
|
7266
|
+
}
|
|
7267
|
+
|
|
7268
|
+
// (Don't bother asking for the rest if we didn't get an org/repo above)
|
|
7269
|
+
if (orgSlug && repoName && !branchName) {
|
|
7270
|
+
const suggestion = await suggestBranchSlug(repoDefaultBranch);
|
|
7271
|
+
if (suggestion) branchName = suggestion;
|
|
7272
|
+
updatedInput = true;
|
|
7273
|
+
}
|
|
7274
|
+
}
|
|
7275
|
+
if (updatedInput && repoName && branchName && orgSlug && targets?.length) {
|
|
7276
|
+
logger.logger.error('Note: You can invoke this command next time to skip the interactive questions:');
|
|
7277
|
+
logger.logger.error('```');
|
|
7278
|
+
logger.logger.error(` socket scan create [other flags...] --repo ${repoName} --branch ${branchName} ${orgSlug} ${targets.join(' ')}`);
|
|
7279
|
+
logger.logger.error('```\n');
|
|
7280
|
+
}
|
|
7281
|
+
if (!orgSlug || !repoName || !branchName || !targets.length) {
|
|
6871
7282
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
6872
7283
|
// options or missing arguments.
|
|
6873
7284
|
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
@@ -6881,28 +7292,25 @@ async function run$7(argv, importMeta, {
|
|
|
6881
7292
|
|
|
6882
7293
|
- Branch name using --branch ${!branchName ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6883
7294
|
|
|
6884
|
-
- At least one TARGET (e.g. \`.\` or \`./package.json\`) ${!targets.length ? '(missing)' : colors.green('(ok)')}
|
|
7295
|
+
- At least one TARGET (e.g. \`.\` or \`./package.json\`) ${!targets.length ? colors.red('(missing)') : colors.green('(ok)')}
|
|
6885
7296
|
|
|
6886
|
-
|
|
7297
|
+
${!apiToken ? 'Note: was unable to make suggestions because no API Token was found; this would make the command fail regardless' : ''}
|
|
6887
7298
|
`);
|
|
6888
7299
|
return;
|
|
6889
7300
|
}
|
|
6890
7301
|
|
|
6891
7302
|
// Note exiting earlier to skirt a hidden auth requirement
|
|
6892
|
-
if (
|
|
7303
|
+
if (dryRun) {
|
|
6893
7304
|
logger.logger.log(DRY_RUN_BAIL_TEXT$7);
|
|
6894
7305
|
return;
|
|
6895
7306
|
}
|
|
6896
|
-
await
|
|
7307
|
+
await handleCreateNewScan({
|
|
6897
7308
|
branchName: branchName,
|
|
6898
|
-
commitHash: cli.flags['commitHash'] ?? '',
|
|
6899
7309
|
commitMessage: cli.flags['commitMessage'] ?? '',
|
|
6900
|
-
committers: cli.flags['committers'] ?? '',
|
|
6901
7310
|
cwd,
|
|
6902
7311
|
defaultBranch: Boolean(cli.flags['defaultBranch']),
|
|
6903
7312
|
orgSlug,
|
|
6904
7313
|
pendingHead: Boolean(cli.flags['pendingHead']),
|
|
6905
|
-
pullRequest: cli.flags['pullRequest'] ?? undefined,
|
|
6906
7314
|
readOnly: Boolean(cli.flags['readOnly']),
|
|
6907
7315
|
repoName: repoName,
|
|
6908
7316
|
targets,
|
|
@@ -6910,26 +7318,37 @@ async function run$7(argv, importMeta, {
|
|
|
6910
7318
|
});
|
|
6911
7319
|
}
|
|
6912
7320
|
|
|
6913
|
-
async function
|
|
7321
|
+
async function fetchDeleteOrgFullScan(orgSlug, scanId) {
|
|
6914
7322
|
const apiToken = shadowNpmInject.getDefaultToken();
|
|
6915
7323
|
if (!apiToken) {
|
|
6916
7324
|
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.');
|
|
6917
7325
|
}
|
|
6918
|
-
await
|
|
7326
|
+
await fetchDeleteOrgFullScanWithToken(apiToken, orgSlug, scanId);
|
|
6919
7327
|
}
|
|
6920
|
-
async function
|
|
7328
|
+
async function fetchDeleteOrgFullScanWithToken(apiToken, orgSlug, scanId) {
|
|
6921
7329
|
// Lazily access constants.spinner.
|
|
6922
7330
|
const {
|
|
6923
7331
|
spinner
|
|
6924
7332
|
} = constants;
|
|
6925
|
-
|
|
6926
|
-
|
|
6927
|
-
const result = await handleApiCall(
|
|
7333
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
7334
|
+
spinner.start('Requesting the scan to be deleted...');
|
|
7335
|
+
const result = await handleApiCall(sockSdk.deleteOrgFullScan(orgSlug, scanId), 'Deleting scan');
|
|
7336
|
+
spinner.successAndStop('Received response for deleting a scan.');
|
|
6928
7337
|
if (!result.success) {
|
|
6929
7338
|
handleUnsuccessfulApiResponse('deleteOrgFullScan', result);
|
|
6930
7339
|
return;
|
|
6931
7340
|
}
|
|
6932
|
-
|
|
7341
|
+
return result.data;
|
|
7342
|
+
}
|
|
7343
|
+
|
|
7344
|
+
async function outputDeleteScan(_data) {
|
|
7345
|
+
logger.logger.success('Scan deleted successfully');
|
|
7346
|
+
}
|
|
7347
|
+
|
|
7348
|
+
async function handleDeleteScan(orgSlug, scanId) {
|
|
7349
|
+
const data = await fetchDeleteOrgFullScan(orgSlug, scanId);
|
|
7350
|
+
if (!data) return;
|
|
7351
|
+
await outputDeleteScan();
|
|
6933
7352
|
}
|
|
6934
7353
|
|
|
6935
7354
|
const {
|
|
@@ -6968,8 +7387,8 @@ async function run$6(argv, importMeta, {
|
|
|
6968
7387
|
importMeta,
|
|
6969
7388
|
parentName
|
|
6970
7389
|
});
|
|
6971
|
-
const [orgSlug = '',
|
|
6972
|
-
if (!orgSlug || !
|
|
7390
|
+
const [orgSlug = '', scanId = ''] = cli.input;
|
|
7391
|
+
if (!orgSlug || !scanId) {
|
|
6973
7392
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
6974
7393
|
// options or missing arguments.
|
|
6975
7394
|
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
@@ -6978,22 +7397,20 @@ async function run$6(argv, importMeta, {
|
|
|
6978
7397
|
|
|
6979
7398
|
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
6980
7399
|
|
|
6981
|
-
- Full Scan ID to delete as second argument ${!
|
|
7400
|
+
- Full Scan ID to delete as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
|
|
6982
7401
|
return;
|
|
6983
7402
|
}
|
|
6984
7403
|
if (cli.flags['dryRun']) {
|
|
6985
7404
|
logger.logger.log(DRY_RUN_BAIL_TEXT$6);
|
|
6986
7405
|
return;
|
|
6987
7406
|
}
|
|
6988
|
-
await
|
|
7407
|
+
await handleDeleteScan(orgSlug, scanId);
|
|
6989
7408
|
}
|
|
6990
7409
|
|
|
6991
|
-
|
|
6992
|
-
async function listFullScans({
|
|
7410
|
+
async function fetchListScans({
|
|
6993
7411
|
direction,
|
|
6994
7412
|
from_time,
|
|
6995
7413
|
orgSlug,
|
|
6996
|
-
outputKind,
|
|
6997
7414
|
page,
|
|
6998
7415
|
per_page,
|
|
6999
7416
|
sort
|
|
@@ -7002,23 +7419,19 @@ async function listFullScans({
|
|
|
7002
7419
|
if (!apiToken) {
|
|
7003
7420
|
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.');
|
|
7004
7421
|
}
|
|
7005
|
-
await
|
|
7006
|
-
apiToken,
|
|
7422
|
+
await fetchListScansWithToken(apiToken, {
|
|
7007
7423
|
direction,
|
|
7008
7424
|
from_time,
|
|
7009
7425
|
orgSlug,
|
|
7010
|
-
outputKind,
|
|
7011
7426
|
page,
|
|
7012
7427
|
per_page,
|
|
7013
7428
|
sort
|
|
7014
7429
|
});
|
|
7015
7430
|
}
|
|
7016
|
-
async function
|
|
7017
|
-
apiToken,
|
|
7431
|
+
async function fetchListScansWithToken(apiToken, {
|
|
7018
7432
|
direction,
|
|
7019
7433
|
from_time,
|
|
7020
7434
|
orgSlug,
|
|
7021
|
-
outputKind,
|
|
7022
7435
|
page,
|
|
7023
7436
|
per_page,
|
|
7024
7437
|
sort
|
|
@@ -7027,22 +7440,27 @@ async function listFullScansWithToken({
|
|
|
7027
7440
|
const {
|
|
7028
7441
|
spinner
|
|
7029
7442
|
} = constants;
|
|
7443
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
7030
7444
|
spinner.start('Fetching list of scans...');
|
|
7031
|
-
const
|
|
7032
|
-
const result = await handleApiCall(socketSdk.getOrgFullScanList(orgSlug, {
|
|
7445
|
+
const result = await handleApiCall(sockSdk.getOrgFullScanList(orgSlug, {
|
|
7033
7446
|
sort,
|
|
7034
7447
|
direction,
|
|
7035
7448
|
per_page: String(per_page),
|
|
7036
7449
|
page: String(page),
|
|
7037
7450
|
from: from_time
|
|
7038
7451
|
}), 'Listing scans');
|
|
7452
|
+
spinner.successAndStop(`Received response for list of scans.`);
|
|
7039
7453
|
if (!result.success) {
|
|
7040
7454
|
handleUnsuccessfulApiResponse('getOrgFullScanList', result);
|
|
7041
7455
|
return;
|
|
7042
7456
|
}
|
|
7043
|
-
|
|
7457
|
+
return result.data;
|
|
7458
|
+
}
|
|
7459
|
+
|
|
7460
|
+
// @ts-ignore
|
|
7461
|
+
async function outputListScans(data, outputKind) {
|
|
7044
7462
|
if (outputKind === 'json') {
|
|
7045
|
-
logger.logger.log(
|
|
7463
|
+
logger.logger.log(data);
|
|
7046
7464
|
return;
|
|
7047
7465
|
}
|
|
7048
7466
|
const options = {
|
|
@@ -7060,7 +7478,7 @@ async function listFullScansWithToken({
|
|
|
7060
7478
|
name: colors.magenta('Created at')
|
|
7061
7479
|
}]
|
|
7062
7480
|
};
|
|
7063
|
-
const formattedResults =
|
|
7481
|
+
const formattedResults = data.results.map(d => {
|
|
7064
7482
|
return {
|
|
7065
7483
|
id: d.id,
|
|
7066
7484
|
report_url: colors.underline(`${d.html_report_url}`),
|
|
@@ -7075,6 +7493,27 @@ async function listFullScansWithToken({
|
|
|
7075
7493
|
logger.logger.log(chalkTable(options, formattedResults));
|
|
7076
7494
|
}
|
|
7077
7495
|
|
|
7496
|
+
async function handleListScans({
|
|
7497
|
+
direction,
|
|
7498
|
+
from_time,
|
|
7499
|
+
orgSlug,
|
|
7500
|
+
outputKind,
|
|
7501
|
+
page,
|
|
7502
|
+
per_page,
|
|
7503
|
+
sort
|
|
7504
|
+
}) {
|
|
7505
|
+
const data = await fetchListScans({
|
|
7506
|
+
direction,
|
|
7507
|
+
from_time,
|
|
7508
|
+
orgSlug,
|
|
7509
|
+
page,
|
|
7510
|
+
per_page,
|
|
7511
|
+
sort
|
|
7512
|
+
});
|
|
7513
|
+
if (!data) return;
|
|
7514
|
+
await outputListScans(data, outputKind);
|
|
7515
|
+
}
|
|
7516
|
+
|
|
7078
7517
|
const {
|
|
7079
7518
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$5
|
|
7080
7519
|
} = constants;
|
|
@@ -7162,7 +7601,7 @@ async function run$5(argv, importMeta, {
|
|
|
7162
7601
|
logger.logger.log(DRY_RUN_BAIL_TEXT$5);
|
|
7163
7602
|
return;
|
|
7164
7603
|
}
|
|
7165
|
-
await
|
|
7604
|
+
await handleListScans({
|
|
7166
7605
|
direction: String(cli.flags['direction'] || ''),
|
|
7167
7606
|
from_time: String(cli.flags['fromTime'] || ''),
|
|
7168
7607
|
orgSlug,
|
|
@@ -7173,46 +7612,56 @@ async function run$5(argv, importMeta, {
|
|
|
7173
7612
|
});
|
|
7174
7613
|
}
|
|
7175
7614
|
|
|
7176
|
-
async function
|
|
7615
|
+
async function fetchScanMetadata(orgSlug, scanId) {
|
|
7177
7616
|
const apiToken = shadowNpmInject.getDefaultToken();
|
|
7178
7617
|
if (!apiToken) {
|
|
7179
7618
|
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.');
|
|
7180
7619
|
}
|
|
7181
|
-
await
|
|
7620
|
+
await fetchScanMetadataWithToken(apiToken, orgSlug, scanId);
|
|
7182
7621
|
}
|
|
7183
|
-
async function
|
|
7622
|
+
async function fetchScanMetadataWithToken(apiToken, orgSlug, scanId) {
|
|
7184
7623
|
// Lazily access constants.spinner.
|
|
7185
7624
|
const {
|
|
7186
7625
|
spinner
|
|
7187
7626
|
} = constants;
|
|
7627
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
7188
7628
|
spinner.start('Fetching meta data for a full scan...');
|
|
7189
|
-
const
|
|
7190
|
-
|
|
7629
|
+
const result = await handleApiCall(sockSdk.getOrgFullScanMetadata(orgSlug, scanId), 'Listing scans');
|
|
7630
|
+
spinner.successAndStop('Received response for scan meta data.');
|
|
7191
7631
|
if (!result.success) {
|
|
7192
7632
|
handleUnsuccessfulApiResponse('getOrgFullScanMetadata', result);
|
|
7193
7633
|
return;
|
|
7194
7634
|
}
|
|
7195
|
-
|
|
7635
|
+
return result.data;
|
|
7636
|
+
}
|
|
7637
|
+
|
|
7638
|
+
async function outputScanMetadata(data, scanId, outputKind) {
|
|
7196
7639
|
if (outputKind === 'json') {
|
|
7197
|
-
logger.logger.log(
|
|
7640
|
+
logger.logger.log(data);
|
|
7198
7641
|
} else {
|
|
7199
7642
|
// Markdown = print
|
|
7200
7643
|
if (outputKind === 'markdown') {
|
|
7201
7644
|
logger.logger.log('# Scan meta data\n');
|
|
7202
7645
|
}
|
|
7203
7646
|
logger.logger.log(`Scan ID: ${scanId}\n`);
|
|
7204
|
-
for (const [key, value] of Object.entries(
|
|
7647
|
+
for (const [key, value] of Object.entries(data)) {
|
|
7205
7648
|
if (['id', 'updated_at', 'organization_id', 'repository_id', 'commit_hash', 'html_report_url'].includes(key)) continue;
|
|
7206
7649
|
logger.logger.log(`- ${key}:`, value);
|
|
7207
7650
|
}
|
|
7208
7651
|
if (outputKind === 'markdown') {
|
|
7209
|
-
logger.logger.log(`\nYou can view this report at: [${
|
|
7652
|
+
logger.logger.log(`\nYou can view this report at: [${data.html_report_url}](${data.html_report_url})\n`);
|
|
7210
7653
|
} else {
|
|
7211
|
-
logger.logger.log(`\nYou can view this report at: ${
|
|
7654
|
+
logger.logger.log(`\nYou can view this report at: ${data.html_report_url}]\n`);
|
|
7212
7655
|
}
|
|
7213
7656
|
}
|
|
7214
7657
|
}
|
|
7215
7658
|
|
|
7659
|
+
async function handleOrgScanMetadata(orgSlug, scanId, outputKind) {
|
|
7660
|
+
const data = await fetchScanMetadata(orgSlug, scanId);
|
|
7661
|
+
if (!data) return;
|
|
7662
|
+
await outputScanMetadata(data, scanId, outputKind);
|
|
7663
|
+
}
|
|
7664
|
+
|
|
7216
7665
|
const {
|
|
7217
7666
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$4
|
|
7218
7667
|
} = constants;
|
|
@@ -7249,8 +7698,8 @@ async function run$4(argv, importMeta, {
|
|
|
7249
7698
|
importMeta,
|
|
7250
7699
|
parentName
|
|
7251
7700
|
});
|
|
7252
|
-
const [orgSlug = '',
|
|
7253
|
-
if (!orgSlug || !
|
|
7701
|
+
const [orgSlug = '', scanId = ''] = cli.input;
|
|
7702
|
+
if (!orgSlug || !scanId) {
|
|
7254
7703
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
7255
7704
|
// options or missing arguments.
|
|
7256
7705
|
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
@@ -7259,14 +7708,14 @@ async function run$4(argv, importMeta, {
|
|
|
7259
7708
|
|
|
7260
7709
|
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7261
7710
|
|
|
7262
|
-
- Full Scan ID to inspect as second argument ${!
|
|
7711
|
+
- Full Scan ID to inspect as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}`);
|
|
7263
7712
|
return;
|
|
7264
7713
|
}
|
|
7265
7714
|
if (cli.flags['dryRun']) {
|
|
7266
7715
|
logger.logger.log(DRY_RUN_BAIL_TEXT$4);
|
|
7267
7716
|
return;
|
|
7268
7717
|
}
|
|
7269
|
-
await
|
|
7718
|
+
await handleOrgScanMetadata(orgSlug, scanId, cli.flags['json'] ? 'json' : cli.flags['markdown'] ? 'markdown' : 'print');
|
|
7270
7719
|
}
|
|
7271
7720
|
|
|
7272
7721
|
/**
|
|
@@ -7274,7 +7723,7 @@ async function run$4(argv, importMeta, {
|
|
|
7274
7723
|
* full scan ID.
|
|
7275
7724
|
* It can optionally only fetch the security or license side of things.
|
|
7276
7725
|
*/
|
|
7277
|
-
async function fetchReportData(orgSlug,
|
|
7726
|
+
async function fetchReportData(orgSlug, scanId,
|
|
7278
7727
|
// includeLicensePolicy: boolean,
|
|
7279
7728
|
includeSecurityPolicy) {
|
|
7280
7729
|
let haveScan = false;
|
|
@@ -7311,18 +7760,18 @@ includeSecurityPolicy) {
|
|
|
7311
7760
|
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.');
|
|
7312
7761
|
}
|
|
7313
7762
|
updateProgress();
|
|
7314
|
-
const
|
|
7763
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
7315
7764
|
|
|
7316
7765
|
// @ts-ignore
|
|
7317
7766
|
const [scan,
|
|
7318
7767
|
// licensePolicyMaybe,
|
|
7319
7768
|
securityPolicyMaybe] = await Promise.all([(async () => {
|
|
7320
7769
|
try {
|
|
7321
|
-
const response = await
|
|
7770
|
+
const response = await queryApi(`orgs/${orgSlug}/full-scans/${encodeURIComponent(scanId)}`, apiToken);
|
|
7322
7771
|
haveScan = true;
|
|
7323
7772
|
updateProgress();
|
|
7324
7773
|
if (!response.ok) {
|
|
7325
|
-
const err = await
|
|
7774
|
+
const err = await handleApiError(response.status);
|
|
7326
7775
|
logger.logger.fail(`${colors.bgRed(colors.white(response.statusText))}: Fetch error: ${err}`);
|
|
7327
7776
|
return undefined;
|
|
7328
7777
|
}
|
|
@@ -7344,7 +7793,7 @@ includeSecurityPolicy) {
|
|
|
7344
7793
|
})(),
|
|
7345
7794
|
// includeLicensePolicy &&
|
|
7346
7795
|
// (async () => {
|
|
7347
|
-
// const r = await
|
|
7796
|
+
// const r = await sockSdk.getOrgSecurityPolicy(orgSlug)
|
|
7348
7797
|
// haveLicensePolicy = true
|
|
7349
7798
|
// updateProgress()
|
|
7350
7799
|
// return await handleApiCall(
|
|
@@ -7353,7 +7802,7 @@ includeSecurityPolicy) {
|
|
|
7353
7802
|
// )
|
|
7354
7803
|
// })(),
|
|
7355
7804
|
includeSecurityPolicy && (async () => {
|
|
7356
|
-
const r = await
|
|
7805
|
+
const r = await sockSdk.getOrgSecurityPolicy(orgSlug);
|
|
7357
7806
|
haveSecurityPolicy = true;
|
|
7358
7807
|
updateProgress();
|
|
7359
7808
|
return await handleApiCall(r, "looking up organization's security policy");
|
|
@@ -7599,40 +8048,31 @@ function* walkNestedMap(map, keys = []) {
|
|
|
7599
8048
|
}
|
|
7600
8049
|
}
|
|
7601
8050
|
|
|
7602
|
-
async function
|
|
8051
|
+
async function outputScanReport(scan,
|
|
8052
|
+
// licensePolicy: undefined | SocketSdkReturnType<'getOrgSecurityPolicy'>,
|
|
8053
|
+
securityPolicy, {
|
|
7603
8054
|
filePath,
|
|
7604
8055
|
fold,
|
|
7605
|
-
fullScanId,
|
|
7606
8056
|
includeLicensePolicy,
|
|
7607
8057
|
includeSecurityPolicy,
|
|
7608
8058
|
orgSlug,
|
|
7609
8059
|
outputKind,
|
|
7610
8060
|
reportLevel,
|
|
8061
|
+
scanId,
|
|
7611
8062
|
short
|
|
7612
8063
|
}) {
|
|
7613
|
-
logger.logger.error('output:', outputKind, ', file:', filePath, ', fold:', fold, ', reportLevel:', reportLevel);
|
|
7614
8064
|
if (!includeSecurityPolicy) {
|
|
8065
|
+
process.exitCode = 1;
|
|
7615
8066
|
return; // caller should assert
|
|
7616
8067
|
}
|
|
7617
|
-
const {
|
|
7618
|
-
// licensePolicy,
|
|
7619
|
-
ok,
|
|
7620
|
-
scan,
|
|
7621
|
-
securityPolicy
|
|
7622
|
-
} = await fetchReportData(orgSlug, fullScanId,
|
|
7623
|
-
// includeLicensePolicy
|
|
7624
|
-
includeSecurityPolicy);
|
|
7625
|
-
if (!ok) {
|
|
7626
|
-
return;
|
|
7627
|
-
}
|
|
7628
8068
|
const scanReport = generateReport(scan, undefined,
|
|
7629
8069
|
// licensePolicy,
|
|
7630
8070
|
securityPolicy, {
|
|
7631
8071
|
orgSlug,
|
|
7632
|
-
scanId
|
|
8072
|
+
scanId,
|
|
7633
8073
|
fold,
|
|
7634
|
-
|
|
7635
|
-
|
|
8074
|
+
reportLevel,
|
|
8075
|
+
short
|
|
7636
8076
|
});
|
|
7637
8077
|
if (!scanReport.healthy) {
|
|
7638
8078
|
process.exitCode = 1;
|
|
@@ -7719,6 +8159,43 @@ ${!report.alerts.size ? '' : mdTable(flatData, ['Policy', 'Alert Type', 'Package
|
|
|
7719
8159
|
return md;
|
|
7720
8160
|
}
|
|
7721
8161
|
|
|
8162
|
+
async function handleScanReport({
|
|
8163
|
+
filePath,
|
|
8164
|
+
fold,
|
|
8165
|
+
includeLicensePolicy,
|
|
8166
|
+
includeSecurityPolicy,
|
|
8167
|
+
orgSlug,
|
|
8168
|
+
outputKind,
|
|
8169
|
+
reportLevel,
|
|
8170
|
+
scanId,
|
|
8171
|
+
short
|
|
8172
|
+
}) {
|
|
8173
|
+
if (!includeSecurityPolicy) {
|
|
8174
|
+
process.exitCode = 1;
|
|
8175
|
+
return; // caller should assert
|
|
8176
|
+
}
|
|
8177
|
+
const {
|
|
8178
|
+
// licensePolicy,
|
|
8179
|
+
ok,
|
|
8180
|
+
scan,
|
|
8181
|
+
securityPolicy
|
|
8182
|
+
} = await fetchReportData(orgSlug, scanId,
|
|
8183
|
+
// includeLicensePolicy
|
|
8184
|
+
includeSecurityPolicy);
|
|
8185
|
+
if (!ok) return;
|
|
8186
|
+
await outputScanReport(scan, securityPolicy, {
|
|
8187
|
+
filePath,
|
|
8188
|
+
fold,
|
|
8189
|
+
scanId: scanId,
|
|
8190
|
+
includeLicensePolicy,
|
|
8191
|
+
includeSecurityPolicy,
|
|
8192
|
+
orgSlug,
|
|
8193
|
+
outputKind,
|
|
8194
|
+
reportLevel,
|
|
8195
|
+
short
|
|
8196
|
+
});
|
|
8197
|
+
}
|
|
8198
|
+
|
|
7722
8199
|
const {
|
|
7723
8200
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$3
|
|
7724
8201
|
} = constants;
|
|
@@ -7805,8 +8282,8 @@ async function run$3(argv, importMeta, {
|
|
|
7805
8282
|
reportLevel = 'warn',
|
|
7806
8283
|
security
|
|
7807
8284
|
} = cli.flags;
|
|
7808
|
-
const [orgSlug = '',
|
|
7809
|
-
if (!orgSlug || !
|
|
8285
|
+
const [orgSlug = '', scanId = '', file = '-'] = cli.input;
|
|
8286
|
+
if (!orgSlug || !scanId ||
|
|
7810
8287
|
// (!license && !security) ||
|
|
7811
8288
|
json && markdown) {
|
|
7812
8289
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
@@ -7818,7 +8295,7 @@ async function run$3(argv, importMeta, {
|
|
|
7818
8295
|
|
|
7819
8296
|
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7820
8297
|
|
|
7821
|
-
- Full Scan ID to fetch as second argument ${!
|
|
8298
|
+
- Full Scan ID to fetch as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7822
8299
|
|
|
7823
8300
|
- Not both the --json and --markdown flags ${json && markdown ? colors.red('(pick one!)') : colors.green('(ok)')}
|
|
7824
8301
|
`
|
|
@@ -7830,9 +8307,9 @@ async function run$3(argv, importMeta, {
|
|
|
7830
8307
|
logger.logger.log(DRY_RUN_BAIL_TEXT$3);
|
|
7831
8308
|
return;
|
|
7832
8309
|
}
|
|
7833
|
-
await
|
|
8310
|
+
await handleScanReport({
|
|
7834
8311
|
orgSlug,
|
|
7835
|
-
|
|
8312
|
+
scanId: scanId,
|
|
7836
8313
|
includeLicensePolicy: false,
|
|
7837
8314
|
// !!license,
|
|
7838
8315
|
includeSecurityPolicy: typeof security === 'boolean' ? security : true,
|
|
@@ -7844,29 +8321,7 @@ async function run$3(argv, importMeta, {
|
|
|
7844
8321
|
});
|
|
7845
8322
|
}
|
|
7846
8323
|
|
|
7847
|
-
async function
|
|
7848
|
-
// Lazily access constants.spinner.
|
|
7849
|
-
const {
|
|
7850
|
-
spinner
|
|
7851
|
-
} = constants;
|
|
7852
|
-
const apiToken = shadowNpmInject.getDefaultToken();
|
|
7853
|
-
if (!apiToken) {
|
|
7854
|
-
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.');
|
|
7855
|
-
}
|
|
7856
|
-
spinner.start('Fetching scan...');
|
|
7857
|
-
const socketSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
7858
|
-
const data = await handleApiCall(socketSdk.getOrgFullScan(orgSlug, fullScanId, file === '-' ? undefined : file), 'Fetching a scan');
|
|
7859
|
-
if (!data?.success) {
|
|
7860
|
-
handleUnsuccessfulApiResponse('getOrgFullScan', data);
|
|
7861
|
-
return;
|
|
7862
|
-
}
|
|
7863
|
-
spinner?.successAndStop(file ? `Full scan details written to ${file}` : 'stdout');
|
|
7864
|
-
return data;
|
|
7865
|
-
}
|
|
7866
|
-
|
|
7867
|
-
async function viewFullScan(orgSlug, fullScanId, filePath) {
|
|
7868
|
-
const artifacts = await getFullScan(orgSlug, fullScanId);
|
|
7869
|
-
if (!artifacts) return;
|
|
8324
|
+
async function outputScanView(artifacts, orgSlug, scanId, filePath) {
|
|
7870
8325
|
const display = artifacts.map(art => {
|
|
7871
8326
|
const author = Array.isArray(art.author) ? `${art.author[0]}${art.author.length > 1 ? ' et.al.' : ''}` : art.author;
|
|
7872
8327
|
return {
|
|
@@ -7883,11 +8338,11 @@ async function viewFullScan(orgSlug, fullScanId, filePath) {
|
|
|
7883
8338
|
|
|
7884
8339
|
These are the artifacts and their scores found.
|
|
7885
8340
|
|
|
7886
|
-
|
|
8341
|
+
Scan ID: ${scanId}
|
|
7887
8342
|
|
|
7888
8343
|
${md}
|
|
7889
8344
|
|
|
7890
|
-
View this report at: https://socket.dev/dashboard/org/${orgSlug}/sbom/${
|
|
8345
|
+
View this report at: https://socket.dev/dashboard/org/${orgSlug}/sbom/${scanId}
|
|
7891
8346
|
`.trim() + '\n';
|
|
7892
8347
|
if (filePath && filePath !== '-') {
|
|
7893
8348
|
try {
|
|
@@ -7903,6 +8358,32 @@ View this report at: https://socket.dev/dashboard/org/${orgSlug}/sbom/${fullScan
|
|
|
7903
8358
|
}
|
|
7904
8359
|
}
|
|
7905
8360
|
|
|
8361
|
+
async function handleScanView(orgSlug, scanId, filePath) {
|
|
8362
|
+
const data = await fetchScan(orgSlug, scanId);
|
|
8363
|
+
if (!data) return;
|
|
8364
|
+
await outputScanView(data, orgSlug, scanId, filePath);
|
|
8365
|
+
}
|
|
8366
|
+
|
|
8367
|
+
async function streamScan(orgSlug, scanId, file) {
|
|
8368
|
+
// Lazily access constants.spinner.
|
|
8369
|
+
const {
|
|
8370
|
+
spinner
|
|
8371
|
+
} = constants;
|
|
8372
|
+
const apiToken = shadowNpmInject.getDefaultToken();
|
|
8373
|
+
if (!apiToken) {
|
|
8374
|
+
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.');
|
|
8375
|
+
}
|
|
8376
|
+
const sockSdk = await shadowNpmInject.setupSdk(apiToken);
|
|
8377
|
+
spinner.start('Fetching scan...');
|
|
8378
|
+
const data = await handleApiCall(sockSdk.getOrgFullScan(orgSlug, scanId, file === '-' ? undefined : file), 'Fetching a scan');
|
|
8379
|
+
spinner?.successAndStop(file ? `Full scan details written to ${file}` : 'stdout');
|
|
8380
|
+
if (!data?.success) {
|
|
8381
|
+
handleUnsuccessfulApiResponse('getOrgFullScan', data);
|
|
8382
|
+
return;
|
|
8383
|
+
}
|
|
8384
|
+
return data;
|
|
8385
|
+
}
|
|
8386
|
+
|
|
7906
8387
|
const {
|
|
7907
8388
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$2
|
|
7908
8389
|
} = constants;
|
|
@@ -7941,8 +8422,8 @@ async function run$2(argv, importMeta, {
|
|
|
7941
8422
|
importMeta,
|
|
7942
8423
|
parentName
|
|
7943
8424
|
});
|
|
7944
|
-
const [orgSlug = '',
|
|
7945
|
-
if (!orgSlug || !
|
|
8425
|
+
const [orgSlug = '', scanId = '', file = '-'] = cli.input;
|
|
8426
|
+
if (!orgSlug || !scanId) {
|
|
7946
8427
|
// Use exit status of 2 to indicate incorrect usage, generally invalid
|
|
7947
8428
|
// options or missing arguments.
|
|
7948
8429
|
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
|
|
@@ -7952,7 +8433,7 @@ async function run$2(argv, importMeta, {
|
|
|
7952
8433
|
|
|
7953
8434
|
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7954
8435
|
|
|
7955
|
-
- Full Scan ID to fetch as second argument ${!
|
|
8436
|
+
- Full Scan ID to fetch as second argument ${!scanId ? colors.red('(missing!)') : colors.green('(ok)')}
|
|
7956
8437
|
`);
|
|
7957
8438
|
return;
|
|
7958
8439
|
}
|
|
@@ -7961,9 +8442,9 @@ async function run$2(argv, importMeta, {
|
|
|
7961
8442
|
return;
|
|
7962
8443
|
}
|
|
7963
8444
|
if (cli.flags['json']) {
|
|
7964
|
-
await
|
|
8445
|
+
await streamScan(orgSlug, scanId, file);
|
|
7965
8446
|
} else {
|
|
7966
|
-
await
|
|
8447
|
+
await handleScanView(orgSlug, scanId, file);
|
|
7967
8448
|
}
|
|
7968
8449
|
}
|
|
7969
8450
|
|
|
@@ -8036,7 +8517,7 @@ async function getThreatFeedWithToken({
|
|
|
8036
8517
|
} = constants;
|
|
8037
8518
|
const queryParams = new URLSearchParams([['direction', direction], ['ecosystem', ecosystem], ['filter', filter], ['page', page], ['per_page', String(perPage)]]);
|
|
8038
8519
|
spinner.start('Fetching Threat Feed data...');
|
|
8039
|
-
const response = await
|
|
8520
|
+
const response = await queryApi(`threat-feed?${queryParams}`, apiToken);
|
|
8040
8521
|
const data = await response.json();
|
|
8041
8522
|
spinner.stop('Threat feed data fetched');
|
|
8042
8523
|
if (outputKind === 'json') {
|
|
@@ -8459,12 +8940,13 @@ void (async () => {
|
|
|
8459
8940
|
await updateNotifier({
|
|
8460
8941
|
name: SOCKET_CLI_BIN_NAME,
|
|
8461
8942
|
// The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_VERSION']".
|
|
8462
|
-
version: "0.14.
|
|
8943
|
+
version: "0.14.67",
|
|
8463
8944
|
ttl: 86_400_000 /* 24 hours in milliseconds */
|
|
8464
8945
|
});
|
|
8465
8946
|
try {
|
|
8466
8947
|
await meowWithSubcommands({
|
|
8467
8948
|
cdxgen: cmdCdxgen,
|
|
8949
|
+
config: cmdConfig,
|
|
8468
8950
|
fix: cmdFix,
|
|
8469
8951
|
info: cmdInfo,
|
|
8470
8952
|
login: cmdLogin,
|
|
@@ -8526,5 +9008,5 @@ void (async () => {
|
|
|
8526
9008
|
await shadowNpmInject.captureException(e);
|
|
8527
9009
|
}
|
|
8528
9010
|
})();
|
|
8529
|
-
//# debugId=
|
|
9011
|
+
//# debugId=436bf807-b015-4a97-803d-9a1ae68db89f
|
|
8530
9012
|
//# sourceMappingURL=cli.js.map
|