Skip to content

Commit 7ffe4a0

Browse files
author
Luca Forstner
authored
feat(esbuild): Add debug ID injection for esbuild (#202)
1 parent 1a61872 commit 7ffe4a0

File tree

4 files changed

+79
-9
lines changed

4 files changed

+79
-9
lines changed

packages/bundler-plugin-core/.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ module.exports = {
1111
"rollup.config.js",
1212
"test/fixtures/**/*",
1313
"sentry-release-injection-file.js",
14+
"sentry-esbuild-debugid-injection-file.js",
1415
],
1516
parserOptions: {
1617
tsconfigRootDir: __dirname,

packages/bundler-plugin-core/package.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
},
1212
"files": [
1313
"dist",
14-
"sentry-release-injection-file.js"
14+
"sentry-release-injection-file.js",
15+
"sentry-esbuild-debugid-injection-file.js"
1516
],
1617
"main": "dist/cjs/index.js",
1718
"module": "dist/esm/index.mjs",
@@ -71,5 +72,9 @@
7172
},
7273
"engines": {
7374
"node": ">= 10"
74-
}
75+
},
76+
"sideEffects": [
77+
"./sentry-release-injection-file.js",
78+
"./sentry-esbuild-debugid-injection-file.js"
79+
]
7580
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
try {
2+
var globalObject =
3+
"undefined" != typeof window
4+
? window
5+
: "undefined" != typeof global
6+
? global
7+
: "undefined" != typeof self
8+
? self
9+
: {};
10+
11+
var stack = new Error().stack;
12+
13+
if (stack) {
14+
globalObject._sentryDebugIds = globalObject._sentryDebugIds || {};
15+
globalObject._sentryDebugIds[stack] = "__SENTRY_DEBUG_ID__";
16+
globalObject._sentryDebugIdIdentifier = "sentry-dbid-__SENTRY_DEBUG_ID__";
17+
}
18+
} catch (e) {}

packages/bundler-plugin-core/src/index.ts

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createUnplugin } from "unplugin";
1+
import { createUnplugin, UnpluginOptions } from "unplugin";
22
import MagicString from "magic-string";
33
import { Options, BuildContext } from "./types";
44
import {
@@ -26,8 +26,8 @@ import { makeMain } from "@sentry/node";
2626
import os from "os";
2727
import path from "path";
2828
import fs from "fs";
29-
import util from "util";
30-
import { getDependencies, getPackageJson, parseMajorVersion } from "./utils";
29+
import { promisify } from "util";
30+
import { getDependencies, getPackageJson, parseMajorVersion, stringToUUID } from "./utils";
3131
import { glob } from "glob";
3232
import { injectDebugIdSnippetIntoChunk, prepareBundleForDebugIdUpload } from "./debug-id";
3333
import { SourceMapSource } from "webpack-sources";
@@ -39,6 +39,10 @@ const releaseInjectionFilePath = require.resolve(
3939
"@sentry/bundler-plugin-core/sentry-release-injection-file"
4040
);
4141

42+
const esbuildDebugIdInjectionFilePath = require.resolve(
43+
"@sentry/bundler-plugin-core/sentry-esbuild-debugid-injection-file"
44+
);
45+
4246
/**
4347
* The sentry bundler plugin concerns itself with two things:
4448
* - Release injection
@@ -66,7 +70,7 @@ const releaseInjectionFilePath = require.resolve(
6670
*
6771
* This release creation pipeline relies on Sentry CLI to execute the different steps.
6872
*/
69-
const unplugin = createUnplugin<Options>((options, unpluginMetaContext) => {
73+
const unplugin = createUnplugin<Options, true>((options, unpluginMetaContext) => {
7074
const internalOptions = normalizeUserOptions(options);
7175

7276
const allowedToSendTelemetryPromise = shouldSendTelemetry(internalOptions);
@@ -113,7 +117,9 @@ const unplugin = createUnplugin<Options>((options, unpluginMetaContext) => {
113117
let transaction: Transaction | undefined;
114118
let releaseInjectionSpan: Span | undefined;
115119

116-
return {
120+
const plugins: UnpluginOptions[] = [];
121+
122+
plugins.push({
117123
name: "sentry-plugin",
118124
enforce: "pre", // needed for Vite to call resolveId hook
119125

@@ -317,7 +323,31 @@ const unplugin = createUnplugin<Options>((options, unpluginMetaContext) => {
317323
})
318324
).filter((p) => p.endsWith(".js") || p.endsWith(".mjs") || p.endsWith(".cjs"));
319325

320-
const sourceFileUploadFolderPromise = util.promisify(fs.mkdtemp)(
326+
if (unpluginMetaContext.framework === "esbuild") {
327+
await Promise.all(
328+
debugIdChunkFilePaths.map(async (debugIdChunkFilePath) => {
329+
const chunkFileContents = await promisify(fs.readFile)(
330+
debugIdChunkFilePath,
331+
"utf-8"
332+
);
333+
334+
const debugId = stringToUUID(chunkFileContents);
335+
336+
const newChunkFileContents = chunkFileContents.replace(
337+
/__SENTRY_DEBUG_ID__/g,
338+
debugId
339+
);
340+
341+
await promisify(fs.writeFile)(
342+
debugIdChunkFilePath,
343+
newChunkFileContents,
344+
"utf-8"
345+
);
346+
})
347+
);
348+
}
349+
350+
const sourceFileUploadFolderPromise = promisify(fs.mkdtemp)(
321351
path.join(os.tmpdir(), "sentry-bundler-plugin-upload-")
322352
);
323353

@@ -455,7 +485,23 @@ const unplugin = createUnplugin<Options>((options, unpluginMetaContext) => {
455485
});
456486
}
457487
},
458-
};
488+
});
489+
490+
if (unpluginMetaContext.framework === "esbuild") {
491+
if (internalOptions._experiments.debugIdUpload) {
492+
plugins.push({
493+
name: "sentry-esbuild-debug-id-plugin",
494+
esbuild: {
495+
setup({ initialOptions }) {
496+
initialOptions.inject = initialOptions.inject || [];
497+
initialOptions.inject.push(esbuildDebugIdInjectionFilePath);
498+
},
499+
},
500+
});
501+
}
502+
}
503+
504+
return plugins;
459505
});
460506

461507
function handleError(

0 commit comments

Comments
 (0)