@chainpatrol/cli 0.1.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/README.md +224 -0
- package/dist/breakdown-JVN66HY3.js +69 -0
- package/dist/chunk-D2QGXYXZ.js +126 -0
- package/dist/chunk-E2LAMILJ.js +48 -0
- package/dist/chunk-EEG7T6WT.js +287 -0
- package/dist/chunk-H7UKKLCV.js +6572 -0
- package/dist/chunk-IUZB3DQW.js +237 -0
- package/dist/chunk-JCMWDZYY.js +39 -0
- package/dist/chunk-U73SABXK.js +46 -0
- package/dist/chunk-VFT3TD3E.js +82 -0
- package/dist/cli.js +895 -0
- package/dist/completions-EGQIARFC.js +12 -0
- package/dist/config-Z3TASRME.js +10 -0
- package/dist/configs-update-BK2S6AZ6.js +101 -0
- package/dist/create-4SQUBQI7.js +128 -0
- package/dist/drift-VRZKQC4P.js +80 -0
- package/dist/found-4O3AISNI.js +93 -0
- package/dist/healthcheck-7DR5MGEQ.js +94 -0
- package/dist/list-6L7XR4SZ.js +94 -0
- package/dist/list-HZAHEHDM.js +40 -0
- package/dist/list-IBMM562A.js +139 -0
- package/dist/list-json-TPBLJBD3.js +24 -0
- package/dist/login-G7LPHKDR.js +162 -0
- package/dist/login-json-LKB72OFY.js +71 -0
- package/dist/logout-LA7VEKON.js +25 -0
- package/dist/logout-json-4GIJZJ46.js +18 -0
- package/dist/run-PABQKATZ.js +112 -0
- package/dist/run-U62KVNTH.js +34 -0
- package/dist/setup-skill-U24CJZ6T.js +211 -0
- package/dist/snapshot-JEVDTE74.js +88 -0
- package/dist/summary-YG5NYIOA.js +61 -0
- package/dist/validate-PI7GPT5I.js +79 -0
- package/package.json +50 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createApiClient
|
|
3
|
+
} from "./chunk-H7UKKLCV.js";
|
|
4
|
+
import {
|
|
5
|
+
ErrorDisplay,
|
|
6
|
+
Spinner
|
|
7
|
+
} from "./chunk-JCMWDZYY.js";
|
|
8
|
+
import {
|
|
9
|
+
AuthCorruptedError,
|
|
10
|
+
AuthExpiredError,
|
|
11
|
+
AuthNotLoggedInError
|
|
12
|
+
} from "./chunk-EEG7T6WT.js";
|
|
13
|
+
import "./chunk-U73SABXK.js";
|
|
14
|
+
|
|
15
|
+
// src/commands/configs/list.tsx
|
|
16
|
+
import { useState, useEffect } from "react";
|
|
17
|
+
import { Text, Box, useApp } from "ink";
|
|
18
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
19
|
+
var shouldAutoExit = process.env.NODE_ENV !== "test";
|
|
20
|
+
function statusColor(status) {
|
|
21
|
+
switch (status) {
|
|
22
|
+
case "enabled":
|
|
23
|
+
return "green";
|
|
24
|
+
case "disabled":
|
|
25
|
+
return "red";
|
|
26
|
+
default:
|
|
27
|
+
return "yellow";
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function formatConfigValue(key, value) {
|
|
31
|
+
if (value === null || value === void 0 || value === "") return "";
|
|
32
|
+
if (typeof value === "boolean") return value ? "yes" : "no";
|
|
33
|
+
return String(value);
|
|
34
|
+
}
|
|
35
|
+
function ConfigsList({ org, apiClient }) {
|
|
36
|
+
const { exit } = useApp();
|
|
37
|
+
const [state, setState] = useState({ phase: "loading" });
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
const fetchConfigs = async () => {
|
|
40
|
+
try {
|
|
41
|
+
const client = apiClient ?? createApiClient();
|
|
42
|
+
const sources = await client.listDetectionConfigs(org);
|
|
43
|
+
setState({ phase: "loaded", sources });
|
|
44
|
+
} catch (err) {
|
|
45
|
+
if (err instanceof AuthNotLoggedInError || err instanceof AuthCorruptedError) {
|
|
46
|
+
setState({ phase: "error", message: err.message });
|
|
47
|
+
} else if (err instanceof AuthExpiredError) {
|
|
48
|
+
setState({ phase: "error", message: err.message });
|
|
49
|
+
} else {
|
|
50
|
+
const message = err instanceof Error ? err.message : "Failed to fetch detection configs";
|
|
51
|
+
if (message.includes("FORBIDDEN") || message.includes("403")) {
|
|
52
|
+
setState({
|
|
53
|
+
phase: "error",
|
|
54
|
+
message: "You don't have permission to view configs for this organization."
|
|
55
|
+
});
|
|
56
|
+
} else {
|
|
57
|
+
setState({ phase: "error", message });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (shouldAutoExit) {
|
|
61
|
+
setTimeout(() => exit(), 100);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
fetchConfigs();
|
|
66
|
+
}, []);
|
|
67
|
+
switch (state.phase) {
|
|
68
|
+
case "loading":
|
|
69
|
+
return /* @__PURE__ */ jsx(Spinner, { label: "Fetching detection configs..." });
|
|
70
|
+
case "error":
|
|
71
|
+
return /* @__PURE__ */ jsx(ErrorDisplay, { message: state.message });
|
|
72
|
+
case "loaded": {
|
|
73
|
+
if (shouldAutoExit) {
|
|
74
|
+
setTimeout(() => exit(), 100);
|
|
75
|
+
}
|
|
76
|
+
const configured = state.sources.filter((s) => s.configs.length > 0);
|
|
77
|
+
const globalOnly = state.sources.filter(
|
|
78
|
+
(s) => s.scope === "global" && s.configs.length === 0
|
|
79
|
+
);
|
|
80
|
+
const notConfigured = state.sources.filter(
|
|
81
|
+
(s) => s.scope !== "global" && s.configs.length === 0
|
|
82
|
+
);
|
|
83
|
+
const totalConfigs = state.sources.reduce((sum, s) => sum + s.configs.length, 0);
|
|
84
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
85
|
+
configured.map((source) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
86
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: source.source }),
|
|
87
|
+
source.configs.map((cfg) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [
|
|
88
|
+
/* @__PURE__ */ jsxs(Box, { gap: 1, children: [
|
|
89
|
+
/* @__PURE__ */ jsx(Text, { color: statusColor(cfg.status), children: cfg.status }),
|
|
90
|
+
cfg.title ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: cfg.title }) : null,
|
|
91
|
+
cfg.cron ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
92
|
+
"cron: ",
|
|
93
|
+
cfg.cron
|
|
94
|
+
] }) : null
|
|
95
|
+
] }),
|
|
96
|
+
Object.keys(cfg.config).length > 0 ? /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginLeft: 2, children: Object.entries(cfg.config).map(([key, value]) => {
|
|
97
|
+
const formatted = formatConfigValue(key, value);
|
|
98
|
+
if (!formatted) return null;
|
|
99
|
+
return /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
100
|
+
key,
|
|
101
|
+
": ",
|
|
102
|
+
formatted
|
|
103
|
+
] }, key);
|
|
104
|
+
}) }) : null
|
|
105
|
+
] }, cfg.id))
|
|
106
|
+
] }, source.source)),
|
|
107
|
+
globalOnly.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
108
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, color: "blue", children: [
|
|
109
|
+
"Global (",
|
|
110
|
+
globalOnly.length,
|
|
111
|
+
"):"
|
|
112
|
+
] }),
|
|
113
|
+
/* @__PURE__ */ jsx(Box, { marginLeft: 2, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: globalOnly.map((s) => s.source).join(", ") }) })
|
|
114
|
+
] }) : null,
|
|
115
|
+
notConfigured.length > 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
116
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, dimColor: true, children: [
|
|
117
|
+
"Not configured (",
|
|
118
|
+
notConfigured.length,
|
|
119
|
+
"):"
|
|
120
|
+
] }),
|
|
121
|
+
/* @__PURE__ */ jsx(Box, { marginLeft: 2, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: notConfigured.map((s) => s.source).join(", ") }) })
|
|
122
|
+
] }) : null,
|
|
123
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
124
|
+
"\n",
|
|
125
|
+
state.sources.length,
|
|
126
|
+
" source(s), ",
|
|
127
|
+
totalConfigs,
|
|
128
|
+
" config(s) across",
|
|
129
|
+
" ",
|
|
130
|
+
configured.length,
|
|
131
|
+
" active source(s)"
|
|
132
|
+
] })
|
|
133
|
+
] });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
export {
|
|
138
|
+
ConfigsList as default
|
|
139
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createApiClient
|
|
3
|
+
} from "./chunk-H7UKKLCV.js";
|
|
4
|
+
import "./chunk-EEG7T6WT.js";
|
|
5
|
+
import "./chunk-U73SABXK.js";
|
|
6
|
+
|
|
7
|
+
// src/commands/configs/list-json.ts
|
|
8
|
+
async function listConfigsJson({
|
|
9
|
+
org,
|
|
10
|
+
apiClient
|
|
11
|
+
}) {
|
|
12
|
+
try {
|
|
13
|
+
const client = apiClient ?? createApiClient();
|
|
14
|
+
const configs = await client.listDetectionConfigs(org);
|
|
15
|
+
console.log(JSON.stringify(configs, null, 2));
|
|
16
|
+
} catch (err) {
|
|
17
|
+
const message = err instanceof Error ? err.message : "Failed to fetch configs";
|
|
18
|
+
console.error(JSON.stringify({ error: message }));
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
listConfigsJson
|
|
24
|
+
};
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ErrorDisplay,
|
|
3
|
+
Spinner
|
|
4
|
+
} from "./chunk-JCMWDZYY.js";
|
|
5
|
+
import {
|
|
6
|
+
fetchUserEmail,
|
|
7
|
+
getCredentials,
|
|
8
|
+
isLoggedIn,
|
|
9
|
+
pollForToken,
|
|
10
|
+
requestDeviceCode,
|
|
11
|
+
storeCredentials
|
|
12
|
+
} from "./chunk-EEG7T6WT.js";
|
|
13
|
+
import "./chunk-U73SABXK.js";
|
|
14
|
+
|
|
15
|
+
// src/commands/login.tsx
|
|
16
|
+
import { useState, useEffect } from "react";
|
|
17
|
+
import { Text, Box, useApp } from "ink";
|
|
18
|
+
import open from "open";
|
|
19
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
20
|
+
function Login() {
|
|
21
|
+
const { exit } = useApp();
|
|
22
|
+
const [state, setState] = useState({ phase: "checking" });
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (isLoggedIn()) {
|
|
25
|
+
const creds = getCredentials();
|
|
26
|
+
if (creds.email) {
|
|
27
|
+
setState({ phase: "already-logged-in", email: creds.email });
|
|
28
|
+
setTimeout(() => exit(), 100);
|
|
29
|
+
} else {
|
|
30
|
+
fetchUserEmail(creds.accessToken).then((email) => {
|
|
31
|
+
if (email) {
|
|
32
|
+
storeCredentials({ ...creds, email });
|
|
33
|
+
}
|
|
34
|
+
setState({ phase: "already-logged-in", email: email ?? "" });
|
|
35
|
+
setTimeout(() => exit(), 100);
|
|
36
|
+
}).catch(() => {
|
|
37
|
+
setState({ phase: "already-logged-in", email: "" });
|
|
38
|
+
setTimeout(() => exit(), 100);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
setState({ phase: "requesting-code" });
|
|
44
|
+
requestDeviceCode().then((deviceCode) => {
|
|
45
|
+
setState({ phase: "waiting-for-approval", deviceCode });
|
|
46
|
+
const uri = deviceCode.verification_uri_complete ?? deviceCode.verification_uri;
|
|
47
|
+
open(uri).catch(() => {
|
|
48
|
+
});
|
|
49
|
+
}).catch((err) => {
|
|
50
|
+
setState({
|
|
51
|
+
phase: "error",
|
|
52
|
+
message: err instanceof Error ? err.message : "Failed to request device code"
|
|
53
|
+
});
|
|
54
|
+
setTimeout(() => exit(), 100);
|
|
55
|
+
});
|
|
56
|
+
}, []);
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (state.phase !== "waiting-for-approval") return;
|
|
59
|
+
let interval = state.deviceCode.interval * 1e3;
|
|
60
|
+
let cancelled = false;
|
|
61
|
+
const poll = async () => {
|
|
62
|
+
while (!cancelled) {
|
|
63
|
+
await new Promise((r) => setTimeout(r, interval));
|
|
64
|
+
if (cancelled) break;
|
|
65
|
+
const result = await pollForToken(state.deviceCode.device_code);
|
|
66
|
+
switch (result.status) {
|
|
67
|
+
case "success": {
|
|
68
|
+
const expiresAt = new Date(
|
|
69
|
+
Date.now() + result.expiresIn * 1e3
|
|
70
|
+
).toISOString();
|
|
71
|
+
const email = await fetchUserEmail(result.accessToken);
|
|
72
|
+
const creds = {
|
|
73
|
+
accessToken: result.accessToken,
|
|
74
|
+
expiresAt,
|
|
75
|
+
...email ? { email } : {}
|
|
76
|
+
};
|
|
77
|
+
storeCredentials(creds);
|
|
78
|
+
setState({ phase: "success", email: email ?? "" });
|
|
79
|
+
setTimeout(() => exit(), 500);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
case "pending":
|
|
83
|
+
continue;
|
|
84
|
+
case "slow_down":
|
|
85
|
+
interval += result.addSeconds * 1e3;
|
|
86
|
+
continue;
|
|
87
|
+
case "expired":
|
|
88
|
+
setState({
|
|
89
|
+
phase: "error",
|
|
90
|
+
message: "Code expired. Run `chainpatrol login` again."
|
|
91
|
+
});
|
|
92
|
+
setTimeout(() => exit(), 100);
|
|
93
|
+
return;
|
|
94
|
+
case "denied":
|
|
95
|
+
setState({ phase: "error", message: "Authorization denied." });
|
|
96
|
+
setTimeout(() => exit(), 100);
|
|
97
|
+
return;
|
|
98
|
+
case "error":
|
|
99
|
+
setState({ phase: "error", message: result.message });
|
|
100
|
+
setTimeout(() => exit(), 100);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
poll().catch((err) => {
|
|
106
|
+
if (!cancelled) {
|
|
107
|
+
setState({
|
|
108
|
+
phase: "error",
|
|
109
|
+
message: err instanceof Error ? `Cannot reach ChainPatrol API. ${err.message}` : "Network error during authentication."
|
|
110
|
+
});
|
|
111
|
+
setTimeout(() => exit(), 100);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
return () => {
|
|
115
|
+
cancelled = true;
|
|
116
|
+
};
|
|
117
|
+
}, [state.phase === "waiting-for-approval" ? state.deviceCode.device_code : null]);
|
|
118
|
+
switch (state.phase) {
|
|
119
|
+
case "checking":
|
|
120
|
+
return /* @__PURE__ */ jsx(Spinner, { label: "Checking authentication status..." });
|
|
121
|
+
case "already-logged-in":
|
|
122
|
+
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
123
|
+
/* @__PURE__ */ jsx(Text, { color: "green", bold: true, children: "\u2713" }),
|
|
124
|
+
/* @__PURE__ */ jsx(Text, { children: " Already logged in" }),
|
|
125
|
+
state.email ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
126
|
+
" ",
|
|
127
|
+
"as ",
|
|
128
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: state.email })
|
|
129
|
+
] }) : null
|
|
130
|
+
] });
|
|
131
|
+
case "requesting-code":
|
|
132
|
+
return /* @__PURE__ */ jsx(Spinner, { label: "Requesting device code..." });
|
|
133
|
+
case "waiting-for-approval":
|
|
134
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
|
|
135
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
136
|
+
/* @__PURE__ */ jsx(Text, { children: "Your code is: " }),
|
|
137
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: state.deviceCode.user_code.length === 8 ? `${state.deviceCode.user_code.slice(0, 4)}-${state.deviceCode.user_code.slice(4)}` : state.deviceCode.user_code })
|
|
138
|
+
] }),
|
|
139
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
140
|
+
"Open this URL in your browser:",
|
|
141
|
+
" ",
|
|
142
|
+
/* @__PURE__ */ jsx(Text, { color: "blue", underline: true, children: state.deviceCode.verification_uri })
|
|
143
|
+
] }),
|
|
144
|
+
/* @__PURE__ */ jsx(Spinner, { label: "Waiting for approval..." })
|
|
145
|
+
] });
|
|
146
|
+
case "success":
|
|
147
|
+
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
148
|
+
/* @__PURE__ */ jsx(Text, { color: "green", bold: true, children: "\u2713" }),
|
|
149
|
+
/* @__PURE__ */ jsx(Text, { children: " Logged in successfully" }),
|
|
150
|
+
state.email ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
151
|
+
" ",
|
|
152
|
+
"as ",
|
|
153
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: state.email })
|
|
154
|
+
] }) : null
|
|
155
|
+
] });
|
|
156
|
+
case "error":
|
|
157
|
+
return /* @__PURE__ */ jsx(ErrorDisplay, { message: state.message });
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
export {
|
|
161
|
+
Login as default
|
|
162
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {
|
|
2
|
+
fetchUserEmail,
|
|
3
|
+
getCredentials,
|
|
4
|
+
isLoggedIn,
|
|
5
|
+
pollForToken,
|
|
6
|
+
requestDeviceCode,
|
|
7
|
+
storeCredentials
|
|
8
|
+
} from "./chunk-EEG7T6WT.js";
|
|
9
|
+
import "./chunk-U73SABXK.js";
|
|
10
|
+
|
|
11
|
+
// src/commands/login-json.ts
|
|
12
|
+
async function loginJson() {
|
|
13
|
+
if (isLoggedIn()) {
|
|
14
|
+
const creds = getCredentials();
|
|
15
|
+
console.log(
|
|
16
|
+
JSON.stringify({ status: "already_logged_in", email: creds.email ?? null })
|
|
17
|
+
);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const deviceCode = await requestDeviceCode();
|
|
21
|
+
console.error(
|
|
22
|
+
JSON.stringify({
|
|
23
|
+
action: "open_url",
|
|
24
|
+
user_code: deviceCode.user_code,
|
|
25
|
+
verification_uri: deviceCode.verification_uri,
|
|
26
|
+
verification_uri_complete: deviceCode.verification_uri_complete ?? null,
|
|
27
|
+
expires_in: deviceCode.expires_in
|
|
28
|
+
})
|
|
29
|
+
);
|
|
30
|
+
let interval = deviceCode.interval * 1e3;
|
|
31
|
+
while (true) {
|
|
32
|
+
await new Promise((r) => setTimeout(r, interval));
|
|
33
|
+
const result = await pollForToken(deviceCode.device_code);
|
|
34
|
+
switch (result.status) {
|
|
35
|
+
case "success": {
|
|
36
|
+
const expiresAt = new Date(Date.now() + result.expiresIn * 1e3).toISOString();
|
|
37
|
+
const email = await fetchUserEmail(result.accessToken);
|
|
38
|
+
const creds = {
|
|
39
|
+
accessToken: result.accessToken,
|
|
40
|
+
expiresAt,
|
|
41
|
+
...email ? { email } : {}
|
|
42
|
+
};
|
|
43
|
+
storeCredentials(creds);
|
|
44
|
+
console.log(JSON.stringify({ status: "success", email: email ?? null }));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
case "pending":
|
|
48
|
+
continue;
|
|
49
|
+
case "slow_down":
|
|
50
|
+
interval += result.addSeconds * 1e3;
|
|
51
|
+
continue;
|
|
52
|
+
case "expired":
|
|
53
|
+
console.error(
|
|
54
|
+
JSON.stringify({ error: "Code expired. Run `chainpatrol login` again." })
|
|
55
|
+
);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
break;
|
|
58
|
+
case "denied":
|
|
59
|
+
console.error(JSON.stringify({ error: "Authorization denied." }));
|
|
60
|
+
process.exit(1);
|
|
61
|
+
break;
|
|
62
|
+
case "error":
|
|
63
|
+
console.error(JSON.stringify({ error: result.message }));
|
|
64
|
+
process.exit(1);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export {
|
|
70
|
+
loginJson
|
|
71
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
clearCredentials,
|
|
3
|
+
isLoggedIn
|
|
4
|
+
} from "./chunk-EEG7T6WT.js";
|
|
5
|
+
import "./chunk-U73SABXK.js";
|
|
6
|
+
|
|
7
|
+
// src/commands/logout.tsx
|
|
8
|
+
import { Text, useApp } from "ink";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
function Logout() {
|
|
11
|
+
const { exit } = useApp();
|
|
12
|
+
if (!isLoggedIn()) {
|
|
13
|
+
setTimeout(() => exit(), 100);
|
|
14
|
+
return /* @__PURE__ */ jsx(Text, { children: "Not currently logged in." });
|
|
15
|
+
}
|
|
16
|
+
clearCredentials();
|
|
17
|
+
setTimeout(() => exit(), 100);
|
|
18
|
+
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
19
|
+
/* @__PURE__ */ jsx(Text, { color: "green", bold: true, children: "\u2713" }),
|
|
20
|
+
/* @__PURE__ */ jsx(Text, { children: " Logged out successfully." })
|
|
21
|
+
] });
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
Logout as default
|
|
25
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
clearCredentials,
|
|
3
|
+
isLoggedIn
|
|
4
|
+
} from "./chunk-EEG7T6WT.js";
|
|
5
|
+
import "./chunk-U73SABXK.js";
|
|
6
|
+
|
|
7
|
+
// src/commands/logout-json.ts
|
|
8
|
+
async function logoutJson() {
|
|
9
|
+
if (!isLoggedIn()) {
|
|
10
|
+
console.log(JSON.stringify({ status: "not_logged_in" }));
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
clearCredentials();
|
|
14
|
+
console.log(JSON.stringify({ status: "logged_out" }));
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
logoutJson
|
|
18
|
+
};
|
|
@@ -0,0 +1,112 @@
|
|
|
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-H7UKKLCV.js";
|
|
12
|
+
import "./chunk-EEG7T6WT.js";
|
|
13
|
+
import "./chunk-U73SABXK.js";
|
|
14
|
+
|
|
15
|
+
// src/commands/detections/run.ts
|
|
16
|
+
async function runDetectionsRun(options) {
|
|
17
|
+
const outputFormat = options.outputFormat ?? (options.json ? "json" : "human");
|
|
18
|
+
if (options.dryRun) {
|
|
19
|
+
const payload = {
|
|
20
|
+
slug: options.org,
|
|
21
|
+
configId: options.configId,
|
|
22
|
+
source: options.source,
|
|
23
|
+
includeDisabled: options.includeDisabled ?? false
|
|
24
|
+
};
|
|
25
|
+
printOutput({
|
|
26
|
+
outputFormat,
|
|
27
|
+
json: {
|
|
28
|
+
dryRun: true,
|
|
29
|
+
mutation: "detection.configs.run",
|
|
30
|
+
payload,
|
|
31
|
+
explanation: options.explain ? "This command triggers on-demand execution for the selected configs." : void 0
|
|
32
|
+
},
|
|
33
|
+
markdown: [
|
|
34
|
+
"# Dry Run: Detection Run",
|
|
35
|
+
"",
|
|
36
|
+
`- Org: ${payload.slug}`,
|
|
37
|
+
`- Config ID: ${payload.configId ?? "all"}`,
|
|
38
|
+
`- Source: ${payload.source ?? "all"}`,
|
|
39
|
+
`- Include disabled: ${payload.includeDisabled}`
|
|
40
|
+
].join("\n"),
|
|
41
|
+
human: () => {
|
|
42
|
+
console.log("Dry run only. No detection configs were executed.");
|
|
43
|
+
console.log(
|
|
44
|
+
`Would run configs for org=${payload.slug} configId=${payload.configId ?? "all"} source=${payload.source ?? "all"}`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const client = options.apiClient ?? createApiClient();
|
|
51
|
+
const result = await client.runDetectionConfigs({
|
|
52
|
+
slug: options.org,
|
|
53
|
+
configId: options.configId,
|
|
54
|
+
source: options.source,
|
|
55
|
+
includeDisabled: options.includeDisabled ?? false
|
|
56
|
+
});
|
|
57
|
+
const csv = toCsvRows(
|
|
58
|
+
result.results.map((item) => ({
|
|
59
|
+
configId: item.configId,
|
|
60
|
+
source: item.source,
|
|
61
|
+
ok: item.ok,
|
|
62
|
+
assetsCount: item.assetsCount,
|
|
63
|
+
message: item.message
|
|
64
|
+
}))
|
|
65
|
+
);
|
|
66
|
+
const markdown = [
|
|
67
|
+
`# Detection Run (${options.org})`,
|
|
68
|
+
"",
|
|
69
|
+
`- Ran: ${result.ranCount}`,
|
|
70
|
+
`- Success: ${result.successCount}`,
|
|
71
|
+
`- Failed: ${result.failedCount}`,
|
|
72
|
+
"",
|
|
73
|
+
...result.results.map(
|
|
74
|
+
(item) => `- ${item.ok ? "OK" : "FAIL"} [${item.source}] #${item.configId} assets=${item.assetsCount}${item.message ? ` (${item.message})` : ""}`
|
|
75
|
+
)
|
|
76
|
+
].join("\n");
|
|
77
|
+
printOutput({
|
|
78
|
+
outputFormat,
|
|
79
|
+
json: {
|
|
80
|
+
...result,
|
|
81
|
+
explanation: options.explain ? {
|
|
82
|
+
checkType: "detection_run",
|
|
83
|
+
failureCondition: "failedCount > 0"
|
|
84
|
+
} : void 0
|
|
85
|
+
},
|
|
86
|
+
markdown,
|
|
87
|
+
csv,
|
|
88
|
+
human: () => {
|
|
89
|
+
console.log(
|
|
90
|
+
`Ran ${result.ranCount} config(s): ${result.successCount} success, ${result.failedCount} failed`
|
|
91
|
+
);
|
|
92
|
+
for (const item of result.results) {
|
|
93
|
+
const icon = item.ok ? "\u2713" : "\u2717";
|
|
94
|
+
console.log(
|
|
95
|
+
`${icon} [${item.source}] config ${item.configId} assets=${item.assetsCount}${item.message ? ` message=${item.message}` : ""}`
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
if (options.explain) {
|
|
99
|
+
console.log("Run is marked failed when at least one config run returns not ok.");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
if (result.failedCount > 0) {
|
|
104
|
+
throw new CliExitError(
|
|
105
|
+
"One or more detection config runs failed.",
|
|
106
|
+
ExitCode.MUTATION_PARTIAL_FAILURE
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
export {
|
|
111
|
+
runDetectionsRun
|
|
112
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getPresetDefinition,
|
|
3
|
+
runPreset
|
|
4
|
+
} from "./chunk-D2QGXYXZ.js";
|
|
5
|
+
import {
|
|
6
|
+
CliExitError,
|
|
7
|
+
ExitCode
|
|
8
|
+
} from "./chunk-E2LAMILJ.js";
|
|
9
|
+
import "./chunk-VFT3TD3E.js";
|
|
10
|
+
import "./chunk-H7UKKLCV.js";
|
|
11
|
+
import "./chunk-EEG7T6WT.js";
|
|
12
|
+
import "./chunk-U73SABXK.js";
|
|
13
|
+
|
|
14
|
+
// src/commands/presets/run.ts
|
|
15
|
+
async function runPresetsRun({
|
|
16
|
+
presetId,
|
|
17
|
+
org,
|
|
18
|
+
outputFormat,
|
|
19
|
+
explain
|
|
20
|
+
}) {
|
|
21
|
+
const preset = getPresetDefinition(presetId);
|
|
22
|
+
if (!preset) {
|
|
23
|
+
throw new CliExitError(`Unknown preset '${presetId}'.`, ExitCode.USAGE);
|
|
24
|
+
}
|
|
25
|
+
await runPreset({
|
|
26
|
+
presetId: preset.id,
|
|
27
|
+
org,
|
|
28
|
+
outputFormat,
|
|
29
|
+
explain
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
export {
|
|
33
|
+
runPresetsRun
|
|
34
|
+
};
|