Skip to content

Commit 454feec

Browse files
betegonclaude
andcommitted
refactor: use markdown renderer for sentry cli dsn output
Switch from manual ANSI formatting (bold/green/muted) to the project's markdown rendering pipeline (renderMarkdown, mdKvTable, colorTag, safeCodeSpan). Produces boxed KV tables, proper heading underlines, and consistent styling with other CLI commands. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5190c8d commit 454feec

1 file changed

Lines changed: 59 additions & 44 deletions

File tree

src/commands/cli/dsn.ts

Lines changed: 59 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@ import {
1717
resolveProject,
1818
} from "../../lib/dsn/index.js";
1919
import { isAuthenticated } from "../../lib/db/auth.js";
20-
import { bold, green, muted, yellow } from "../../lib/formatters/colors.js";
20+
import {
21+
colorTag,
22+
escapeMarkdownInline,
23+
mdKvTable,
24+
renderMarkdown,
25+
safeCodeSpan,
26+
} from "../../lib/formatters/markdown.js";
2127
import { CommandOutput } from "../../lib/formatters/output.js";
2228
import {
2329
applyFreshFlag,
@@ -85,101 +91,110 @@ type DsnDiscoveryData = {
8591

8692
/** Mask the middle of a DSN's public key for display */
8793
function maskDsnKey(dsn: string): string {
88-
// Replace the public key portion: https://KEY@host/id → https://KEY[masked]@host/id
8994
return dsn.replace(
9095
/^(https?:\/\/)([a-z0-9]{4})[a-z0-9]+(@)/i,
9196
(_, proto, start, at) => `${proto}${start}****${at}`
9297
);
9398
}
9499

95-
function formatDsnEntry(
96-
entry: DsnDiscoveryData["dsns"][number],
97-
index: number,
98-
total: number
99-
): string {
100+
function formatDsnEntry(entry: DsnDiscoveryData["dsns"][number]): string {
100101
const lines: string[] = [];
101102

102-
const prefix = total > 1 ? `${index + 1}. ` : "";
103-
const primaryTag = entry.primary ? green(" (primary)") : "";
104-
lines.push(`${prefix}${bold(maskDsnKey(entry.dsn))}${primaryTag}`);
105-
lines.push(` Source: ${entry.sourceDescription}`);
103+
const rows: [string, string][] = [
104+
["DSN", safeCodeSpan(maskDsnKey(entry.dsn))],
105+
["Source", escapeMarkdownInline(entry.sourceDescription)],
106+
];
106107
if (entry.packagePath) {
107-
lines.push(` Package: ${entry.packagePath}`);
108+
rows.push(["Package", safeCodeSpan(entry.packagePath)]);
108109
}
109-
lines.push(` Project ID: ${entry.projectId}`);
110+
rows.push(["Project ID", safeCodeSpan(entry.projectId)]);
110111
if (entry.orgId) {
111-
lines.push(` Org ID: ${entry.orgId}`);
112+
rows.push(["Org ID", safeCodeSpan(entry.orgId)]);
112113
}
113114
if (entry.resolved) {
114-
lines.push(
115-
` Resolved: ${green(`${entry.resolved.orgSlug}/${entry.resolved.projectSlug}`)}`
116-
);
115+
rows.push([
116+
"Resolved",
117+
colorTag(
118+
"green",
119+
`${entry.resolved.orgSlug}/${entry.resolved.projectSlug}`
120+
),
121+
]);
117122
} else {
118-
lines.push(` Resolved: ${muted("(not yet resolved)")}`);
123+
rows.push(["Resolved", colorTag("muted", "(not yet resolved)")]);
119124
}
120125

126+
lines.push(mdKvTable(rows));
121127
return lines.join("\n");
122128
}
123129

124130
function formatDsnDiscovery(data: DsnDiscoveryData): string {
125131
const lines: string[] = [];
126132

127133
// Project root
128-
lines.push(bold("Project root"));
129-
lines.push(` Path: ${data.projectRoot.path}`);
130-
lines.push(` Reason: ${data.projectRoot.reason}`);
134+
lines.push("## Project root");
135+
lines.push("");
136+
lines.push(
137+
mdKvTable([
138+
["Path", safeCodeSpan(data.projectRoot.path)],
139+
["Reason", data.projectRoot.reason],
140+
])
141+
);
131142

132143
// Scan summary
144+
lines.push("## Scan");
133145
lines.push("");
134-
lines.push(bold("Scan"));
146+
const dirCount = data.scan.dirs.length;
147+
const fileCount = data.scan.files;
135148
lines.push(
136-
` ${data.scan.dirs.length} director${data.scan.dirs.length === 1 ? "y" : "ies"}, ${data.scan.files} file${data.scan.files === 1 ? "" : "s"} checked`
149+
`${dirCount} director${dirCount === 1 ? "y" : "ies"}, ${fileCount} file${fileCount === 1 ? "" : "s"} checked`
137150
);
138-
if (data.scan.dirs.length > 0) {
139-
// Sort dirs for stable display, show relative paths
151+
lines.push("");
152+
if (dirCount > 0) {
140153
const sortedDirs = [...data.scan.dirs].sort();
141154
for (const dir of sortedDirs) {
142-
lines.push(` ${muted(dir)}`);
155+
lines.push(`- ${colorTag("muted", dir)}`);
143156
}
157+
lines.push("");
144158
}
145159

146160
// Env var
161+
lines.push("## Environment");
147162
lines.push("");
148-
lines.push(bold("Environment"));
149163
if (data.envVar) {
150-
lines.push(` SENTRY_DSN: ${maskDsnKey(data.envVar)}`);
164+
lines.push(`SENTRY\\_DSN: ${safeCodeSpan(maskDsnKey(data.envVar))}`);
151165
} else {
152-
lines.push(` SENTRY_DSN: ${muted("(not set)")}`);
166+
lines.push(`SENTRY\\_DSN: ${colorTag("muted", "(not set)")}`);
153167
}
168+
lines.push("");
154169

155170
// DSNs
156-
lines.push("");
157171
if (data.count === 0) {
158-
lines.push(yellow("No DSNs found"));
172+
lines.push(colorTag("yellow", "No DSNs found"));
159173
lines.push("");
160174
lines.push("The CLI looks for DSNs in:");
161-
lines.push(" 1. Source code (Sentry.init calls, DSN strings)");
162-
lines.push(" 2. .env files (SENTRY_DSN=...)");
163-
lines.push(" 3. SENTRY_DSN environment variable");
175+
lines.push("1. Source code (Sentry.init calls, DSN strings)");
176+
lines.push("2. .env files (SENTRY\\_DSN=...)");
177+
lines.push("3. SENTRY\\_DSN environment variable");
164178
lines.push("");
165179
lines.push(
166-
`Searched from ${muted(data.cwd)} up to ${muted(data.projectRoot.path)}`
180+
`Searched from ${safeCodeSpan(data.cwd)} up to ${safeCodeSpan(data.projectRoot.path)}`
167181
);
168182
} else {
169-
lines.push(
170-
bold(`Found ${data.count} DSN${data.count > 1 ? "s" : ""}`)
171-
);
172-
lines.push("");
173-
for (let i = 0; i < data.dsns.length; i++) {
174-
const entry = data.dsns[i]!;
175-
lines.push(formatDsnEntry(entry, i, data.count));
176-
if (i < data.dsns.length - 1) {
183+
lines.push(`## Found ${data.count} DSN${data.count > 1 ? "s" : ""}`);
184+
for (const [i, entry] of data.dsns.entries()) {
185+
lines.push("");
186+
if (data.count > 1) {
187+
const primaryTag = entry.primary
188+
? ` ${colorTag("green", "(primary)")}`
189+
: "";
190+
lines.push(`### ${i + 1}.${primaryTag}`);
177191
lines.push("");
178192
}
193+
lines.push(formatDsnEntry(entry));
179194
}
180195
}
181196

182-
return lines.join("\n");
197+
return renderMarkdown(lines.join("\n"));
183198
}
184199

185200
function mapDsn(

0 commit comments

Comments
 (0)