Skip to content

Commit 39953bc

Browse files
veksenclaude
andcommitted
feat(mikroorm): normalize source-map-resolved file paths
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 865de85 commit 39953bc

3 files changed

Lines changed: 73 additions & 1 deletion

File tree

nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { alreadyHasTrailingComment, serializeTags, type Tag } from "./sqlcommenter.js";
22
import { als } from "./als.js";
33
import { pushW3CTraceContext } from "./tracing.js";
4+
import { resolveFilePath } from "./path.js";
45

56
const LIBRARY_NAME = "sqlcommenter-mikroorm";
67

@@ -42,7 +43,7 @@ export function traceCaller(): string | undefined {
4243
}
4344
const match = methodCaller.match(filepathRegex);
4445
if (match) {
45-
return match[1];
46+
return resolveFilePath(match[1]);
4647
}
4748
}
4849

nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/src/path.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,35 @@ export function findProjectRoot(): string {
2828
return projectRoot;
2929
}
3030

31+
/**
32+
* Resolves a file path from a stack trace to a correct absolute path.
33+
*
34+
* When compiled JS is relocated (e.g., postbuild copies `dist/` to a deployment directory),
35+
* source-map-resolved paths become incorrect because the relative `sources` entries in
36+
* `.map` files resolve against the new location instead of the original project.
37+
*
38+
* This extracts the `src/`-relative portion and reconstructs the path using the real
39+
* project root.
40+
*
41+
* @param raw - A stack trace entry like "/wrong/path/src/routes/admin.ts:12:15"
42+
* @returns The resolved path like "/project/root/src/routes/admin.ts:12:15"
43+
*/
44+
export function resolveFilePath(raw: string): string {
45+
// Split off :line:column suffix
46+
const match = raw.match(/^(.*?):(\d+:\d+)$/);
47+
if (!match) {
48+
return raw;
49+
}
50+
const [, filePath, lineCol] = match;
51+
const srcIdx = filePath.indexOf("src/");
52+
if (srcIdx < 0) {
53+
return raw;
54+
}
55+
const projectRoot = findProjectRoot();
56+
const relativePath = filePath.substring(srcIdx);
57+
return `${projectRoot}/${relativePath}:${lineCol}`;
58+
}
59+
3160
/** @internal Exposed for testing only */
3261
export function _resetProjectRootCache() {
3362
cachedProjectRoot = undefined;

nodejs/sqlcommenter-nodejs/packages/sqlcommenter-mikroorm/test/path.spec.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { existsSync } from "node:fs";
44
import { join } from "node:path";
55
import {
66
findProjectRoot,
7+
resolveFilePath,
78
_resetProjectRootCache,
89
} from "../src/path.js";
910

@@ -26,3 +27,44 @@ test("findProjectRoot", async (t) => {
2627
assert.strictEqual(first, second);
2728
});
2829
});
30+
31+
test("resolveFilePath", async (t) => {
32+
t.afterEach(() => {
33+
_resetProjectRootCache();
34+
});
35+
36+
await t.test("resolves path with src/ to project root", () => {
37+
const projectRoot = findProjectRoot();
38+
const result = resolveFilePath(
39+
"/wrong/deploy/dir/src/routes/admin.ts:12:15",
40+
);
41+
assert.strictEqual(result, `${projectRoot}/src/routes/admin.ts:12:15`);
42+
});
43+
44+
await t.test("leaves path without src/ unchanged", () => {
45+
const result = resolveFilePath("/some/other/path/routes/admin.ts:5:10");
46+
assert.strictEqual(result, "/some/other/path/routes/admin.ts:5:10");
47+
});
48+
49+
await t.test("preserves line:column suffix", () => {
50+
const projectRoot = findProjectRoot();
51+
const result = resolveFilePath("/bad/path/src/index.ts:99:3");
52+
assert.strictEqual(result, `${projectRoot}/src/index.ts:99:3`);
53+
});
54+
55+
await t.test("uses first src/ occurrence", () => {
56+
const projectRoot = findProjectRoot();
57+
const result = resolveFilePath(
58+
"/deploy/src/nested/src/routes/admin.ts:1:1",
59+
);
60+
assert.strictEqual(
61+
result,
62+
`${projectRoot}/src/nested/src/routes/admin.ts:1:1`,
63+
);
64+
});
65+
66+
await t.test("returns raw string if no line:column suffix", () => {
67+
const result = resolveFilePath("/some/path/src/file.ts");
68+
assert.strictEqual(result, "/some/path/src/file.ts");
69+
});
70+
});

0 commit comments

Comments
 (0)