securewithtrace 0.16.0 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +138 -35
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -23943,7 +23943,9 @@ var VulnerabilityAggregatedCountsRequestSchema = external_exports.object({
23943
23943
  excludeStatuses: external_exports.array(VulnerabilityStatus).optional(),
23944
23944
  defaultBranchOnly: external_exports.boolean().default(true).optional(),
23945
23945
  /** Lower bound for time-series data. Only vulnerabilities created on or after this date are included in the timeSeries field. Does not affect byRepoAndSeverity or byStatusAndSeverity. */
23946
- timeSeriesSince: external_exports.coerce.date().optional()
23946
+ timeSeriesSince: external_exports.coerce.date().optional(),
23947
+ /** When provided, only include vulnerabilities belonging to this repository. */
23948
+ repositoryId: external_exports.uuid().optional()
23947
23949
  });
23948
23950
  var VulnerabilityAggregatedCountsResponseSchema = external_exports.object({
23949
23951
  byRepoAndSeverity: external_exports.array(RepoSeverityCountSchema),
@@ -25050,6 +25052,21 @@ async function resolveOrganizationIdSafe(client) {
25050
25052
  }
25051
25053
  }
25052
25054
 
25055
+ // src/format.ts
25056
+ var SEVERITY_ORDER = {
25057
+ CRITICAL: 0,
25058
+ HIGH: 1,
25059
+ MEDIUM: 2,
25060
+ LOW: 3,
25061
+ INFORMATIONAL: 4
25062
+ };
25063
+ function formatStatus(status) {
25064
+ return status.toLowerCase().replace("_", " ");
25065
+ }
25066
+ function tsvSafe(value) {
25067
+ return (value ?? "").replace(/[\t\r\n]/g, " ");
25068
+ }
25069
+
25053
25070
  // src/auth/commands.ts
25054
25071
  function getClientId() {
25055
25072
  const clientId = "client_01KEZ01W5Q3107GTBY51WQ67HT";
@@ -25312,7 +25329,14 @@ function createStatusCommand() {
25312
25329
  });
25313
25330
  }
25314
25331
  function createOrgListCommand() {
25315
- return new Command("list").description("List organizations available to your account").option("--json", "Output as JSON").action(async (options) => {
25332
+ return new Command("list").description("List organizations available to your account").option("-o, --output <format>", "Output format: table (default), json, tsv").addHelpText(
25333
+ "after",
25334
+ `
25335
+ Examples:
25336
+ tracecli org list
25337
+ tracecli org list --output json
25338
+ tracecli org list --output tsv | cut -f1`
25339
+ ).action(async (options) => {
25316
25340
  const organizationContext = await fetchOrganizationContext();
25317
25341
  const items = organizationContext.organizations.map(
25318
25342
  (organization) => ({
@@ -25321,10 +25345,23 @@ function createOrgListCommand() {
25321
25345
  selected: organization.organizationId === organizationContext.selectedOrganizationId
25322
25346
  })
25323
25347
  );
25324
- if (options.json) {
25348
+ if (options.output === "json") {
25325
25349
  console.log(JSON.stringify(items, null, 2));
25326
25350
  return;
25327
25351
  }
25352
+ if (options.output === "tsv") {
25353
+ for (const item of items) {
25354
+ console.log(
25355
+ [
25356
+ tsvSafe(item.name),
25357
+ tsvSafe(item.slug),
25358
+ tsvSafe(item.organizationId),
25359
+ item.active ? "true" : "false"
25360
+ ].join(" ")
25361
+ );
25362
+ }
25363
+ return;
25364
+ }
25328
25365
  for (const item of items) {
25329
25366
  const marker = item.active ? "*" : " ";
25330
25367
  const labels = [item.active ? "active" : null, item.selected ? "selected" : null].filter(
@@ -25341,11 +25378,18 @@ function createOrgListCommand() {
25341
25378
  });
25342
25379
  }
25343
25380
  function createOrgCurrentCommand() {
25344
- return new Command("current").description("Show the active organization used by CLI commands").option("--json", "Output as JSON").action(async (options) => {
25381
+ return new Command("current").description("Show the active organization used by CLI commands").option("-o, --output <format>", "Output format: table (default), json, tsv").addHelpText(
25382
+ "after",
25383
+ `
25384
+ Examples:
25385
+ tracecli org current
25386
+ tracecli org current --output json
25387
+ tracecli org current --output tsv`
25388
+ ).action(async (options) => {
25345
25389
  const organizationContext = await fetchOrganizationContext();
25346
25390
  const active = organizationContext.activeOrganization;
25347
25391
  const source = organizationContext.selectedOrganizationId === active.organizationId ? "selected" : "default";
25348
- if (options.json) {
25392
+ if (options.output === "json") {
25349
25393
  console.log(
25350
25394
  JSON.stringify(
25351
25395
  {
@@ -25358,6 +25402,17 @@ function createOrgCurrentCommand() {
25358
25402
  );
25359
25403
  return;
25360
25404
  }
25405
+ if (options.output === "tsv") {
25406
+ console.log(
25407
+ [
25408
+ tsvSafe(active.name),
25409
+ tsvSafe(active.slug),
25410
+ tsvSafe(active.organizationId),
25411
+ tsvSafe(source)
25412
+ ].join(" ")
25413
+ );
25414
+ return;
25415
+ }
25361
25416
  console.log(
25362
25417
  `Active organization: ${sanitizeForOutput(active.name)} (${sanitizeForOutput(active.slug)})`
25363
25418
  );
@@ -25792,22 +25847,10 @@ function createCompletionCommand(program3) {
25792
25847
  });
25793
25848
  }
25794
25849
 
25795
- // src/format.ts
25796
- var SEVERITY_ORDER = {
25797
- CRITICAL: 0,
25798
- HIGH: 1,
25799
- MEDIUM: 2,
25800
- LOW: 3,
25801
- INFORMATIONAL: 4
25802
- };
25803
- function formatStatus(status) {
25804
- return status.toLowerCase().replace("_", " ");
25805
- }
25806
-
25807
25850
  // src/pentest/commands.ts
25808
25851
  var DEFAULT_LIMIT = 30;
25809
25852
  var MAX_LIMIT = 100;
25810
- function tsvSafe(value) {
25853
+ function tsvSafe2(value) {
25811
25854
  return value.replace(/[\t\n\r]/g, " ");
25812
25855
  }
25813
25856
  function formatDate(date5) {
@@ -25926,7 +25969,7 @@ Examples:
25926
25969
  for (const pt of pentests) {
25927
25970
  const cols = [
25928
25971
  `PT-${pt.displayId}`,
25929
- tsvSafe(pt.title),
25972
+ tsvSafe2(pt.title),
25930
25973
  pt.status,
25931
25974
  pt.startedAt ? String(pt.startedAt) : "",
25932
25975
  pt.endedAt ? String(pt.endedAt) : "",
@@ -26009,8 +26052,8 @@ Examples:
26009
26052
  const cols = [
26010
26053
  finding.severity,
26011
26054
  finding.status,
26012
- tsvSafe(finding.category),
26013
- tsvSafe(finding.title),
26055
+ tsvSafe2(finding.category),
26056
+ tsvSafe2(finding.title),
26014
26057
  finding.cweIds.join(";"),
26015
26058
  finding.cvssScore != null ? String(finding.cvssScore) : ""
26016
26059
  ];
@@ -26098,6 +26141,8 @@ function extractRepoName(input) {
26098
26141
  }
26099
26142
  var BRANCH_NAME_PATTERN = /^[a-zA-Z0-9._/+-]+$/;
26100
26143
  var TRACE_GIT_ASKPASS_TOKEN_ENV = "TRACE_GIT_ASKPASS_TOKEN";
26144
+ var DEFAULT_LIMIT2 = 30;
26145
+ var MAX_LIMIT2 = 100;
26101
26146
  var REPOSITORY_PLATFORMS = ["GITHUB", "GITLAB", "BITBUCKET"];
26102
26147
  var REPOSITORY_STATUSES = ["CONNECTED", "DISCONNECTED"];
26103
26148
  function validateBranchName(branch) {
@@ -26304,6 +26349,29 @@ function filterRepositories(repositories, options) {
26304
26349
  return true;
26305
26350
  });
26306
26351
  }
26352
+ function parseListLimit(value) {
26353
+ const n = Number(value);
26354
+ if (!Number.isInteger(n) || n < 1) {
26355
+ throw new Error("--limit must be a positive integer");
26356
+ }
26357
+ if (n > MAX_LIMIT2) {
26358
+ throw new Error(`--limit cannot exceed ${MAX_LIMIT2}`);
26359
+ }
26360
+ return n;
26361
+ }
26362
+ function printRepositoriesTsv(repositories) {
26363
+ for (const repo of repositories) {
26364
+ console.log(
26365
+ [
26366
+ tsvSafe(repo.repositoryUrl),
26367
+ tsvSafe(repo.platform),
26368
+ tsvSafe(repo.status),
26369
+ tsvSafe(repo.defaultBranch),
26370
+ tsvSafe(repo.primaryLanguage)
26371
+ ].join(" ")
26372
+ );
26373
+ }
26374
+ }
26307
26375
  function collectFilterExpression(value, previous) {
26308
26376
  previous.push(value);
26309
26377
  return previous;
@@ -26328,11 +26396,16 @@ function addRepositoryFilterOptions(command) {
26328
26396
  "Filter by status (CONNECTED, DISCONNECTED)",
26329
26397
  (value) => value.toUpperCase()
26330
26398
  ).option("--query <query>", "Case-insensitive search across URL, repo, branch, and language").option("--default-branch <branch>", "Filter by default branch (case-insensitive contains)").option("--language <language>", "Filter by primary language (case-insensitive contains)").option(
26331
- "--filter <expression>",
26332
- "Advanced filter expression. Repeatable. Examples: platform=GITHUB, repo:trace, status!=DISCONNECTED, language!:typescript",
26399
+ "-f, --filter <expression>",
26400
+ "Advanced filter expression. Repeatable. Examples: platform=GITHUB, repo:trace, status!=DISCONNECTED",
26333
26401
  collectFilterExpression,
26334
26402
  []
26335
- ).option("--json", "Output as JSON").option(
26403
+ ).option("-o, --output <format>", "Output format: table (default), json, tsv").option(
26404
+ "-L, --limit <n>",
26405
+ `Maximum repositories to display (default ${DEFAULT_LIMIT2}, max ${MAX_LIMIT2})`,
26406
+ parseListLimit,
26407
+ DEFAULT_LIMIT2
26408
+ ).option(
26336
26409
  "--dependency <pkg>",
26337
26410
  "Filter repositories that use a dependency (e.g. lodash, lodash@4.17.21, @types/node@20)"
26338
26411
  );
@@ -26371,11 +26444,17 @@ async function runRepositoryListCommand(options) {
26371
26444
  console.log("No repositories found.");
26372
26445
  return;
26373
26446
  }
26374
- if (options.json) {
26375
- console.log(JSON.stringify(filteredRepositories, null, 2));
26447
+ const limit = options.limit ?? DEFAULT_LIMIT2;
26448
+ const displayedRepositories = filteredRepositories.slice(0, limit);
26449
+ if (options.output === "json") {
26450
+ console.log(JSON.stringify(displayedRepositories, null, 2));
26376
26451
  return;
26377
26452
  }
26378
- for (const repo of filteredRepositories) {
26453
+ if (options.output === "tsv") {
26454
+ printRepositoriesTsv(displayedRepositories);
26455
+ return;
26456
+ }
26457
+ for (const repo of displayedRepositories) {
26379
26458
  const status = repo.status === "CONNECTED" ? "connected" : "disconnected";
26380
26459
  const url2 = stripAnsi(String(repo.repositoryUrl));
26381
26460
  const platform = stripAnsi(String(repo.platform)).toLowerCase();
@@ -26430,11 +26509,19 @@ async function runDependencyFilter(organizationId, options) {
26430
26509
  console.log(`No repositories found using dependency '${label}'.`);
26431
26510
  return;
26432
26511
  }
26433
- if (options.json) {
26434
- console.log(JSON.stringify(repos, null, 2));
26512
+ const limit = options.limit ?? DEFAULT_LIMIT2;
26513
+ const displayedRepos = repos.slice(0, limit);
26514
+ if (options.output === "json") {
26515
+ console.log(JSON.stringify(displayedRepos, null, 2));
26516
+ return;
26517
+ }
26518
+ if (options.output === "tsv") {
26519
+ for (const repo of displayedRepos) {
26520
+ console.log(`${tsvSafe(repo.fullName)} ${tsvSafe(repo.versions.join(","))}`);
26521
+ }
26435
26522
  return;
26436
26523
  }
26437
- for (const repo of repos) {
26524
+ for (const repo of displayedRepos) {
26438
26525
  const versions = repo.versions.join(", ");
26439
26526
  console.log(`${repo.fullName} (${versions})`);
26440
26527
  }
@@ -26442,6 +26529,16 @@ async function runDependencyFilter(organizationId, options) {
26442
26529
  function createListCommand2() {
26443
26530
  return addRepositoryFilterOptions(
26444
26531
  new Command("list").description("List repositories in your organization")
26532
+ ).addHelpText(
26533
+ "after",
26534
+ `
26535
+ Examples:
26536
+ tracecli repo list
26537
+ tracecli repo list --platform GITHUB --status CONNECTED
26538
+ tracecli repo list --output json | jq '.[].repositoryUrl'
26539
+ tracecli repo list --output tsv | cut -f1
26540
+ tracecli repo list --filter "language:typescript" --limit 10
26541
+ tracecli repo list --dependency lodash@4.17.21`
26445
26542
  ).action(async (options) => {
26446
26543
  await runRepositoryListCommand(options);
26447
26544
  });
@@ -26449,6 +26546,12 @@ function createListCommand2() {
26449
26546
  function createFilterCommand() {
26450
26547
  return addRepositoryFilterOptions(
26451
26548
  new Command("filter").description("Filter repositories in your organization")
26549
+ ).addHelpText(
26550
+ "after",
26551
+ `
26552
+ Examples:
26553
+ tracecli repo filter --filter "platform=GITHUB" --filter "status=CONNECTED"
26554
+ tracecli repo filter --language typescript --output json`
26452
26555
  ).action(async (options) => {
26453
26556
  await runRepositoryListCommand(options);
26454
26557
  });
@@ -26570,8 +26673,8 @@ function createRepoCommand() {
26570
26673
  }
26571
26674
 
26572
26675
  // src/vulnerabilities/commands.ts
26573
- var DEFAULT_LIMIT2 = 30;
26574
- var MAX_LIMIT2 = 100;
26676
+ var DEFAULT_LIMIT3 = 30;
26677
+ var MAX_LIMIT3 = 100;
26575
26678
  async function resolveRepositoryIdAuthenticated(organizationId, repoIdentifier) {
26576
26679
  const result = await authenticatedRequest(
26577
26680
  (client) => client.repository.listRepositories({
@@ -26680,13 +26783,13 @@ function createListCommand3() {
26680
26783
  (value) => value.toUpperCase()
26681
26784
  ).option(
26682
26785
  "-L, --limit <n>",
26683
- `Max results to return (default: ${DEFAULT_LIMIT2}, max: ${MAX_LIMIT2})`,
26786
+ `Max results to return (default: ${DEFAULT_LIMIT3}, max: ${MAX_LIMIT3})`,
26684
26787
  (v) => {
26685
26788
  const n = Number.parseInt(v, 10);
26686
26789
  if (Number.isNaN(n) || n < 1) {
26687
26790
  throw new Error("--limit must be a positive integer");
26688
26791
  }
26689
- return Math.min(n, MAX_LIMIT2);
26792
+ return Math.min(n, MAX_LIMIT3);
26690
26793
  }
26691
26794
  ).option("-o, --output <format>", "Output format: table, json, tsv (default: table)", "table").addHelpText(
26692
26795
  "after",
@@ -26717,7 +26820,7 @@ Examples:
26717
26820
  sortBy: "severity",
26718
26821
  sortOrder: "desc"
26719
26822
  };
26720
- const limit = options.limit ?? DEFAULT_LIMIT2;
26823
+ const limit = options.limit ?? DEFAULT_LIMIT3;
26721
26824
  const isJson = options.output === "json";
26722
26825
  const isTsv = options.output === "tsv";
26723
26826
  const collected = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securewithtrace",
3
- "version": "0.16.0",
3
+ "version": "0.16.1",
4
4
  "description": "Official Trace CLI for vulnerability intelligence in your terminal",
5
5
  "type": "module",
6
6
  "bin": {