@chainpatrol/cli 0.10.0 → 0.12.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.
- package/CHANGELOG.md +64 -0
- package/README.md +2 -0
- package/dist/{breakdown-63FAOVL7.js → breakdown-KCTKQNDY.js} +1 -1
- package/dist/{check-7QDINQPT.js → check-P5JJJNEX.js} +1 -1
- package/dist/{chunk-BJISZ3CY.js → chunk-DJVB73FL.js} +1 -1
- package/dist/{chunk-Z76CUWSS.js → chunk-NQT77IB7.js} +62 -9
- package/dist/chunk-OSRFCVBT.js +382 -0
- package/dist/{chunk-R2DZGMGT.js → chunk-W42ITB5J.js} +1 -1
- package/dist/cli.js +486 -65
- package/dist/{completions-D6SOLU2D.js → completions-6C6KG5DH.js} +1 -1
- package/dist/{configs-update-2IOSKZH5.js → configs-update-3ZVXGADV.js} +1 -1
- package/dist/{create-EWS3SFCH.js → create-DFH2G7RH.js} +1 -1
- package/dist/{drift-Q3VG3XG3.js → drift-T74V2C3J.js} +1 -1
- package/dist/{found-22B7RZT5.js → found-EVXJZGYX.js} +1 -1
- package/dist/{healthcheck-C3AIMUJT.js → healthcheck-HZYEIIOR.js} +1 -1
- package/dist/{list-DNRWKM5O.js → list-23QQYAV5.js} +1 -1
- package/dist/list-EIVPGMWJ.js +82 -0
- package/dist/list-I7SBGA52.js +50 -0
- package/dist/{list-IA4CSOIY.js → list-IYJBKE2F.js} +1 -1
- package/dist/list-PBAXQSL5.js +85 -0
- package/dist/list-QUFY4IP7.js +146 -0
- package/dist/list-WJQT2XLE.js +143 -0
- package/dist/{list-HFWSMLGJ.js → list-WX5G3IOF.js} +2 -2
- package/dist/list-YCT6DYDI.js +89 -0
- package/dist/{list-SDBLGBVW.js → list-YRJPN4PI.js} +1 -1
- package/dist/{list-AYHDFSQG.js → list-ZFPML3ZR.js} +47 -3
- package/dist/{list-json-CEPGVUGF.js → list-json-T2Z7NV7G.js} +1 -1
- package/dist/organization-IIIOSTHF.js +75 -0
- package/dist/{run-WJGHJPXN.js → run-BHEXWBAS.js} +2 -2
- package/dist/{run-AQMJRFGL.js → run-CJGN6TX4.js} +1 -1
- package/dist/{run-YTWNQD5X.js → run-MSO6IXEV.js} +1 -1
- package/dist/search-WPSKQGUS.js +71 -0
- package/dist/{setup-skill-BLJLRCXL.js → setup-skill-FA4STSGA.js} +2 -2
- package/dist/{snapshot-C5MZWJTW.js → snapshot-ZWAHEG64.js} +1 -1
- package/dist/{summary-NQDZQEOD.js → summary-Y2LG6UJM.js} +1 -1
- package/dist/{validate-5DVPSXJP.js → validate-SM5DD7I2.js} +1 -1
- package/dist/whoami-DH5HVLFN.js +69 -0
- package/package.json +1 -1
- package/dist/chunk-RIKR2WFT.js +0 -174
|
@@ -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-
|
|
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
|
|
75
|
+
status,
|
|
44
76
|
searchQuery: options.searchQuery,
|
|
45
|
-
|
|
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({
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import {
|
|
2
|
+
printOutput,
|
|
3
|
+
toCsvRows
|
|
4
|
+
} from "./chunk-VFT3TD3E.js";
|
|
5
|
+
import {
|
|
6
|
+
createApiClient
|
|
7
|
+
} from "./chunk-OSRFCVBT.js";
|
|
8
|
+
import "./chunk-EGWK6SRQ.js";
|
|
9
|
+
import "./chunk-TFCNKBRC.js";
|
|
10
|
+
import "./chunk-U73SABXK.js";
|
|
11
|
+
|
|
12
|
+
// src/commands/metrics/organization.ts
|
|
13
|
+
async function runMetricsOrganization(options) {
|
|
14
|
+
const outputFormat = options.outputFormat ?? (options.json ? "json" : "human");
|
|
15
|
+
const client = options.apiClient ?? createApiClient();
|
|
16
|
+
const input = {
|
|
17
|
+
organizationSlug: options.org,
|
|
18
|
+
brandSlug: options.brandSlug,
|
|
19
|
+
startDate: options.from,
|
|
20
|
+
endDate: options.to
|
|
21
|
+
};
|
|
22
|
+
const result = await client.getOrganizationMetrics(input);
|
|
23
|
+
const label = options.org ?? "your organization";
|
|
24
|
+
printOutput({
|
|
25
|
+
outputFormat,
|
|
26
|
+
json: result,
|
|
27
|
+
markdown: [
|
|
28
|
+
`# Organization Metrics (${label})`,
|
|
29
|
+
"",
|
|
30
|
+
`- Reports: ${result.metrics.reports}`,
|
|
31
|
+
`- New threats: ${result.metrics.newThreats}`,
|
|
32
|
+
`- Watchlisted threats: ${result.metrics.threatsWatchlisted}`,
|
|
33
|
+
`- Takedowns filed: ${result.metrics.takedownsFiled}`,
|
|
34
|
+
`- Takedowns completed: ${result.metrics.takedownsCompleted}`,
|
|
35
|
+
`- Domain threats: ${result.metrics.domainThreats}`,
|
|
36
|
+
`- Twitter threats: ${result.metrics.twitterThreats}`,
|
|
37
|
+
`- Telegram threats: ${result.metrics.telegramThreats}`,
|
|
38
|
+
`- Other threats: ${result.metrics.otherThreats}`
|
|
39
|
+
].join("\n"),
|
|
40
|
+
csv: toCsvRows([
|
|
41
|
+
{
|
|
42
|
+
reports: result.metrics.reports,
|
|
43
|
+
newThreats: result.metrics.newThreats,
|
|
44
|
+
threatsWatchlisted: result.metrics.threatsWatchlisted,
|
|
45
|
+
takedownsFiled: result.metrics.takedownsFiled,
|
|
46
|
+
takedownsCompleted: result.metrics.takedownsCompleted,
|
|
47
|
+
domainThreats: result.metrics.domainThreats,
|
|
48
|
+
twitterThreats: result.metrics.twitterThreats,
|
|
49
|
+
telegramThreats: result.metrics.telegramThreats,
|
|
50
|
+
otherThreats: result.metrics.otherThreats
|
|
51
|
+
}
|
|
52
|
+
]),
|
|
53
|
+
human: () => {
|
|
54
|
+
console.log(`Organization metrics for ${label}`);
|
|
55
|
+
console.log(`Reports: ${result.metrics.reports}`);
|
|
56
|
+
console.log(`New threats: ${result.metrics.newThreats}`);
|
|
57
|
+
console.log(`Watchlisted threats: ${result.metrics.threatsWatchlisted}`);
|
|
58
|
+
console.log(`Takedowns filed: ${result.metrics.takedownsFiled}`);
|
|
59
|
+
console.log(`Takedowns completed: ${result.metrics.takedownsCompleted}`);
|
|
60
|
+
console.log(
|
|
61
|
+
`Threat breakdown: domains=${result.metrics.domainThreats}, twitter=${result.metrics.twitterThreats}, telegram=${result.metrics.telegramThreats}, other=${result.metrics.otherThreats}`
|
|
62
|
+
);
|
|
63
|
+
if (result.blockedByDay.length > 0) {
|
|
64
|
+
console.log("");
|
|
65
|
+
console.log(`Blocked by day (${result.blockedByDay.length} entries):`);
|
|
66
|
+
for (const entry of result.blockedByDay) {
|
|
67
|
+
console.log(` ${entry.date}: ${entry.count}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
export {
|
|
74
|
+
runMetricsOrganization
|
|
75
|
+
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getPresetDefinition,
|
|
3
3
|
runPreset
|
|
4
|
-
} from "./chunk-
|
|
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-
|
|
10
|
+
import "./chunk-OSRFCVBT.js";
|
|
11
11
|
import "./chunk-EGWK6SRQ.js";
|
|
12
12
|
import "./chunk-TFCNKBRC.js";
|
|
13
13
|
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-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-W42ITB5J.js";
|
|
10
|
+
import "./chunk-NQT77IB7.js";
|
|
11
11
|
export {
|
|
12
12
|
getBundledSkillContent,
|
|
13
13
|
getBundledSkillVersion,
|
|
@@ -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.
|
|
5
|
+
"version": "0.12.0",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
7
|
"homepage": "https://chainpatrol.com/docs/cli",
|
|
8
8
|
"keywords": [
|
package/dist/chunk-RIKR2WFT.js
DELETED
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getValidCredentials
|
|
3
|
-
} from "./chunk-EGWK6SRQ.js";
|
|
4
|
-
import {
|
|
5
|
-
DateTime
|
|
6
|
-
} from "./chunk-TFCNKBRC.js";
|
|
7
|
-
import {
|
|
8
|
-
getConfig
|
|
9
|
-
} from "./chunk-U73SABXK.js";
|
|
10
|
-
|
|
11
|
-
// src/lib/api-client.ts
|
|
12
|
-
function parseIsoDate(value) {
|
|
13
|
-
if (!value) return void 0;
|
|
14
|
-
const dt = DateTime.fromISO(value, { zone: "utc" });
|
|
15
|
-
if (!dt.isValid) {
|
|
16
|
-
throw new Error(`Invalid ISO date: '${value}'. Use YYYY-MM-DD or full ISO 8601.`);
|
|
17
|
-
}
|
|
18
|
-
return dt.toJSDate();
|
|
19
|
-
}
|
|
20
|
-
var REQUEST_TIMEOUT_MS = 3e4;
|
|
21
|
-
function defaultGetCredential() {
|
|
22
|
-
const envKey = process.env.CHAINPATROL_API_KEY;
|
|
23
|
-
if (envKey && envKey.trim().length > 0) {
|
|
24
|
-
return { kind: "api-key", value: envKey.trim() };
|
|
25
|
-
}
|
|
26
|
-
return { kind: "bearer", value: getValidCredentials().accessToken };
|
|
27
|
-
}
|
|
28
|
-
function createApiClient(options) {
|
|
29
|
-
const config = getConfig();
|
|
30
|
-
const apiUrl = options?.apiUrl ?? config.apiUrl;
|
|
31
|
-
const getCredential = options?.getCredential ?? (options?.getToken ? () => ({ kind: "bearer", value: options.getToken() }) : defaultGetCredential);
|
|
32
|
-
async function request(path, body) {
|
|
33
|
-
const credential = getCredential();
|
|
34
|
-
const headers = {
|
|
35
|
-
"Content-Type": "application/json"
|
|
36
|
-
};
|
|
37
|
-
if (credential.kind === "api-key") {
|
|
38
|
-
headers["x-api-key"] = credential.value;
|
|
39
|
-
} else {
|
|
40
|
-
headers["Authorization"] = `Bearer ${credential.value}`;
|
|
41
|
-
}
|
|
42
|
-
let res;
|
|
43
|
-
try {
|
|
44
|
-
res = await fetch(`${apiUrl}/api/v2${path}`, {
|
|
45
|
-
method: "POST",
|
|
46
|
-
headers,
|
|
47
|
-
body: JSON.stringify(body),
|
|
48
|
-
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
49
|
-
});
|
|
50
|
-
} catch (err) {
|
|
51
|
-
if (err instanceof DOMException && err.name === "TimeoutError") {
|
|
52
|
-
throw new Error(
|
|
53
|
-
"Request timed out. Check your network connection and try again."
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
if (err instanceof TypeError && err.code === "ECONNREFUSED") {
|
|
57
|
-
throw new Error(`Cannot connect to ${apiUrl}. Is the server running?`);
|
|
58
|
-
}
|
|
59
|
-
throw new Error("Network error. Check your internet connection and try again.");
|
|
60
|
-
}
|
|
61
|
-
if (!res.ok) {
|
|
62
|
-
let errorMessageFromResponse = null;
|
|
63
|
-
try {
|
|
64
|
-
const errorBody = await res.json();
|
|
65
|
-
errorMessageFromResponse = errorBody.message ?? null;
|
|
66
|
-
} catch {
|
|
67
|
-
}
|
|
68
|
-
if (res.status === 401) {
|
|
69
|
-
throw new Error(
|
|
70
|
-
errorMessageFromResponse ?? "Authentication failed. Run `chainpatrol login` to re-authenticate."
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
if (res.status === 403) {
|
|
74
|
-
throw new Error(
|
|
75
|
-
errorMessageFromResponse ?? "You don't have permission to access this resource. Check your --org slug and permissions."
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
if (res.status === 404) {
|
|
79
|
-
throw new Error(
|
|
80
|
-
errorMessageFromResponse ?? "Organization not found. Check your --org slug."
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
if (res.status === 422) {
|
|
84
|
-
throw new Error(errorMessageFromResponse ?? "Request validation failed.");
|
|
85
|
-
}
|
|
86
|
-
if (res.status >= 500) {
|
|
87
|
-
throw new Error(
|
|
88
|
-
"ChainPatrol API is temporarily unavailable. Please try again later."
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
|
-
throw new Error(
|
|
92
|
-
errorMessageFromResponse ?? `Request failed (${res.status}). Run with --json for details.`
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
return await res.json();
|
|
96
|
-
}
|
|
97
|
-
return {
|
|
98
|
-
assetCheck(input) {
|
|
99
|
-
return request("/asset/check", input);
|
|
100
|
-
},
|
|
101
|
-
listDetectionConfigs(slug) {
|
|
102
|
-
return request("/detection/configs/list", { slug });
|
|
103
|
-
},
|
|
104
|
-
updateDetectionConfig(input) {
|
|
105
|
-
return request("/detection/configs/update", input);
|
|
106
|
-
},
|
|
107
|
-
runDetectionConfigs(input) {
|
|
108
|
-
return request("/detection/configs/run", input);
|
|
109
|
-
},
|
|
110
|
-
validateDetectionConfigs(input) {
|
|
111
|
-
return request("/detection/configs/validate", input);
|
|
112
|
-
},
|
|
113
|
-
getDetectionDrift(input) {
|
|
114
|
-
return request("/detection/drift", {
|
|
115
|
-
...input,
|
|
116
|
-
startDate: parseIsoDate(input.startDate),
|
|
117
|
-
endDate: parseIsoDate(input.endDate)
|
|
118
|
-
});
|
|
119
|
-
},
|
|
120
|
-
getOperationsQueuesSnapshot(input) {
|
|
121
|
-
return request(
|
|
122
|
-
"/operations/queues/snapshot",
|
|
123
|
-
input
|
|
124
|
-
);
|
|
125
|
-
},
|
|
126
|
-
getMetricsSummary(input) {
|
|
127
|
-
return request("/metrics/summary", {
|
|
128
|
-
...input,
|
|
129
|
-
startDate: parseIsoDate(input.startDate),
|
|
130
|
-
endDate: parseIsoDate(input.endDate)
|
|
131
|
-
});
|
|
132
|
-
},
|
|
133
|
-
getMetricsFound(input) {
|
|
134
|
-
return request("/metrics/found", {
|
|
135
|
-
...input,
|
|
136
|
-
startDate: parseIsoDate(input.startDate),
|
|
137
|
-
endDate: parseIsoDate(input.endDate)
|
|
138
|
-
});
|
|
139
|
-
},
|
|
140
|
-
getMetricsBreakdown(input) {
|
|
141
|
-
return request("/metrics/breakdown", {
|
|
142
|
-
...input,
|
|
143
|
-
startDate: parseIsoDate(input.startDate),
|
|
144
|
-
endDate: parseIsoDate(input.endDate)
|
|
145
|
-
});
|
|
146
|
-
},
|
|
147
|
-
createReport(input) {
|
|
148
|
-
return request("/report/create", input);
|
|
149
|
-
},
|
|
150
|
-
listOrganizationReports(input) {
|
|
151
|
-
return request("/public/getOrganizationReports", {
|
|
152
|
-
slug: input.slug,
|
|
153
|
-
limit: input.limit ?? 10,
|
|
154
|
-
cursor: input.cursor,
|
|
155
|
-
status: input.status,
|
|
156
|
-
searchQuery: input.searchQuery,
|
|
157
|
-
reportedByCustomer: input.reportedByCustomer
|
|
158
|
-
});
|
|
159
|
-
},
|
|
160
|
-
listHealthchecks() {
|
|
161
|
-
return request("/healthchecks/list", {});
|
|
162
|
-
},
|
|
163
|
-
runHealthcheck(endpoint, input) {
|
|
164
|
-
return request(endpoint, input);
|
|
165
|
-
},
|
|
166
|
-
getUserOrgs(input) {
|
|
167
|
-
return request("/user/orgs", input);
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
export {
|
|
173
|
-
createApiClient
|
|
174
|
-
};
|