Skip to content

Commit a43b66c

Browse files
authored
chore(cli): normalize source map paths for Sentry display (#15186)
Rewrite each .map file's `sources` array after the tsup build so that every entry is a clean repo-root-relative path (e.g. `packages/cli/cli/src/cli.ts`) instead of the esbuild default (`../../src/cli.ts`). Made-with: Cursor
1 parent 2084571 commit a43b66c

1 file changed

Lines changed: 43 additions & 1 deletion

File tree

packages/cli/cli/build-utils.mjs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { exec } from "child_process";
2-
import { writeFile } from "fs/promises";
2+
import { existsSync } from "fs";
3+
import { readdir, readFile, writeFile } from "fs/promises";
34
import path from "path";
45
import tsup from "tsup";
56
import { fileURLToPath } from "url";
@@ -9,6 +10,42 @@ import packageJson from "./package.json" with { type: "json" };
910
const execAsync = promisify(exec);
1011

1112
const __dirname = path.dirname(fileURLToPath(import.meta.url));
13+
const REPO_ROOT = path.resolve(__dirname, "../../..");
14+
15+
/**
16+
* Rewrite every .map file in absOutDir so each entry in `sources` is a clean
17+
* path relative to the repo root (e.g. "packages/cli/cli/src/cli.ts") instead
18+
* of a relative path like "../../src/cli.ts". This gives Sentry a tidy,
19+
* already-normalised filename to display and lets a single repo-root-based
20+
* code mapping resolve every frame regardless of package depth.
21+
*/
22+
async function rewriteSourceMapSources(absOutDir) {
23+
if (!existsSync(absOutDir)) {
24+
return;
25+
}
26+
const entries = await readdir(absOutDir, { withFileTypes: true });
27+
for (const entry of entries) {
28+
if (!entry.isFile() || !entry.name.endsWith(".map")) {
29+
continue;
30+
}
31+
const mapPath = path.join(absOutDir, entry.name);
32+
const mapDir = path.dirname(mapPath);
33+
const map = JSON.parse(await readFile(mapPath, "utf8"));
34+
if (!Array.isArray(map.sources)) {
35+
continue;
36+
}
37+
map.sources = map.sources.map((src) => {
38+
if (typeof src !== "string" || src === "" || src.startsWith("<") || src.startsWith("data:")) {
39+
return src;
40+
}
41+
return path.relative(REPO_ROOT, path.resolve(mapDir, src));
42+
});
43+
if ("sourceRoot" in map) {
44+
delete map.sourceRoot;
45+
}
46+
await writeFile(mapPath, JSON.stringify(map));
47+
}
48+
}
1249

1350
/**
1451
* Get a dependency version from package.json, preferring dependencies over devDependencies.
@@ -93,6 +130,11 @@ export async function buildCli(config) {
93130

94131
const outDirAbs = path.join(__dirname, outDir);
95132

133+
// Rewrite source map `sources` to repo-root-relative paths so Sentry
134+
// displays clean filenames (e.g. "packages/cli/cli/src/cli.ts") and a
135+
// single repo-root-based code mapping resolves every frame.
136+
await rewriteSourceMapSources(outDirAbs);
137+
96138
// Collect runtime dependencies
97139
const dependencies = {};
98140
for (const dep of runtimeDependencies) {

0 commit comments

Comments
 (0)