@sentry/nitro 10.68.0 → 11.0.0-alpha.0

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.
@@ -1 +1 @@
1
- {"type":"module","version":"10.68.0","sideEffects":false}
1
+ {"type":"module","version":"11.0.0-alpha.0","sideEffects":false}
@@ -1,4 +1,4 @@
1
- import { getClient, parseUrl, getCurrentScope, getActiveSpan, getRootSpan, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, captureException, flushIfServerless } from '@sentry/core';
1
+ import { getClient, captureException, flushIfServerless, parseUrl } from '@sentry/core';
2
2
  import { HTTPError } from 'h3';
3
3
 
4
4
  function extractErrorContext(errorContext) {
@@ -24,15 +24,6 @@ async function captureErrorHook(error, errorContext) {
24
24
  if (HTTPError.isError(error) && error.status >= 300 && error.status < 500) {
25
25
  return;
26
26
  }
27
- const method = errorContext.event?.req.method ?? "";
28
- const path = errorContext.event?.req.url ? parseUrl(errorContext.event.req.url).path : null;
29
- if (path) {
30
- getCurrentScope().setTransactionName(`${method} ${path}`);
31
- const activeSpan = getActiveSpan();
32
- const activeRootSpan = activeSpan ? getRootSpan(activeSpan) : void 0;
33
- activeRootSpan?.updateName(`${method} ${path}`);
34
- activeRootSpan?.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, "route");
35
- }
36
27
  const structuredContext = extractErrorContext(errorContext);
37
28
  captureException(error, {
38
29
  captureContext: { contexts: { nitro: structuredContext } },
@@ -1 +1 @@
1
- {"version":3,"file":"captureErrorHook.js","sources":["../../../../src/runtime/hooks/captureErrorHook.ts"],"sourcesContent":["import {\n captureException,\n flushIfServerless,\n getActiveSpan,\n getClient,\n getCurrentScope,\n getRootSpan,\n parseUrl,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n} from '@sentry/core';\nimport { HTTPError } from 'h3';\nimport type { CapturedErrorContext } from 'nitro/types';\n\n/**\n * Extracts the relevant context information from the error context (HTTPEvent in Nitro Error)\n * and creates a structured context object.\n */\nfunction extractErrorContext(errorContext: CapturedErrorContext | undefined): Record<string, unknown> {\n const ctx: Record<string, unknown> = {};\n\n if (!errorContext) {\n return ctx;\n }\n\n if (errorContext.event) {\n ctx.method = errorContext.event.req.method;\n ctx.path = parseUrl(errorContext.event.req.url).path;\n }\n\n if (Array.isArray(errorContext.tags)) {\n ctx.tags = errorContext.tags;\n }\n\n return ctx;\n}\n\n/**\n * Hook that can be added in a Nitro plugin. It captures an error and sends it to Sentry.\n */\nexport async function captureErrorHook(error: Error, errorContext: CapturedErrorContext): Promise<void> {\n const sentryClient = getClient();\n const sentryClientOptions = sentryClient?.getOptions();\n\n if (\n sentryClientOptions &&\n 'enableNitroErrorHandler' in sentryClientOptions &&\n sentryClientOptions.enableNitroErrorHandler === false\n ) {\n return;\n }\n\n // Do not report HTTPErrors with 3xx or 4xx status codes\n if (HTTPError.isError(error) && error.status >= 300 && error.status < 500) {\n return;\n }\n\n const method = errorContext.event?.req.method ?? '';\n const path = errorContext.event?.req.url ? parseUrl(errorContext.event.req.url).path : null;\n\n if (path) {\n getCurrentScope().setTransactionName(`${method} ${path}`);\n const activeSpan = getActiveSpan();\n const activeRootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n activeRootSpan?.updateName(`${method} ${path}`);\n activeRootSpan?.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, 'route');\n }\n\n const structuredContext = extractErrorContext(errorContext);\n\n captureException(error, {\n captureContext: { contexts: { nitro: structuredContext } },\n mechanism: { handled: false, type: 'auto.function.nitro.captureErrorHook' },\n });\n\n await flushIfServerless();\n}\n"],"names":[],"mappings":";;;AAiBA,SAAS,oBAAoB,YAAA,EAAyE;AACpG,EAAA,MAAM,MAA+B,EAAC;AAEtC,EAAA,IAAI,CAAC,YAAA,EAAc;AACjB,IAAA,OAAO,GAAA;AAAA,EACT;AAEA,EAAA,IAAI,aAAa,KAAA,EAAO;AACtB,IAAA,GAAA,CAAI,MAAA,GAAS,YAAA,CAAa,KAAA,CAAM,GAAA,CAAI,MAAA;AACpC,IAAA,GAAA,CAAI,OAAO,QAAA,CAAS,YAAA,CAAa,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA,CAAE,IAAA;AAAA,EAClD;AAEA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,YAAA,CAAa,IAAI,CAAA,EAAG;AACpC,IAAA,GAAA,CAAI,OAAO,YAAA,CAAa,IAAA;AAAA,EAC1B;AAEA,EAAA,OAAO,GAAA;AACT;AAKA,eAAsB,gBAAA,CAAiB,OAAc,YAAA,EAAmD;AACtG,EAAA,MAAM,eAAe,SAAA,EAAU;AAC/B,EAAA,MAAM,mBAAA,GAAsB,cAAc,UAAA,EAAW;AAErD,EAAA,IACE,mBAAA,IACA,yBAAA,IAA6B,mBAAA,IAC7B,mBAAA,CAAoB,4BAA4B,KAAA,EAChD;AACA,IAAA;AAAA,EACF;AAGA,EAAA,IAAI,SAAA,CAAU,QAAQ,KAAK,CAAA,IAAK,MAAM,MAAA,IAAU,GAAA,IAAO,KAAA,CAAM,MAAA,GAAS,GAAA,EAAK;AACzE,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,MAAA,GAAS,YAAA,CAAa,KAAA,EAAO,GAAA,CAAI,MAAA,IAAU,EAAA;AACjD,EAAA,MAAM,IAAA,GAAO,YAAA,CAAa,KAAA,EAAO,GAAA,CAAI,GAAA,GAAM,QAAA,CAAS,YAAA,CAAa,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA,CAAE,IAAA,GAAO,IAAA;AAEvF,EAAA,IAAI,IAAA,EAAM;AACR,IAAA,eAAA,GAAkB,kBAAA,CAAmB,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,IAAI,CAAA,CAAE,CAAA;AACxD,IAAA,MAAM,aAAa,aAAA,EAAc;AACjC,IAAA,MAAM,cAAA,GAAiB,UAAA,GAAa,WAAA,CAAY,UAAU,CAAA,GAAI,MAAA;AAC9D,IAAA,cAAA,EAAgB,UAAA,CAAW,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,IAAI,CAAA,CAAE,CAAA;AAC9C,IAAA,cAAA,EAAgB,YAAA,CAAa,kCAAkC,OAAO,CAAA;AAAA,EACxE;AAEA,EAAA,MAAM,iBAAA,GAAoB,oBAAoB,YAAY,CAAA;AAE1D,EAAA,gBAAA,CAAiB,KAAA,EAAO;AAAA,IACtB,gBAAgB,EAAE,QAAA,EAAU,EAAE,KAAA,EAAO,mBAAkB,EAAE;AAAA,IACzD,SAAA,EAAW,EAAE,OAAA,EAAS,KAAA,EAAO,MAAM,sCAAA;AAAuC,GAC3E,CAAA;AAED,EAAA,MAAM,iBAAA,EAAkB;AAC1B;;;;"}
1
+ {"version":3,"file":"captureErrorHook.js","sources":["../../../../src/runtime/hooks/captureErrorHook.ts"],"sourcesContent":["import { captureException, flushIfServerless, getClient, parseUrl } from '@sentry/core';\nimport { HTTPError } from 'h3';\nimport type { CapturedErrorContext } from 'nitro/types';\n\n/**\n * Extracts the relevant context information from the error context (HTTPEvent in Nitro Error)\n * and creates a structured context object.\n */\nfunction extractErrorContext(errorContext: CapturedErrorContext | undefined): Record<string, unknown> {\n const ctx: Record<string, unknown> = {};\n\n if (!errorContext) {\n return ctx;\n }\n\n if (errorContext.event) {\n ctx.method = errorContext.event.req.method;\n ctx.path = parseUrl(errorContext.event.req.url).path;\n }\n\n if (Array.isArray(errorContext.tags)) {\n ctx.tags = errorContext.tags;\n }\n\n return ctx;\n}\n\n/**\n * Hook that can be added in a Nitro plugin. It captures an error and sends it to Sentry.\n */\nexport async function captureErrorHook(error: Error, errorContext: CapturedErrorContext): Promise<void> {\n const sentryClient = getClient();\n const sentryClientOptions = sentryClient?.getOptions();\n\n if (\n sentryClientOptions &&\n 'enableNitroErrorHandler' in sentryClientOptions &&\n sentryClientOptions.enableNitroErrorHandler === false\n ) {\n return;\n }\n\n // Do not report HTTPErrors with 3xx or 4xx status codes\n if (HTTPError.isError(error) && error.status >= 300 && error.status < 500) {\n return;\n }\n\n const structuredContext = extractErrorContext(errorContext);\n\n captureException(error, {\n captureContext: { contexts: { nitro: structuredContext } },\n mechanism: { handled: false, type: 'auto.function.nitro.captureErrorHook' },\n });\n\n await flushIfServerless();\n}\n"],"names":[],"mappings":";;;AAQA,SAAS,oBAAoB,YAAA,EAAyE;AACpG,EAAA,MAAM,MAA+B,EAAC;AAEtC,EAAA,IAAI,CAAC,YAAA,EAAc;AACjB,IAAA,OAAO,GAAA;AAAA,EACT;AAEA,EAAA,IAAI,aAAa,KAAA,EAAO;AACtB,IAAA,GAAA,CAAI,MAAA,GAAS,YAAA,CAAa,KAAA,CAAM,GAAA,CAAI,MAAA;AACpC,IAAA,GAAA,CAAI,OAAO,QAAA,CAAS,YAAA,CAAa,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA,CAAE,IAAA;AAAA,EAClD;AAEA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,YAAA,CAAa,IAAI,CAAA,EAAG;AACpC,IAAA,GAAA,CAAI,OAAO,YAAA,CAAa,IAAA;AAAA,EAC1B;AAEA,EAAA,OAAO,GAAA;AACT;AAKA,eAAsB,gBAAA,CAAiB,OAAc,YAAA,EAAmD;AACtG,EAAA,MAAM,eAAe,SAAA,EAAU;AAC/B,EAAA,MAAM,mBAAA,GAAsB,cAAc,UAAA,EAAW;AAErD,EAAA,IACE,mBAAA,IACA,yBAAA,IAA6B,mBAAA,IAC7B,mBAAA,CAAoB,4BAA4B,KAAA,EAChD;AACA,IAAA;AAAA,EACF;AAGA,EAAA,IAAI,SAAA,CAAU,QAAQ,KAAK,CAAA,IAAK,MAAM,MAAA,IAAU,GAAA,IAAO,KAAA,CAAM,MAAA,GAAS,GAAA,EAAK;AACzE,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,iBAAA,GAAoB,oBAAoB,YAAY,CAAA;AAE1D,EAAA,gBAAA,CAAiB,KAAA,EAAO;AAAA,IACtB,gBAAgB,EAAE,QAAA,EAAU,EAAE,KAAA,EAAO,mBAAkB,EAAE;AAAA,IACzD,SAAA,EAAW,EAAE,OAAA,EAAS,KAAA,EAAO,MAAM,sCAAA;AAAuC,GAC3E,CAAA;AAED,EAAA,MAAM,iBAAA,EAAkB;AAC1B;;;;"}
@@ -1,5 +1,7 @@
1
1
  import * as dc from 'node:diagnostics_channel';
2
- import { GLOBAL_OBJ, startInactiveSpan, SEMANTIC_ATTRIBUTE_CACHE_KEY, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_CACHE_HIT, flushIfServerless } from '@sentry/core';
2
+ import { SENTRY_OP } from '@sentry/conventions/attributes';
3
+ import { DATABASE_CACHE_REMOVE_SPAN_OP, DATABASE_CACHE_PUT_SPAN_OP, DATABASE_CACHE_GET_SPAN_OP } from '@sentry/conventions/op';
4
+ import { GLOBAL_OBJ, startInactiveSpan, SEMANTIC_ATTRIBUTE_CACHE_KEY, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_CACHE_HIT, flushIfServerless, isObjectLike } from '@sentry/core';
3
5
  import { bindTracingChannelToSpan } from '@sentry/server-utils';
4
6
 
5
7
  const ORIGIN = "auto.cache.nitro";
@@ -16,7 +18,19 @@ const TRACED_OPERATIONS = [
16
18
  "getKeys",
17
19
  "clear"
18
20
  ];
19
- const CACHE_HIT_OPERATIONS = /* @__PURE__ */ new Set(["hasItem", "getItem", "getItemRaw"]);
21
+ const CACHE_HIT_OPERATIONS = /* @__PURE__ */ new Set(["hasItem", "getItem", "getItemRaw", "getItems"]);
22
+ const OPERATION_SPAN_OPS = {
23
+ hasItem: DATABASE_CACHE_GET_SPAN_OP,
24
+ getItem: DATABASE_CACHE_GET_SPAN_OP,
25
+ getItemRaw: DATABASE_CACHE_GET_SPAN_OP,
26
+ getItems: DATABASE_CACHE_GET_SPAN_OP,
27
+ getKeys: DATABASE_CACHE_GET_SPAN_OP,
28
+ setItem: DATABASE_CACHE_PUT_SPAN_OP,
29
+ setItemRaw: DATABASE_CACHE_PUT_SPAN_OP,
30
+ setItems: DATABASE_CACHE_PUT_SPAN_OP,
31
+ removeItem: DATABASE_CACHE_REMOVE_SPAN_OP,
32
+ clear: DATABASE_CACHE_REMOVE_SPAN_OP
33
+ };
20
34
  const CACHED_FN_HANDLERS_RE = /^nitro:(functions|handlers):/i;
21
35
  function captureStorageEvents() {
22
36
  if (globalWithStorageChannels.__SENTRY_NITRO_STORAGE_CHANNELS_INSTRUMENTED__) {
@@ -40,7 +54,7 @@ function setupStorageTracingChannel(operation) {
40
54
  return startInactiveSpan({
41
55
  name: cacheKeys.join(", ") || operation,
42
56
  attributes: {
43
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: `cache.${normalizeMethodName(operation)}`,
57
+ [SENTRY_OP]: OPERATION_SPAN_OPS[operation],
44
58
  [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,
45
59
  [SEMANTIC_ATTRIBUTE_CACHE_KEY]: cacheKeys.length > 1 ? cacheKeys : cacheKeys[0],
46
60
  "db.operation.name": operation,
@@ -54,8 +68,7 @@ function setupStorageTracingChannel(operation) {
54
68
  if (!("error" in data)) {
55
69
  const result = data.result;
56
70
  if (CACHE_HIT_OPERATIONS.has(operation)) {
57
- const hit = operation === "hasItem" ? Boolean(result) : isCacheHit(data.keys?.[0], result);
58
- span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_HIT, hit);
71
+ span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_HIT, resolveCacheHit(operation, data.keys?.[0], result));
59
72
  }
60
73
  }
61
74
  void flushIfServerless();
@@ -63,8 +76,14 @@ function setupStorageTracingChannel(operation) {
63
76
  }
64
77
  );
65
78
  }
66
- function normalizeMethodName(methodName) {
67
- return methodName.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
79
+ function resolveCacheHit(operation, key, result) {
80
+ if (operation === "hasItem") {
81
+ return Boolean(result);
82
+ }
83
+ if (operation === "getItems") {
84
+ return Array.isArray(result) && result.some((item) => isObjectLike(item) && item.value != null);
85
+ }
86
+ return isCacheHit(key, result);
68
87
  }
69
88
  function isCacheHit(key, value) {
70
89
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"captureStorageEvents.js","sources":["../../../../src/runtime/hooks/captureStorageEvents.ts"],"sourcesContent":["import * as dc from 'node:diagnostics_channel';\nimport {\n flushIfServerless,\n GLOBAL_OBJ,\n SEMANTIC_ATTRIBUTE_CACHE_HIT,\n SEMANTIC_ATTRIBUTE_CACHE_KEY,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startInactiveSpan,\n} from '@sentry/core';\nimport { bindTracingChannelToSpan } from '@sentry/server-utils';\nimport type { TraceContext } from 'unstorage/tracing';\n\nconst ORIGIN = 'auto.cache.nitro';\n\nconst globalWithStorageChannels = GLOBAL_OBJ as typeof GLOBAL_OBJ & {\n __SENTRY_NITRO_STORAGE_CHANNELS_INSTRUMENTED__: boolean;\n};\n\nconst TRACED_OPERATIONS = [\n 'hasItem',\n 'getItem',\n 'getItemRaw',\n 'getItems',\n 'setItem',\n 'setItemRaw',\n 'setItems',\n 'removeItem',\n 'getKeys',\n 'clear',\n] as const;\n\ntype TracedOperation = (typeof TRACED_OPERATIONS)[number];\n\nconst CACHE_HIT_OPERATIONS = new Set<TracedOperation>(['hasItem', 'getItem', 'getItemRaw']);\n\nconst CACHED_FN_HANDLERS_RE = /^nitro:(functions|handlers):/i;\n\n/**\n * Subscribes to unstorage tracing channels and creates Sentry spans for storage operations.\n */\nexport function captureStorageEvents(): void {\n if (globalWithStorageChannels.__SENTRY_NITRO_STORAGE_CHANNELS_INSTRUMENTED__) {\n return;\n }\n\n for (const operation of TRACED_OPERATIONS) {\n setupStorageTracingChannel(operation);\n }\n\n globalWithStorageChannels.__SENTRY_NITRO_STORAGE_CHANNELS_INSTRUMENTED__ = true;\n}\n\nfunction setupStorageTracingChannel(operation: TracedOperation): void {\n const keys = (data: TraceContext): string[] => data.keys ?? [];\n const mountBase = (data: TraceContext): string => (data.base ?? '').replace(/:$/, '');\n\n // Bail if this is not available\n if (!dc.tracingChannel) {\n return;\n }\n\n bindTracingChannelToSpan(\n dc.tracingChannel<TraceContext>(`unstorage.${operation}`),\n data => {\n const cacheKeys = keys(data);\n\n return startInactiveSpan({\n name: cacheKeys.join(', ') || operation,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: `cache.${normalizeMethodName(operation)}`,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n [SEMANTIC_ATTRIBUTE_CACHE_KEY]: cacheKeys.length > 1 ? cacheKeys : cacheKeys[0],\n 'db.operation.name': operation,\n 'db.collection.name': mountBase(data),\n 'db.system.name': data.driver?.name ?? 'unknown',\n },\n });\n },\n {\n beforeSpanEnd(span, data) {\n // Error status is set by the binding; the error itself is captured at the request boundary,\n // not here (cache ops aren't an error boundary). Only enrich the success path.\n if (!('error' in data)) {\n const result = (data as { result?: unknown }).result;\n if (CACHE_HIT_OPERATIONS.has(operation)) {\n const hit = operation === 'hasItem' ? Boolean(result) : isCacheHit(data.keys?.[0], result);\n span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_HIT, hit);\n }\n }\n\n void flushIfServerless();\n },\n },\n );\n}\n\nfunction normalizeMethodName(methodName: string): string {\n return methodName.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);\n}\n\ninterface CacheEntry<T = unknown> {\n value?: T;\n expires?: number;\n}\n\ninterface ResponseCacheEntry {\n status?: number;\n body?: unknown;\n headers?: Record<string, string | undefined>;\n}\n\nfunction isCacheHit(key: unknown, value: unknown): boolean {\n try {\n const isEmpty = value == null;\n if (isEmpty || typeof key !== 'string' || !CACHED_FN_HANDLERS_RE.test(key)) {\n return !isEmpty;\n }\n\n const entry = typeof value === 'string' ? (JSON.parse(value) as CacheEntry) : (value as CacheEntry);\n\n return validateCacheEntry(key, entry);\n } catch {\n return false;\n }\n}\n\nfunction validateCacheEntry(\n key: string,\n entry: CacheEntry | CacheEntry<ResponseCacheEntry & { status: number }>,\n): boolean {\n if (entry.value == null) {\n return false;\n }\n\n if (Date.now() > (entry.expires || 0)) {\n return false;\n }\n\n if (isResponseCacheEntry(key, entry)) {\n if ((entry.value.status ?? 0) >= 400) {\n return false;\n }\n\n if (entry.value.body === undefined) {\n return false;\n }\n\n if (entry.value.headers?.etag === 'undefined' || entry.value.headers?.['last-modified'] === 'undefined') {\n return false;\n }\n }\n\n return true;\n}\n\nfunction isResponseCacheEntry(key: string, _: CacheEntry): _ is CacheEntry<ResponseCacheEntry & { status: number }> {\n return key.startsWith('nitro:handlers:');\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"captureStorageEvents.js","sources":["../../../../src/runtime/hooks/captureStorageEvents.ts"],"sourcesContent":["import * as dc from 'node:diagnostics_channel';\nimport { SENTRY_OP } from '@sentry/conventions/attributes';\nimport {\n DATABASE_CACHE_GET_SPAN_OP,\n DATABASE_CACHE_PUT_SPAN_OP,\n DATABASE_CACHE_REMOVE_SPAN_OP,\n} from '@sentry/conventions/op';\nimport {\n flushIfServerless,\n GLOBAL_OBJ,\n isObjectLike,\n SEMANTIC_ATTRIBUTE_CACHE_HIT,\n SEMANTIC_ATTRIBUTE_CACHE_KEY,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startInactiveSpan,\n} from '@sentry/core';\nimport { bindTracingChannelToSpan } from '@sentry/server-utils';\nimport type { TraceContext } from 'unstorage/tracing';\n\nconst ORIGIN = 'auto.cache.nitro';\n\nconst globalWithStorageChannels = GLOBAL_OBJ as typeof GLOBAL_OBJ & {\n __SENTRY_NITRO_STORAGE_CHANNELS_INSTRUMENTED__: boolean;\n};\n\nconst TRACED_OPERATIONS = [\n 'hasItem',\n 'getItem',\n 'getItemRaw',\n 'getItems',\n 'setItem',\n 'setItemRaw',\n 'setItems',\n 'removeItem',\n 'getKeys',\n 'clear',\n] as const;\n\ntype TracedOperation = (typeof TRACED_OPERATIONS)[number];\n\nconst CACHE_HIT_OPERATIONS = new Set<TracedOperation>(['hasItem', 'getItem', 'getItemRaw', 'getItems']);\n\n/**\n * Maps each unstorage operation to a convention cache op. Reads (including existence and key\n * listing) are `cache.get`, writes are `cache.put`, and deletions are `cache.remove`.\n * The precise operation stays available on `db.operation.name`.\n */\nconst OPERATION_SPAN_OPS = {\n hasItem: DATABASE_CACHE_GET_SPAN_OP,\n getItem: DATABASE_CACHE_GET_SPAN_OP,\n getItemRaw: DATABASE_CACHE_GET_SPAN_OP,\n getItems: DATABASE_CACHE_GET_SPAN_OP,\n getKeys: DATABASE_CACHE_GET_SPAN_OP,\n setItem: DATABASE_CACHE_PUT_SPAN_OP,\n setItemRaw: DATABASE_CACHE_PUT_SPAN_OP,\n setItems: DATABASE_CACHE_PUT_SPAN_OP,\n removeItem: DATABASE_CACHE_REMOVE_SPAN_OP,\n clear: DATABASE_CACHE_REMOVE_SPAN_OP,\n} as const satisfies Record<TracedOperation, string>;\n\nconst CACHED_FN_HANDLERS_RE = /^nitro:(functions|handlers):/i;\n\n/**\n * Subscribes to unstorage tracing channels and creates Sentry spans for storage operations.\n */\nexport function captureStorageEvents(): void {\n if (globalWithStorageChannels.__SENTRY_NITRO_STORAGE_CHANNELS_INSTRUMENTED__) {\n return;\n }\n\n for (const operation of TRACED_OPERATIONS) {\n setupStorageTracingChannel(operation);\n }\n\n globalWithStorageChannels.__SENTRY_NITRO_STORAGE_CHANNELS_INSTRUMENTED__ = true;\n}\n\nfunction setupStorageTracingChannel(operation: TracedOperation): void {\n const keys = (data: TraceContext): string[] => data.keys ?? [];\n const mountBase = (data: TraceContext): string => (data.base ?? '').replace(/:$/, '');\n\n // Bail if this is not available\n if (!dc.tracingChannel) {\n return;\n }\n\n bindTracingChannelToSpan(\n dc.tracingChannel<TraceContext>(`unstorage.${operation}`),\n data => {\n const cacheKeys = keys(data);\n\n return startInactiveSpan({\n name: cacheKeys.join(', ') || operation,\n attributes: {\n [SENTRY_OP]: OPERATION_SPAN_OPS[operation],\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n [SEMANTIC_ATTRIBUTE_CACHE_KEY]: cacheKeys.length > 1 ? cacheKeys : cacheKeys[0],\n 'db.operation.name': operation,\n 'db.collection.name': mountBase(data),\n 'db.system.name': data.driver?.name ?? 'unknown',\n },\n });\n },\n {\n beforeSpanEnd(span, data) {\n // Error status is set by the binding; the error itself is captured at the request boundary,\n // not here (cache ops aren't an error boundary). Only enrich the success path.\n if (!('error' in data)) {\n const result = (data as { result?: unknown }).result;\n if (CACHE_HIT_OPERATIONS.has(operation)) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_HIT, resolveCacheHit(operation, data.keys?.[0], result));\n }\n }\n\n void flushIfServerless();\n },\n },\n );\n}\n\n/**\n * Resolves the `cache.hit` value for a read operation. `hasItem` returns a boolean directly,\n * `getItems` returns a `{ key, value }[]` where a hit means at least one entry has a value,\n * and single-key reads fall back to the value-based `isCacheHit` check.\n */\nfunction resolveCacheHit(operation: TracedOperation, key: unknown, result: unknown): boolean {\n if (operation === 'hasItem') {\n return Boolean(result);\n }\n\n if (operation === 'getItems') {\n return Array.isArray(result) && result.some(item => isObjectLike(item) && item.value != null);\n }\n\n return isCacheHit(key, result);\n}\n\ninterface CacheEntry<T = unknown> {\n value?: T;\n expires?: number;\n}\n\ninterface ResponseCacheEntry {\n status?: number;\n body?: unknown;\n headers?: Record<string, string | undefined>;\n}\n\nfunction isCacheHit(key: unknown, value: unknown): boolean {\n try {\n const isEmpty = value == null;\n if (isEmpty || typeof key !== 'string' || !CACHED_FN_HANDLERS_RE.test(key)) {\n return !isEmpty;\n }\n\n const entry = typeof value === 'string' ? (JSON.parse(value) as CacheEntry) : (value as CacheEntry);\n\n return validateCacheEntry(key, entry);\n } catch {\n return false;\n }\n}\n\nfunction validateCacheEntry(\n key: string,\n entry: CacheEntry | CacheEntry<ResponseCacheEntry & { status: number }>,\n): boolean {\n if (entry.value == null) {\n return false;\n }\n\n if (Date.now() > (entry.expires || 0)) {\n return false;\n }\n\n if (isResponseCacheEntry(key, entry)) {\n if ((entry.value.status ?? 0) >= 400) {\n return false;\n }\n\n if (entry.value.body === undefined) {\n return false;\n }\n\n if (entry.value.headers?.etag === 'undefined' || entry.value.headers?.['last-modified'] === 'undefined') {\n return false;\n }\n }\n\n return true;\n}\n\nfunction isResponseCacheEntry(key: string, _: CacheEntry): _ is CacheEntry<ResponseCacheEntry & { status: number }> {\n return key.startsWith('nitro:handlers:');\n}\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  import * as dc from 'node:diagnostics_channel';
2
- import { GLOBAL_OBJ, parseStringToURLObject, getHttpSpanDetailsFromUrlObject, startInactiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, getRootSpan, updateSpanName, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, httpHeadersToSpanAttributes, getClient, getActiveSpan, isObjectLike, setHttpStatus } from '@sentry/core';
3
- import { bindTracingChannelToSpan } from '@sentry/server-utils';
2
+ import { SENTRY_OP } from '@sentry/conventions/attributes';
3
+ import { WEB_SERVER_MIDDLEWARE_SPAN_OP, WEB_SERVER_HTTP_SERVER_SPAN_OP } from '@sentry/conventions/op';
4
+ import { GLOBAL_OBJ, parseStringToURLObject, getHttpSpanDetailsFromUrlObject, startInactiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, getClient, httpHeadersToSpanAttributes, getActiveSpan, getRootSpan, isObjectLike, setHttpStatus } from '@sentry/core';
5
+ import { bindTracingChannelToSpan, setHttpServerSpanRouteAttribute } from '@sentry/server-utils';
4
6
  import { setServerTimingHeaders } from './setServerTimingHeaders.js';
5
7
 
6
8
  const globalWithTraceChannels = GLOBAL_OBJ;
@@ -56,7 +58,7 @@ function setupH3TracingChannels() {
56
58
  attributes: {
57
59
  ...urlAttributes,
58
60
  [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.nitro.h3",
59
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: data?.type === "middleware" ? "middleware.nitro" : "http.server"
61
+ [SENTRY_OP]: data?.type === "middleware" ? WEB_SERVER_MIDDLEWARE_SPAN_OP : WEB_SERVER_HTTP_SERVER_SPAN_OP
60
62
  }
61
63
  });
62
64
  setParameterizedRouteAttributes(span, data.event);
@@ -71,17 +73,9 @@ function setupH3TracingChannels() {
71
73
  }),
72
74
  beforeSpanEnd(span, data) {
73
75
  applyResponseStatus(span, data);
74
- const rootSpan = getRootSpan(span);
75
- if (rootSpan && rootSpan !== span) {
76
- const routePattern = getParameterizedRoute(data.event);
77
- if (routePattern) {
78
- const method = data.event.req.method || "GET";
79
- updateSpanName(rootSpan, `${method} ${routePattern}`);
80
- rootSpan.setAttributes({
81
- [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "route",
82
- "http.route": routePattern
83
- });
84
- }
76
+ const routePattern = getParameterizedRoute(data.event);
77
+ if (routePattern) {
78
+ setHttpServerSpanRouteAttribute(routePattern);
85
79
  }
86
80
  }
87
81
  }
@@ -101,20 +95,26 @@ function setupSrvxTracingChannels() {
101
95
  dc.tracingChannel("srvx.request"),
102
96
  (data) => {
103
97
  const parsedUrl = data.request._url ? parseStringToURLObject(data.request._url.href) : void 0;
104
- const [spanName, urlAttributes] = getHttpSpanDetailsFromUrlObject(parsedUrl, "server", "auto.http.nitro.srvx", {
105
- method: data.request.method
106
- });
107
- const headerAttributes = httpHeadersToSpanAttributes(
108
- Object.fromEntries(data.request.headers.entries()),
109
- getClient()?.getDataCollectionOptions() ?? false
98
+ const client = getClient();
99
+ const [spanName, urlAttributes] = getHttpSpanDetailsFromUrlObject(
100
+ parsedUrl,
101
+ "server",
102
+ "auto.http.nitro.srvx",
103
+ { method: data.request.method },
104
+ void 0,
105
+ client
110
106
  );
107
+ const headerAttributes = client ? httpHeadersToSpanAttributes(
108
+ Object.fromEntries(data.request.headers.entries()),
109
+ client.getDataCollectionOptions()
110
+ ) : {};
111
111
  return startInactiveSpan({
112
112
  name: spanName,
113
113
  attributes: {
114
114
  ...urlAttributes,
115
115
  ...headerAttributes,
116
116
  [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.nitro.srvx",
117
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: data.middleware ? "middleware.nitro" : "http.server",
117
+ [SENTRY_OP]: data.middleware ? WEB_SERVER_MIDDLEWARE_SPAN_OP : WEB_SERVER_HTTP_SERVER_SPAN_OP,
118
118
  "server.port": data.server.options.port
119
119
  },
120
120
  // Use the same parent span as middleware to make them siblings
@@ -146,7 +146,7 @@ function setupSrvxTracingChannels() {
146
146
  attributes: {
147
147
  ...urlAttributes,
148
148
  [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.nitro.srvx",
149
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "middleware.nitro"
149
+ [SENTRY_OP]: WEB_SERVER_MIDDLEWARE_SPAN_OP
150
150
  },
151
151
  parentSpan: requestParentSpans.get(data.request) || void 0
152
152
  });
@@ -159,18 +159,15 @@ function setupSrvxTracingChannels() {
159
159
  );
160
160
  }
161
161
  function setParameterizedRouteAttributes(span, event) {
162
- const rootSpan = getRootSpan(span);
163
- if (!rootSpan) {
164
- return;
165
- }
166
162
  const matchedRoutePath = getParameterizedRoute(event);
167
163
  if (!matchedRoutePath) {
168
164
  return;
169
165
  }
170
- rootSpan.setAttributes({
171
- [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "route",
172
- "http.route": matchedRoutePath
173
- });
166
+ setHttpServerSpanRouteAttribute(matchedRoutePath);
167
+ const rootSpan = getRootSpan(span);
168
+ if (!rootSpan) {
169
+ return;
170
+ }
174
171
  const params = event.context?.params;
175
172
  if (isObjectLike(params)) {
176
173
  Object.entries(params).forEach(([key, value]) => {
@@ -1 +1 @@
1
- {"version":3,"file":"captureTracingEvents.js","sources":["../../../../src/runtime/hooks/captureTracingEvents.ts"],"sourcesContent":["import * as dc from 'node:diagnostics_channel';\nimport {\n isObjectLike,\n getActiveSpan,\n getClient,\n getHttpSpanDetailsFromUrlObject,\n getRootSpan,\n GLOBAL_OBJ,\n httpHeadersToSpanAttributes,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n setHttpStatus,\n type Span,\n startInactiveSpan,\n updateSpanName,\n} from '@sentry/core';\nimport { bindTracingChannelToSpan, type TracingChannelPayloadWithSpan } from '@sentry/server-utils';\nimport type { TracingRequestEvent as H3TracingRequestEvent } from 'h3/tracing';\nimport type { RequestEvent as SrvxRequestEvent } from 'srvx/tracing';\nimport { setServerTimingHeaders } from './setServerTimingHeaders';\n\n/**\n * Global object with the trace channels\n */\nconst globalWithTraceChannels = GLOBAL_OBJ as typeof GLOBAL_OBJ & {\n __SENTRY_NITRO_HTTP_CHANNELS_INSTRUMENTED__: boolean;\n};\n\n/**\n * Captures tracing events emitted by Nitro tracing channels.\n */\nexport function captureTracingEvents(): void {\n if (globalWithTraceChannels.__SENTRY_NITRO_HTTP_CHANNELS_INSTRUMENTED__) {\n return;\n }\n\n setupH3TracingChannels();\n setupSrvxTracingChannels();\n globalWithTraceChannels.__SENTRY_NITRO_HTTP_CHANNELS_INSTRUMENTED__ = true;\n}\n\n/**\n * Extracts the HTTP status code from a tracing channel result.\n * The result is the return value of the traced handler, which is a Response for srvx\n * and may or may not be a Response for h3.\n */\nfunction getResponseStatusCode(result: unknown): number | undefined {\n if (isObjectLike(result) && 'status' in result && typeof result.status === 'number') {\n return result.status;\n }\n return undefined;\n}\n\n/** Applies the HTTP status from the traced handler's result to the span, when present. */\nfunction applyResponseStatus(span: Span, data: TracingChannelPayloadWithSpan<{ result?: unknown }>): void {\n const statusCode = getResponseStatusCode(data.result);\n if (statusCode !== undefined) {\n setHttpStatus(span, statusCode);\n }\n}\n\n/**\n * Extracts the parameterized route pattern from the h3 event context.\n */\nfunction getParameterizedRoute(event: H3TracingRequestEvent['event']): string | undefined {\n const matchedRoute = event.context?.matchedRoute;\n if (!matchedRoute) {\n return undefined;\n }\n\n const routePath = matchedRoute.route;\n\n // Skip catch-all routes as they're not useful for transaction grouping\n if (!routePath || routePath === '/**') {\n return undefined;\n }\n\n return routePath;\n}\n\nfunction setupH3TracingChannels(): void {\n // Bail if this is not available\n if (!dc.tracingChannel) {\n return;\n }\n\n const { channel: h3Channel } = bindTracingChannelToSpan(\n dc.tracingChannel<H3TracingRequestEvent>('h3.request'),\n data => {\n const parsedUrl = parseStringToURLObject(data.event.url.href);\n const routePattern = getParameterizedRoute(data.event);\n\n const [spanName, urlAttributes] = getHttpSpanDetailsFromUrlObject(\n parsedUrl,\n 'server',\n 'auto.http.nitro.h3',\n { method: data.event.req.method },\n routePattern,\n );\n\n const span = startInactiveSpan({\n name: spanName,\n attributes: {\n ...urlAttributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.nitro.h3',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: data?.type === 'middleware' ? 'middleware.nitro' : 'http.server',\n },\n });\n\n setParameterizedRouteAttributes(span, data.event);\n\n return span;\n },\n {\n captureError: () => ({\n mechanism: {\n handled: false,\n type: 'auto.http.nitro.onTraceError',\n },\n }),\n beforeSpanEnd(span, data) {\n applyResponseStatus(span, data);\n\n // Update the root span (srvx transaction) with the parameterized route name.\n // The srvx span is created before h3 resolves the route, so it initially has the raw URL.\n // Note: data.type is always 'middleware' here regardless of handler type, so we rely on\n // getParameterizedRoute() to filter out catch-all routes instead.\n const rootSpan = getRootSpan(span);\n if (rootSpan && rootSpan !== span) {\n const routePattern = getParameterizedRoute(data.event);\n if (routePattern) {\n const method = data.event.req.method || 'GET';\n updateSpanName(rootSpan, `${method} ${routePattern}`);\n rootSpan.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n 'http.route': routePattern,\n });\n }\n }\n },\n },\n );\n\n h3Channel.subscribe({\n start: (data: H3TracingRequestEvent) => {\n setServerTimingHeaders(data.event);\n },\n });\n}\n\nfunction setupSrvxTracingChannels(): void {\n if (!dc.tracingChannel) {\n return;\n }\n\n // Store the parent span per-request so middleware and fetch share the same parent.\n // WeakMap ensures per-request isolation in concurrent environments and automatic cleanup.\n const requestParentSpans = new WeakMap<Request, Span>();\n\n bindTracingChannelToSpan(\n dc.tracingChannel<SrvxRequestEvent>('srvx.request'),\n data => {\n const parsedUrl = data.request._url ? parseStringToURLObject(data.request._url.href) : undefined;\n const [spanName, urlAttributes] = getHttpSpanDetailsFromUrlObject(parsedUrl, 'server', 'auto.http.nitro.srvx', {\n method: data.request.method,\n });\n\n const headerAttributes = httpHeadersToSpanAttributes(\n Object.fromEntries(data.request.headers.entries()),\n getClient()?.getDataCollectionOptions() ?? false,\n );\n\n return startInactiveSpan({\n name: spanName,\n attributes: {\n ...urlAttributes,\n ...headerAttributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.nitro.srvx',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: data.middleware ? 'middleware.nitro' : 'http.server',\n 'server.port': data.server.options.port,\n },\n // Use the same parent span as middleware to make them siblings\n parentSpan: requestParentSpans.get(data.request) || undefined,\n });\n },\n {\n beforeSpanEnd(span, data) {\n applyResponseStatus(span, data);\n\n // Clean up parent span reference after the fetch handler completes (success or error).\n requestParentSpans.delete(data.request);\n },\n },\n );\n\n bindTracingChannelToSpan(\n dc.tracingChannel<SrvxRequestEvent>('srvx.middleware'),\n data => {\n // For the first middleware, capture the current parent span per-request\n if (data.middleware?.index === 0) {\n const activeSpan = getActiveSpan();\n if (activeSpan) {\n requestParentSpans.set(data.request, activeSpan);\n }\n }\n\n const parsedUrl = data.request._url ? parseStringToURLObject(data.request._url.href) : undefined;\n const [, urlAttributes] = getHttpSpanDetailsFromUrlObject(parsedUrl, 'server', 'auto.http.nitro.srvx', {\n method: data.request.method,\n });\n\n // Create span as a child of the original parent, not the previous middleware\n return startInactiveSpan({\n name: `${data.middleware?.handler.name ?? 'unknown'} - ${data.request.method} ${data.request._url?.pathname}`,\n attributes: {\n ...urlAttributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.nitro.srvx',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'middleware.nitro',\n },\n parentSpan: requestParentSpans.get(data.request) || undefined,\n });\n },\n {\n beforeSpanEnd(span, data) {\n applyResponseStatus(span, data);\n },\n },\n );\n}\n\n/**\n * Sets the parameterized route attributes on the span.\n */\nfunction setParameterizedRouteAttributes(span: Span, event: H3TracingRequestEvent['event']): void {\n const rootSpan = getRootSpan(span);\n if (!rootSpan) {\n return;\n }\n\n const matchedRoutePath = getParameterizedRoute(event);\n if (!matchedRoutePath) {\n return;\n }\n\n rootSpan.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n 'http.route': matchedRoutePath,\n });\n\n const params = event.context?.params;\n\n if (isObjectLike(params)) {\n Object.entries(params).forEach(([key, value]) => {\n // Based on this convention: https://getsentry.github.io/sentry-conventions/generated/attributes/url.html#urlpathparameterkey\n rootSpan.setAttributes({\n [`url.path.parameter.${key}`]: String(value),\n [`params.${key}`]: String(value),\n });\n });\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"captureTracingEvents.js","sources":["../../../../src/runtime/hooks/captureTracingEvents.ts"],"sourcesContent":["import * as dc from 'node:diagnostics_channel';\nimport { SENTRY_OP } from '@sentry/conventions/attributes';\nimport { WEB_SERVER_HTTP_SERVER_SPAN_OP, WEB_SERVER_MIDDLEWARE_SPAN_OP } from '@sentry/conventions/op';\nimport {\n isObjectLike,\n getActiveSpan,\n getClient,\n getHttpSpanDetailsFromUrlObject,\n getRootSpan,\n GLOBAL_OBJ,\n httpHeadersToSpanAttributes,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n setHttpStatus,\n type Span,\n startInactiveSpan,\n} from '@sentry/core';\nimport {\n bindTracingChannelToSpan,\n setHttpServerSpanRouteAttribute,\n type TracingChannelPayloadWithSpan,\n} from '@sentry/server-utils';\nimport type { TracingRequestEvent as H3TracingRequestEvent } from 'h3/tracing';\nimport type { RequestEvent as SrvxRequestEvent } from 'srvx/tracing';\nimport { setServerTimingHeaders } from './setServerTimingHeaders';\n\n/**\n * Global object with the trace channels\n */\nconst globalWithTraceChannels = GLOBAL_OBJ as typeof GLOBAL_OBJ & {\n __SENTRY_NITRO_HTTP_CHANNELS_INSTRUMENTED__: boolean;\n};\n\n/**\n * Captures tracing events emitted by Nitro tracing channels.\n */\nexport function captureTracingEvents(): void {\n if (globalWithTraceChannels.__SENTRY_NITRO_HTTP_CHANNELS_INSTRUMENTED__) {\n return;\n }\n\n setupH3TracingChannels();\n setupSrvxTracingChannels();\n globalWithTraceChannels.__SENTRY_NITRO_HTTP_CHANNELS_INSTRUMENTED__ = true;\n}\n\n/**\n * Extracts the HTTP status code from a tracing channel result.\n * The result is the return value of the traced handler, which is a Response for srvx\n * and may or may not be a Response for h3.\n */\nfunction getResponseStatusCode(result: unknown): number | undefined {\n if (isObjectLike(result) && 'status' in result && typeof result.status === 'number') {\n return result.status;\n }\n return undefined;\n}\n\n/** Applies the HTTP status from the traced handler's result to the span, when present. */\nfunction applyResponseStatus(span: Span, data: TracingChannelPayloadWithSpan<{ result?: unknown }>): void {\n const statusCode = getResponseStatusCode(data.result);\n if (statusCode !== undefined) {\n setHttpStatus(span, statusCode);\n }\n}\n\n/**\n * Extracts the parameterized route pattern from the h3 event context.\n */\nfunction getParameterizedRoute(event: H3TracingRequestEvent['event']): string | undefined {\n const matchedRoute = event.context?.matchedRoute;\n if (!matchedRoute) {\n return undefined;\n }\n\n const routePath = matchedRoute.route;\n\n // Skip catch-all routes as they're not useful for transaction grouping\n if (!routePath || routePath === '/**') {\n return undefined;\n }\n\n return routePath;\n}\n\nfunction setupH3TracingChannels(): void {\n // Bail if this is not available\n if (!dc.tracingChannel) {\n return;\n }\n\n const { channel: h3Channel } = bindTracingChannelToSpan(\n dc.tracingChannel<H3TracingRequestEvent>('h3.request'),\n data => {\n const parsedUrl = parseStringToURLObject(data.event.url.href);\n const routePattern = getParameterizedRoute(data.event);\n\n const [spanName, urlAttributes] = getHttpSpanDetailsFromUrlObject(\n parsedUrl,\n 'server',\n 'auto.http.nitro.h3',\n { method: data.event.req.method },\n routePattern,\n );\n\n const span = startInactiveSpan({\n name: spanName,\n attributes: {\n ...urlAttributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.nitro.h3',\n [SENTRY_OP]: data?.type === 'middleware' ? WEB_SERVER_MIDDLEWARE_SPAN_OP : WEB_SERVER_HTTP_SERVER_SPAN_OP,\n },\n });\n\n setParameterizedRouteAttributes(span, data.event);\n\n return span;\n },\n {\n captureError: () => ({\n mechanism: {\n handled: false,\n type: 'auto.http.nitro.onTraceError',\n },\n }),\n beforeSpanEnd(span, data) {\n applyResponseStatus(span, data);\n\n // Update the root span (srvx transaction) with the parameterized route name.\n // The srvx span is created before h3 resolves the route, so it initially has the raw URL.\n // Note: data.type is always 'middleware' here regardless of handler type, so we rely on\n // getParameterizedRoute() to filter out catch-all routes instead.\n const routePattern = getParameterizedRoute(data.event);\n if (routePattern) {\n setHttpServerSpanRouteAttribute(routePattern);\n }\n },\n },\n );\n\n h3Channel.subscribe({\n start: (data: H3TracingRequestEvent) => {\n setServerTimingHeaders(data.event);\n },\n });\n}\n\nfunction setupSrvxTracingChannels(): void {\n if (!dc.tracingChannel) {\n return;\n }\n\n // Store the parent span per-request so middleware and fetch share the same parent.\n // WeakMap ensures per-request isolation in concurrent environments and automatic cleanup.\n const requestParentSpans = new WeakMap<Request, Span>();\n\n bindTracingChannelToSpan(\n dc.tracingChannel<SrvxRequestEvent>('srvx.request'),\n data => {\n const parsedUrl = data.request._url ? parseStringToURLObject(data.request._url.href) : undefined;\n const client = getClient();\n const [spanName, urlAttributes] = getHttpSpanDetailsFromUrlObject(\n parsedUrl,\n 'server',\n 'auto.http.nitro.srvx',\n { method: data.request.method },\n undefined,\n client,\n );\n\n const headerAttributes = client\n ? httpHeadersToSpanAttributes(\n Object.fromEntries(data.request.headers.entries()),\n client.getDataCollectionOptions(),\n )\n : {};\n\n return startInactiveSpan({\n name: spanName,\n attributes: {\n ...urlAttributes,\n ...headerAttributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.nitro.srvx',\n [SENTRY_OP]: data.middleware ? WEB_SERVER_MIDDLEWARE_SPAN_OP : WEB_SERVER_HTTP_SERVER_SPAN_OP,\n 'server.port': data.server.options.port,\n },\n // Use the same parent span as middleware to make them siblings\n parentSpan: requestParentSpans.get(data.request) || undefined,\n });\n },\n {\n beforeSpanEnd(span, data) {\n applyResponseStatus(span, data);\n\n // Clean up parent span reference after the fetch handler completes (success or error).\n requestParentSpans.delete(data.request);\n },\n },\n );\n\n bindTracingChannelToSpan(\n dc.tracingChannel<SrvxRequestEvent>('srvx.middleware'),\n data => {\n // For the first middleware, capture the current parent span per-request\n if (data.middleware?.index === 0) {\n const activeSpan = getActiveSpan();\n if (activeSpan) {\n requestParentSpans.set(data.request, activeSpan);\n }\n }\n\n const parsedUrl = data.request._url ? parseStringToURLObject(data.request._url.href) : undefined;\n const [, urlAttributes] = getHttpSpanDetailsFromUrlObject(parsedUrl, 'server', 'auto.http.nitro.srvx', {\n method: data.request.method,\n });\n\n // Create span as a child of the original parent, not the previous middleware\n return startInactiveSpan({\n name: `${data.middleware?.handler.name ?? 'unknown'} - ${data.request.method} ${data.request._url?.pathname}`,\n attributes: {\n ...urlAttributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.nitro.srvx',\n [SENTRY_OP]: WEB_SERVER_MIDDLEWARE_SPAN_OP,\n },\n parentSpan: requestParentSpans.get(data.request) || undefined,\n });\n },\n {\n beforeSpanEnd(span, data) {\n applyResponseStatus(span, data);\n },\n },\n );\n}\n\n/**\n * Sets the parameterized route attributes on the span.\n */\nfunction setParameterizedRouteAttributes(span: Span, event: H3TracingRequestEvent['event']): void {\n const matchedRoutePath = getParameterizedRoute(event);\n if (!matchedRoutePath) {\n return;\n }\n\n setHttpServerSpanRouteAttribute(matchedRoutePath);\n\n const rootSpan = getRootSpan(span);\n if (!rootSpan) {\n return;\n }\n\n const params = event.context?.params;\n\n if (isObjectLike(params)) {\n Object.entries(params).forEach(([key, value]) => {\n // Based on this convention: https://getsentry.github.io/sentry-conventions/generated/attributes/url.html#urlpathparameterkey\n rootSpan.setAttributes({\n [`url.path.parameter.${key}`]: String(value),\n [`params.${key}`]: String(value),\n });\n });\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { createSentryBuildPluginManager } from '@sentry/bundler-plugin-core';
1
+ import { createSentryBuildPluginManager } from '@sentry/bundler-plugins/core';
2
2
 
3
3
  function setupSourceMaps(nitro, options, sentryEnabledSourcemaps) {
4
4
  if (shouldSkipSourcemapUpload(nitro, options)) {
@@ -1 +1 @@
1
- {"version":3,"file":"sourceMaps.js","sources":["../../src/sourceMaps.ts"],"sourcesContent":["import type { Options as BundlerPluginOptions } from '@sentry/bundler-plugin-core';\nimport { createSentryBuildPluginManager } from '@sentry/bundler-plugin-core';\nimport type { Nitro, NitroConfig } from 'nitro/types';\nimport type { SentryNitroOptions } from './config';\n\n/**\n * Registers a `compiled` hook to upload source maps after the build completes.\n */\nexport function setupSourceMaps(nitro: Nitro, options?: SentryNitroOptions, sentryEnabledSourcemaps?: boolean): void {\n // The `compiled` hook fires on EVERY rebuild during `nitro dev` watch mode.\n // nitro.options.dev is reliably set by the time module setup runs.\n if (shouldSkipSourcemapUpload(nitro, options)) {\n return;\n }\n\n nitro.hooks.hook('compiled', async (_nitro: Nitro) => {\n await handleSourceMapUpload(_nitro, options, sentryEnabledSourcemaps);\n });\n}\n\n/**\n * Determines if sourcemap uploads should be skipped.\n */\nfunction shouldSkipSourcemapUpload(nitro: Nitro, options?: SentryNitroOptions): boolean {\n return !!(\n nitro.options.dev ||\n nitro.options.preset === 'nitro-prerender' ||\n nitro.options.sourcemap === false ||\n (nitro.options.sourcemap as unknown) === 'inline' ||\n options?.sourcemaps?.disable === true\n );\n}\n\n/**\n * Handles the actual source map upload after the build completes.\n */\nasync function handleSourceMapUpload(\n nitro: Nitro,\n options?: SentryNitroOptions,\n sentryEnabledSourcemaps?: boolean,\n): Promise<void> {\n const outputDir = nitro.options.output.serverDir;\n const pluginOptions = getPluginOptions(options, sentryEnabledSourcemaps, outputDir);\n\n const sentryBuildPluginManager = createSentryBuildPluginManager(pluginOptions, {\n buildTool: 'nitro',\n loggerPrefix: '[@sentry/nitro]',\n });\n\n await sentryBuildPluginManager.telemetry.emitBundlerPluginExecutionSignal();\n await sentryBuildPluginManager.createRelease();\n\n await sentryBuildPluginManager.injectDebugIds([outputDir]);\n\n if (options?.sourcemaps?.disable !== 'disable-upload') {\n await sentryBuildPluginManager.uploadSourcemaps([outputDir], {\n // We don't prepare the artifacts because we injected debug IDs manually before\n prepareArtifacts: false,\n });\n await sentryBuildPluginManager.deleteArtifacts();\n }\n}\n\n/**\n * Normalizes the beginning of a path from e.g. ../../../ to ./\n */\nfunction normalizePath(path: string): string {\n return path.replace(/^(\\.\\.\\/)+/, './');\n}\n\n/**\n * Removes a trailing slash from a path so glob patterns can be appended cleanly.\n */\nfunction removeTrailingSlash(path: string): string {\n return path.replace(/\\/$/, '');\n}\n\n/**\n * Builds the plugin options for `createSentryBuildPluginManager` from the Sentry Nitro options.\n *\n * Only exported for testing purposes.\n */\n// oxlint-disable-next-line complexity\nexport function getPluginOptions(\n options?: SentryNitroOptions,\n sentryEnabledSourcemaps?: boolean,\n outputDir?: string,\n): BundlerPluginOptions {\n const defaultFilesToDelete =\n sentryEnabledSourcemaps && outputDir ? [`${removeTrailingSlash(outputDir)}/**/*.map`] : undefined;\n\n if (options?.debug && defaultFilesToDelete && options?.sourcemaps?.filesToDeleteAfterUpload === undefined) {\n // eslint-disable-next-line no-console\n console.log(\n `[@sentry/nitro] Setting \\`sourcemaps.filesToDeleteAfterUpload: [\"${defaultFilesToDelete[0]}\"]\\` to delete generated source maps after they were uploaded to Sentry.`,\n );\n }\n\n return {\n org: options?.org ?? process.env.SENTRY_ORG,\n project: options?.project ?? process.env.SENTRY_PROJECT,\n authToken: options?.authToken ?? process.env.SENTRY_AUTH_TOKEN,\n url: options?.sentryUrl ?? process.env.SENTRY_URL,\n headers: options?.headers,\n telemetry: options?.telemetry ?? true,\n debug: options?.debug ?? false,\n silent: options?.silent ?? false,\n errorHandler: options?.errorHandler,\n sourcemaps: {\n disable: options?.sourcemaps?.disable,\n assets: options?.sourcemaps?.assets,\n ignore: options?.sourcemaps?.ignore,\n filesToDeleteAfterUpload: options?.sourcemaps?.filesToDeleteAfterUpload ?? defaultFilesToDelete,\n rewriteSources: options?.sourcemaps?.rewriteSources ?? ((source: string) => normalizePath(source)),\n },\n release: options?.release,\n bundleSizeOptimizations: options?.bundleSizeOptimizations,\n _metaOptions: {\n telemetry: {\n metaFramework: 'nitro',\n },\n },\n };\n}\n\n/* Source map configuration rules:\n 1. User explicitly disabled source maps (sourcemap: false)\n - Keep their setting, emit a warning that errors won't be unminified in Sentry\n - We will not upload anything\n 2. User enabled source map generation (true)\n - Keep their setting (don't modify besides uploading)\n 3. User did not set source maps (undefined)\n - We enable source maps for Sentry\n - Configure `filesToDeleteAfterUpload` to clean up .map files after upload\n*/\nexport function configureSourcemapSettings(\n config: NitroConfig,\n moduleOptions?: SentryNitroOptions,\n): { sentryEnabledSourcemaps: boolean } {\n const sourcemapUploadDisabled = moduleOptions?.sourcemaps?.disable === true;\n if (sourcemapUploadDisabled) {\n return { sentryEnabledSourcemaps: false };\n }\n\n // Nitro types `sourcemap` as `boolean`, but it forwards the value to Vite which also accepts `'hidden'` and `'inline'`.\n const userSourcemap = (config as { sourcemap?: boolean | 'hidden' | 'inline' }).sourcemap;\n\n if (userSourcemap === false) {\n // eslint-disable-next-line no-console\n console.warn(\n '[@sentry/nitro] You have explicitly disabled source maps (`sourcemap: false`). Sentry will not upload source maps, and errors will not be unminified. To let Sentry handle source maps, remove the `sourcemap` option from your Nitro config, or use `sourcemaps: { disable: true }` in your Sentry options to silence this warning.',\n );\n return { sentryEnabledSourcemaps: false };\n }\n\n if (userSourcemap === 'inline') {\n // eslint-disable-next-line no-console\n console.warn(\n '[@sentry/nitro] You have set `sourcemap: \"inline\"`. Inline source maps are embedded in the output bundle, so there are no `.map` files to upload. Sentry will not upload source maps. Set `sourcemap: \"hidden\"` (or leave it unset) to let Sentry upload source maps and un-minify errors.',\n );\n return { sentryEnabledSourcemaps: false };\n }\n\n let sentryEnabledSourcemaps = false;\n if (userSourcemap === true || userSourcemap === 'hidden') {\n if (moduleOptions?.debug) {\n // eslint-disable-next-line no-console\n console.log(\n `[@sentry/nitro] Source maps are already enabled (\\`sourcemap: ${JSON.stringify(userSourcemap)}\\`). Sentry will upload them for error unminification.`,\n );\n }\n } else {\n // User did not explicitly set sourcemap, enable hidden source maps for Sentry.\n // `'hidden'` emits .map files without adding a `//# sourceMappingURL=` comment to the output, avoiding public exposure.\n (config as { sourcemap?: unknown }).sourcemap = 'hidden';\n sentryEnabledSourcemaps = true;\n if (moduleOptions?.debug) {\n // eslint-disable-next-line no-console\n console.log(\n '[@sentry/nitro] Enabled hidden source map generation for Sentry. Source map files will be deleted after upload.',\n );\n }\n }\n\n // Nitro v3 has a `sourcemapMinify` plugin that destructively deletes `sourcesContent`,\n // `x_google_ignoreList`, and clears `mappings` for any chunk containing `node_modules`.\n // This makes sourcemaps unusable for Sentry.\n config.experimental = config.experimental || {};\n config.experimental.sourcemapMinify = false;\n\n return { sentryEnabledSourcemaps };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sourceMaps.js","sources":["../../src/sourceMaps.ts"],"sourcesContent":["import type { Options as BundlerPluginOptions } from '@sentry/bundler-plugins/core';\nimport { createSentryBuildPluginManager } from '@sentry/bundler-plugins/core';\nimport type { Nitro, NitroConfig } from 'nitro/types';\nimport type { SentryNitroOptions } from './config';\n\n/**\n * Registers a `compiled` hook to upload source maps after the build completes.\n */\nexport function setupSourceMaps(nitro: Nitro, options?: SentryNitroOptions, sentryEnabledSourcemaps?: boolean): void {\n // The `compiled` hook fires on EVERY rebuild during `nitro dev` watch mode.\n // nitro.options.dev is reliably set by the time module setup runs.\n if (shouldSkipSourcemapUpload(nitro, options)) {\n return;\n }\n\n nitro.hooks.hook('compiled', async (_nitro: Nitro) => {\n await handleSourceMapUpload(_nitro, options, sentryEnabledSourcemaps);\n });\n}\n\n/**\n * Determines if sourcemap uploads should be skipped.\n */\nfunction shouldSkipSourcemapUpload(nitro: Nitro, options?: SentryNitroOptions): boolean {\n return !!(\n nitro.options.dev ||\n nitro.options.preset === 'nitro-prerender' ||\n nitro.options.sourcemap === false ||\n (nitro.options.sourcemap as unknown) === 'inline' ||\n options?.sourcemaps?.disable === true\n );\n}\n\n/**\n * Handles the actual source map upload after the build completes.\n */\nasync function handleSourceMapUpload(\n nitro: Nitro,\n options?: SentryNitroOptions,\n sentryEnabledSourcemaps?: boolean,\n): Promise<void> {\n const outputDir = nitro.options.output.serverDir;\n const pluginOptions = getPluginOptions(options, sentryEnabledSourcemaps, outputDir);\n\n const sentryBuildPluginManager = createSentryBuildPluginManager(pluginOptions, {\n buildTool: 'nitro',\n loggerPrefix: '[@sentry/nitro]',\n });\n\n await sentryBuildPluginManager.telemetry.emitBundlerPluginExecutionSignal();\n await sentryBuildPluginManager.createRelease();\n\n await sentryBuildPluginManager.injectDebugIds([outputDir]);\n\n if (options?.sourcemaps?.disable !== 'disable-upload') {\n await sentryBuildPluginManager.uploadSourcemaps([outputDir], {\n // We don't prepare the artifacts because we injected debug IDs manually before\n prepareArtifacts: false,\n });\n await sentryBuildPluginManager.deleteArtifacts();\n }\n}\n\n/**\n * Normalizes the beginning of a path from e.g. ../../../ to ./\n */\nfunction normalizePath(path: string): string {\n return path.replace(/^(\\.\\.\\/)+/, './');\n}\n\n/**\n * Removes a trailing slash from a path so glob patterns can be appended cleanly.\n */\nfunction removeTrailingSlash(path: string): string {\n return path.replace(/\\/$/, '');\n}\n\n/**\n * Builds the plugin options for `createSentryBuildPluginManager` from the Sentry Nitro options.\n *\n * Only exported for testing purposes.\n */\n// oxlint-disable-next-line complexity\nexport function getPluginOptions(\n options?: SentryNitroOptions,\n sentryEnabledSourcemaps?: boolean,\n outputDir?: string,\n): BundlerPluginOptions {\n const defaultFilesToDelete =\n sentryEnabledSourcemaps && outputDir ? [`${removeTrailingSlash(outputDir)}/**/*.map`] : undefined;\n\n if (options?.debug && defaultFilesToDelete && options?.sourcemaps?.filesToDeleteAfterUpload === undefined) {\n // eslint-disable-next-line no-console\n console.log(\n `[@sentry/nitro] Setting \\`sourcemaps.filesToDeleteAfterUpload: [\"${defaultFilesToDelete[0]}\"]\\` to delete generated source maps after they were uploaded to Sentry.`,\n );\n }\n\n return {\n org: options?.org ?? process.env.SENTRY_ORG,\n project: options?.project ?? process.env.SENTRY_PROJECT,\n authToken: options?.authToken ?? process.env.SENTRY_AUTH_TOKEN,\n url: options?.sentryUrl ?? process.env.SENTRY_URL,\n headers: options?.headers,\n telemetry: options?.telemetry ?? true,\n debug: options?.debug ?? false,\n silent: options?.silent ?? false,\n errorHandler: options?.errorHandler,\n sourcemaps: {\n disable: options?.sourcemaps?.disable,\n assets: options?.sourcemaps?.assets,\n ignore: options?.sourcemaps?.ignore,\n filesToDeleteAfterUpload: options?.sourcemaps?.filesToDeleteAfterUpload ?? defaultFilesToDelete,\n rewriteSources: options?.sourcemaps?.rewriteSources ?? ((source: string) => normalizePath(source)),\n },\n release: options?.release,\n bundleSizeOptimizations: options?.bundleSizeOptimizations,\n _metaOptions: {\n telemetry: {\n metaFramework: 'nitro',\n },\n },\n };\n}\n\n/* Source map configuration rules:\n 1. User explicitly disabled source maps (sourcemap: false)\n - Keep their setting, emit a warning that errors won't be unminified in Sentry\n - We will not upload anything\n 2. User enabled source map generation (true)\n - Keep their setting (don't modify besides uploading)\n 3. User did not set source maps (undefined)\n - We enable source maps for Sentry\n - Configure `filesToDeleteAfterUpload` to clean up .map files after upload\n*/\nexport function configureSourcemapSettings(\n config: NitroConfig,\n moduleOptions?: SentryNitroOptions,\n): { sentryEnabledSourcemaps: boolean } {\n const sourcemapUploadDisabled = moduleOptions?.sourcemaps?.disable === true;\n if (sourcemapUploadDisabled) {\n return { sentryEnabledSourcemaps: false };\n }\n\n // Nitro types `sourcemap` as `boolean`, but it forwards the value to Vite which also accepts `'hidden'` and `'inline'`.\n const userSourcemap = (config as { sourcemap?: boolean | 'hidden' | 'inline' }).sourcemap;\n\n if (userSourcemap === false) {\n // eslint-disable-next-line no-console\n console.warn(\n '[@sentry/nitro] You have explicitly disabled source maps (`sourcemap: false`). Sentry will not upload source maps, and errors will not be unminified. To let Sentry handle source maps, remove the `sourcemap` option from your Nitro config, or use `sourcemaps: { disable: true }` in your Sentry options to silence this warning.',\n );\n return { sentryEnabledSourcemaps: false };\n }\n\n if (userSourcemap === 'inline') {\n // eslint-disable-next-line no-console\n console.warn(\n '[@sentry/nitro] You have set `sourcemap: \"inline\"`. Inline source maps are embedded in the output bundle, so there are no `.map` files to upload. Sentry will not upload source maps. Set `sourcemap: \"hidden\"` (or leave it unset) to let Sentry upload source maps and un-minify errors.',\n );\n return { sentryEnabledSourcemaps: false };\n }\n\n let sentryEnabledSourcemaps = false;\n if (userSourcemap === true || userSourcemap === 'hidden') {\n if (moduleOptions?.debug) {\n // eslint-disable-next-line no-console\n console.log(\n `[@sentry/nitro] Source maps are already enabled (\\`sourcemap: ${JSON.stringify(userSourcemap)}\\`). Sentry will upload them for error unminification.`,\n );\n }\n } else {\n // User did not explicitly set sourcemap, enable hidden source maps for Sentry.\n // `'hidden'` emits .map files without adding a `//# sourceMappingURL=` comment to the output, avoiding public exposure.\n (config as { sourcemap?: unknown }).sourcemap = 'hidden';\n sentryEnabledSourcemaps = true;\n if (moduleOptions?.debug) {\n // eslint-disable-next-line no-console\n console.log(\n '[@sentry/nitro] Enabled hidden source map generation for Sentry. Source map files will be deleted after upload.',\n );\n }\n }\n\n // Nitro v3 has a `sourcemapMinify` plugin that destructively deletes `sourcesContent`,\n // `x_google_ignoreList`, and clears `mappings` for any chunk containing `node_modules`.\n // This makes sourcemaps unusable for Sentry.\n config.experimental = config.experimental || {};\n config.experimental.sourcemapMinify = false;\n\n return { sentryEnabledSourcemaps };\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"captureErrorHook.d.ts","sourceRoot":"","sources":["../../../../src/runtime/hooks/captureErrorHook.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAyBxD;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoCtG"}
1
+ {"version":3,"file":"captureErrorHook.d.ts","sourceRoot":"","sources":["../../../../src/runtime/hooks/captureErrorHook.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAyBxD;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBtG"}
@@ -1 +1 @@
1
- {"version":3,"file":"captureStorageEvents.d.ts","sourceRoot":"","sources":["../../../../src/runtime/hooks/captureStorageEvents.ts"],"names":[],"mappings":"AAsCA;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAU3C"}
1
+ {"version":3,"file":"captureStorageEvents.d.ts","sourceRoot":"","sources":["../../../../src/runtime/hooks/captureStorageEvents.ts"],"names":[],"mappings":"AA8DA;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAU3C"}
@@ -1 +1 @@
1
- {"version":3,"file":"captureTracingEvents.d.ts","sourceRoot":"","sources":["../../../../src/runtime/hooks/captureTracingEvents.ts"],"names":[],"mappings":"AA8BA;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAQ3C"}
1
+ {"version":3,"file":"captureTracingEvents.d.ts","sourceRoot":"","sources":["../../../../src/runtime/hooks/captureTracingEvents.ts"],"names":[],"mappings":"AAiCA;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAQ3C"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../src/runtime/plugins/server.ts"],"names":[],"mappings":";AAKA,wBAKG"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../src/runtime/plugins/server.ts"],"names":[],"mappings":""}
@@ -1,4 +1,4 @@
1
- import type { Options as BundlerPluginOptions } from '@sentry/bundler-plugin-core';
1
+ import type { Options as BundlerPluginOptions } from '@sentry/bundler-plugins/core';
2
2
  import type { Nitro, NitroConfig } from 'nitro/types';
3
3
  import type { SentryNitroOptions } from './config';
4
4
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"sourceMaps.d.ts","sourceRoot":"","sources":["../../src/sourceMaps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAEnF,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEnD;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,kBAAkB,EAAE,uBAAuB,CAAC,EAAE,OAAO,GAAG,IAAI,CAUnH;AA2DD;;;;GAIG;AAEH,wBAAgB,gBAAgB,CAC9B,OAAO,CAAC,EAAE,kBAAkB,EAC5B,uBAAuB,CAAC,EAAE,OAAO,EACjC,SAAS,CAAC,EAAE,MAAM,GACjB,oBAAoB,CAoCtB;AAYD,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,WAAW,EACnB,aAAa,CAAC,EAAE,kBAAkB,GACjC;IAAE,uBAAuB,EAAE,OAAO,CAAA;CAAE,CAqDtC"}
1
+ {"version":3,"file":"sourceMaps.d.ts","sourceRoot":"","sources":["../../src/sourceMaps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEpF,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEnD;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,kBAAkB,EAAE,uBAAuB,CAAC,EAAE,OAAO,GAAG,IAAI,CAUnH;AA2DD;;;;GAIG;AAEH,wBAAgB,gBAAgB,CAC9B,OAAO,CAAC,EAAE,kBAAkB,EAC5B,uBAAuB,CAAC,EAAE,OAAO,EACjC,SAAS,CAAC,EAAE,MAAM,GACjB,oBAAoB,CAoCtB;AAYD,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,WAAW,EACnB,aAAa,CAAC,EAAE,kBAAkB,GACjC;IAAE,uBAAuB,EAAE,OAAO,CAAA;CAAE,CAqDtC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/nitro",
3
- "version": "10.68.0",
3
+ "version": "11.0.0-alpha.0",
4
4
  "description": "Official Sentry SDK for Nitro",
5
5
  "repository": "git://github.com/getsentry/sentry-javascript.git",
6
6
  "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/nitro",
@@ -14,7 +14,7 @@
14
14
  "error-tracking"
15
15
  ],
16
16
  "engines": {
17
- "node": ">=18.19.1"
17
+ "node": ">=20.19.0 <22.0.0 || >=22.12.0 <23.0.0 || >=23.2.0"
18
18
  },
19
19
  "files": [
20
20
  "/build"
@@ -35,10 +35,11 @@
35
35
  "nitro": ">=3.0.0-0 <4.0.0 || 3.0.260311-beta || 3.0.260415-beta"
36
36
  },
37
37
  "dependencies": {
38
- "@sentry/bundler-plugin-core": "^5.3.0",
39
- "@sentry/core": "10.68.0",
40
- "@sentry/node": "10.68.0",
41
- "@sentry/server-utils": "10.68.0"
38
+ "@sentry/bundler-plugins": "11.0.0-alpha.0",
39
+ "@sentry/conventions": "^0.16.0",
40
+ "@sentry/core": "11.0.0-alpha.0",
41
+ "@sentry/node": "11.0.0-alpha.0",
42
+ "@sentry/server-utils": "11.0.0-alpha.0"
42
43
  },
43
44
  "devDependencies": {
44
45
  "nitro": "^3.0.260415-beta",
@@ -56,8 +57,8 @@
56
57
  "build:types:watch": "tsc -p tsconfig.types.json --watch",
57
58
  "build:tarball": "npm pack",
58
59
  "clean": "rimraf build coverage sentry-nitro-*.tgz",
59
- "lint": "OXLINT_TSGOLINT_DANGEROUSLY_SUPPRESS_PROGRAM_DIAGNOSTICS=true oxlint . --type-aware",
60
- "lint:fix": "OXLINT_TSGOLINT_DANGEROUSLY_SUPPRESS_PROGRAM_DIAGNOSTICS=true oxlint . --fix --type-aware",
60
+ "lint": "oxlint . --type-aware",
61
+ "lint:fix": "oxlint . --fix --type-aware",
61
62
  "lint:es-compatibility": "es-check es2022 ./build/esm/*.js --module",
62
63
  "test": "vitest run",
63
64
  "test:watch": "vitest --watch",