@ganakailabs/cloudeval-cli 0.18.4
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/LICENSE +77 -0
- package/NOTICE +10 -0
- package/README.md +23 -0
- package/THIRD_PARTY_NOTICES.md +124 -0
- package/dist/App-64BACPSQ.js +7023 -0
- package/dist/Banner-BIUMDX72.js +12 -0
- package/dist/Onboarding-HVCYIPTL.js +8 -0
- package/dist/ReportDashboard-6JFJJVRW.js +229 -0
- package/dist/chunk-3DVPEIVB.js +185 -0
- package/dist/chunk-4QIKW5TJ.js +3472 -0
- package/dist/chunk-GY4W535V.js +131 -0
- package/dist/chunk-RQ2GBK43.js +6 -0
- package/dist/chunk-TA4WC462.js +174 -0
- package/dist/chunk-UOCT7M4J.js +43 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +14026 -0
- package/dist/dist-I4IPYCRC.js +144 -0
- package/package.json +108 -0
- package/sbom.spdx.json +1627 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import {
|
|
2
|
+
terminalTheme
|
|
3
|
+
} from "./chunk-UOCT7M4J.js";
|
|
4
|
+
|
|
5
|
+
// src/reports/ReportDashboard.tsx
|
|
6
|
+
import { useMemo, useState } from "react";
|
|
7
|
+
import { Box, Text, useApp, useInput } from "ink";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
var modeOrder = [
|
|
10
|
+
"overview",
|
|
11
|
+
"formatted",
|
|
12
|
+
"parsed",
|
|
13
|
+
"raw"
|
|
14
|
+
];
|
|
15
|
+
var isCostReport = (report) => report.kind === "cost";
|
|
16
|
+
var isWafReport = (report) => report.kind === "waf";
|
|
17
|
+
var formatCurrency = (amount, currency = "USD") => {
|
|
18
|
+
const prefix = currency === "USD" ? "$" : `${currency} `;
|
|
19
|
+
return amount >= 1e3 ? `${prefix}${(amount / 1e3).toFixed(1)}k` : `${prefix}${amount}`;
|
|
20
|
+
};
|
|
21
|
+
var truncate = (value, width) => value.length > width ? `${value.slice(0, Math.max(0, width - 3))}...` : value;
|
|
22
|
+
var statusColor = (status) => {
|
|
23
|
+
if (status === "pass" || status === "ok") return terminalTheme.success;
|
|
24
|
+
if (status === "fail" || status === "over") return terminalTheme.danger;
|
|
25
|
+
return terminalTheme.warning;
|
|
26
|
+
};
|
|
27
|
+
var Panel = ({ title, label, children }) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: terminalTheme.muted, paddingX: 1, children: [
|
|
28
|
+
/* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", children: [
|
|
29
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: title }),
|
|
30
|
+
label ? /* @__PURE__ */ jsx(Text, { color: terminalTheme.accent, children: label }) : null
|
|
31
|
+
] }),
|
|
32
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 1, flexDirection: "column", children })
|
|
33
|
+
] });
|
|
34
|
+
var Metric = ({
|
|
35
|
+
label,
|
|
36
|
+
value,
|
|
37
|
+
note,
|
|
38
|
+
color
|
|
39
|
+
}) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: terminalTheme.muted, paddingX: 1, minWidth: 22, children: [
|
|
40
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: label }),
|
|
41
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color, children: value }),
|
|
42
|
+
note ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: note }) : null
|
|
43
|
+
] });
|
|
44
|
+
var Bar = ({
|
|
45
|
+
value,
|
|
46
|
+
max = 100,
|
|
47
|
+
color,
|
|
48
|
+
width = 24
|
|
49
|
+
}) => {
|
|
50
|
+
const filled = Math.max(0, Math.min(width, Math.round(value / max * width)));
|
|
51
|
+
return /* @__PURE__ */ jsxs(Text, { color, children: [
|
|
52
|
+
"\u2588".repeat(filled),
|
|
53
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2591".repeat(width - filled) })
|
|
54
|
+
] });
|
|
55
|
+
};
|
|
56
|
+
var JsonBlock = ({ value }) => /* @__PURE__ */ jsx(Text, { wrap: "wrap", children: JSON.stringify(value, null, 2) });
|
|
57
|
+
var FormattedBlock = ({ report }) => {
|
|
58
|
+
const formatted = report.formatted;
|
|
59
|
+
if (!formatted) {
|
|
60
|
+
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No formatted report returned. Use parsed/raw view." });
|
|
61
|
+
}
|
|
62
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
63
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: formatted.title }),
|
|
64
|
+
/* @__PURE__ */ jsx(Text, { wrap: "wrap", children: formatted.summary }),
|
|
65
|
+
formatted.sections.map((section) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
66
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: terminalTheme.brand, children: section.title }),
|
|
67
|
+
/* @__PURE__ */ jsx(Text, { wrap: "wrap", children: section.markdown })
|
|
68
|
+
] }, section.id))
|
|
69
|
+
] });
|
|
70
|
+
};
|
|
71
|
+
var CostOverview = ({
|
|
72
|
+
report
|
|
73
|
+
}) => {
|
|
74
|
+
const parsed = report.parsed;
|
|
75
|
+
const maxService = Math.max(...parsed.serviceGroups.map((group) => group.amount), 1);
|
|
76
|
+
const compact = (process.stdout.columns || 100) < 110;
|
|
77
|
+
const chartWidth = compact ? 16 : 24;
|
|
78
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
|
|
79
|
+
/* @__PURE__ */ jsxs(Box, { gap: 1, flexWrap: "wrap", children: [
|
|
80
|
+
/* @__PURE__ */ jsx(
|
|
81
|
+
Metric,
|
|
82
|
+
{
|
|
83
|
+
label: "Monthly spend",
|
|
84
|
+
value: formatCurrency(parsed.totalSpend.amount, parsed.totalSpend.currency),
|
|
85
|
+
note: `${parsed.totalSpend.changePercent?.toFixed(1) ?? "0"}% vs previous`,
|
|
86
|
+
color: terminalTheme.warning
|
|
87
|
+
}
|
|
88
|
+
),
|
|
89
|
+
/* @__PURE__ */ jsx(
|
|
90
|
+
Metric,
|
|
91
|
+
{
|
|
92
|
+
label: "Estimated savings",
|
|
93
|
+
value: formatCurrency(parsed.estimatedSavings.amount, parsed.estimatedSavings.currency),
|
|
94
|
+
note: `${parsed.estimatedSavings.percentOfSpend?.toFixed(1) ?? "0"}% addressable`,
|
|
95
|
+
color: terminalTheme.success
|
|
96
|
+
}
|
|
97
|
+
),
|
|
98
|
+
/* @__PURE__ */ jsx(
|
|
99
|
+
Metric,
|
|
100
|
+
{
|
|
101
|
+
label: "Anomalies",
|
|
102
|
+
value: String(parsed.anomalies.length),
|
|
103
|
+
note: "spend spikes",
|
|
104
|
+
color: terminalTheme.warning
|
|
105
|
+
}
|
|
106
|
+
)
|
|
107
|
+
] }),
|
|
108
|
+
/* @__PURE__ */ jsxs(Box, { gap: 1, flexDirection: compact ? "column" : "row", children: [
|
|
109
|
+
/* @__PURE__ */ jsx(Panel, { title: "Spend mix", label: "top services", children: parsed.serviceGroups.slice(0, 6).map((group) => /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
|
|
110
|
+
/* @__PURE__ */ jsx(Text, { children: truncate(group.name, 12).padEnd(12) }),
|
|
111
|
+
/* @__PURE__ */ jsx(Bar, { value: group.amount, max: maxService, color: terminalTheme.brand, width: chartWidth }),
|
|
112
|
+
/* @__PURE__ */ jsx(Text, { children: formatCurrency(group.amount, group.currency) })
|
|
113
|
+
] }, group.name)) }),
|
|
114
|
+
/* @__PURE__ */ jsx(Panel, { title: "Savings recommendations", label: `${formatCurrency(parsed.estimatedSavings.amount)}/mo`, children: parsed.recommendations.slice(0, 5).map((item, index) => /* @__PURE__ */ jsxs(Text, { wrap: "wrap", children: [
|
|
115
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
116
|
+
String(index + 1).padStart(2, "0"),
|
|
117
|
+
". "
|
|
118
|
+
] }),
|
|
119
|
+
item.title,
|
|
120
|
+
" ",
|
|
121
|
+
/* @__PURE__ */ jsxs(Text, { color: terminalTheme.success, children: [
|
|
122
|
+
formatCurrency(item.monthlySavings, item.currency),
|
|
123
|
+
"/mo"
|
|
124
|
+
] }),
|
|
125
|
+
" ",
|
|
126
|
+
/* @__PURE__ */ jsxs(Text, { color: statusColor(item.risk), children: [
|
|
127
|
+
"risk ",
|
|
128
|
+
item.risk
|
|
129
|
+
] })
|
|
130
|
+
] }, item.id)) })
|
|
131
|
+
] }),
|
|
132
|
+
/* @__PURE__ */ jsx(Panel, { title: "Budgets", label: "usage", children: parsed.budgets.map((budget) => /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
|
|
133
|
+
/* @__PURE__ */ jsx(Text, { children: budget.name.padEnd(8) }),
|
|
134
|
+
/* @__PURE__ */ jsx(Bar, { value: budget.usedPercent, max: 110, color: statusColor(budget.status) }),
|
|
135
|
+
/* @__PURE__ */ jsxs(Text, { color: statusColor(budget.status), children: [
|
|
136
|
+
budget.usedPercent,
|
|
137
|
+
"%"
|
|
138
|
+
] })
|
|
139
|
+
] }, budget.name)) })
|
|
140
|
+
] });
|
|
141
|
+
};
|
|
142
|
+
var WafOverview = ({
|
|
143
|
+
report
|
|
144
|
+
}) => {
|
|
145
|
+
const parsed = report.parsed;
|
|
146
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
|
|
147
|
+
/* @__PURE__ */ jsxs(Box, { gap: 1, flexWrap: "wrap", children: [
|
|
148
|
+
/* @__PURE__ */ jsx(Metric, { label: "WAF score", value: `${parsed.score.overall}/100`, color: terminalTheme.warning }),
|
|
149
|
+
/* @__PURE__ */ jsx(Metric, { label: "Passed controls", value: String(parsed.counts.passed), color: terminalTheme.success }),
|
|
150
|
+
/* @__PURE__ */ jsx(Metric, { label: "High risk", value: String(parsed.counts.highRisk), color: terminalTheme.danger }),
|
|
151
|
+
/* @__PURE__ */ jsx(Metric, { label: "Evidence coverage", value: `${parsed.counts.evidenceCoveragePercent}%`, color: terminalTheme.brand })
|
|
152
|
+
] }),
|
|
153
|
+
/* @__PURE__ */ jsx(Panel, { title: "Pillar distribution", label: "score", children: parsed.score.pillars.map((pillar) => /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
|
|
154
|
+
/* @__PURE__ */ jsx(Text, { children: truncate(pillar.label, 12).padEnd(12) }),
|
|
155
|
+
/* @__PURE__ */ jsx(Bar, { value: pillar.score, color: statusColor(pillar.score < 70 ? "fail" : pillar.score < 80 ? "warn" : "pass"), width: 30 }),
|
|
156
|
+
/* @__PURE__ */ jsx(Text, { children: String(pillar.score).padStart(3) }),
|
|
157
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
158
|
+
pillar.passed,
|
|
159
|
+
" pass / ",
|
|
160
|
+
pillar.warned,
|
|
161
|
+
" warn / ",
|
|
162
|
+
pillar.failed,
|
|
163
|
+
" fail"
|
|
164
|
+
] })
|
|
165
|
+
] }, pillar.id)) }),
|
|
166
|
+
/* @__PURE__ */ jsx(Panel, { title: "Rule matrix", label: "priority", children: parsed.rules.slice(0, 8).map((rule) => /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
|
|
167
|
+
/* @__PURE__ */ jsx(Text, { children: rule.id.padEnd(8) }),
|
|
168
|
+
/* @__PURE__ */ jsx(Text, { color: statusColor(rule.status), children: rule.status.padEnd(4) }),
|
|
169
|
+
/* @__PURE__ */ jsx(Text, { children: truncate(rule.pillar, 12).padEnd(12) }),
|
|
170
|
+
/* @__PURE__ */ jsx(Text, { children: truncate(rule.title, 52) })
|
|
171
|
+
] }, rule.id)) })
|
|
172
|
+
] });
|
|
173
|
+
};
|
|
174
|
+
var ReportDashboard = ({
|
|
175
|
+
report,
|
|
176
|
+
initialMode = "overview"
|
|
177
|
+
}) => {
|
|
178
|
+
const { exit } = useApp();
|
|
179
|
+
const [mode, setMode] = useState(initialMode);
|
|
180
|
+
const modeIndex = modeOrder.indexOf(mode);
|
|
181
|
+
const generated = useMemo(() => new Date(report.generatedAt).toISOString(), [report.generatedAt]);
|
|
182
|
+
useInput((input, key) => {
|
|
183
|
+
if (input === "q" || key.escape) {
|
|
184
|
+
exit();
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (input === "1") setMode("overview");
|
|
188
|
+
if (input === "2") setMode("formatted");
|
|
189
|
+
if (input === "3") setMode("parsed");
|
|
190
|
+
if (input === "4") setMode("raw");
|
|
191
|
+
if (key.leftArrow || key.rightArrow || key.tab) {
|
|
192
|
+
const direction = key.leftArrow ? -1 : 1;
|
|
193
|
+
setMode(modeOrder[(modeIndex + direction + modeOrder.length) % modeOrder.length]);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, gap: 1, children: [
|
|
197
|
+
/* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", children: [
|
|
198
|
+
/* @__PURE__ */ jsxs(Text, { color: terminalTheme.success, children: [
|
|
199
|
+
"CloudEval ",
|
|
200
|
+
report.kind.toUpperCase(),
|
|
201
|
+
" report"
|
|
202
|
+
] }),
|
|
203
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: report.id })
|
|
204
|
+
] }),
|
|
205
|
+
/* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", children: [
|
|
206
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
207
|
+
"Project ",
|
|
208
|
+
report.projectId,
|
|
209
|
+
" | Generated ",
|
|
210
|
+
generated,
|
|
211
|
+
" | Source ",
|
|
212
|
+
report.source.provider
|
|
213
|
+
] }),
|
|
214
|
+
/* @__PURE__ */ jsx(Text, { children: "[1] overview [2] formatted [3] parsed [4] raw | q quit" })
|
|
215
|
+
] }),
|
|
216
|
+
/* @__PURE__ */ jsxs(Text, { color: terminalTheme.brand, children: [
|
|
217
|
+
"View: ",
|
|
218
|
+
mode
|
|
219
|
+
] }),
|
|
220
|
+
mode === "overview" && isCostReport(report) ? /* @__PURE__ */ jsx(CostOverview, { report }) : null,
|
|
221
|
+
mode === "overview" && isWafReport(report) ? /* @__PURE__ */ jsx(WafOverview, { report }) : null,
|
|
222
|
+
mode === "formatted" ? /* @__PURE__ */ jsx(Panel, { title: "Formatted report", label: "human", children: /* @__PURE__ */ jsx(FormattedBlock, { report }) }) : null,
|
|
223
|
+
mode === "parsed" ? /* @__PURE__ */ jsx(Panel, { title: "Parsed report", label: "normalized", children: /* @__PURE__ */ jsx(JsonBlock, { value: report.parsed }) }) : null,
|
|
224
|
+
mode === "raw" ? /* @__PURE__ */ jsx(Panel, { title: "Raw report", label: "provider", children: /* @__PURE__ */ jsx(JsonBlock, { value: report.raw }) }) : null
|
|
225
|
+
] });
|
|
226
|
+
};
|
|
227
|
+
export {
|
|
228
|
+
ReportDashboard
|
|
229
|
+
};
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import {
|
|
2
|
+
completeOnboarding
|
|
3
|
+
} from "./chunk-4QIKW5TJ.js";
|
|
4
|
+
import {
|
|
5
|
+
terminalTheme
|
|
6
|
+
} from "./chunk-UOCT7M4J.js";
|
|
7
|
+
|
|
8
|
+
// src/ui/components/Onboarding.tsx
|
|
9
|
+
import { useState } from "react";
|
|
10
|
+
import { Box, Text, useInput } from "ink";
|
|
11
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
var ROLES = [
|
|
13
|
+
"Developer",
|
|
14
|
+
"DevOps Engineer",
|
|
15
|
+
"Cloud Architect",
|
|
16
|
+
"Platform Engineer",
|
|
17
|
+
"SRE",
|
|
18
|
+
"Other"
|
|
19
|
+
];
|
|
20
|
+
var TEAM_SIZES = ["1", "2-5", "6-10", "11-50", "51-200", "200+"];
|
|
21
|
+
var GOALS = [
|
|
22
|
+
"Infrastructure as Code",
|
|
23
|
+
"Cloud Migration",
|
|
24
|
+
"Cost Optimization",
|
|
25
|
+
"Security & Compliance",
|
|
26
|
+
"Automation",
|
|
27
|
+
"Multi-cloud Strategy"
|
|
28
|
+
];
|
|
29
|
+
var CLOUD_PROVIDERS = ["Azure", "AWS", "GCP", "Multi-cloud", "Other"];
|
|
30
|
+
var Onboarding = ({
|
|
31
|
+
baseUrl,
|
|
32
|
+
token,
|
|
33
|
+
onComplete
|
|
34
|
+
}) => {
|
|
35
|
+
const [step, setStep] = useState(0);
|
|
36
|
+
const [data, setData] = useState({
|
|
37
|
+
name: "",
|
|
38
|
+
role: "",
|
|
39
|
+
teamSize: "",
|
|
40
|
+
goals: [],
|
|
41
|
+
cloudProvider: ""
|
|
42
|
+
});
|
|
43
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
44
|
+
const [error, setError] = useState(null);
|
|
45
|
+
const [submitting, setSubmitting] = useState(false);
|
|
46
|
+
useInput((input, key) => {
|
|
47
|
+
if (submitting) return;
|
|
48
|
+
if (key.upArrow) {
|
|
49
|
+
setSelectedIndex((i) => Math.max(0, i - 1));
|
|
50
|
+
} else if (key.downArrow) {
|
|
51
|
+
if (step === 3) {
|
|
52
|
+
setSelectedIndex((i) => Math.min(GOALS.length - 1, i + 1));
|
|
53
|
+
} else if (step === 1) {
|
|
54
|
+
setSelectedIndex((i) => Math.min(ROLES.length - 1, i + 1));
|
|
55
|
+
} else if (step === 2) {
|
|
56
|
+
setSelectedIndex((i) => Math.min(TEAM_SIZES.length - 1, i + 1));
|
|
57
|
+
} else if (step === 4) {
|
|
58
|
+
setSelectedIndex((i) => Math.min(CLOUD_PROVIDERS.length - 1, i + 1));
|
|
59
|
+
}
|
|
60
|
+
} else if (input === " " && step === 3) {
|
|
61
|
+
const goal = GOALS[selectedIndex];
|
|
62
|
+
setData((prev) => ({
|
|
63
|
+
...prev,
|
|
64
|
+
goals: prev.goals.includes(goal) ? prev.goals.filter((g) => g !== goal) : [...prev.goals, goal]
|
|
65
|
+
}));
|
|
66
|
+
} else if (key.return) {
|
|
67
|
+
if (step === 0) {
|
|
68
|
+
if (data.name.trim()) {
|
|
69
|
+
setStep(1);
|
|
70
|
+
setSelectedIndex(0);
|
|
71
|
+
}
|
|
72
|
+
} else if (step === 1) {
|
|
73
|
+
setData((prev) => ({ ...prev, role: ROLES[selectedIndex] }));
|
|
74
|
+
setStep(2);
|
|
75
|
+
setSelectedIndex(0);
|
|
76
|
+
} else if (step === 2) {
|
|
77
|
+
setData((prev) => ({ ...prev, teamSize: TEAM_SIZES[selectedIndex] }));
|
|
78
|
+
setStep(3);
|
|
79
|
+
setSelectedIndex(0);
|
|
80
|
+
} else if (step === 3) {
|
|
81
|
+
if (data.goals.length > 0) {
|
|
82
|
+
setStep(4);
|
|
83
|
+
setSelectedIndex(0);
|
|
84
|
+
}
|
|
85
|
+
} else if (step === 4) {
|
|
86
|
+
const nextData = {
|
|
87
|
+
...data,
|
|
88
|
+
cloudProvider: CLOUD_PROVIDERS[selectedIndex]
|
|
89
|
+
};
|
|
90
|
+
setData(nextData);
|
|
91
|
+
handleSubmit(nextData);
|
|
92
|
+
}
|
|
93
|
+
} else if (key.backspace && step === 0) {
|
|
94
|
+
setData((prev) => ({ ...prev, name: prev.name.slice(0, -1) }));
|
|
95
|
+
} else if (step === 0 && input.length === 1 && !key.ctrl && !key.meta) {
|
|
96
|
+
setData((prev) => ({ ...prev, name: prev.name + input }));
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
const handleSubmit = async (submission = data) => {
|
|
100
|
+
setSubmitting(true);
|
|
101
|
+
setError(null);
|
|
102
|
+
try {
|
|
103
|
+
await completeOnboarding(baseUrl, token, {
|
|
104
|
+
name: submission.name,
|
|
105
|
+
role: submission.role,
|
|
106
|
+
teamSize: submission.teamSize,
|
|
107
|
+
goals: submission.goals,
|
|
108
|
+
cloudProvider: submission.cloudProvider
|
|
109
|
+
});
|
|
110
|
+
onComplete();
|
|
111
|
+
} catch (err) {
|
|
112
|
+
setError(err.message || "Failed to complete onboarding");
|
|
113
|
+
setSubmitting(false);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, gap: 1, children: [
|
|
117
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: terminalTheme.brand, children: "Welcome to Cloudeval CLI! Let's get you set up." }),
|
|
118
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
119
|
+
"Step ",
|
|
120
|
+
step + 1,
|
|
121
|
+
" of 5"
|
|
122
|
+
] }),
|
|
123
|
+
step === 0 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
|
|
124
|
+
/* @__PURE__ */ jsx(Text, { children: "What's your name?" }),
|
|
125
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
126
|
+
/* @__PURE__ */ jsx(Text, { color: terminalTheme.success, children: data.name }),
|
|
127
|
+
/* @__PURE__ */ jsx(Text, { color: terminalTheme.cursor, children: "\u258C" })
|
|
128
|
+
] }),
|
|
129
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Type your name and press Enter" })
|
|
130
|
+
] }),
|
|
131
|
+
step === 1 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
|
|
132
|
+
/* @__PURE__ */ jsx(Text, { children: "What's your role?" }),
|
|
133
|
+
ROLES.map((role, idx) => /* @__PURE__ */ jsxs(Text, { color: idx === selectedIndex ? terminalTheme.brand : void 0, children: [
|
|
134
|
+
idx === selectedIndex ? "> " : " ",
|
|
135
|
+
role
|
|
136
|
+
] }, role)),
|
|
137
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Use \u2191\u2193 to navigate, Enter to select" })
|
|
138
|
+
] }),
|
|
139
|
+
step === 2 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
|
|
140
|
+
/* @__PURE__ */ jsx(Text, { children: "What's your team size?" }),
|
|
141
|
+
TEAM_SIZES.map((size, idx) => /* @__PURE__ */ jsxs(Text, { color: idx === selectedIndex ? terminalTheme.brand : void 0, children: [
|
|
142
|
+
idx === selectedIndex ? "> " : " ",
|
|
143
|
+
size
|
|
144
|
+
] }, size)),
|
|
145
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Use \u2191\u2193 to navigate, Enter to select" })
|
|
146
|
+
] }),
|
|
147
|
+
step === 3 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
|
|
148
|
+
/* @__PURE__ */ jsx(Text, { children: "What are your goals? (Select multiple with Space)" }),
|
|
149
|
+
GOALS.map((goal, idx) => /* @__PURE__ */ jsxs(Text, { color: idx === selectedIndex ? terminalTheme.brand : void 0, children: [
|
|
150
|
+
data.goals.includes(goal) ? "\u2713 " : " ",
|
|
151
|
+
idx === selectedIndex ? "> " : " ",
|
|
152
|
+
goal
|
|
153
|
+
] }, goal)),
|
|
154
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
155
|
+
"Selected: ",
|
|
156
|
+
data.goals.length,
|
|
157
|
+
" goal(s). Press Enter to continue."
|
|
158
|
+
] })
|
|
159
|
+
] }),
|
|
160
|
+
step === 4 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
|
|
161
|
+
/* @__PURE__ */ jsx(Text, { children: "Which cloud provider do you use?" }),
|
|
162
|
+
CLOUD_PROVIDERS.map((provider, idx) => /* @__PURE__ */ jsxs(
|
|
163
|
+
Text,
|
|
164
|
+
{
|
|
165
|
+
color: idx === selectedIndex ? terminalTheme.brand : void 0,
|
|
166
|
+
children: [
|
|
167
|
+
idx === selectedIndex ? "> " : " ",
|
|
168
|
+
provider
|
|
169
|
+
]
|
|
170
|
+
},
|
|
171
|
+
provider
|
|
172
|
+
)),
|
|
173
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "Use \u2191\u2193 to navigate, Enter to select" })
|
|
174
|
+
] }),
|
|
175
|
+
error && /* @__PURE__ */ jsxs(Text, { color: terminalTheme.danger, children: [
|
|
176
|
+
"Error: ",
|
|
177
|
+
error
|
|
178
|
+
] }),
|
|
179
|
+
submitting && /* @__PURE__ */ jsx(Text, { color: terminalTheme.warning, children: "Completing onboarding..." })
|
|
180
|
+
] });
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export {
|
|
184
|
+
Onboarding
|
|
185
|
+
};
|