From 2acbf7d97e4a4d2956d50800d1e2095c92d2b5c4 Mon Sep 17 00:00:00 2001 From: s1gr1d Date: Wed, 25 Jun 2025 09:50:56 +0200 Subject: [PATCH] feat(nuxt): Add alias for `@opentelemetry/resources` --- packages/nuxt/src/module.ts | 4 ++- packages/nuxt/src/vite/utils.ts | 18 ++++++++++ packages/nuxt/test/vite/utils.test.ts | 48 +++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/packages/nuxt/src/module.ts b/packages/nuxt/src/module.ts index 377508e860a2..bb9843bd6ce2 100644 --- a/packages/nuxt/src/module.ts +++ b/packages/nuxt/src/module.ts @@ -4,7 +4,7 @@ import * as path from 'path'; import type { SentryNuxtModuleOptions } from './common/types'; import { addDynamicImportEntryFileWrapper, addSentryTopImport, addServerConfigToBuild } from './vite/addServerConfig'; import { setupSourceMaps } from './vite/sourceMaps'; -import { findDefaultSdkInitFile } from './vite/utils'; +import { addOTelCommonJSImportAlias, findDefaultSdkInitFile } from './vite/utils'; export type ModuleOptions = SentryNuxtModuleOptions; @@ -69,6 +69,8 @@ export default defineNuxtModule({ setupSourceMaps(moduleOptions, nuxt); } + addOTelCommonJSImportAlias(nuxt); + nuxt.hooks.hook('nitro:init', nitro => { if (serverConfigFile?.includes('.server.config')) { if (nitro.options.dev) { diff --git a/packages/nuxt/src/vite/utils.ts b/packages/nuxt/src/vite/utils.ts index f1ef1c9e4cf2..53d4e57d16e3 100644 --- a/packages/nuxt/src/vite/utils.ts +++ b/packages/nuxt/src/vite/utils.ts @@ -179,3 +179,21 @@ export function constructFunctionReExport(pathWithQuery: string, entryId: string ), ); } + +/** + * Sets up alias to work around OpenTelemetry's incomplete ESM imports. + * https://github.com/getsentry/sentry-javascript/issues/15204 + * + * OpenTelemetry's @opentelemetry/resources package has incomplete imports missing + * the .js file extensions (like execAsync for machine-id detection). This causes module resolution + * errors in certain Nuxt configurations, particularly when local Nuxt modules in Nuxt 4 are present. + * + * @see https://nuxt.com/docs/guide/concepts/esm#aliasing-libraries + */ +export function addOTelCommonJSImportAlias(nuxt: Nuxt): void { + if (!nuxt.options.alias) { + nuxt.options.alias = {}; + } + + nuxt.options.alias['@opentelemetry/resources'] = '@opentelemetry/resources/build/src/index.js'; +} diff --git a/packages/nuxt/test/vite/utils.test.ts b/packages/nuxt/test/vite/utils.test.ts index f19ec98b4b64..8bb77bc6e12b 100644 --- a/packages/nuxt/test/vite/utils.test.ts +++ b/packages/nuxt/test/vite/utils.test.ts @@ -2,6 +2,7 @@ import * as fs from 'fs'; import type { Nuxt } from 'nuxt/schema'; import { afterEach, describe, expect, it, vi } from 'vitest'; import { + addOTelCommonJSImportAlias, constructFunctionReExport, constructWrappedFunctionExportQuery, extractFunctionReexportQueryParameters, @@ -366,3 +367,50 @@ export { foo_sentryWrapped as foo }; expect(result).toBe(''); }); }); + +describe('addOTelCommonJSImportAlias', () => { + it('adds alias for @opentelemetry/resources when options.alias does not exist', () => { + const nuxtMock: Nuxt = { + options: {}, + } as unknown as Nuxt; + + addOTelCommonJSImportAlias(nuxtMock); + + expect(nuxtMock.options.alias).toEqual({ + '@opentelemetry/resources': '@opentelemetry/resources/build/src/index.js', + }); + }); + + it('adds alias for @opentelemetry/resources when options.alias already exists', () => { + const nuxtMock: Nuxt = { + options: { + alias: { + 'existing-alias': 'some-path', + }, + }, + } as unknown as Nuxt; + + addOTelCommonJSImportAlias(nuxtMock); + + expect(nuxtMock.options.alias).toEqual({ + 'existing-alias': 'some-path', + '@opentelemetry/resources': '@opentelemetry/resources/build/src/index.js', + }); + }); + + it('overwrites existing alias for @opentelemetry/resources if already present', () => { + const nuxtMock: Nuxt = { + options: { + alias: { + '@opentelemetry/resources': 'some-other-path', + }, + }, + } as unknown as Nuxt; + + addOTelCommonJSImportAlias(nuxtMock); + + expect(nuxtMock.options.alias).toEqual({ + '@opentelemetry/resources': '@opentelemetry/resources/build/src/index.js', + }); + }); +});