@chainpatrol/cli 0.11.0 → 0.13.0

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 (39) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/dist/{breakdown-MM5GSZKV.js → breakdown-B6QUGYI6.js} +21 -6
  3. package/dist/{check-GDKUHVQI.js → check-P5JJJNEX.js} +1 -1
  4. package/dist/{chunk-EPKNZRX6.js → chunk-BQDMAEQU.js} +51 -6
  5. package/dist/{chunk-37KYJWB3.js → chunk-DJVB73FL.js} +1 -1
  6. package/dist/{chunk-YXRFUYA6.js → chunk-NQT77IB7.js} +50 -8
  7. package/dist/{chunk-SX3L6NKR.js → chunk-OSRFCVBT.js} +129 -2
  8. package/dist/chunk-S37VFIZY.js +66 -0
  9. package/dist/cli.js +411 -86
  10. package/dist/{completions-62OW3B3Y.js → completions-6C6KG5DH.js} +1 -1
  11. package/dist/{configs-update-7X7657PB.js → configs-update-3ZVXGADV.js} +1 -1
  12. package/dist/{create-FL4QQTPN.js → create-DFH2G7RH.js} +1 -1
  13. package/dist/{drift-JKBHWWFU.js → drift-T74V2C3J.js} +1 -1
  14. package/dist/found-NXAWEIEK.js +59 -0
  15. package/dist/{healthcheck-EVQVPGWW.js → healthcheck-HZYEIIOR.js} +1 -1
  16. package/dist/{list-BLNIE4GL.js → list-23QQYAV5.js} +1 -1
  17. package/dist/list-EIVPGMWJ.js +82 -0
  18. package/dist/list-I7SBGA52.js +50 -0
  19. package/dist/{list-5DN6X3DP.js → list-IYJBKE2F.js} +1 -1
  20. package/dist/list-PBAXQSL5.js +85 -0
  21. package/dist/list-QUFY4IP7.js +146 -0
  22. package/dist/{list-JPG2ZSR4.js → list-WJQT2XLE.js} +7 -1
  23. package/dist/{list-ULHPOUJV.js → list-WX5G3IOF.js} +2 -2
  24. package/dist/list-YCT6DYDI.js +89 -0
  25. package/dist/{list-XDGU6SJQ.js → list-YRJPN4PI.js} +1 -1
  26. package/dist/{list-E5XNR2YG.js → list-ZFPML3ZR.js} +47 -3
  27. package/dist/{list-json-R2MIXADX.js → list-json-T2Z7NV7G.js} +1 -1
  28. package/dist/{organization-MJRKWC4Z.js → organization-GS5LFIWO.js} +19 -6
  29. package/dist/{run-EUVRC72M.js → run-BHEXWBAS.js} +2 -2
  30. package/dist/{run-2YZZGZYN.js → run-CJGN6TX4.js} +1 -1
  31. package/dist/{run-5E5EC3MP.js → run-MSO6IXEV.js} +1 -1
  32. package/dist/search-WPSKQGUS.js +71 -0
  33. package/dist/{setup-skill-HAENFIFQ.js → setup-skill-TPMTULHJ.js} +2 -2
  34. package/dist/{snapshot-3FUJICJJ.js → snapshot-ZWAHEG64.js} +1 -1
  35. package/dist/{summary-RVYQUKWV.js → summary-CV657J5V.js} +19 -6
  36. package/dist/{validate-UOVKEAJM.js → validate-SM5DD7I2.js} +1 -1
  37. package/dist/whoami-DH5HVLFN.js +69 -0
  38. package/package.json +1 -1
  39. package/dist/found-3WI4XQG4.js +0 -95
@@ -7,13 +7,17 @@ import {
7
7
  toCsvRows
8
8
  } from "./chunk-VFT3TD3E.js";
9
9
  import {
10
+ REPORT_REVIEW_DECISIONS,
11
+ REPORT_STATUSES,
10
12
  createApiClient
11
- } from "./chunk-SX3L6NKR.js";
13
+ } from "./chunk-OSRFCVBT.js";
12
14
  import "./chunk-EGWK6SRQ.js";
13
15
  import "./chunk-TFCNKBRC.js";
14
16
  import "./chunk-U73SABXK.js";
15
17
 
16
18
  // src/commands/reports/list.ts
19
+ var REVIEW_DECISION_SET = new Set(REPORT_REVIEW_DECISIONS);
20
+ var REPORT_STATUS_SET = new Set(REPORT_STATUSES);
17
21
  function toReportRow(report) {
18
22
  return {
19
23
  id: report.id,
@@ -35,14 +39,54 @@ async function runReportsList(options) {
35
39
  ExitCode.USAGE
36
40
  );
37
41
  }
42
+ const status = options.status ? options.status.toUpperCase() : void 0;
43
+ if (status && !REPORT_STATUS_SET.has(status)) {
44
+ throw new CliExitError(
45
+ `Invalid --status '${options.status}'. Valid: ${REPORT_STATUSES.join(", ")}`,
46
+ ExitCode.USAGE
47
+ );
48
+ }
49
+ let reviewStatuses;
50
+ if (options.reviewStatuses?.length) {
51
+ const normalized = options.reviewStatuses.map((value) => value.toUpperCase());
52
+ const invalid = normalized.filter((value) => !REVIEW_DECISION_SET.has(value));
53
+ if (invalid.length > 0) {
54
+ throw new CliExitError(
55
+ `Invalid --review-status value(s): ${invalid.join(", ")}. Valid: ${REPORT_REVIEW_DECISIONS.join(
56
+ ", "
57
+ )}`,
58
+ ExitCode.USAGE
59
+ );
60
+ }
61
+ reviewStatuses = normalized;
62
+ }
63
+ const countryCodes = options.countryCodes?.length ? options.countryCodes.map((code) => code.toUpperCase()) : void 0;
64
+ if (countryCodes?.some((code) => code.length !== 2)) {
65
+ throw new CliExitError(
66
+ "--country-code values must be 2-letter ISO country codes (e.g. US, GB).",
67
+ ExitCode.USAGE
68
+ );
69
+ }
38
70
  const client = options.apiClient ?? createApiClient();
39
71
  const result = await client.listOrganizationReports({
40
72
  slug: options.org,
41
73
  limit,
42
74
  cursor: options.cursor,
43
- status: options.status,
75
+ status,
44
76
  searchQuery: options.searchQuery,
45
- reportedByCustomer: options.reportedByCustomer
77
+ reporterQuery: options.reporterQuery,
78
+ reportedByCustomer: options.reportedByCustomer,
79
+ excludeAutomation: options.excludeAutomation,
80
+ onlyRejected: options.onlyRejected,
81
+ reviewStatuses,
82
+ assetTypes: options.assetTypes?.length ? options.assetTypes.map((t) => t.toUpperCase()) : void 0,
83
+ brandIds: options.brandIds?.length ? options.brandIds : void 0,
84
+ countryCodes,
85
+ reviewedByUserId: options.reviewedByUserId,
86
+ startDate: options.from,
87
+ endDate: options.to,
88
+ updatedAtStartDate: options.updatedFrom,
89
+ updatedAtEndDate: options.updatedTo
46
90
  });
47
91
  const rows = result.reports.map(toReportRow);
48
92
  printOutput({
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createApiClient
3
- } from "./chunk-SX3L6NKR.js";
3
+ } from "./chunk-OSRFCVBT.js";
4
4
  import "./chunk-EGWK6SRQ.js";
5
5
  import "./chunk-TFCNKBRC.js";
6
6
  import "./chunk-U73SABXK.js";
@@ -1,10 +1,13 @@
1
+ import {
2
+ resolveDateRange
3
+ } from "./chunk-S37VFIZY.js";
1
4
  import {
2
5
  printOutput,
3
6
  toCsvRows
4
7
  } from "./chunk-VFT3TD3E.js";
5
8
  import {
6
9
  createApiClient
7
- } from "./chunk-SX3L6NKR.js";
10
+ } from "./chunk-OSRFCVBT.js";
8
11
  import "./chunk-EGWK6SRQ.js";
9
12
  import "./chunk-TFCNKBRC.js";
10
13
  import "./chunk-U73SABXK.js";
@@ -13,20 +16,26 @@ import "./chunk-U73SABXK.js";
13
16
  async function runMetricsOrganization(options) {
14
17
  const outputFormat = options.outputFormat ?? (options.json ? "json" : "human");
15
18
  const client = options.apiClient ?? createApiClient();
19
+ const range = resolveDateRange({
20
+ from: options.from,
21
+ to: options.to,
22
+ thisWeek: options.thisWeek
23
+ });
16
24
  const input = {
17
25
  organizationSlug: options.org,
18
26
  brandSlug: options.brandSlug,
19
- startDate: options.from,
20
- endDate: options.to
27
+ startDate: range.startDate,
28
+ endDate: range.endDate
21
29
  };
22
30
  const result = await client.getOrganizationMetrics(input);
23
31
  const label = options.org ?? "your organization";
24
32
  printOutput({
25
33
  outputFormat,
26
- json: result,
34
+ json: { ...result, range },
27
35
  markdown: [
28
- `# Organization Metrics (${label})`,
36
+ `# Organization Metrics (${label}) \u2014 ${range.label}`,
29
37
  "",
38
+ `- Range: ${range.startDate} \u2192 ${range.endDate}`,
30
39
  `- Reports: ${result.metrics.reports}`,
31
40
  `- New threats: ${result.metrics.newThreats}`,
32
41
  `- Watchlisted threats: ${result.metrics.threatsWatchlisted}`,
@@ -39,6 +48,9 @@ async function runMetricsOrganization(options) {
39
48
  ].join("\n"),
40
49
  csv: toCsvRows([
41
50
  {
51
+ rangeLabel: range.label,
52
+ startDate: range.startDate,
53
+ endDate: range.endDate,
42
54
  reports: result.metrics.reports,
43
55
  newThreats: result.metrics.newThreats,
44
56
  threatsWatchlisted: result.metrics.threatsWatchlisted,
@@ -51,7 +63,8 @@ async function runMetricsOrganization(options) {
51
63
  }
52
64
  ]),
53
65
  human: () => {
54
- console.log(`Organization metrics for ${label}`);
66
+ console.log(`Organization metrics for ${label} \u2014 ${range.label}`);
67
+ console.log(`Range: ${range.startDate} \u2192 ${range.endDate}`);
55
68
  console.log(`Reports: ${result.metrics.reports}`);
56
69
  console.log(`New threats: ${result.metrics.newThreats}`);
57
70
  console.log(`Watchlisted threats: ${result.metrics.threatsWatchlisted}`);
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  getPresetDefinition,
3
3
  runPreset
4
- } from "./chunk-37KYJWB3.js";
4
+ } from "./chunk-DJVB73FL.js";
5
5
  import {
6
6
  CliExitError,
7
7
  ExitCode
8
8
  } from "./chunk-E2LAMILJ.js";
9
9
  import "./chunk-VFT3TD3E.js";
10
- import "./chunk-SX3L6NKR.js";
10
+ import "./chunk-OSRFCVBT.js";
11
11
  import "./chunk-EGWK6SRQ.js";
12
12
  import "./chunk-TFCNKBRC.js";
13
13
  import "./chunk-U73SABXK.js";
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-VFT3TD3E.js";
9
9
  import {
10
10
  createApiClient
11
- } from "./chunk-SX3L6NKR.js";
11
+ } from "./chunk-OSRFCVBT.js";
12
12
  import "./chunk-EGWK6SRQ.js";
13
13
  import "./chunk-TFCNKBRC.js";
14
14
  import "./chunk-U73SABXK.js";
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-VFT3TD3E.js";
9
9
  import {
10
10
  createApiClient
11
- } from "./chunk-SX3L6NKR.js";
11
+ } from "./chunk-OSRFCVBT.js";
12
12
  import "./chunk-EGWK6SRQ.js";
13
13
  import "./chunk-TFCNKBRC.js";
14
14
  import "./chunk-U73SABXK.js";
@@ -0,0 +1,71 @@
1
+ import {
2
+ CliExitError,
3
+ ExitCode
4
+ } from "./chunk-E2LAMILJ.js";
5
+ import {
6
+ printOutput,
7
+ toCsvRows
8
+ } from "./chunk-VFT3TD3E.js";
9
+ import {
10
+ createApiClient
11
+ } from "./chunk-OSRFCVBT.js";
12
+ import "./chunk-EGWK6SRQ.js";
13
+ import "./chunk-TFCNKBRC.js";
14
+ import "./chunk-U73SABXK.js";
15
+
16
+ // src/commands/reports/search.ts
17
+ function toRow(report) {
18
+ return {
19
+ id: report.id,
20
+ status: report.status,
21
+ reportedByCustomer: report.reportedByCustomer,
22
+ assets: report.assets.join("|")
23
+ };
24
+ }
25
+ async function runReportsSearch(options) {
26
+ const outputFormat = options.outputFormat ?? (options.json ? "json" : "human");
27
+ if (options.assetContents.length === 0) {
28
+ throw new CliExitError(
29
+ "reports search requires at least one asset content. Pass --asset <content> (repeatable) or positional arguments.",
30
+ ExitCode.USAGE
31
+ );
32
+ }
33
+ const client = options.apiClient ?? createApiClient();
34
+ const input = {
35
+ assetContents: options.assetContents,
36
+ reportedByCustomer: options.reportedByCustomer
37
+ };
38
+ const result = await client.searchReports(input);
39
+ const rows = result.reports.map(toRow);
40
+ printOutput({
41
+ outputFormat,
42
+ json: result,
43
+ markdown: [
44
+ "# Report search results",
45
+ "",
46
+ `- Searched: ${options.assetContents.length} asset(s)`,
47
+ `- Matched: ${result.reports.length} report(s)`,
48
+ "",
49
+ ...rows.map(
50
+ (row) => `- #${row.id} [${row.status}]${row.reportedByCustomer ? " (customer)" : ""} assets=${row.assets}`
51
+ )
52
+ ].join("\n"),
53
+ csv: toCsvRows(rows),
54
+ human: () => {
55
+ if (result.reports.length === 0) {
56
+ console.log("No matching reports found.");
57
+ return;
58
+ }
59
+ console.log(
60
+ `Matched ${result.reports.length} report(s) for ${options.assetContents.length} asset(s)`
61
+ );
62
+ for (const row of rows) {
63
+ const customerTag = row.reportedByCustomer ? " (customer)" : "";
64
+ console.log(`#${row.id} [${row.status}]${customerTag} assets=${row.assets}`);
65
+ }
66
+ }
67
+ });
68
+ }
69
+ export {
70
+ runReportsSearch
71
+ };
@@ -6,8 +6,8 @@ import {
6
6
  readInstalledSkillVersion,
7
7
  setupSkill,
8
8
  uninstallSkill
9
- } from "./chunk-EPKNZRX6.js";
10
- import "./chunk-YXRFUYA6.js";
9
+ } from "./chunk-BQDMAEQU.js";
10
+ import "./chunk-NQT77IB7.js";
11
11
  export {
12
12
  getBundledSkillContent,
13
13
  getBundledSkillVersion,
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-VFT3TD3E.js";
9
9
  import {
10
10
  createApiClient
11
- } from "./chunk-SX3L6NKR.js";
11
+ } from "./chunk-OSRFCVBT.js";
12
12
  import "./chunk-EGWK6SRQ.js";
13
13
  import "./chunk-TFCNKBRC.js";
14
14
  import "./chunk-U73SABXK.js";
@@ -1,30 +1,39 @@
1
+ import {
2
+ resolveDateRange
3
+ } from "./chunk-S37VFIZY.js";
1
4
  import {
2
5
  printOutput,
3
6
  toCsvRows
4
7
  } from "./chunk-VFT3TD3E.js";
5
8
  import {
6
9
  createApiClient
7
- } from "./chunk-SX3L6NKR.js";
10
+ } from "./chunk-OSRFCVBT.js";
8
11
  import "./chunk-EGWK6SRQ.js";
9
12
  import "./chunk-TFCNKBRC.js";
10
13
  import "./chunk-U73SABXK.js";
11
14
 
12
15
  // src/commands/metrics/summary.ts
13
16
  async function runMetricsSummary(options) {
17
+ const range = resolveDateRange({
18
+ from: options.from,
19
+ to: options.to,
20
+ thisWeek: options.thisWeek
21
+ });
14
22
  const client = options.apiClient ?? createApiClient();
15
23
  const result = await client.getMetricsSummary({
16
24
  slug: options.org,
17
- startDate: options.from,
18
- endDate: options.to,
25
+ startDate: range.startDate,
26
+ endDate: range.endDate,
19
27
  brandIds: options.brandIds
20
28
  });
21
29
  const outputFormat = options.outputFormat ?? (options.json ? "json" : "human");
22
30
  printOutput({
23
31
  outputFormat,
24
- json: result,
32
+ json: { ...result, range },
25
33
  markdown: [
26
- `# Metrics Summary (${options.org})`,
34
+ `# Metrics Summary (${options.org}) \u2014 ${range.label}`,
27
35
  "",
36
+ `- Range: ${range.startDate} \u2192 ${range.endDate}`,
28
37
  `- Reports: ${result.metrics.reports}`,
29
38
  `- New threats: ${result.metrics.newThreats}`,
30
39
  `- Watchlisted threats: ${result.metrics.threatsWatchlisted}`,
@@ -33,6 +42,9 @@ async function runMetricsSummary(options) {
33
42
  ].join("\n"),
34
43
  csv: toCsvRows([
35
44
  {
45
+ rangeLabel: range.label,
46
+ startDate: range.startDate,
47
+ endDate: range.endDate,
36
48
  reports: result.metrics.reports,
37
49
  newThreats: result.metrics.newThreats,
38
50
  threatsWatchlisted: result.metrics.threatsWatchlisted,
@@ -45,7 +57,8 @@ async function runMetricsSummary(options) {
45
57
  }
46
58
  ]),
47
59
  human: () => {
48
- console.log(`Metrics summary for ${options.org}`);
60
+ console.log(`Metrics summary for ${options.org} \u2014 ${range.label}`);
61
+ console.log(`Range: ${range.startDate} \u2192 ${range.endDate}`);
49
62
  console.log(`Reports: ${result.metrics.reports}`);
50
63
  console.log(`New threats: ${result.metrics.newThreats}`);
51
64
  console.log(`Watchlisted threats: ${result.metrics.threatsWatchlisted}`);
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-VFT3TD3E.js";
9
9
  import {
10
10
  createApiClient
11
- } from "./chunk-SX3L6NKR.js";
11
+ } from "./chunk-OSRFCVBT.js";
12
12
  import "./chunk-EGWK6SRQ.js";
13
13
  import "./chunk-TFCNKBRC.js";
14
14
  import "./chunk-U73SABXK.js";
@@ -0,0 +1,69 @@
1
+ import {
2
+ printOutput
3
+ } from "./chunk-VFT3TD3E.js";
4
+ import {
5
+ createApiClient
6
+ } from "./chunk-OSRFCVBT.js";
7
+ import "./chunk-EGWK6SRQ.js";
8
+ import "./chunk-TFCNKBRC.js";
9
+ import "./chunk-U73SABXK.js";
10
+
11
+ // src/commands/whoami.ts
12
+ function detectAuthKind() {
13
+ const envKey = process.env.CHAINPATROL_API_KEY;
14
+ if (envKey && envKey.trim().length > 0) return "api-key";
15
+ return "bearer";
16
+ }
17
+ async function runWhoami(options) {
18
+ const outputFormat = options.outputFormat ?? (options.json ? "json" : "human");
19
+ const client = options.apiClient ?? createApiClient();
20
+ const authKind = options.authKind ?? detectAuthKind();
21
+ if (authKind === "api-key") {
22
+ const result2 = await client.validateApiKey();
23
+ const payload2 = {
24
+ authKind,
25
+ status: result2.status,
26
+ message: result2.message
27
+ };
28
+ printOutput({
29
+ outputFormat,
30
+ json: payload2,
31
+ markdown: [
32
+ "# whoami",
33
+ "",
34
+ `- Auth: API key`,
35
+ `- Status: ${result2.status}`,
36
+ `- Message: ${result2.message}`
37
+ ].join("\n"),
38
+ human: () => {
39
+ console.log(`Auth: API key (CHAINPATROL_API_KEY)`);
40
+ console.log(`Status: ${result2.status}`);
41
+ console.log(`Message: ${result2.message}`);
42
+ }
43
+ });
44
+ return;
45
+ }
46
+ const result = await client.getCurrentUser();
47
+ const payload = { authKind, ...result };
48
+ printOutput({
49
+ outputFormat,
50
+ json: payload,
51
+ markdown: [
52
+ "# whoami",
53
+ "",
54
+ `- Auth: session token`,
55
+ `- User: ${result.user.name} <${result.user.email}>`,
56
+ `- Role: ${result.user.role}`,
57
+ `- ID: ${result.user.id}`
58
+ ].join("\n"),
59
+ human: () => {
60
+ console.log(`Auth: session token`);
61
+ console.log(`User: ${result.user.name} <${result.user.email}>`);
62
+ console.log(`Role: ${result.user.role}`);
63
+ console.log(`ID: ${result.user.id}`);
64
+ }
65
+ });
66
+ }
67
+ export {
68
+ runWhoami
69
+ };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@chainpatrol/cli",
3
3
  "description": "The official ChainPatrol CLI — terminal interface for threat detection",
4
4
  "author": "Umar Ahmed <umar@chainpatrol.io>",
5
- "version": "0.11.0",
5
+ "version": "0.13.0",
6
6
  "license": "UNLICENSED",
7
7
  "homepage": "https://chainpatrol.com/docs/cli",
8
8
  "keywords": [
@@ -1,95 +0,0 @@
1
- import {
2
- printOutput,
3
- toCsvRows
4
- } from "./chunk-VFT3TD3E.js";
5
- import {
6
- createApiClient
7
- } from "./chunk-SX3L6NKR.js";
8
- import "./chunk-EGWK6SRQ.js";
9
- import {
10
- DateTime
11
- } from "./chunk-TFCNKBRC.js";
12
- import "./chunk-U73SABXK.js";
13
-
14
- // src/lib/date-range.ts
15
- function resolveDateRange({
16
- from,
17
- to,
18
- thisWeek
19
- }) {
20
- if (from && to) {
21
- return {
22
- startDate: DateTime.fromISO(from).toUTC().toISO() ?? from,
23
- endDate: DateTime.fromISO(to).toUTC().toISO() ?? to
24
- };
25
- }
26
- if (from && !to) {
27
- const now2 = DateTime.now().toUTC();
28
- return {
29
- startDate: DateTime.fromISO(from).toUTC().toISO() ?? from,
30
- endDate: now2.toISO() ?? ""
31
- };
32
- }
33
- if (!from && to) {
34
- const end = DateTime.fromISO(to).toUTC();
35
- return {
36
- startDate: end.minus({ days: 7 }).toISO() ?? "",
37
- endDate: end.toISO() ?? to
38
- };
39
- }
40
- if (thisWeek) {
41
- const now2 = DateTime.now().toUTC();
42
- return {
43
- startDate: now2.startOf("week").toISO() ?? now2.minus({ days: 7 }).toISO() ?? "",
44
- endDate: now2.endOf("week").toISO() ?? now2.toISO() ?? ""
45
- };
46
- }
47
- const now = DateTime.now().toUTC();
48
- return {
49
- startDate: now.minus({ days: 7 }).toISO() ?? "",
50
- endDate: now.toISO() ?? ""
51
- };
52
- }
53
-
54
- // src/commands/metrics/found.ts
55
- async function runMetricsFound(options) {
56
- const range = resolveDateRange({
57
- from: options.from,
58
- to: options.to,
59
- thisWeek: options.thisWeek
60
- });
61
- const client = options.apiClient ?? createApiClient();
62
- const result = await client.getMetricsFound({
63
- slug: options.org,
64
- startDate: range.startDate,
65
- endDate: range.endDate,
66
- brandIds: options.brandIds
67
- });
68
- const outputFormat = options.outputFormat ?? (options.json ? "json" : "human");
69
- printOutput({
70
- outputFormat,
71
- json: result,
72
- markdown: [
73
- `# Found Threats (${options.org})`,
74
- "",
75
- `- Metric: ${result.metric}`,
76
- `- Found: ${result.found}`,
77
- `- Range: ${range.startDate} -> ${range.endDate}`
78
- ].join("\n"),
79
- csv: toCsvRows([
80
- {
81
- metric: result.metric,
82
- found: result.found,
83
- startDate: range.startDate,
84
- endDate: range.endDate
85
- }
86
- ]),
87
- human: () => {
88
- console.log(`Found threats (${result.metric}) for ${options.org}: ${result.found}`);
89
- console.log(`Range: ${range.startDate} -> ${range.endDate}`);
90
- }
91
- });
92
- }
93
- export {
94
- runMetricsFound
95
- };