@sentry/nuxt 11.0.0-beta.0 → 11.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/common/devMode.js +16 -0
- package/build/cjs/common/devMode.js.map +1 -1
- package/build/cjs/module.js +32 -48
- package/build/cjs/module.js.map +1 -1
- package/build/cjs/server/sdk.js +15 -0
- package/build/cjs/server/sdk.js.map +1 -1
- package/build/cjs/vite/addServerConfig.js +106 -37
- package/build/cjs/vite/addServerConfig.js.map +1 -1
- package/build/cjs/vite/middlewareConfig.js +7 -6
- package/build/cjs/vite/middlewareConfig.js.map +1 -1
- package/build/cjs/vite/orchestrion.js +2 -1
- package/build/cjs/vite/orchestrion.js.map +1 -1
- package/build/cjs/vite/utils.js +34 -9
- package/build/cjs/vite/utils.js.map +1 -1
- package/build/esm/common/devMode.js +12 -1
- package/build/esm/common/devMode.js.map +1 -1
- package/build/esm/module.js +34 -50
- package/build/esm/module.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/server/sdk.js +17 -2
- package/build/esm/server/sdk.js.map +1 -1
- package/build/esm/vite/addServerConfig.js +108 -40
- package/build/esm/vite/addServerConfig.js.map +1 -1
- package/build/esm/vite/middlewareConfig.js +7 -6
- package/build/esm/vite/middlewareConfig.js.map +1 -1
- package/build/esm/vite/orchestrion.js +2 -1
- package/build/esm/vite/orchestrion.js.map +1 -1
- package/build/esm/vite/utils.js +33 -9
- package/build/esm/vite/utils.js.map +1 -1
- package/build/module/common/devMode.d.ts +12 -2
- package/build/module/common/types.d.ts +7 -0
- package/build/module/module.json +1 -1
- package/build/module/module.mjs +177 -99
- package/build/module/runtime/utils/instrumentDatabase.js +3 -2
- package/build/module/vite/addServerConfig.d.ts +23 -8
- package/build/module/vite/middlewareConfig.d.ts +2 -1
- package/build/module/vite/utils.d.ts +22 -3
- package/build/types/common/devMode.d.ts +12 -2
- package/build/types/common/devMode.d.ts.map +1 -1
- package/build/types/common/types.d.ts +7 -0
- package/build/types/common/types.d.ts.map +1 -1
- package/build/types/module.d.ts.map +1 -1
- package/build/types/runtime/utils/instrumentDatabase.d.ts.map +1 -1
- package/build/types/server/sdk.d.ts.map +1 -1
- package/build/types/vite/addServerConfig.d.ts +23 -8
- package/build/types/vite/addServerConfig.d.ts.map +1 -1
- package/build/types/vite/middlewareConfig.d.ts +2 -1
- package/build/types/vite/middlewareConfig.d.ts.map +1 -1
- package/build/types/vite/orchestrion.d.ts.map +1 -1
- package/build/types/vite/utils.d.ts +22 -3
- package/build/types/vite/utils.d.ts.map +1 -1
- package/package.json +9 -9
package/build/esm/vite/utils.js
CHANGED
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
import { consoleSandbox } from '@sentry/core';
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import * as path from 'path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
4
5
|
import { resolvePath } from '@nuxt/kit';
|
|
5
6
|
|
|
6
|
-
async function getNitroMajorVersion() {
|
|
7
|
+
async function getNitroMajorVersion(rootDir) {
|
|
7
8
|
try {
|
|
8
9
|
const { getPackageInfo } = await import('local-pkg');
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
const fromPackage = (dir) => ({ paths: [path.join(dir, "package.json")] });
|
|
11
|
+
let provider = await getPackageInfo("nuxt", fromPackage(rootDir));
|
|
12
|
+
if (provider?.packageJson.dependencies?.["@nuxt/nitro-server"]) {
|
|
13
|
+
provider = await getPackageInfo("@nuxt/nitro-server", fromPackage(provider.rootPath)) ?? provider;
|
|
13
14
|
}
|
|
15
|
+
if (!provider?.packageJson.dependencies?.nitro) {
|
|
16
|
+
return 2;
|
|
17
|
+
}
|
|
18
|
+
const info = await getPackageInfo("nitro", fromPackage(provider.rootPath));
|
|
19
|
+
const major = parseInt(info?.version?.split(".")[0] ?? "", 10);
|
|
20
|
+
return isNaN(major) ? 3 : major;
|
|
14
21
|
} catch {
|
|
22
|
+
return 2;
|
|
15
23
|
}
|
|
16
|
-
return 2;
|
|
17
24
|
}
|
|
18
25
|
async function findDefaultSdkInitFile(type, nuxt, options) {
|
|
19
26
|
const possibleFileExtensions = ["ts", "js", "mjs", "cjs", "mts", "cts"];
|
|
@@ -37,8 +44,8 @@ async function findDefaultSdkInitFile(type, nuxt, options) {
|
|
|
37
44
|
return void 0;
|
|
38
45
|
}
|
|
39
46
|
const SERVER_CONFIG_FILENAME = "sentry.server.config";
|
|
40
|
-
function
|
|
41
|
-
return
|
|
47
|
+
function isCloudflarePreset(preset) {
|
|
48
|
+
return !!preset?.replace(/-/g, "_").startsWith("cloudflare");
|
|
42
49
|
}
|
|
43
50
|
function getFilenameFromNodeStartCommand(nodeCommand) {
|
|
44
51
|
const regex = /[^/\\]+\.[^/\\]+$/;
|
|
@@ -111,6 +118,23 @@ export { ${currFunctionName}_sentryWrapped as ${currFunctionName} };
|
|
|
111
118
|
)
|
|
112
119
|
);
|
|
113
120
|
}
|
|
121
|
+
function toResolvablePath(source) {
|
|
122
|
+
if (!source.startsWith("file://")) {
|
|
123
|
+
return { path: source, wasFileUrl: false };
|
|
124
|
+
}
|
|
125
|
+
if (source === "file://" || source === "file:///") {
|
|
126
|
+
return void 0;
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
const filePath = fileURLToPath(source);
|
|
130
|
+
if (!filePath || filePath === "/" || filePath === "\\") {
|
|
131
|
+
return void 0;
|
|
132
|
+
}
|
|
133
|
+
return { path: filePath, wasFileUrl: true };
|
|
134
|
+
} catch {
|
|
135
|
+
return void 0;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
114
138
|
function addOTelCommonJSImportAlias(nuxt, isNitroV3 = false) {
|
|
115
139
|
if (!nuxt.options.dev || isNitroV3) {
|
|
116
140
|
return;
|
|
@@ -123,5 +147,5 @@ function addOTelCommonJSImportAlias(nuxt, isNitroV3 = false) {
|
|
|
123
147
|
}
|
|
124
148
|
}
|
|
125
149
|
|
|
126
|
-
export { QUERY_END_INDICATOR, SENTRY_REEXPORTED_FUNCTIONS, SENTRY_WRAPPED_ENTRY, SENTRY_WRAPPED_FUNCTIONS, SERVER_CONFIG_FILENAME, addOTelCommonJSImportAlias, constructFunctionReExport, constructWrappedFunctionExportQuery, extractFunctionReexportQueryParameters, findDefaultSdkInitFile, getFilenameFromNodeStartCommand, getNitroMajorVersion, removeSentryQueryFromPath,
|
|
150
|
+
export { QUERY_END_INDICATOR, SENTRY_REEXPORTED_FUNCTIONS, SENTRY_WRAPPED_ENTRY, SENTRY_WRAPPED_FUNCTIONS, SERVER_CONFIG_FILENAME, addOTelCommonJSImportAlias, constructFunctionReExport, constructWrappedFunctionExportQuery, extractFunctionReexportQueryParameters, findDefaultSdkInitFile, getFilenameFromNodeStartCommand, getNitroMajorVersion, isCloudflarePreset, removeSentryQueryFromPath, toResolvablePath };
|
|
127
151
|
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../../src/vite/utils.ts"],"sourcesContent":["import type { Nuxt } from '@nuxt/schema';\nimport { consoleSandbox } from '@sentry/core';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { SentryNuxtModuleOptions } from '../common/types';\nimport { resolvePath } from '@nuxt/kit';\n\n/**\n * Gets the major version of the installed nitro package.\n * Returns 2 as the default if nitro is not found or the version cannot be determined.\n */\nexport async function getNitroMajorVersion(): Promise<number> {\n try {\n const { getPackageInfo } = await import('local-pkg');\n const info = await getPackageInfo('nitro');\n if (info?.version) {\n const major = parseInt(info.version.split('.')[0] ?? '2', 10);\n return isNaN(major) ? 2 : major;\n }\n } catch {\n // If local-pkg is unavailable or nitro is not found, default to v2\n }\n return 2;\n}\n\n/**\n * Find the default SDK init file for the given type (client or server).\n */\nexport async function findDefaultSdkInitFile(\n type: 'server' | 'client',\n nuxt?: Nuxt,\n options?: SentryNuxtModuleOptions,\n): Promise<string | undefined> {\n const possibleFileExtensions = ['ts', 'js', 'mjs', 'cjs', 'mts', 'cts'];\n const relativePaths = possibleFileExtensions.map(ext => `sentry.${type}.config.${ext}`);\n\n // Get layers from highest priority to lowest\n const layers = [...(nuxt?.options._layers ?? [])].reverse();\n\n for (const layer of layers) {\n for (const relativePath of relativePaths) {\n const fullPath = path.resolve(layer.cwd, relativePath);\n if (fs.existsSync(fullPath)) {\n return fullPath;\n }\n }\n }\n\n // As a fallback, also check CWD (left for pure compatibility)\n const rootDir = options?.configDir ? await resolvePath(options.configDir, { type: 'dir' }) : process.cwd();\n for (const relativePath of relativePaths) {\n const fullPath = path.resolve(rootDir, relativePath);\n if (fs.existsSync(fullPath)) {\n return fullPath;\n }\n }\n\n return undefined;\n}\n\nexport const SERVER_CONFIG_FILENAME = 'sentry.server.config';\n\n/** Builds the value for `node --import`. Node reads it as a URL, so it needs forward slashes on Windows too. */\nexport function toImportSpecifier(fromDir: string, filePath: string): string {\n return `./${path.relative(fromDir, filePath).split(/[\\\\/]/).join('/')}`;\n}\n\n/**\n * Extracts the filename from a node command with a path.\n */\nexport function getFilenameFromNodeStartCommand(nodeCommand: string): string | null {\n const regex = /[^/\\\\]+\\.[^/\\\\]+$/;\n const match = nodeCommand.match(regex);\n return match ? match[0] : null;\n}\n\nexport const SENTRY_WRAPPED_ENTRY = '?sentry-query-wrapped-entry';\nexport const SENTRY_WRAPPED_FUNCTIONS = '?sentry-query-wrapped-functions=';\nexport const SENTRY_REEXPORTED_FUNCTIONS = '?sentry-query-reexported-functions=';\nexport const QUERY_END_INDICATOR = 'SENTRY-QUERY-END';\n\n/**\n * Strips the Sentry query part from a path.\n * Example: example/path?sentry-query-wrapped-entry?sentry-query-functions-reexport=foo,SENTRY-QUERY-END -> /example/path\n *\n * Only exported for testing.\n */\nexport function removeSentryQueryFromPath(url: string): string {\n // oxlint-disable-next-line sdk/no-regexp-constructor\n const regex = new RegExp(`\\\\${SENTRY_WRAPPED_ENTRY}.*?\\\\${QUERY_END_INDICATOR}`);\n return url.replace(regex, '');\n}\n\n/**\n * Extracts and sanitizes function re-export and function wrap query parameters from a query string.\n * If it is a default export, it is not considered for re-exporting.\n *\n * Only exported for testing.\n */\nexport function extractFunctionReexportQueryParameters(query: string): { wrap: string[]; reexport: string[] } {\n // Regex matches the comma-separated params between the functions query\n // oxlint-disable-next-line sdk/no-regexp-constructor\n const wrapRegex = new RegExp(\n `\\\\${SENTRY_WRAPPED_FUNCTIONS}(.*?)(\\\\${QUERY_END_INDICATOR}|\\\\${SENTRY_REEXPORTED_FUNCTIONS})`,\n );\n // oxlint-disable-next-line sdk/no-regexp-constructor\n const reexportRegex = new RegExp(`\\\\${SENTRY_REEXPORTED_FUNCTIONS}(.*?)(\\\\${QUERY_END_INDICATOR})`);\n\n const wrapMatch = query.match(wrapRegex);\n const reexportMatch = query.match(reexportRegex);\n\n const wrap =\n wrapMatch?.[1]\n ?.split(',')\n .filter(param => param !== '')\n // Sanitize, as code could be injected with another rollup plugin\n .map((str: string) => str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')) || [];\n\n const reexport =\n reexportMatch?.[1]\n ?.split(',')\n .filter(param => param !== '' && param !== 'default')\n // Sanitize, as code could be injected with another rollup plugin\n .map((str: string) => str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')) || [];\n\n return { wrap, reexport };\n}\n\n/**\n * Constructs a comma-separated string with all functions that need to be re-exported later from the server entry.\n * It uses Rollup's `exportedBindings` to determine the functions to re-export. Functions which should be wrapped\n * (e.g. serverless handlers) are wrapped by Sentry.\n */\nexport function constructWrappedFunctionExportQuery(\n exportedBindings: Record<string, string[]> | null,\n entrypointWrappedFunctions: string[],\n debug?: boolean,\n): string {\n const functionsToExport: { wrap: string[]; reexport: string[] } = {\n wrap: [],\n reexport: [],\n };\n\n // `exportedBindings` can look like this: `{ '.': [ 'handler' ] }` or `{ '.': [], './firebase-gen-1.mjs': [ 'server' ] }`\n // The key `.` refers to exports within the current file, while other keys show from where exports were imported first.\n Object.values(exportedBindings || {}).forEach(functions =>\n functions.forEach(fn => {\n if (entrypointWrappedFunctions.includes(fn)) {\n functionsToExport.wrap.push(fn);\n } else {\n functionsToExport.reexport.push(fn);\n }\n }),\n );\n\n if (debug && functionsToExport.wrap.length === 0) {\n consoleSandbox(() =>\n // eslint-disable-next-line no-console\n console.warn(\n \"[Sentry] No functions found to wrap. In case the server needs to export async functions other than `handler` or `server`, consider adding the name(s) to Sentry's build options `sentry.experimental_entrypointWrappedFunctions` in `nuxt.config.ts`.\",\n ),\n );\n }\n\n const wrapQuery = functionsToExport.wrap.length\n ? `${SENTRY_WRAPPED_FUNCTIONS}${functionsToExport.wrap.join(',')}`\n : '';\n const reexportQuery = functionsToExport.reexport.length\n ? `${SENTRY_REEXPORTED_FUNCTIONS}${functionsToExport.reexport.join(',')}`\n : '';\n\n return [wrapQuery, reexportQuery].join('');\n}\n\n/**\n * Constructs a code snippet with function reexports (can be used in Rollup plugins as a return value for `load()`)\n */\nexport function constructFunctionReExport(pathWithQuery: string, entryId: string): string {\n const { wrap: wrapFunctions, reexport: reexportFunctions } = extractFunctionReexportQueryParameters(pathWithQuery);\n\n return wrapFunctions\n .reduce(\n (functionsCode, currFunctionName) =>\n functionsCode.concat(\n `async function ${currFunctionName}_sentryWrapped(...args) {\\n` +\n ` const res = await import(${JSON.stringify(entryId)});\\n` +\n ` return res.${currFunctionName}.call(this, ...args);\\n` +\n '}\\n' +\n `export { ${currFunctionName}_sentryWrapped as ${currFunctionName} };\\n`,\n ),\n '',\n )\n .concat(\n reexportFunctions.reduce(\n (functionsCode, currFunctionName) =>\n functionsCode.concat(`export { ${currFunctionName} } from ${JSON.stringify(entryId)};`),\n '',\n ),\n );\n}\n\n/**\n * Sets up alias to work around OpenTelemetry's incomplete ESM imports.\n * https://github.com/getsentry/sentry-javascript/issues/15204\n *\n * OpenTelemetry's @opentelemetry/resources package has incomplete imports missing\n * the .js file extensions (like execAsync for machine-id detection). This causes module resolution\n * errors in certain Nuxt configurations, particularly when local Nuxt modules in Nuxt 4 are present.\n *\n * @see https://nuxt.com/docs/guide/concepts/esm#aliasing-libraries\n */\nexport function addOTelCommonJSImportAlias(nuxt: Nuxt, isNitroV3 = false): void {\n if (!nuxt.options.dev || isNitroV3) {\n return;\n }\n\n if (!nuxt.options.alias) {\n nuxt.options.alias = {};\n }\n\n if (!nuxt.options.alias['@opentelemetry/resources']) {\n nuxt.options.alias['@opentelemetry/resources'] = '@opentelemetry/resources/build/src/index.js';\n }\n}\n"],"names":[],"mappings":";;;;;AAWA,eAAsB,oBAAA,GAAwC;AAC5D,EAAA,IAAI;AACF,IAAA,MAAM,EAAE,cAAA,EAAe,GAAI,MAAM,OAAO,WAAW,CAAA;AACnD,IAAA,MAAM,IAAA,GAAO,MAAM,cAAA,CAAe,OAAO,CAAA;AACzC,IAAA,IAAI,MAAM,OAAA,EAAS;AACjB,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,IAAK,GAAA,EAAK,EAAE,CAAA;AAC5D,MAAA,OAAO,KAAA,CAAM,KAAK,CAAA,GAAI,CAAA,GAAI,KAAA;AAAA,IAC5B;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,OAAO,CAAA;AACT;AAKA,eAAsB,sBAAA,CACpB,IAAA,EACA,IAAA,EACA,OAAA,EAC6B;AAC7B,EAAA,MAAM,yBAAyB,CAAC,IAAA,EAAM,MAAM,KAAA,EAAO,KAAA,EAAO,OAAO,KAAK,CAAA;AACtE,EAAA,MAAM,aAAA,GAAgB,uBAAuB,GAAA,CAAI,CAAA,GAAA,KAAO,UAAU,IAAI,CAAA,QAAA,EAAW,GAAG,CAAA,CAAE,CAAA;AAGtF,EAAA,MAAM,MAAA,GAAS,CAAC,GAAI,IAAA,EAAM,QAAQ,OAAA,IAAW,EAAG,CAAA,CAAE,OAAA,EAAQ;AAE1D,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,KAAA,MAAW,gBAAgB,aAAA,EAAe;AACxC,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,KAAK,YAAY,CAAA;AACrD,MAAA,IAAI,EAAA,CAAG,UAAA,CAAW,QAAQ,CAAA,EAAG;AAC3B,QAAA,OAAO,QAAA;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAGA,EAAA,MAAM,OAAA,GAAU,OAAA,EAAS,SAAA,GAAY,MAAM,WAAA,CAAY,OAAA,CAAQ,SAAA,EAAW,EAAE,IAAA,EAAM,KAAA,EAAO,CAAA,GAAI,QAAQ,GAAA,EAAI;AACzG,EAAA,KAAA,MAAW,gBAAgB,aAAA,EAAe;AACxC,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,OAAA,CAAQ,OAAA,EAAS,YAAY,CAAA;AACnD,IAAA,IAAI,EAAA,CAAG,UAAA,CAAW,QAAQ,CAAA,EAAG;AAC3B,MAAA,OAAO,QAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAEO,MAAM,sBAAA,GAAyB;AAG/B,SAAS,iBAAA,CAAkB,SAAiB,QAAA,EAA0B;AAC3E,EAAA,OAAO,CAAA,EAAA,EAAK,IAAA,CAAK,QAAA,CAAS,OAAA,EAAS,QAAQ,CAAA,CAAE,KAAA,CAAM,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AACvE;AAKO,SAAS,gCAAgC,WAAA,EAAoC;AAClF,EAAA,MAAM,KAAA,GAAQ,mBAAA;AACd,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,KAAA,CAAM,KAAK,CAAA;AACrC,EAAA,OAAO,KAAA,GAAQ,KAAA,CAAM,CAAC,CAAA,GAAI,IAAA;AAC5B;AAEO,MAAM,oBAAA,GAAuB;AAC7B,MAAM,wBAAA,GAA2B;AACjC,MAAM,2BAAA,GAA8B;AACpC,MAAM,mBAAA,GAAsB;AAQ5B,SAAS,0BAA0B,GAAA,EAAqB;AAE7D,EAAA,MAAM,QAAQ,IAAI,MAAA,CAAO,KAAK,oBAAoB,CAAA,KAAA,EAAQ,mBAAmB,CAAA,CAAE,CAAA;AAC/E,EAAA,OAAO,GAAA,CAAI,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAC9B;AAQO,SAAS,uCAAuC,KAAA,EAAuD;AAG5G,EAAA,MAAM,YAAY,IAAI,MAAA;AAAA,IACpB,CAAA,EAAA,EAAK,wBAAwB,CAAA,QAAA,EAAW,mBAAmB,MAAM,2BAA2B,CAAA,CAAA;AAAA,GAC9F;AAEA,EAAA,MAAM,gBAAgB,IAAI,MAAA,CAAO,KAAK,2BAA2B,CAAA,QAAA,EAAW,mBAAmB,CAAA,CAAA,CAAG,CAAA;AAElG,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,KAAA,CAAM,SAAS,CAAA;AACvC,EAAA,MAAM,aAAA,GAAgB,KAAA,CAAM,KAAA,CAAM,aAAa,CAAA;AAE/C,EAAA,MAAM,IAAA,GACJ,YAAY,CAAC,CAAA,EACT,MAAM,GAAG,CAAA,CACV,OAAO,CAAA,KAAA,KAAS,KAAA,KAAU,EAAE,CAAA,CAE5B,GAAA,CAAI,CAAC,GAAA,KAAgB,GAAA,CAAI,QAAQ,qBAAA,EAAuB,MAAM,CAAC,CAAA,IAAK,EAAC;AAE1E,EAAA,MAAM,QAAA,GACJ,gBAAgB,CAAC,CAAA,EACb,MAAM,GAAG,CAAA,CACV,MAAA,CAAO,CAAA,KAAA,KAAS,KAAA,KAAU,EAAA,IAAM,UAAU,SAAS,CAAA,CAEnD,GAAA,CAAI,CAAC,GAAA,KAAgB,GAAA,CAAI,QAAQ,qBAAA,EAAuB,MAAM,CAAC,CAAA,IAAK,EAAC;AAE1E,EAAA,OAAO,EAAE,MAAM,QAAA,EAAS;AAC1B;AAOO,SAAS,mCAAA,CACd,gBAAA,EACA,0BAAA,EACA,KAAA,EACQ;AACR,EAAA,MAAM,iBAAA,GAA4D;AAAA,IAChE,MAAM,EAAC;AAAA,IACP,UAAU;AAAC,GACb;AAIA,EAAA,MAAA,CAAO,MAAA,CAAO,gBAAA,IAAoB,EAAE,CAAA,CAAE,OAAA;AAAA,IAAQ,CAAA,SAAA,KAC5C,SAAA,CAAU,OAAA,CAAQ,CAAA,EAAA,KAAM;AACtB,MAAA,IAAI,0BAAA,CAA2B,QAAA,CAAS,EAAE,CAAA,EAAG;AAC3C,QAAA,iBAAA,CAAkB,IAAA,CAAK,KAAK,EAAE,CAAA;AAAA,MAChC,CAAA,MAAO;AACL,QAAA,iBAAA,CAAkB,QAAA,CAAS,KAAK,EAAE,CAAA;AAAA,MACpC;AAAA,IACF,CAAC;AAAA,GACH;AAEA,EAAA,IAAI,KAAA,IAAS,iBAAA,CAAkB,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AAChD,IAAA,cAAA;AAAA,MAAe;AAAA;AAAA,QAEb,OAAA,CAAQ,IAAA;AAAA,UACN;AAAA;AACF;AAAA,KACF;AAAA,EACF;AAEA,EAAA,MAAM,SAAA,GAAY,iBAAA,CAAkB,IAAA,CAAK,MAAA,GACrC,CAAA,EAAG,wBAAwB,CAAA,EAAG,iBAAA,CAAkB,IAAA,CAAK,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,GAC9D,EAAA;AACJ,EAAA,MAAM,aAAA,GAAgB,iBAAA,CAAkB,QAAA,CAAS,MAAA,GAC7C,CAAA,EAAG,2BAA2B,CAAA,EAAG,iBAAA,CAAkB,QAAA,CAAS,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,GACrE,EAAA;AAEJ,EAAA,OAAO,CAAC,SAAA,EAAW,aAAa,CAAA,CAAE,KAAK,EAAE,CAAA;AAC3C;AAKO,SAAS,yBAAA,CAA0B,eAAuB,OAAA,EAAyB;AACxF,EAAA,MAAM,EAAE,IAAA,EAAM,aAAA,EAAe,UAAU,iBAAA,EAAkB,GAAI,uCAAuC,aAAa,CAAA;AAEjH,EAAA,OAAO,aAAA,CACJ,MAAA;AAAA,IACC,CAAC,aAAA,EAAe,gBAAA,KACd,aAAA,CAAc,MAAA;AAAA,MACZ,kBAAkB,gBAAgB,CAAA;AAAA,2BAAA,EACF,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC,CAAA;AAAA,aAAA,EACrC,gBAAgB,CAAA;AAAA;AAAA,SAAA,EAEpB,gBAAgB,qBAAqB,gBAAgB,CAAA;AAAA;AAAA,KACrE;AAAA,IACF;AAAA,GACF,CACC,MAAA;AAAA,IACC,iBAAA,CAAkB,MAAA;AAAA,MAChB,CAAC,aAAA,EAAe,gBAAA,KACd,aAAA,CAAc,MAAA,CAAO,CAAA,SAAA,EAAY,gBAAgB,CAAA,QAAA,EAAW,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,MACxF;AAAA;AACF,GACF;AACJ;AAYO,SAAS,0BAAA,CAA2B,IAAA,EAAY,SAAA,GAAY,KAAA,EAAa;AAC9E,EAAA,IAAI,CAAC,IAAA,CAAK,OAAA,CAAQ,GAAA,IAAO,SAAA,EAAW;AAClC,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,IAAA,CAAK,OAAA,CAAQ,KAAA,EAAO;AACvB,IAAA,IAAA,CAAK,OAAA,CAAQ,QAAQ,EAAC;AAAA,EACxB;AAEA,EAAA,IAAI,CAAC,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,0BAA0B,CAAA,EAAG;AACnD,IAAA,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,0BAA0B,CAAA,GAAI,6CAAA;AAAA,EACnD;AACF;;;;"}
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../../src/vite/utils.ts"],"sourcesContent":["import type { Nuxt } from '@nuxt/schema';\nimport { consoleSandbox } from '@sentry/core';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { fileURLToPath } from 'node:url';\nimport type { SentryNuxtModuleOptions } from '../common/types';\nimport { resolvePath } from '@nuxt/kit';\n\n/**\n * Gets the major version of the Nitro package used by the app's Nuxt installation.\n * Returns 2 as the default if the version cannot be determined.\n *\n * Nitro v2 is published as `nitropack`, v3 as `nitro`. Resolving `nitro` directly is\n * unreliable: module resolution walks up the directory tree, so in a monorepo an\n * unrelated `nitro` v3 above the app wins even when the app's Nuxt uses `nitropack` v2.\n * Instead, follow the dependency chain Nuxt itself imports Nitro through:\n * `nuxt` -> (`@nuxt/nitro-server` ->) `nitro` | `nitropack`.\n */\nexport async function getNitroMajorVersion(rootDir: string): Promise<number> {\n try {\n const { getPackageInfo } = await import('local-pkg');\n\n // `paths` entries must point at a file: for a bare directory, resolution starts at the\n // directory's parent and skips the directory's own `node_modules`, so a hoisted copy higher\n // up the tree (e.g. a monorepo root) wins over the app's actual dependency.\n const fromPackage = (dir: string): { paths: string[] } => ({ paths: [path.join(dir, 'package.json')] });\n\n // The package that declares the Nitro dependency: `nuxt` itself, or `@nuxt/nitro-server` (Nuxt >= 3.21) when nuxt delegates to it\n let provider = await getPackageInfo('nuxt', fromPackage(rootDir));\n if (provider?.packageJson.dependencies?.['@nuxt/nitro-server']) {\n provider = (await getPackageInfo('@nuxt/nitro-server', fromPackage(provider.rootPath))) ?? provider;\n }\n\n if (!provider?.packageJson.dependencies?.nitro) {\n return 2;\n }\n\n const info = await getPackageInfo('nitro', fromPackage(provider.rootPath));\n const major = parseInt(info?.version?.split('.')[0] ?? '', 10);\n // The provider imports `nitro` (not `nitropack`), so it is at least v3 even if the version is unreadable\n return isNaN(major) ? 3 : major;\n } catch {\n // If local-pkg is unavailable or resolution fails, default to v2\n return 2;\n }\n}\n\n/**\n * Find the default SDK init file for the given type (client or server).\n */\nexport async function findDefaultSdkInitFile(\n type: 'server' | 'client',\n nuxt?: Nuxt,\n options?: SentryNuxtModuleOptions,\n): Promise<string | undefined> {\n const possibleFileExtensions = ['ts', 'js', 'mjs', 'cjs', 'mts', 'cts'];\n const relativePaths = possibleFileExtensions.map(ext => `sentry.${type}.config.${ext}`);\n\n // Get layers from highest priority to lowest\n const layers = [...(nuxt?.options._layers ?? [])].reverse();\n\n for (const layer of layers) {\n for (const relativePath of relativePaths) {\n const fullPath = path.resolve(layer.cwd, relativePath);\n if (fs.existsSync(fullPath)) {\n return fullPath;\n }\n }\n }\n\n // As a fallback, also check CWD (left for pure compatibility)\n const rootDir = options?.configDir ? await resolvePath(options.configDir, { type: 'dir' }) : process.cwd();\n for (const relativePath of relativePaths) {\n const fullPath = path.resolve(rootDir, relativePath);\n if (fs.existsSync(fullPath)) {\n return fullPath;\n }\n }\n\n return undefined;\n}\n\nexport const SERVER_CONFIG_FILENAME = 'sentry.server.config';\n\n/** Whether a resolved Nitro preset targets Cloudflare (workerd). Nitro normalizes preset names, so any `cloudflare*` spelling matches. */\nexport function isCloudflarePreset(preset: string | undefined): boolean {\n return !!preset?.replace(/-/g, '_').startsWith('cloudflare');\n}\n\n/** Builds the value for `node --import`. Node reads it as a URL, so it needs forward slashes on Windows too. */\nexport function toImportSpecifier(fromDir: string, filePath: string): string {\n return `./${path.relative(fromDir, filePath).split(/[\\\\/]/).join('/')}`;\n}\n\n/**\n * Extracts the filename from a node command with a path.\n */\nexport function getFilenameFromNodeStartCommand(nodeCommand: string): string | null {\n const regex = /[^/\\\\]+\\.[^/\\\\]+$/;\n const match = nodeCommand.match(regex);\n return match ? match[0] : null;\n}\n\nexport const SENTRY_WRAPPED_ENTRY = '?sentry-query-wrapped-entry';\nexport const SENTRY_WRAPPED_FUNCTIONS = '?sentry-query-wrapped-functions=';\nexport const SENTRY_REEXPORTED_FUNCTIONS = '?sentry-query-reexported-functions=';\nexport const QUERY_END_INDICATOR = 'SENTRY-QUERY-END';\n\n/**\n * Strips the Sentry query part from a path.\n * Example: example/path?sentry-query-wrapped-entry?sentry-query-functions-reexport=foo,SENTRY-QUERY-END -> /example/path\n *\n * Only exported for testing.\n */\nexport function removeSentryQueryFromPath(url: string): string {\n // oxlint-disable-next-line sdk/no-regexp-constructor\n const regex = new RegExp(`\\\\${SENTRY_WRAPPED_ENTRY}.*?\\\\${QUERY_END_INDICATOR}`);\n return url.replace(regex, '');\n}\n\n/**\n * Extracts and sanitizes function re-export and function wrap query parameters from a query string.\n * If it is a default export, it is not considered for re-exporting.\n *\n * Only exported for testing.\n */\nexport function extractFunctionReexportQueryParameters(query: string): { wrap: string[]; reexport: string[] } {\n // Regex matches the comma-separated params between the functions query\n // oxlint-disable-next-line sdk/no-regexp-constructor\n const wrapRegex = new RegExp(\n `\\\\${SENTRY_WRAPPED_FUNCTIONS}(.*?)(\\\\${QUERY_END_INDICATOR}|\\\\${SENTRY_REEXPORTED_FUNCTIONS})`,\n );\n // oxlint-disable-next-line sdk/no-regexp-constructor\n const reexportRegex = new RegExp(`\\\\${SENTRY_REEXPORTED_FUNCTIONS}(.*?)(\\\\${QUERY_END_INDICATOR})`);\n\n const wrapMatch = query.match(wrapRegex);\n const reexportMatch = query.match(reexportRegex);\n\n const wrap =\n wrapMatch?.[1]\n ?.split(',')\n .filter(param => param !== '')\n // Sanitize, as code could be injected with another rollup plugin\n .map((str: string) => str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')) || [];\n\n const reexport =\n reexportMatch?.[1]\n ?.split(',')\n .filter(param => param !== '' && param !== 'default')\n // Sanitize, as code could be injected with another rollup plugin\n .map((str: string) => str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')) || [];\n\n return { wrap, reexport };\n}\n\n/**\n * Constructs a comma-separated string with all functions that need to be re-exported later from the server entry.\n * It uses Rollup's `exportedBindings` to determine the functions to re-export. Functions which should be wrapped\n * (e.g. serverless handlers) are wrapped by Sentry.\n */\nexport function constructWrappedFunctionExportQuery(\n exportedBindings: Record<string, string[]> | null,\n entrypointWrappedFunctions: string[],\n debug?: boolean,\n): string {\n const functionsToExport: { wrap: string[]; reexport: string[] } = {\n wrap: [],\n reexport: [],\n };\n\n // `exportedBindings` can look like this: `{ '.': [ 'handler' ] }` or `{ '.': [], './firebase-gen-1.mjs': [ 'server' ] }`\n // The key `.` refers to exports within the current file, while other keys show from where exports were imported first.\n Object.values(exportedBindings || {}).forEach(functions =>\n functions.forEach(fn => {\n if (entrypointWrappedFunctions.includes(fn)) {\n functionsToExport.wrap.push(fn);\n } else {\n functionsToExport.reexport.push(fn);\n }\n }),\n );\n\n if (debug && functionsToExport.wrap.length === 0) {\n consoleSandbox(() =>\n // eslint-disable-next-line no-console\n console.warn(\n \"[Sentry] No functions found to wrap. In case the server needs to export async functions other than `handler` or `server`, consider adding the name(s) to Sentry's build options `sentry.experimental_entrypointWrappedFunctions` in `nuxt.config.ts`.\",\n ),\n );\n }\n\n const wrapQuery = functionsToExport.wrap.length\n ? `${SENTRY_WRAPPED_FUNCTIONS}${functionsToExport.wrap.join(',')}`\n : '';\n const reexportQuery = functionsToExport.reexport.length\n ? `${SENTRY_REEXPORTED_FUNCTIONS}${functionsToExport.reexport.join(',')}`\n : '';\n\n return [wrapQuery, reexportQuery].join('');\n}\n\n/**\n * Constructs a code snippet with function reexports (can be used in Rollup plugins as a return value for `load()`)\n */\nexport function constructFunctionReExport(pathWithQuery: string, entryId: string): string {\n const { wrap: wrapFunctions, reexport: reexportFunctions } = extractFunctionReexportQueryParameters(pathWithQuery);\n\n return wrapFunctions\n .reduce(\n (functionsCode, currFunctionName) =>\n functionsCode.concat(\n `async function ${currFunctionName}_sentryWrapped(...args) {\\n` +\n ` const res = await import(${JSON.stringify(entryId)});\\n` +\n ` return res.${currFunctionName}.call(this, ...args);\\n` +\n '}\\n' +\n `export { ${currFunctionName}_sentryWrapped as ${currFunctionName} };\\n`,\n ),\n '',\n )\n .concat(\n reexportFunctions.reduce(\n (functionsCode, currFunctionName) =>\n functionsCode.concat(`export { ${currFunctionName} } from ${JSON.stringify(entryId)};`),\n '',\n ),\n );\n}\n\n/**\n * `load()` emits `file://` specifiers because Node's ESM loader rejects bare Windows\n * paths (`ERR_UNSUPPORTED_ESM_URL_SCHEME`), but Rollup's resolver only understands\n * filesystem paths. Returns `undefined` for a malformed `file://` URL.\n *\n * Only exported for testing.\n */\nexport function toResolvablePath(source: string): { path: string; wasFileUrl: boolean } | undefined {\n if (!source.startsWith('file://')) {\n return { path: source, wasFileUrl: false };\n }\n if (source === 'file://' || source === 'file:///') {\n return undefined;\n }\n try {\n const filePath = fileURLToPath(source);\n if (!filePath || filePath === '/' || filePath === '\\\\') {\n return undefined;\n }\n return { path: filePath, wasFileUrl: true };\n } catch {\n return undefined;\n }\n}\n\n/**\n * Sets up alias to work around OpenTelemetry's incomplete ESM imports.\n * https://github.com/getsentry/sentry-javascript/issues/15204\n *\n * OpenTelemetry's @opentelemetry/resources package has incomplete imports missing\n * the .js file extensions (like execAsync for machine-id detection). This causes module resolution\n * errors in certain Nuxt configurations, particularly when local Nuxt modules in Nuxt 4 are present.\n *\n * @see https://nuxt.com/docs/guide/concepts/esm#aliasing-libraries\n */\nexport function addOTelCommonJSImportAlias(nuxt: Nuxt, isNitroV3 = false): void {\n if (!nuxt.options.dev || isNitroV3) {\n return;\n }\n\n if (!nuxt.options.alias) {\n nuxt.options.alias = {};\n }\n\n if (!nuxt.options.alias['@opentelemetry/resources']) {\n nuxt.options.alias['@opentelemetry/resources'] = '@opentelemetry/resources/build/src/index.js';\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
/** Global flag set by the generated
|
|
1
|
+
/** Global flag set by the generated runtime-flags module before the Sentry server config evaluates. */
|
|
2
2
|
export declare const NUXT_DEV_MODE_FLAG = "__SENTRY_NUXT_DEV_MODE__";
|
|
3
|
-
/**
|
|
3
|
+
/** Global flag set by the generated runtime-flags module during a prerender build. */
|
|
4
|
+
export declare const NUXT_PRERENDER_FLAG = "__SENTRY_NUXT_PRERENDER__";
|
|
5
|
+
/** Global flag set by the Nuxt server SDK after a successful `init`, to guard against a second init. */
|
|
6
|
+
export declare const NUXT_SERVER_INITIALIZED_FLAG = "__SENTRY_NUXT_SERVER_INITIALIZED__";
|
|
7
|
+
/** Whether the server runs in `nuxt dev`. */
|
|
4
8
|
export declare function isNuxtDevRuntime(): boolean;
|
|
9
|
+
/** Whether the server bundle is executed by the Nitro prerenderer at build time. */
|
|
10
|
+
export declare function isNuxtPrerenderRuntime(): boolean;
|
|
11
|
+
/** Whether a Nuxt server SDK `init` already ran in this process. */
|
|
12
|
+
export declare function isNuxtServerInitialized(): boolean;
|
|
13
|
+
/** Records that the Nuxt server SDK initialized in this process. */
|
|
14
|
+
export declare function markNuxtServerInitialized(): void;
|
|
@@ -51,6 +51,10 @@ export type SentryNuxtModuleOptions = BuildTimeOptionsBase & {
|
|
|
51
51
|
* If `"experimental_dynamic-import"` is enabled, the Sentry SDK wraps the server entry file with `import()`.
|
|
52
52
|
*
|
|
53
53
|
* @default undefined
|
|
54
|
+
*
|
|
55
|
+
* @deprecated The Sentry server config is bundled into the Nitro server build by default now and
|
|
56
|
+
* initializes itself at server startup — no `node --import` preload and no inject mode needed.
|
|
57
|
+
* Remove this option to use the default behavior. It will be removed in a future major version.
|
|
54
58
|
*/
|
|
55
59
|
autoInjectServerSentry?: 'top-level-import' | 'experimental_dynamic-import';
|
|
56
60
|
/**
|
|
@@ -80,6 +84,9 @@ export type SentryNuxtModuleOptions = BuildTimeOptionsBase & {
|
|
|
80
84
|
* Any wrapped export is expected to be an async function.
|
|
81
85
|
*
|
|
82
86
|
* @default ['default', 'handler', 'server']
|
|
87
|
+
*
|
|
88
|
+
* @deprecated Only used with the deprecated `autoInjectServerSentry: 'experimental_dynamic-import'`
|
|
89
|
+
* mode. It will be removed in a future major version together with that mode.
|
|
83
90
|
*/
|
|
84
91
|
experimental_entrypointWrappedFunctions?: string[];
|
|
85
92
|
};
|
package/build/module/module.json
CHANGED
package/build/module/module.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { resolvePath, createResolver, addTemplate,
|
|
1
|
+
import { resolvePath, createResolver, addTemplate, addServerPlugin, useNuxt, addServerImports, defineNuxtModule, addPluginTemplate, addPlugin, addVitePlugin } from '@nuxt/kit';
|
|
2
2
|
import { consoleSandbox, debug, warnOnRemovedBuildOptions } from '@sentry/core';
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import { existsSync } from 'node:fs';
|
|
5
|
-
import {
|
|
5
|
+
import { basename } from 'node:path';
|
|
6
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
6
7
|
import * as fs from 'fs';
|
|
7
8
|
import { INSTRUMENTED_MODULE_NAMES } from '@sentry/server-utils/orchestrion/config';
|
|
8
9
|
import { sentryOrchestrionPlugin } from '@sentry/server-utils/orchestrion/rollup';
|
|
@@ -11,18 +12,25 @@ import { sentryVitePlugin } from '@sentry/bundler-plugins/vite';
|
|
|
11
12
|
import { createSentryBuildPluginManager } from '@sentry/bundler-plugins/core';
|
|
12
13
|
|
|
13
14
|
const NUXT_DEV_MODE_FLAG = "__SENTRY_NUXT_DEV_MODE__";
|
|
15
|
+
const NUXT_PRERENDER_FLAG = "__SENTRY_NUXT_PRERENDER__";
|
|
14
16
|
|
|
15
|
-
async function getNitroMajorVersion() {
|
|
17
|
+
async function getNitroMajorVersion(rootDir) {
|
|
16
18
|
try {
|
|
17
19
|
const { getPackageInfo } = await import('local-pkg');
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
const fromPackage = (dir) => ({ paths: [path.join(dir, "package.json")] });
|
|
21
|
+
let provider = await getPackageInfo("nuxt", fromPackage(rootDir));
|
|
22
|
+
if (provider?.packageJson.dependencies?.["@nuxt/nitro-server"]) {
|
|
23
|
+
provider = await getPackageInfo("@nuxt/nitro-server", fromPackage(provider.rootPath)) ?? provider;
|
|
22
24
|
}
|
|
25
|
+
if (!provider?.packageJson.dependencies?.nitro) {
|
|
26
|
+
return 2;
|
|
27
|
+
}
|
|
28
|
+
const info = await getPackageInfo("nitro", fromPackage(provider.rootPath));
|
|
29
|
+
const major = parseInt(info?.version?.split(".")[0] ?? "", 10);
|
|
30
|
+
return isNaN(major) ? 3 : major;
|
|
23
31
|
} catch {
|
|
32
|
+
return 2;
|
|
24
33
|
}
|
|
25
|
-
return 2;
|
|
26
34
|
}
|
|
27
35
|
async function findDefaultSdkInitFile(type, nuxt, options) {
|
|
28
36
|
const possibleFileExtensions = ["ts", "js", "mjs", "cjs", "mts", "cts"];
|
|
@@ -46,8 +54,8 @@ async function findDefaultSdkInitFile(type, nuxt, options) {
|
|
|
46
54
|
return void 0;
|
|
47
55
|
}
|
|
48
56
|
const SERVER_CONFIG_FILENAME = "sentry.server.config";
|
|
49
|
-
function
|
|
50
|
-
return
|
|
57
|
+
function isCloudflarePreset(preset) {
|
|
58
|
+
return !!preset?.replace(/-/g, "_").startsWith("cloudflare");
|
|
51
59
|
}
|
|
52
60
|
function getFilenameFromNodeStartCommand(nodeCommand) {
|
|
53
61
|
const regex = /[^/\\]+\.[^/\\]+$/;
|
|
@@ -120,6 +128,23 @@ export { ${currFunctionName}_sentryWrapped as ${currFunctionName} };
|
|
|
120
128
|
)
|
|
121
129
|
);
|
|
122
130
|
}
|
|
131
|
+
function toResolvablePath(source) {
|
|
132
|
+
if (!source.startsWith("file://")) {
|
|
133
|
+
return { path: source, wasFileUrl: false };
|
|
134
|
+
}
|
|
135
|
+
if (source === "file://" || source === "file:///") {
|
|
136
|
+
return void 0;
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
const filePath = fileURLToPath(source);
|
|
140
|
+
if (!filePath || filePath === "/" || filePath === "\\") {
|
|
141
|
+
return void 0;
|
|
142
|
+
}
|
|
143
|
+
return { path: filePath, wasFileUrl: true };
|
|
144
|
+
} catch {
|
|
145
|
+
return void 0;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
123
148
|
function addOTelCommonJSImportAlias(nuxt, isNitroV3 = false) {
|
|
124
149
|
if (!nuxt.options.dev || isNitroV3) {
|
|
125
150
|
return;
|
|
@@ -132,30 +157,13 @@ function addOTelCommonJSImportAlias(nuxt, isNitroV3 = false) {
|
|
|
132
157
|
}
|
|
133
158
|
}
|
|
134
159
|
|
|
135
|
-
const
|
|
136
|
-
function
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
);
|
|
142
|
-
const failureMessage = `[Sentry] Could not load \`${path.basename(configPath)}\`, so Sentry is disabled during development. Node loads this file without a build step, so it supports neither path aliases (like #import) nor non-erasable TypeScript syntax (like enums).`;
|
|
143
|
-
addTemplate({
|
|
144
|
-
filename: DEV_SERVER_CONFIG_PATH,
|
|
145
|
-
write: true,
|
|
146
|
-
getContents: () => [
|
|
147
|
-
"// Generated by @sentry/nuxt. Preload it to enable Sentry during development:",
|
|
148
|
-
`// NODE_OPTIONS='--import ${importSpecifier}' nuxt dev`,
|
|
149
|
-
// A static import would hoist above this assignment, and would make a broken config crash the dev server.
|
|
150
|
-
`globalThis.${NUXT_DEV_MODE_FLAG} = true;`,
|
|
151
|
-
"try {",
|
|
152
|
-
` await import(${JSON.stringify(pathToFileURL(configPath).href)});`,
|
|
153
|
-
"} catch (error) {",
|
|
154
|
-
` console.warn(${JSON.stringify(failureMessage)}, error);`,
|
|
155
|
-
"}",
|
|
156
|
-
""
|
|
157
|
-
].join("\n")
|
|
158
|
-
});
|
|
160
|
+
const CONFIG_EXTENSIONS = [".ts", ".js", ".mjs", ".cjs", ".mts", ".cts"];
|
|
161
|
+
function isServerConfigFile(sourcePath, resolvedPath) {
|
|
162
|
+
if (sourcePath === resolvedPath) {
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
const name = basename(sourcePath);
|
|
166
|
+
return name === SERVER_CONFIG_FILENAME || CONFIG_EXTENSIONS.some((ext) => name === `${SERVER_CONFIG_FILENAME}${ext}`);
|
|
159
167
|
}
|
|
160
168
|
function addServerConfigToBuild(moduleOptions, nitro, serverConfigFile) {
|
|
161
169
|
nitro.hooks.hook("rollup:before", (nitro2, rollupConfig) => {
|
|
@@ -196,6 +204,78 @@ ${data}`;
|
|
|
196
204
|
}
|
|
197
205
|
});
|
|
198
206
|
}
|
|
207
|
+
function addServerConfigPlugin(nuxt, serverConfigFile) {
|
|
208
|
+
const configPath = createResolver(nuxt.options.rootDir).resolve(serverConfigFile);
|
|
209
|
+
const runtimeFlagsTemplate = addTemplate({
|
|
210
|
+
filename: "sentry-runtime-flags.mjs",
|
|
211
|
+
write: true,
|
|
212
|
+
getContents: () => [
|
|
213
|
+
"// Generated by @sentry/nuxt. Sets runtime flags before the Sentry server config evaluates.",
|
|
214
|
+
`globalThis.${NUXT_DEV_MODE_FLAG} = import.meta.dev === true;`,
|
|
215
|
+
`globalThis.${NUXT_PRERENDER_FLAG} = import.meta.prerender === true;`,
|
|
216
|
+
""
|
|
217
|
+
].join("\n")
|
|
218
|
+
});
|
|
219
|
+
const configPluginTemplate = addTemplate({
|
|
220
|
+
filename: "sentry-server-config-plugin.mjs",
|
|
221
|
+
write: true,
|
|
222
|
+
getContents: () => `import ${JSON.stringify(runtimeFlagsTemplate.dst)};
|
|
223
|
+
import ${JSON.stringify(configPath)};
|
|
224
|
+
export default () => {};
|
|
225
|
+
`
|
|
226
|
+
});
|
|
227
|
+
addServerPlugin(configPluginTemplate.dst);
|
|
228
|
+
nuxt.options.nitro.moduleSideEffects = [
|
|
229
|
+
...nuxt.options.nitro.moduleSideEffects ?? [],
|
|
230
|
+
configPath,
|
|
231
|
+
runtimeFlagsTemplate.dst
|
|
232
|
+
];
|
|
233
|
+
nuxt.hook("nitro:config", (nitroConfig) => {
|
|
234
|
+
if (isCloudflarePreset(nitroConfig.preset)) {
|
|
235
|
+
nitroConfig.plugins = (nitroConfig.plugins ?? []).filter((plugin) => plugin !== configPluginTemplate.dst);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const plugins = nitroConfig.plugins ?? [];
|
|
239
|
+
nitroConfig.plugins = [configPluginTemplate.dst, ...plugins.filter((plugin) => plugin !== configPluginTemplate.dst)];
|
|
240
|
+
const externals = nitroConfig.externals ?? (nitroConfig.externals = {});
|
|
241
|
+
const inline = externals.inline;
|
|
242
|
+
const existingInline = Array.isArray(inline) ? inline : inline ? [inline] : [];
|
|
243
|
+
externals.inline = [...existingInline, configPath, configPluginTemplate.dst, runtimeFlagsTemplate.dst];
|
|
244
|
+
});
|
|
245
|
+
nuxt.hook("nitro:init", (nitro) => {
|
|
246
|
+
if (nuxt.options._prepare || !isCloudflarePreset(nitro.options.preset)) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
nitro.options.plugins = (nitro.options.plugins ?? []).filter((plugin) => plugin !== configPluginTemplate.dst);
|
|
250
|
+
consoleSandbox(() => {
|
|
251
|
+
console.warn(
|
|
252
|
+
`[Sentry] Found \`${basename(configPath)}\`, but the Nitro preset targets Cloudflare, where this file is not used. Set up the SDK with \`sentryCloudflareNitroPlugin\` instead: https://docs.sentry.io/platforms/javascript/guides/nuxt/install/cloudflare-workers/`
|
|
253
|
+
);
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
function addServerConfigShimWithWarning(nitro) {
|
|
258
|
+
nitro.hooks.hook("close", async () => {
|
|
259
|
+
if (nitro.options.dev || nitro.options.preset === "nitro-prerender" || isCloudflarePreset(nitro.options.preset)) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
const shimPath = createResolver(nitro.options.output.serverDir).resolve(`${SERVER_CONFIG_FILENAME}.mjs`);
|
|
263
|
+
const contents = [
|
|
264
|
+
"// Generated by @sentry/nuxt.",
|
|
265
|
+
"// The Sentry server config is bundled into the server build and initializes automatically.",
|
|
266
|
+
"// This file only keeps existing `node --import ./.output/server/sentry.server.config.mjs` commands working.",
|
|
267
|
+
"console.warn('[Sentry] The `--import` flag for the Sentry server config is no longer needed and should be removed.');",
|
|
268
|
+
""
|
|
269
|
+
].join("\n");
|
|
270
|
+
try {
|
|
271
|
+
await fs.promises.writeFile(shimPath, contents, "utf8");
|
|
272
|
+
} catch (error) {
|
|
273
|
+
consoleSandbox(() => {
|
|
274
|
+
console.warn(`[Sentry] Could not write the \`--import\` compatibility shim to ${shimPath}`, error);
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
}
|
|
199
279
|
function addDynamicImportEntryFileWrapper(nitro, serverConfigFile, moduleOptions) {
|
|
200
280
|
if (!nitro.options.rollupConfig) {
|
|
201
281
|
nitro.options.rollupConfig = { output: {} };
|
|
@@ -207,7 +287,8 @@ function addDynamicImportEntryFileWrapper(nitro, serverConfigFile, moduleOptions
|
|
|
207
287
|
}
|
|
208
288
|
nitro.options.rollupConfig.plugins.push(
|
|
209
289
|
wrapEntryWithDynamicImport({
|
|
210
|
-
resolvedSentryConfigPath: createResolver(nitro.options.rootDir).resolve(
|
|
290
|
+
resolvedSentryConfigPath: createResolver(nitro.options.rootDir).resolve(serverConfigFile),
|
|
291
|
+
// oxlint-disable-next-line typescript/no-deprecated -- supported until removal
|
|
211
292
|
experimental_entrypointWrappedFunctions: moduleOptions.experimental_entrypointWrappedFunctions
|
|
212
293
|
})
|
|
213
294
|
);
|
|
@@ -217,7 +298,7 @@ function injectServerConfigPlugin(nitro, serverConfigFile, isDebug) {
|
|
|
217
298
|
return {
|
|
218
299
|
name: "rollup-plugin-inject-sentry-server-config",
|
|
219
300
|
buildStart() {
|
|
220
|
-
const configPath = createResolver(nitro.options.rootDir).resolve(
|
|
301
|
+
const configPath = createResolver(nitro.options.rootDir).resolve(serverConfigFile);
|
|
221
302
|
if (!existsSync(configPath)) {
|
|
222
303
|
if (isDebug) {
|
|
223
304
|
debug.log(`[Sentry] Sentry server config file not found: ${configPath}`);
|
|
@@ -233,7 +314,7 @@ function injectServerConfigPlugin(nitro, serverConfigFile, isDebug) {
|
|
|
233
314
|
resolveId(source) {
|
|
234
315
|
if (source.startsWith(filePrefix)) {
|
|
235
316
|
const originalFilePath = source.replace(filePrefix, "");
|
|
236
|
-
const configPath = createResolver(nitro.options.rootDir).resolve(
|
|
317
|
+
const configPath = createResolver(nitro.options.rootDir).resolve(originalFilePath);
|
|
237
318
|
return { id: configPath };
|
|
238
319
|
}
|
|
239
320
|
return null;
|
|
@@ -249,11 +330,16 @@ function wrapEntryWithDynamicImport({
|
|
|
249
330
|
return {
|
|
250
331
|
name: "sentry-wrap-entry-with-dynamic-import",
|
|
251
332
|
async resolveId(source, importer, options) {
|
|
252
|
-
|
|
253
|
-
|
|
333
|
+
const resolvable = toResolvablePath(source);
|
|
334
|
+
if (!resolvable) {
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
const { path: normalizedSource, wasFileUrl } = resolvable;
|
|
338
|
+
if (isServerConfigFile(normalizedSource, resolvedSentryConfigPath)) {
|
|
339
|
+
return { id: normalizedSource, moduleSideEffects: true };
|
|
254
340
|
}
|
|
255
|
-
if (options.isEntry &&
|
|
256
|
-
const resolution = await this.resolve(
|
|
341
|
+
if (options.isEntry && normalizedSource.includes(".mjs") && !normalizedSource.includes(`.mjs${SENTRY_WRAPPED_ENTRY}`)) {
|
|
342
|
+
const resolution = await this.resolve(normalizedSource, importer, options);
|
|
257
343
|
if (!resolution || resolution?.external) return resolution;
|
|
258
344
|
const moduleInfo = await this.load(resolution);
|
|
259
345
|
moduleInfo.moduleSideEffects = true;
|
|
@@ -265,16 +351,23 @@ function wrapEntryWithDynamicImport({
|
|
|
265
351
|
)
|
|
266
352
|
).concat(QUERY_END_INDICATOR)}`;
|
|
267
353
|
}
|
|
354
|
+
if (wasFileUrl) {
|
|
355
|
+
const resolved = await this.resolve(normalizedSource, importer, { ...options, isEntry: false });
|
|
356
|
+
if (resolved) return resolved;
|
|
357
|
+
return { id: normalizedSource };
|
|
358
|
+
}
|
|
268
359
|
return null;
|
|
269
360
|
},
|
|
270
361
|
load(id) {
|
|
271
362
|
if (id.includes(`.mjs${SENTRY_WRAPPED_ENTRY}`)) {
|
|
272
363
|
const entryId = removeSentryQueryFromPath(id).slice(resolutionIdPrefix.length);
|
|
273
|
-
const
|
|
364
|
+
const entryIdUrl = pathToFileURL(entryId).href;
|
|
365
|
+
const configUrl = pathToFileURL(resolvedSentryConfigPath).href;
|
|
366
|
+
const reExportedFunctions = id.includes(SENTRY_WRAPPED_FUNCTIONS) || id.includes(SENTRY_REEXPORTED_FUNCTIONS) ? constructFunctionReExport(id, entryIdUrl) : "";
|
|
274
367
|
return (
|
|
275
368
|
// Regular `import` of the Sentry config
|
|
276
|
-
`import ${JSON.stringify(
|
|
277
|
-
import(${JSON.stringify(
|
|
369
|
+
`import ${JSON.stringify(configUrl)};
|
|
370
|
+
import(${JSON.stringify(entryIdUrl)});
|
|
278
371
|
${reExportedFunctions}
|
|
279
372
|
`
|
|
280
373
|
);
|
|
@@ -324,7 +417,7 @@ function addMiddlewareImports() {
|
|
|
324
417
|
}
|
|
325
418
|
]);
|
|
326
419
|
}
|
|
327
|
-
function addMiddlewareInstrumentation(nitro) {
|
|
420
|
+
function addMiddlewareInstrumentation(nitro, isNitroV3) {
|
|
328
421
|
nitro.hooks.hook("rollup:before", (nitro2, rollupConfig) => {
|
|
329
422
|
if (!rollupConfig.plugins) {
|
|
330
423
|
rollupConfig.plugins = [];
|
|
@@ -332,11 +425,12 @@ function addMiddlewareInstrumentation(nitro) {
|
|
|
332
425
|
if (!Array.isArray(rollupConfig.plugins)) {
|
|
333
426
|
rollupConfig.plugins = [rollupConfig.plugins];
|
|
334
427
|
}
|
|
335
|
-
rollupConfig.plugins.push(middlewareInstrumentationPlugin(nitro2));
|
|
428
|
+
rollupConfig.plugins.push(middlewareInstrumentationPlugin(nitro2, isNitroV3));
|
|
336
429
|
});
|
|
337
430
|
}
|
|
338
|
-
function middlewareInstrumentationPlugin(nitro) {
|
|
431
|
+
function middlewareInstrumentationPlugin(nitro, isNitroV3) {
|
|
339
432
|
const middlewareFiles = /* @__PURE__ */ new Set();
|
|
433
|
+
const wrapperModule = isNitroV3 ? "#imports/server" : "#imports";
|
|
340
434
|
return {
|
|
341
435
|
name: "sentry-nuxt-middleware-instrumentation",
|
|
342
436
|
buildStart() {
|
|
@@ -350,7 +444,7 @@ function middlewareInstrumentationPlugin(nitro) {
|
|
|
350
444
|
if (middlewareFiles.has(id)) {
|
|
351
445
|
const fileName = path.basename(id);
|
|
352
446
|
return {
|
|
353
|
-
code: wrapMiddlewareCode(code, fileName),
|
|
447
|
+
code: wrapMiddlewareCode(code, fileName, wrapperModule),
|
|
354
448
|
map: null
|
|
355
449
|
};
|
|
356
450
|
}
|
|
@@ -358,10 +452,10 @@ function middlewareInstrumentationPlugin(nitro) {
|
|
|
358
452
|
}
|
|
359
453
|
};
|
|
360
454
|
}
|
|
361
|
-
function wrapMiddlewareCode(originalCode, fileName) {
|
|
455
|
+
function wrapMiddlewareCode(originalCode, fileName, wrapperModule) {
|
|
362
456
|
const cleanFileName = fileName.replace(/\.(ts|js|mjs|mts|cts)$/, "");
|
|
363
457
|
return `
|
|
364
|
-
import { wrapMiddlewareHandlerWithSentry } from '
|
|
458
|
+
import { wrapMiddlewareHandlerWithSentry } from '${wrapperModule}';
|
|
365
459
|
|
|
366
460
|
function defineInstrumentedEventHandler(handlerOrObject) {
|
|
367
461
|
return defineEventHandler(wrapMiddlewareHandlerWithSentry(handlerOrObject, '${cleanFileName}'));
|
|
@@ -391,7 +485,7 @@ function setupOrchestrion(nuxt, hasServerConfig, buildTimeInstrumentation) {
|
|
|
391
485
|
if (nuxt.options?.dev) {
|
|
392
486
|
return;
|
|
393
487
|
}
|
|
394
|
-
const isCloudflare =
|
|
488
|
+
const isCloudflare = isCloudflarePreset(nitroConfig.preset);
|
|
395
489
|
if (!hasServerConfig && !isCloudflare) {
|
|
396
490
|
return;
|
|
397
491
|
}
|
|
@@ -728,7 +822,9 @@ var module$1 = defineNuxtModule({
|
|
|
728
822
|
}
|
|
729
823
|
const moduleOptions = {
|
|
730
824
|
...moduleOptionsParam,
|
|
825
|
+
// oxlint-disable-next-line typescript/no-deprecated -- supported until removal
|
|
731
826
|
autoInjectServerSentry: moduleOptionsParam.autoInjectServerSentry,
|
|
827
|
+
// oxlint-disable-next-line typescript/no-deprecated -- supported until removal
|
|
732
828
|
experimental_entrypointWrappedFunctions: moduleOptionsParam.experimental_entrypointWrappedFunctions || [
|
|
733
829
|
"default",
|
|
734
830
|
"handler",
|
|
@@ -762,11 +858,15 @@ var module$1 = defineNuxtModule({
|
|
|
762
858
|
});
|
|
763
859
|
}
|
|
764
860
|
const serverConfigFile = await findDefaultSdkInitFile("server", nuxt, moduleOptions);
|
|
765
|
-
const isNitroV3 = await getNitroMajorVersion() >= 3;
|
|
861
|
+
const isNitroV3 = await getNitroMajorVersion(nuxt.options.rootDir) >= 3;
|
|
766
862
|
const nuxtMajor = parseInt(nuxt._version?.split(".")[0] ?? "3", 10);
|
|
767
863
|
const isMinNuxtV4 = nuxtMajor >= 4;
|
|
768
864
|
setupOrchestrion(nuxt, !!serverConfigFile, moduleOptions.buildTimeInstrumentation);
|
|
865
|
+
const usesDeprecatedInjectMode = moduleOptions.autoInjectServerSentry === "top-level-import" || moduleOptions.autoInjectServerSentry === "experimental_dynamic-import";
|
|
769
866
|
if (serverConfigFile) {
|
|
867
|
+
if (!usesDeprecatedInjectMode) {
|
|
868
|
+
addServerConfigPlugin(nuxt, serverConfigFile);
|
|
869
|
+
}
|
|
770
870
|
if (isNitroV3) {
|
|
771
871
|
addServerPlugin(moduleDirResolver.resolve("./runtime/plugins/handler.server"));
|
|
772
872
|
addServerPlugin(moduleDirResolver.resolve("./runtime/plugins/update-route-name.server"));
|
|
@@ -783,9 +883,6 @@ var module$1 = defineNuxtModule({
|
|
|
783
883
|
addMiddlewareImports();
|
|
784
884
|
addStorageInstrumentation(nuxt, !isNitroV3);
|
|
785
885
|
addDatabaseInstrumentation(nuxt.options.nitro, !isNitroV3, moduleOptions);
|
|
786
|
-
if (isNitroV3) {
|
|
787
|
-
addDevServerConfigFile(nuxt, serverConfigFile);
|
|
788
|
-
}
|
|
789
886
|
}
|
|
790
887
|
if (clientConfigFile || serverConfigFile) {
|
|
791
888
|
setupSourceMaps(moduleOptions, nuxt, addVitePlugin);
|
|
@@ -829,56 +926,37 @@ var module$1 = defineNuxtModule({
|
|
|
829
926
|
return;
|
|
830
927
|
}
|
|
831
928
|
if (serverConfigFile) {
|
|
832
|
-
addMiddlewareInstrumentation(nitro);
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
if (serverDir.includes(".netlify") || !!process.env.NETLIFY) {
|
|
836
|
-
console.warn(
|
|
837
|
-
"[Sentry] Warning: The Sentry SDK detected a Netlify build. Server-side support for the Sentry Nuxt SDK on Netlify is currently unreliable due to technical limitations of serverless functions. Traces are not collected, and errors may occasionally not be reported. For more information on setting up Sentry on the Nuxt server-side, please refer to the documentation: https://docs.sentry.io/platforms/javascript/guides/nuxt/install/"
|
|
838
|
-
);
|
|
839
|
-
}
|
|
840
|
-
if (serverDir.includes(".vercel") || !!process.env.VERCEL) {
|
|
841
|
-
console.warn(
|
|
842
|
-
"[Sentry] Warning: The Sentry SDK detected a Vercel build. The Sentry Nuxt SDK currently does not support tracing on Vercel. For more information on setting up Sentry on the Nuxt server-side, please refer to the documentation: https://docs.sentry.io/platforms/javascript/guides/nuxt/install/"
|
|
843
|
-
);
|
|
844
|
-
}
|
|
845
|
-
});
|
|
846
|
-
if (moduleOptions.autoInjectServerSentry !== "experimental_dynamic-import") {
|
|
847
|
-
if (!(isNitroV3 && nitro.options.dev)) {
|
|
848
|
-
addServerConfigToBuild(moduleOptions, nitro, serverConfigFile);
|
|
849
|
-
}
|
|
929
|
+
addMiddlewareInstrumentation(nitro, isNitroV3);
|
|
930
|
+
if (!usesDeprecatedInjectMode) {
|
|
931
|
+
addServerConfigShimWithWarning(nitro);
|
|
850
932
|
if (moduleOptions.debug) {
|
|
851
|
-
const serverDirResolver = createResolver(nitro.options.output.serverDir);
|
|
852
|
-
const serverConfigPath = serverDirResolver.resolve("sentry.server.config.mjs");
|
|
853
|
-
const serverConfigRelativePath = toImportSpecifier(nitro.options.rootDir, serverConfigPath);
|
|
854
|
-
const devConfigRelativePath = isNitroV3 ? toImportSpecifier(nuxt.options.rootDir, path.join(nuxt.options.buildDir, DEV_SERVER_CONFIG_PATH)) : serverConfigRelativePath;
|
|
855
933
|
consoleSandbox(() => {
|
|
856
934
|
console.log(
|
|
857
|
-
`[Sentry]
|
|
935
|
+
`[Sentry] Bundled \`${serverConfigFile}\` into the Nitro server build. The SDK initializes itself at server startup \u2014 no \`node --import\` preload needed.`
|
|
858
936
|
);
|
|
859
|
-
if (nitro.options.dev) {
|
|
860
|
-
console.log(
|
|
861
|
-
`[Sentry] During development, preload Sentry with the NODE_OPTIONS environment variable: \`NODE_OPTIONS='--import ${devConfigRelativePath}' nuxt dev\`. The file is generated in the build directory (usually '.nuxt'). If you delete the build directory, run \`nuxt prepare\` to regenerate it.`
|
|
862
|
-
);
|
|
863
|
-
} else {
|
|
864
|
-
console.log(
|
|
865
|
-
`[Sentry] When running your built application, preload Sentry via a command-line flag (\`node --import ${serverConfigRelativePath} [...]\`) or via an environment variable (\`NODE_OPTIONS='--import ${serverConfigRelativePath}' node [...]\`).`
|
|
866
|
-
);
|
|
867
|
-
}
|
|
868
937
|
});
|
|
869
938
|
}
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
if (moduleOptions.
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
939
|
+
} else {
|
|
940
|
+
consoleSandbox(() => {
|
|
941
|
+
console.warn(
|
|
942
|
+
`[Sentry] \`autoInjectServerSentry: '${moduleOptions.autoInjectServerSentry}'\` is deprecated and will be removed in a future major version. The Sentry server config is bundled into the Nitro server build by default now. Remove the option to use the default behavior.`
|
|
943
|
+
);
|
|
944
|
+
});
|
|
945
|
+
if (moduleOptions.autoInjectServerSentry === "top-level-import") {
|
|
946
|
+
if (!(isNitroV3 && nitro.options.dev)) {
|
|
947
|
+
addServerConfigToBuild(moduleOptions, nitro, serverConfigFile);
|
|
948
|
+
}
|
|
949
|
+
addSentryTopImport(moduleOptions, nitro);
|
|
950
|
+
}
|
|
951
|
+
if (moduleOptions.autoInjectServerSentry === "experimental_dynamic-import") {
|
|
952
|
+
addDynamicImportEntryFileWrapper(nitro, serverConfigFile, moduleOptions);
|
|
953
|
+
if (moduleOptions.debug) {
|
|
954
|
+
consoleSandbox(() => {
|
|
955
|
+
console.log(
|
|
956
|
+
"[Sentry] Wrapping the server entry file with a dynamic `import()`, so Sentry can be preloaded before the server initializes."
|
|
957
|
+
);
|
|
958
|
+
});
|
|
959
|
+
}
|
|
882
960
|
}
|
|
883
961
|
}
|
|
884
962
|
}
|