Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/bundler-plugin-core/src/debug-id-upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,10 @@ async function prepareSourceMapForDebugIdUpload(
}

if (map["sources"] && Array.isArray(map["sources"])) {
map["sources"] = map["sources"].map((source: string) => rewriteSourcesHook(source, map));
const mapDir = path.dirname(sourceMapPath);
map["sources"] = map["sources"].map((source: string) =>
rewriteSourcesHook(source, map, { mapDir })
);
}

try {
Expand Down
5 changes: 4 additions & 1 deletion packages/bundler-plugin-core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ export interface Options {
/**
* Hook to rewrite the `sources` field inside the source map before being uploaded to Sentry. Does not modify the actual source map.
*
* The hook receives the source path, the parsed source map object, and a context object containing `mapDir` -
* the directory of the source map file, useful for resolving relative source paths.
*
* Defaults to making all sources relative to `process.cwd()` while building.
*/
rewriteSources?: RewriteSourcesHook;
Expand Down Expand Up @@ -427,7 +430,7 @@ export interface Options {
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type RewriteSourcesHook = (source: string, map: any) => string;
export type RewriteSourcesHook = (source: string, map: any, context?: { mapDir: string }) => string;

export type ResolveSourceMapHook = (
artifactPath: string,
Expand Down
71 changes: 71 additions & 0 deletions packages/bundler-plugin-core/test/debug-id-upload.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import * as fs from "fs";
import * as path from "path";
import * as os from "os";
import { prepareBundleForDebugIdUpload } from "../src/debug-id-upload";
import type { RewriteSourcesHook } from "../src/types";
import { Logger } from "../src";

describe("prepareBundleForDebugIdUpload", () => {
let tmpDir: string;

beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "sentry-test-"));
});

afterEach(() => {
fs.rmSync(tmpDir, { recursive: true, force: true });
});

it("passes mapDir context to rewriteSources hook", async () => {
const bundleDir = path.join(tmpDir, "src");
const uploadDir = path.join(tmpDir, "upload");
fs.mkdirSync(bundleDir, { recursive: true });
fs.mkdirSync(uploadDir, { recursive: true });

const debugId = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee";
const bundlePath = path.join(bundleDir, "bundle.js");
const mapPath = path.join(bundleDir, "bundle.js.map");

// Bundle with debug ID snippet and sourceMappingURL
fs.writeFileSync(
bundlePath,
`"use strict";\n// some code\n;!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="${debugId}",e._sentryDebugIdIdentifier="sentry-dbid-${debugId}")}catch(e){}}();\n//# sourceMappingURL=bundle.js.map`
);

// Source map file
fs.writeFileSync(
mapPath,
JSON.stringify({
version: 3,
sources: ["../original/file.ts"],
mappings: "AAAA",
})
);

const capturedContexts: Array<{ mapDir?: string } | undefined> = [];
const rewriteHook: RewriteSourcesHook = (source, _map, context) => {
capturedContexts.push(context);
return source;
};

const logger = {
info: vi.fn(),
warn: vi.fn(),
error: vi.fn(),
debug: vi.fn(),
};

await prepareBundleForDebugIdUpload(
bundlePath,
uploadDir,
0,
logger as Logger,
rewriteHook,
undefined
);

expect(capturedContexts).toHaveLength(1);
expect(capturedContexts[0]!.mapDir).toBe(bundleDir);
});
});
4 changes: 2 additions & 2 deletions packages/dev-utils/src/generate-documentation-table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ errorHandler: (err) => {
},
{
name: "rewriteSources",
type: "(source: string, map: any) => string",
type: "(source: string, map: any, context?: { mapDir: string }) => string",
fullDescription:
"Hook to rewrite the `sources` field inside the source map before being uploaded to Sentry. Does not modify the actual source map. Effectively, this modifies how files inside the stacktrace will show up in Sentry.\n\nDefaults to making all sources relative to `process.cwd()` while building.",
"Hook to rewrite the `sources` field inside the source map before being uploaded to Sentry. Does not modify the actual source map. Effectively, this modifies how files inside the stacktrace will show up in Sentry.\n\nThe `context.mapDir` parameter provides the directory path of the source map file, which is useful for resolving relative source paths (e.g. `path.resolve(context.mapDir, source)`).\n\nDefaults to making all sources relative to `process.cwd()` while building.",
},
{
name: "resolveSourceMap",
Expand Down
Loading