Skip to content

Commit f22747b

Browse files
authored
feat: Promote experimental moduleMetadata option to stable (#538)
1 parent 929aa15 commit f22747b

File tree

6 files changed

+69
-30
lines changed

6 files changed

+69
-30
lines changed

Diff for: packages/bundler-plugin-core/src/index.ts

+14-9
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import { logger } from "@sentry/utils";
2929
interface SentryUnpluginFactoryOptions {
3030
releaseInjectionPlugin: (injectionCode: string) => UnpluginOptions;
3131
componentNameAnnotatePlugin?: () => UnpluginOptions;
32-
moduleMetadataInjectionPlugin?: (injectionCode: string) => UnpluginOptions;
32+
moduleMetadataInjectionPlugin: (injectionCode: string) => UnpluginOptions;
3333
debugIdInjectionPlugin: (logger: Logger) => UnpluginOptions;
3434
debugIdUploadPlugin: (upload: (buildArtifacts: string[]) => Promise<void>) => UnpluginOptions;
3535
bundleSizeOptimizationsPlugin: (buildFlags: SentrySDKBuildFlags) => UnpluginOptions;
@@ -96,6 +96,13 @@ export function sentryUnpluginFactory({
9696

9797
const options = normalizeUserOptions(userOptions);
9898

99+
// TODO(v3): Remove this warning
100+
if (userOptions._experiments?.moduleMetadata) {
101+
logger.warn(
102+
"The `_experiments.moduleMetadata` option has been promoted to being stable. You can safely move the option out of the `_experiments` object scope."
103+
);
104+
}
105+
99106
if (unpluginMetaContext.watchMode || options.disable) {
100107
return [
101108
{
@@ -217,25 +224,23 @@ export function sentryUnpluginFactory({
217224
plugins.push(releaseInjectionPlugin(injectionCode));
218225
}
219226

220-
if (moduleMetadataInjectionPlugin && options._experiments.moduleMetadata) {
221-
let metadata: object;
222-
if (typeof options._experiments.moduleMetadata === "function") {
227+
if (options.moduleMetadata) {
228+
let metadata: Record<string, unknown>;
229+
if (typeof options.moduleMetadata === "function") {
223230
const args = {
224231
org: options.org,
225232
project: options.project,
226233
release: options.release.name,
227234
};
228-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
229-
metadata = options._experiments.moduleMetadata(args);
235+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
236+
metadata = options.moduleMetadata(args);
230237
} else {
231238
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
232-
metadata = options._experiments.moduleMetadata;
239+
metadata = options.moduleMetadata;
233240
}
234241

235242
const injectionCode = generateModuleMetadataInjectorCode(metadata);
236243
plugins.push(moduleMetadataInjectionPlugin(injectionCode));
237-
} else if (options._experiments.moduleMetadata) {
238-
logger.warn("'moduleMetadata' is currently only supported by '@sentry/webpack-plugin'");
239244
}
240245

241246
if (!options.release.name) {

Diff for: packages/bundler-plugin-core/src/options-mapping.ts

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export function normalizeUserOptions(userOptions: UserOptions) {
2929
},
3030
bundleSizeOptimizations: userOptions.bundleSizeOptimizations,
3131
reactComponentAnnotation: userOptions.reactComponentAnnotation,
32+
moduleMetadata: userOptions.moduleMetadata || userOptions._experiments?.moduleMetadata,
3233
_experiments: userOptions._experiments ?? {},
3334
};
3435

Diff for: packages/bundler-plugin-core/src/sentry/telemetry.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export function setTelemetryDataOnHub(options: NormalizedOptions, hub: Hub, bund
7070
);
7171
}
7272

73-
hub.setTag("module-metadata", !!options._experiments.moduleMetadata);
73+
hub.setTag("module-metadata", !!options.moduleMetadata);
7474
hub.setTag("inject-build-information", !!options._experiments.injectBuildInformation);
7575

7676
// Optional release pipeline steps

Diff for: packages/bundler-plugin-core/src/types.ts

+31-5
Original file line numberDiff line numberDiff line change
@@ -297,11 +297,27 @@ export interface Options {
297297
enabled?: boolean;
298298
};
299299

300+
/**
301+
* Metadata that should be associated with the built application.
302+
*
303+
* The metadata is serialized and can be looked up at runtime from within the SDK (for example in the `beforeSend`,
304+
* event processors, or the transport), allowing for custom event filtering logic or routing of events.
305+
*
306+
* Metadata can either be passed directly or alternatively a callback can be provided that will be
307+
* called with the following parameters:
308+
* - `org`: The organization slug.
309+
* - `project`: The project slug.
310+
* - `release`: The release name.
311+
*/
312+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
313+
moduleMetadata?: ModuleMetadata | ModuleMetadataCallback;
314+
300315
/**
301316
* Options that are considered experimental and subject to change.
302317
*
303318
* @experimental API that does not follow semantic versioning and may change in any release
304319
*/
320+
// TODO(v3): Remove these
305321
_experiments?: {
306322
/**
307323
* If set to true, the plugin will inject an additional `SENTRY_BUILD_INFO` variable.
@@ -312,18 +328,23 @@ export interface Options {
312328
injectBuildInformation?: boolean;
313329

314330
/**
315-
* Metadata associated with this module.
331+
* NOTE: This option has been promoted to stable.
316332
*
317-
* The metadata is serialized and can be looked up at runtime by filename.
333+
* Metadata that should be associated with the built application.
334+
*
335+
* The metadata is serialized and can be looked up at runtime from within the SDK (for example in the `beforeSend`,
336+
* event processors, or the transport), allowing for custom event filtering logic or routing of events.
318337
*
319338
* Metadata can either be passed directly or alternatively a callback can be provided that will be
320-
* called with the following arguments:
339+
* called with the following parameters:
321340
* - `org`: The organization slug.
322341
* - `project`: The project slug.
323342
* - `release`: The release name.
343+
*
344+
* @deprecated Use the non-experimental `moduleMetadata` option instead. (Basically just move this option out of `_experiments`)
324345
*/
325346
// eslint-disable-next-line @typescript-eslint/no-explicit-any
326-
moduleMetadata?: any | ModuleMetadataCallback;
347+
moduleMetadata?: ModuleMetadata | ModuleMetadataCallback;
327348
};
328349

329350
/**
@@ -340,13 +361,18 @@ export interface Options {
340361
};
341362
}
342363

364+
export interface ModuleMetadata {
365+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
366+
[key: string]: any;
367+
}
368+
343369
export interface ModuleMetadataCallbackArgs {
344370
org?: string;
345371
project?: string;
346372
release?: string;
347373
}
348374

349-
export type ModuleMetadataCallback = (args: ModuleMetadataCallbackArgs) => object;
375+
export type ModuleMetadataCallback = (args: ModuleMetadataCallbackArgs) => ModuleMetadata;
350376

351377
export type IncludeEntry = {
352378
/**

Diff for: packages/bundler-plugin-core/src/utils.ts

+21-12
Original file line numberDiff line numberDiff line change
@@ -280,18 +280,27 @@ export function generateGlobalInjectorCode({
280280
export function generateModuleMetadataInjectorCode(metadata: any) {
281281
// The code below is mostly ternary operators because it saves bundle size.
282282
// The checks are to support as many environments as possible. (Node.js, Browser, webworkers, etc.)
283-
return `
284-
var _global2 =
285-
typeof window !== 'undefined' ?
286-
window :
287-
typeof global !== 'undefined' ?
288-
global :
289-
typeof self !== 'undefined' ?
290-
self :
291-
{};
292-
293-
_global2._sentryModuleMetadata = _global2._sentryModuleMetadata || {};
294-
_global2._sentryModuleMetadata[new Error().stack] = ${JSON.stringify(metadata)};`;
283+
// We are merging the metadata objects in case modules are bundled twice with the plugin
284+
return `{
285+
var _sentryModuleMetadataGlobal =
286+
typeof window !== "undefined"
287+
? window
288+
: typeof global !== "undefined"
289+
? global
290+
: typeof self !== "undefined"
291+
? self
292+
: {};
293+
294+
_sentryModuleMetadataGlobal._sentryModuleMetadata =
295+
_sentryModuleMetadataGlobal._sentryModuleMetadata || {};
296+
297+
_sentryModuleMetadataGlobal._sentryModuleMetadata[new Error().stack] =
298+
Object.assign(
299+
{},
300+
_sentryModuleMetadataGlobal._sentryModuleMetadata[new Error().stack],
301+
${JSON.stringify(metadata)}
302+
);
303+
}`;
295304
}
296305

297306
function getBuildInformation() {

Diff for: packages/integration-tests/fixtures/metadata-injection/setup.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ createCjsBundles(
99
},
1010
outputDir,
1111
{
12-
_experiments: {
13-
moduleMetadata: { team: "frontend" },
14-
},
12+
moduleMetadata: { team: "frontend" },
1513
},
1614
["webpack4", "webpack5", "esbuild", "rollup", "vite"]
1715
);

0 commit comments

Comments
 (0)