-
-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathformatters.ts
More file actions
149 lines (132 loc) · 4.57 KB
/
formatters.ts
File metadata and controls
149 lines (132 loc) · 4.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/**
* Output Formatters
*
* Translate the raw workflow result into the structured `WizardSummary`
* the UI implementations render. The previous version assembled
* terminal-flavored markdown (color tags, an aligned key/value table,
* a tree of changed files) and pushed it through `ui.log.message`.
* That worked for `LoggingUI` (which calls `renderMarkdown`) but the
* earlier TUI showed literal markup like `<yellow>~</yellow>` and
* pipe-cells because the underlying text primitive couldn't parse
* markdown — only strip ANSI.
*
* Now `formatResult` calls `ui.summary(structuredData)` and lets each
* implementation decide how to lay it out. `formatError` still uses
* `ui.log.*` because errors are short enough to live as plain text.
*/
import { terminalLink } from "../formatters/colors.js";
import { stripAnsi } from "../formatters/plain-detect.js";
import { featureLabel, sortFeatures } from "./clack-utils.js";
import {
EXIT_DEPENDENCY_INSTALL_FAILED,
EXIT_PLATFORM_NOT_DETECTED,
EXIT_VERIFICATION_FAILED,
} from "./constants.js";
import type { WizardOutput, WorkflowRunResult } from "./types.js";
import type { WizardSummary, WizardUI } from "./ui/types.js";
/**
* Build the structured summary handed to `ui.summary()`.
*
* Returns `null` when there's nothing useful to display — the caller
* skips the summary call entirely in that case so empty panels don't
* appear.
*/
function buildSummary(output: WizardOutput): WizardSummary | null {
// Resolve blurbs first so the Features row can check the *resolved* length.
// If the agent returns blurbs with wrong IDs they all drop out here, and
// the Features row falls back to showing correctly.
const blurbMap = new Map(
(output.featureBlurbs ?? []).map(({ feature, blurb }) => [
feature,
stripAnsi(blurb),
])
);
const featureBlurbs = sortFeatures(output.features ?? [])
.map((feature) => {
const blurb = blurbMap.get(feature);
return blurb ? { label: featureLabel(feature), blurb } : null;
})
.filter((b): b is { label: string; blurb: string } => b !== null);
const fields: WizardSummary["fields"] = [];
if (output.platform) {
fields.push({ label: "Platform", value: output.platform });
}
if (output.projectDir) {
fields.push({ label: "Directory", value: output.projectDir });
}
if (output.features?.length && !featureBlurbs.length) {
fields.push({
label: "Features",
value: output.features.map(featureLabel).join(", "),
});
}
if (output.commands?.length) {
fields.push({
label: "Commands",
value: output.commands.join("; "),
});
}
if (output.sentryProjectUrl) {
fields.push({ label: "Project", value: output.sentryProjectUrl });
}
if (output.docsUrl) {
fields.push({ label: "Docs", value: output.docsUrl });
}
const changedFiles = output.changedFiles ?? [];
if (
fields.length === 0 &&
changedFiles.length === 0 &&
featureBlurbs.length === 0
) {
return null;
}
return {
fields,
...(changedFiles.length > 0 ? { changedFiles } : {}),
...(featureBlurbs.length > 0 ? { featureBlurbs } : {}),
};
}
export function formatResult(result: WorkflowRunResult, ui: WizardUI): void {
const output: WizardOutput = result.result ?? {};
const summary = buildSummary(output);
if (summary) {
ui.summary(summary);
}
if (output.warnings?.length) {
for (const w of output.warnings) {
ui.log.warn(w);
}
}
ui.log.info("Please review the changes above before committing.");
ui.outro("Sentry SDK installed successfully!");
ui.feedback("success");
}
export function formatError(result: WorkflowRunResult, ui: WizardUI): void {
const inner = result.result;
const message =
result.error ?? inner?.message ?? "Wizard failed with an unknown error";
const exitCode = inner?.exitCode ?? 1;
ui.log.error(String(message));
if (exitCode === EXIT_PLATFORM_NOT_DETECTED) {
ui.log.warn(
"Hint: Could not detect your project's platform. Check that the directory contains a valid project."
);
} else if (exitCode === EXIT_DEPENDENCY_INSTALL_FAILED) {
const commands = inner?.commands;
if (commands?.length) {
ui.log.warn(
`You can install dependencies manually:\n${commands.map((cmd) => ` $ ${cmd}`).join("\n")}`
);
}
} else if (exitCode === EXIT_VERIFICATION_FAILED) {
ui.log.warn(
"Hint: Fix the verification issues and run 'sentry init' again."
);
}
const docsUrl = inner?.docsUrl;
if (docsUrl) {
ui.log.info(`Docs: ${terminalLink(docsUrl)}`);
}
ui.cancel("Setup failed");
ui.feedback("failed");
}