@sentry/tanstackstart-react 10.53.0 → 10.54.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.
Files changed (58) hide show
  1. package/build/cjs/client/index.js +5 -26
  2. package/build/cjs/client/index.js.map +1 -1
  3. package/build/cjs/client/sdk.js +2 -9
  4. package/build/cjs/client/sdk.js.map +1 -1
  5. package/build/cjs/client/tunnelRoute.js +2 -13
  6. package/build/cjs/client/tunnelRoute.js.map +1 -1
  7. package/build/cjs/server/globalMiddleware.js +7 -21
  8. package/build/cjs/server/globalMiddleware.js.map +1 -1
  9. package/build/cjs/server/index.js +8 -29
  10. package/build/cjs/server/index.js.map +1 -1
  11. package/build/cjs/server/middleware.js +10 -66
  12. package/build/cjs/server/middleware.js.map +1 -1
  13. package/build/cjs/server/sdk.js +2 -7
  14. package/build/cjs/server/sdk.js.map +1 -1
  15. package/build/cjs/server/tunnelRoute.js +11 -31
  16. package/build/cjs/server/tunnelRoute.js.map +1 -1
  17. package/build/cjs/server/utils.js +5 -17
  18. package/build/cjs/server/utils.js.map +1 -1
  19. package/build/cjs/server/wrapFetchWithSentry.js +9 -38
  20. package/build/cjs/server/wrapFetchWithSentry.js.map +1 -1
  21. package/build/cjs/vite/autoInstrumentMiddleware.js +15 -97
  22. package/build/cjs/vite/autoInstrumentMiddleware.js.map +1 -1
  23. package/build/cjs/vite/sentryTanstackStart.js +3 -40
  24. package/build/cjs/vite/sentryTanstackStart.js.map +1 -1
  25. package/build/cjs/vite/sourceMaps.js +30 -76
  26. package/build/cjs/vite/sourceMaps.js.map +1 -1
  27. package/build/cjs/vite/tunnelRoute.js +30 -63
  28. package/build/cjs/vite/tunnelRoute.js.map +1 -1
  29. package/build/esm/client/index.js +5 -26
  30. package/build/esm/client/index.js.map +1 -1
  31. package/build/esm/client/sdk.js +2 -9
  32. package/build/esm/client/sdk.js.map +1 -1
  33. package/build/esm/client/tunnelRoute.js +2 -13
  34. package/build/esm/client/tunnelRoute.js.map +1 -1
  35. package/build/esm/package.json +1 -1
  36. package/build/esm/server/globalMiddleware.js +7 -21
  37. package/build/esm/server/globalMiddleware.js.map +1 -1
  38. package/build/esm/server/index.js +8 -29
  39. package/build/esm/server/index.js.map +1 -1
  40. package/build/esm/server/middleware.js +10 -66
  41. package/build/esm/server/middleware.js.map +1 -1
  42. package/build/esm/server/sdk.js +2 -7
  43. package/build/esm/server/sdk.js.map +1 -1
  44. package/build/esm/server/tunnelRoute.js +11 -31
  45. package/build/esm/server/tunnelRoute.js.map +1 -1
  46. package/build/esm/server/utils.js +5 -17
  47. package/build/esm/server/utils.js.map +1 -1
  48. package/build/esm/server/wrapFetchWithSentry.js +9 -38
  49. package/build/esm/server/wrapFetchWithSentry.js.map +1 -1
  50. package/build/esm/vite/autoInstrumentMiddleware.js +15 -97
  51. package/build/esm/vite/autoInstrumentMiddleware.js.map +1 -1
  52. package/build/esm/vite/sentryTanstackStart.js +3 -40
  53. package/build/esm/vite/sentryTanstackStart.js.map +1 -1
  54. package/build/esm/vite/sourceMaps.js +30 -76
  55. package/build/esm/vite/sourceMaps.js.map +1 -1
  56. package/build/esm/vite/tunnelRoute.js +30 -63
  57. package/build/esm/vite/tunnelRoute.js.map +1 -1
  58. package/package.json +5 -5
@@ -2,109 +2,53 @@ import { addNonEnumerableProperty } from '@sentry/core';
2
2
  import { getActiveSpan, startSpanManual, withActiveSpan } from '@sentry/node';
3
3
  import { getMiddlewareSpanOptions } from './utils.js';
4
4
 
5
- const SENTRY_WRAPPED = '__SENTRY_WRAPPED__';
6
- const SENTRY_INTERNAL = '__SENTRY_INTERNAL__';
7
-
8
- /**
9
- * Creates a proxy for the next function that ends the current span and restores the parent span.
10
- * This ensures that subsequent middleware spans are children of the root span, not nested children.
11
- */
12
- function getNextProxy(
13
- next,
14
- span,
15
- prevSpan,
16
- nextState,
17
- ) {
5
+ const SENTRY_WRAPPED = "__SENTRY_WRAPPED__";
6
+ const SENTRY_INTERNAL = "__SENTRY_INTERNAL__";
7
+ function getNextProxy(next, span, prevSpan, nextState) {
18
8
  return new Proxy(next, {
19
9
  apply: (originalNext, thisArgNext, argsNext) => {
20
10
  nextState.called = true;
21
11
  span.end();
22
-
23
12
  if (prevSpan) {
24
13
  return withActiveSpan(prevSpan, () => {
25
14
  return Reflect.apply(originalNext, thisArgNext, argsNext);
26
15
  });
27
16
  }
28
-
29
17
  return Reflect.apply(originalNext, thisArgNext, argsNext);
30
- },
18
+ }
31
19
  });
32
20
  }
33
-
34
- /**
35
- * Wraps a TanStack Start middleware with Sentry instrumentation to create spans.
36
- */
37
- function wrapMiddlewareWithSentry(
38
- middleware,
39
- options,
40
- ) {
41
- if (
42
- (middleware )[SENTRY_WRAPPED] ||
43
- (middleware )[SENTRY_INTERNAL]
44
- ) {
45
- // already instrumented or internal Sentry middleware
21
+ function wrapMiddlewareWithSentry(middleware, options) {
22
+ if (middleware[SENTRY_WRAPPED] || middleware[SENTRY_INTERNAL]) {
46
23
  return middleware;
47
24
  }
48
-
49
- // instrument server middleware
50
25
  if (middleware.options?.server) {
51
26
  middleware.options.server = new Proxy(middleware.options.server, {
52
27
  apply: (originalServer, thisArgServer, argsServer) => {
53
28
  const prevSpan = getActiveSpan();
54
-
55
29
  return startSpanManual(getMiddlewareSpanOptions(options.name), async (span) => {
56
30
  const nextState = { called: false };
57
-
58
- // The server function receives { next, context, request } as first argument
59
- // Users call next() inside their middleware to move down the middleware chain. We proxy next() to end the span when it is called.
60
- const middlewareArgs = argsServer[0] ;
61
- if (middlewareArgs && typeof middlewareArgs === 'object' && typeof middlewareArgs.next === 'function') {
31
+ const middlewareArgs = argsServer[0];
32
+ if (middlewareArgs && typeof middlewareArgs === "object" && typeof middlewareArgs.next === "function") {
62
33
  middlewareArgs.next = getNextProxy(middlewareArgs.next, span, prevSpan, nextState);
63
34
  }
64
-
65
35
  try {
66
36
  const result = await originalServer.apply(thisArgServer, argsServer);
67
-
68
- // End span here if next() wasn't called, else we already ended it in next()
69
37
  if (!nextState.called) {
70
38
  span.end();
71
39
  }
72
-
73
40
  return result;
74
41
  } catch (e) {
75
42
  span.end();
76
43
  throw e;
77
44
  }
78
45
  });
79
- },
46
+ }
80
47
  });
81
-
82
- // mark as instrumented
83
- addNonEnumerableProperty(middleware , SENTRY_WRAPPED, true);
48
+ addNonEnumerableProperty(middleware, SENTRY_WRAPPED, true);
84
49
  }
85
-
86
50
  return middleware;
87
51
  }
88
-
89
- /**
90
- * Wraps multiple TanStack Start middlewares with Sentry instrumentation.
91
- * Object keys are used as span names to avoid users having to specify this manually.
92
- *
93
- * @example
94
- * ```ts
95
- * import { wrapMiddlewaresWithSentry } from '@sentry/tanstackstart-react';
96
- *
97
- * const wrappedMiddlewares = wrapMiddlewaresWithSentry({
98
- * authMiddleware,
99
- * loggingMiddleware,
100
- * });
101
- *
102
- * createServerFn().middleware(wrappedMiddlewares)
103
- * ```
104
- *
105
- * @param middlewares - An object containing middlewares
106
- * @returns An array of wrapped middlewares
107
- */
108
52
  function wrapMiddlewaresWithSentry(middlewares) {
109
53
  return Object.entries(middlewares).map(([name, middleware]) => {
110
54
  return wrapMiddlewareWithSentry(middleware, { name });
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.js","sources":["../../../src/server/middleware.ts"],"sourcesContent":["import { addNonEnumerableProperty } from '@sentry/core';\nimport type { Span } from '@sentry/node';\nimport { getActiveSpan, startSpanManual, withActiveSpan } from '@sentry/node';\nimport type { MiddlewareWrapperOptions, TanStackMiddlewareBase } from '../common/types';\nimport { getMiddlewareSpanOptions } from './utils';\n\nconst SENTRY_WRAPPED = '__SENTRY_WRAPPED__';\nexport const SENTRY_INTERNAL = '__SENTRY_INTERNAL__';\n\n/**\n * Creates a proxy for the next function that ends the current span and restores the parent span.\n * This ensures that subsequent middleware spans are children of the root span, not nested children.\n */\nfunction getNextProxy<T extends (...args: unknown[]) => unknown>(\n next: T,\n span: Span,\n prevSpan: Span | undefined,\n nextState: { called: boolean },\n): T {\n return new Proxy(next, {\n apply: (originalNext, thisArgNext, argsNext) => {\n nextState.called = true;\n span.end();\n\n if (prevSpan) {\n return withActiveSpan(prevSpan, () => {\n return Reflect.apply(originalNext, thisArgNext, argsNext);\n });\n }\n\n return Reflect.apply(originalNext, thisArgNext, argsNext);\n },\n });\n}\n\n/**\n * Wraps a TanStack Start middleware with Sentry instrumentation to create spans.\n */\nfunction wrapMiddlewareWithSentry<T extends TanStackMiddlewareBase>(\n middleware: T,\n options: MiddlewareWrapperOptions,\n): T {\n if (\n (middleware as TanStackMiddlewareBase & { [SENTRY_WRAPPED]?: boolean })[SENTRY_WRAPPED] ||\n (middleware as TanStackMiddlewareBase & { [SENTRY_INTERNAL]?: boolean })[SENTRY_INTERNAL]\n ) {\n // already instrumented or internal Sentry middleware\n return middleware;\n }\n\n // instrument server middleware\n if (middleware.options?.server) {\n middleware.options.server = new Proxy(middleware.options.server, {\n apply: (originalServer, thisArgServer, argsServer) => {\n const prevSpan = getActiveSpan();\n\n return startSpanManual(getMiddlewareSpanOptions(options.name), async (span: Span) => {\n const nextState = { called: false };\n\n // The server function receives { next, context, request } as first argument\n // Users call next() inside their middleware to move down the middleware chain. We proxy next() to end the span when it is called.\n const middlewareArgs = argsServer[0] as { next?: (...args: unknown[]) => unknown } | undefined;\n if (middlewareArgs && typeof middlewareArgs === 'object' && typeof middlewareArgs.next === 'function') {\n middlewareArgs.next = getNextProxy(middlewareArgs.next, span, prevSpan, nextState);\n }\n\n try {\n const result = await originalServer.apply(thisArgServer, argsServer);\n\n // End span here if next() wasn't called, else we already ended it in next()\n if (!nextState.called) {\n span.end();\n }\n\n return result;\n } catch (e) {\n span.end();\n throw e;\n }\n });\n },\n });\n\n // mark as instrumented\n addNonEnumerableProperty(middleware as unknown as Record<string, unknown>, SENTRY_WRAPPED, true);\n }\n\n return middleware;\n}\n\n/**\n * Wraps multiple TanStack Start middlewares with Sentry instrumentation.\n * Object keys are used as span names to avoid users having to specify this manually.\n *\n * @example\n * ```ts\n * import { wrapMiddlewaresWithSentry } from '@sentry/tanstackstart-react';\n *\n * const wrappedMiddlewares = wrapMiddlewaresWithSentry({\n * authMiddleware,\n * loggingMiddleware,\n * });\n *\n * createServerFn().middleware(wrappedMiddlewares)\n * ```\n *\n * @param middlewares - An object containing middlewares\n * @returns An array of wrapped middlewares\n */\nexport function wrapMiddlewaresWithSentry<T extends TanStackMiddlewareBase>(middlewares: Record<string, T>): T[] {\n return Object.entries(middlewares).map(([name, middleware]) => {\n return wrapMiddlewareWithSentry(middleware, { name });\n });\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"middleware.js","sources":["../../../src/server/middleware.ts"],"sourcesContent":["import { addNonEnumerableProperty } from '@sentry/core';\nimport type { Span } from '@sentry/node';\nimport { getActiveSpan, startSpanManual, withActiveSpan } from '@sentry/node';\nimport type { MiddlewareWrapperOptions, TanStackMiddlewareBase } from '../common/types';\nimport { getMiddlewareSpanOptions } from './utils';\n\nconst SENTRY_WRAPPED = '__SENTRY_WRAPPED__';\nexport const SENTRY_INTERNAL = '__SENTRY_INTERNAL__';\n\n/**\n * Creates a proxy for the next function that ends the current span and restores the parent span.\n * This ensures that subsequent middleware spans are children of the root span, not nested children.\n */\nfunction getNextProxy<T extends (...args: unknown[]) => unknown>(\n next: T,\n span: Span,\n prevSpan: Span | undefined,\n nextState: { called: boolean },\n): T {\n return new Proxy(next, {\n apply: (originalNext, thisArgNext, argsNext) => {\n nextState.called = true;\n span.end();\n\n if (prevSpan) {\n return withActiveSpan(prevSpan, () => {\n return Reflect.apply(originalNext, thisArgNext, argsNext);\n });\n }\n\n return Reflect.apply(originalNext, thisArgNext, argsNext);\n },\n });\n}\n\n/**\n * Wraps a TanStack Start middleware with Sentry instrumentation to create spans.\n */\nfunction wrapMiddlewareWithSentry<T extends TanStackMiddlewareBase>(\n middleware: T,\n options: MiddlewareWrapperOptions,\n): T {\n if (\n (middleware as TanStackMiddlewareBase & { [SENTRY_WRAPPED]?: boolean })[SENTRY_WRAPPED] ||\n (middleware as TanStackMiddlewareBase & { [SENTRY_INTERNAL]?: boolean })[SENTRY_INTERNAL]\n ) {\n // already instrumented or internal Sentry middleware\n return middleware;\n }\n\n // instrument server middleware\n if (middleware.options?.server) {\n middleware.options.server = new Proxy(middleware.options.server, {\n apply: (originalServer, thisArgServer, argsServer) => {\n const prevSpan = getActiveSpan();\n\n return startSpanManual(getMiddlewareSpanOptions(options.name), async (span: Span) => {\n const nextState = { called: false };\n\n // The server function receives { next, context, request } as first argument\n // Users call next() inside their middleware to move down the middleware chain. We proxy next() to end the span when it is called.\n const middlewareArgs = argsServer[0] as { next?: (...args: unknown[]) => unknown } | undefined;\n if (middlewareArgs && typeof middlewareArgs === 'object' && typeof middlewareArgs.next === 'function') {\n middlewareArgs.next = getNextProxy(middlewareArgs.next, span, prevSpan, nextState);\n }\n\n try {\n const result = await originalServer.apply(thisArgServer, argsServer);\n\n // End span here if next() wasn't called, else we already ended it in next()\n if (!nextState.called) {\n span.end();\n }\n\n return result;\n } catch (e) {\n span.end();\n throw e;\n }\n });\n },\n });\n\n // mark as instrumented\n addNonEnumerableProperty(middleware as unknown as Record<string, unknown>, SENTRY_WRAPPED, true);\n }\n\n return middleware;\n}\n\n/**\n * Wraps multiple TanStack Start middlewares with Sentry instrumentation.\n * Object keys are used as span names to avoid users having to specify this manually.\n *\n * @example\n * ```ts\n * import { wrapMiddlewaresWithSentry } from '@sentry/tanstackstart-react';\n *\n * const wrappedMiddlewares = wrapMiddlewaresWithSentry({\n * authMiddleware,\n * loggingMiddleware,\n * });\n *\n * createServerFn().middleware(wrappedMiddlewares)\n * ```\n *\n * @param middlewares - An object containing middlewares\n * @returns An array of wrapped middlewares\n */\nexport function wrapMiddlewaresWithSentry<T extends TanStackMiddlewareBase>(middlewares: Record<string, T>): T[] {\n return Object.entries(middlewares).map(([name, middleware]) => {\n return wrapMiddlewareWithSentry(middleware, { name });\n });\n}\n"],"names":[],"mappings":";;;;AAMA,MAAM,cAAA,GAAiB,oBAAA;AAChB,MAAM,eAAA,GAAkB;AAM/B,SAAS,YAAA,CACP,IAAA,EACA,IAAA,EACA,QAAA,EACA,SAAA,EACG;AACH,EAAA,OAAO,IAAI,MAAM,IAAA,EAAM;AAAA,IACrB,KAAA,EAAO,CAAC,YAAA,EAAc,WAAA,EAAa,QAAA,KAAa;AAC9C,MAAA,SAAA,CAAU,MAAA,GAAS,IAAA;AACnB,MAAA,IAAA,CAAK,GAAA,EAAI;AAET,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,OAAO,cAAA,CAAe,UAAU,MAAM;AACpC,UAAA,OAAO,OAAA,CAAQ,KAAA,CAAM,YAAA,EAAc,WAAA,EAAa,QAAQ,CAAA;AAAA,QAC1D,CAAC,CAAA;AAAA,MACH;AAEA,MAAA,OAAO,OAAA,CAAQ,KAAA,CAAM,YAAA,EAAc,WAAA,EAAa,QAAQ,CAAA;AAAA,IAC1D;AAAA,GACD,CAAA;AACH;AAKA,SAAS,wBAAA,CACP,YACA,OAAA,EACG;AACH,EAAA,IACG,UAAA,CAAuE,cAAc,CAAA,IACrF,UAAA,CAAwE,eAAe,CAAA,EACxF;AAEA,IAAA,OAAO,UAAA;AAAA,EACT;AAGA,EAAA,IAAI,UAAA,CAAW,SAAS,MAAA,EAAQ;AAC9B,IAAA,UAAA,CAAW,QAAQ,MAAA,GAAS,IAAI,KAAA,CAAM,UAAA,CAAW,QAAQ,MAAA,EAAQ;AAAA,MAC/D,KAAA,EAAO,CAAC,cAAA,EAAgB,aAAA,EAAe,UAAA,KAAe;AACpD,QAAA,MAAM,WAAW,aAAA,EAAc;AAE/B,QAAA,OAAO,gBAAgB,wBAAA,CAAyB,OAAA,CAAQ,IAAI,CAAA,EAAG,OAAO,IAAA,KAAe;AACnF,UAAA,MAAM,SAAA,GAAY,EAAE,MAAA,EAAQ,KAAA,EAAM;AAIlC,UAAA,MAAM,cAAA,GAAiB,WAAW,CAAC,CAAA;AACnC,UAAA,IAAI,kBAAkB,OAAO,cAAA,KAAmB,YAAY,OAAO,cAAA,CAAe,SAAS,UAAA,EAAY;AACrG,YAAA,cAAA,CAAe,OAAO,YAAA,CAAa,cAAA,CAAe,IAAA,EAAM,IAAA,EAAM,UAAU,SAAS,CAAA;AAAA,UACnF;AAEA,UAAA,IAAI;AACF,YAAA,MAAM,MAAA,GAAS,MAAM,cAAA,CAAe,KAAA,CAAM,eAAe,UAAU,CAAA;AAGnE,YAAA,IAAI,CAAC,UAAU,MAAA,EAAQ;AACrB,cAAA,IAAA,CAAK,GAAA,EAAI;AAAA,YACX;AAEA,YAAA,OAAO,MAAA;AAAA,UACT,SAAS,CAAA,EAAG;AACV,YAAA,IAAA,CAAK,GAAA,EAAI;AACT,YAAA,MAAM,CAAA;AAAA,UACR;AAAA,QACF,CAAC,CAAA;AAAA,MACH;AAAA,KACD,CAAA;AAGD,IAAA,wBAAA,CAAyB,UAAA,EAAkD,gBAAgB,IAAI,CAAA;AAAA,EACjG;AAEA,EAAA,OAAO,UAAA;AACT;AAqBO,SAAS,0BAA4D,WAAA,EAAqC;AAC/G,EAAA,OAAO,MAAA,CAAO,QAAQ,WAAW,CAAA,CAAE,IAAI,CAAC,CAAC,IAAA,EAAM,UAAU,CAAA,KAAM;AAC7D,IAAA,OAAO,wBAAA,CAAyB,UAAA,EAAY,EAAE,IAAA,EAAM,CAAA;AAAA,EACtD,CAAC,CAAA;AACH;;;;"}
@@ -1,17 +1,12 @@
1
1
  import { applySdkMetadata } from '@sentry/core';
2
2
  import { getDefaultIntegrations, init as init$1 } from '@sentry/node';
3
3
 
4
- /**
5
- * Initializes the server side of the TanStack Start React SDK
6
- */
7
4
  function init(options) {
8
5
  const sentryOptions = {
9
6
  defaultIntegrations: [...getDefaultIntegrations(options)],
10
- ...options,
7
+ ...options
11
8
  };
12
-
13
- applySdkMetadata(sentryOptions, 'tanstackstart-react', ['tanstackstart-react', 'node']);
14
-
9
+ applySdkMetadata(sentryOptions, "tanstackstart-react", ["tanstackstart-react", "node"]);
15
10
  return init$1(sentryOptions);
16
11
  }
17
12
 
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.js","sources":["../../../src/server/sdk.ts"],"sourcesContent":["import { applySdkMetadata } from '@sentry/core';\nimport type { NodeClient, NodeOptions } from '@sentry/node';\nimport { getDefaultIntegrations as getDefaultNodeIntegrations, init as initNodeSdk } from '@sentry/node';\n\n/**\n * Initializes the server side of the TanStack Start React SDK\n */\nexport function init(options: NodeOptions): NodeClient | undefined {\n const sentryOptions: NodeOptions = {\n defaultIntegrations: [...getDefaultNodeIntegrations(options)],\n ...options,\n };\n\n applySdkMetadata(sentryOptions, 'tanstackstart-react', ['tanstackstart-react', 'node']);\n\n return initNodeSdk(sentryOptions);\n}\n"],"names":["getDefaultNodeIntegrations","initNodeSdk"],"mappings":";;;AAIA;AACA;AACA;AACO,SAAS,IAAI,CAAC,OAAO,EAAuC;AACnE,EAAE,MAAM,aAAa,GAAgB;AACrC,IAAI,mBAAmB,EAAE,CAAC,GAAGA,sBAA0B,CAAC,OAAO,CAAC,CAAC;AACjE,IAAI,GAAG,OAAO;AACd,GAAG;;AAEH,EAAE,gBAAgB,CAAC,aAAa,EAAE,qBAAqB,EAAE,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;;AAEzF,EAAE,OAAOC,MAAW,CAAC,aAAa,CAAC;AACnC;;;;"}
1
+ {"version":3,"file":"sdk.js","sources":["../../../src/server/sdk.ts"],"sourcesContent":["import { applySdkMetadata } from '@sentry/core';\nimport type { NodeClient, NodeOptions } from '@sentry/node';\nimport { getDefaultIntegrations as getDefaultNodeIntegrations, init as initNodeSdk } from '@sentry/node';\n\n/**\n * Initializes the server side of the TanStack Start React SDK\n */\nexport function init(options: NodeOptions): NodeClient | undefined {\n const sentryOptions: NodeOptions = {\n defaultIntegrations: [...getDefaultNodeIntegrations(options)],\n ...options,\n };\n\n applySdkMetadata(sentryOptions, 'tanstackstart-react', ['tanstackstart-react', 'node']);\n\n return initNodeSdk(sentryOptions);\n}\n"],"names":["getDefaultNodeIntegrations","initNodeSdk"],"mappings":";;;AAOO,SAAS,KAAK,OAAA,EAA8C;AACjE,EAAA,MAAM,aAAA,GAA6B;AAAA,IACjC,mBAAA,EAAqB,CAAC,GAAGA,sBAAA,CAA2B,OAAO,CAAC,CAAA;AAAA,IAC5D,GAAG;AAAA,GACL;AAEA,EAAA,gBAAA,CAAiB,aAAA,EAAe,qBAAA,EAAuB,CAAC,qBAAA,EAAuB,MAAM,CAAC,CAAA;AAEtF,EAAA,OAAOC,OAAY,aAAa,CAAA;AAClC;;;;"}
@@ -1,47 +1,27 @@
1
1
  import { getClient, dsnToString, handleTunnelRequest } from '@sentry/core';
2
2
 
3
- /**
4
- * Creates a TanStack Start server route configuration for tunneling Sentry envelopes.
5
- *
6
- * @example
7
- * ```ts
8
- * import { createFileRoute } from '@tanstack/react-router';
9
- * import * as Sentry from '@sentry/tanstackstart-react';
10
- *
11
- * export const Route = createFileRoute('/monitoring')({
12
- * server: Sentry.createSentryTunnelRoute({
13
- * allowedDsns: ['https://public@o0.ingest.sentry.io/0'],
14
- * }),
15
- * });
16
- * ```
17
- */
18
3
  function createSentryTunnelRoute(options) {
19
4
  return {
20
5
  handlers: {
21
6
  POST: async ({ request }) => {
22
- const allowedDsnsFromOptions = options.allowedDsns?.length ? options.allowedDsns : undefined;
23
-
24
- const allowedDsns =
25
- allowedDsnsFromOptions ??
26
- (() => {
27
- const client = getClient();
28
- const dsn = client?.getDsn();
29
- return dsn ? [dsnToString(dsn)] : undefined;
30
- })();
31
-
7
+ const allowedDsnsFromOptions = options.allowedDsns?.length ? options.allowedDsns : void 0;
8
+ const allowedDsns = allowedDsnsFromOptions ?? (() => {
9
+ const client = getClient();
10
+ const dsn = client?.getDsn();
11
+ return dsn ? [dsnToString(dsn)] : void 0;
12
+ })();
32
13
  if (!allowedDsns) {
33
14
  return new Response(
34
- 'Tunnel route requires Sentry server SDK initialized with a DSN, or pass allowedDsns explicitly.',
35
- { status: 500 },
15
+ "Tunnel route requires Sentry server SDK initialized with a DSN, or pass allowedDsns explicitly.",
16
+ { status: 500 }
36
17
  );
37
18
  }
38
-
39
19
  return handleTunnelRequest({
40
20
  request,
41
- allowedDsns,
21
+ allowedDsns
42
22
  });
43
- },
44
- },
23
+ }
24
+ }
45
25
  };
46
26
  }
47
27
 
@@ -1 +1 @@
1
- {"version":3,"file":"tunnelRoute.js","sources":["../../../src/server/tunnelRoute.ts"],"sourcesContent":["import { dsnToString, getClient, handleTunnelRequest } from '@sentry/core';\n\nexport interface CreateSentryTunnelRouteOptions {\n allowedDsns?: string[];\n}\n\ntype SentryTunnelRouteHandlerContext = {\n request: Request;\n};\n\ntype SentryTunnelRoute = {\n handlers: {\n POST: (context: SentryTunnelRouteHandlerContext) => Promise<Response>;\n };\n};\n\n/**\n * Creates a TanStack Start server route configuration for tunneling Sentry envelopes.\n *\n * @example\n * ```ts\n * import { createFileRoute } from '@tanstack/react-router';\n * import * as Sentry from '@sentry/tanstackstart-react';\n *\n * export const Route = createFileRoute('/monitoring')({\n * server: Sentry.createSentryTunnelRoute({\n * allowedDsns: ['https://public@o0.ingest.sentry.io/0'],\n * }),\n * });\n * ```\n */\nexport function createSentryTunnelRoute(options: CreateSentryTunnelRouteOptions): SentryTunnelRoute {\n return {\n handlers: {\n POST: async ({ request }) => {\n const allowedDsnsFromOptions = options.allowedDsns?.length ? options.allowedDsns : undefined;\n\n const allowedDsns =\n allowedDsnsFromOptions ??\n (() => {\n const client = getClient();\n const dsn = client?.getDsn();\n return dsn ? [dsnToString(dsn)] : undefined;\n })();\n\n if (!allowedDsns) {\n return new Response(\n 'Tunnel route requires Sentry server SDK initialized with a DSN, or pass allowedDsns explicitly.',\n { status: 500 },\n );\n }\n\n return handleTunnelRequest({\n request,\n allowedDsns,\n });\n },\n },\n };\n}\n"],"names":[],"mappings":";;AAgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,uBAAuB,CAAC,OAAO,EAAqD;AACpG,EAAE,OAAO;AACT,IAAI,QAAQ,EAAE;AACd,MAAM,IAAI,EAAE,OAAO,EAAE,OAAA,EAAS,KAAK;AACnC,QAAQ,MAAM,sBAAA,GAAyB,OAAO,CAAC,WAAW,EAAE,MAAA,GAAS,OAAO,CAAC,WAAA,GAAc,SAAS;;AAEpG,QAAQ,MAAM,WAAA;AACd,UAAU,sBAAA;AACV,UAAU,CAAC,MAAM;AACjB,YAAY,MAAM,MAAA,GAAS,SAAS,EAAE;AACtC,YAAY,MAAM,GAAA,GAAM,MAAM,EAAE,MAAM,EAAE;AACxC,YAAY,OAAO,GAAA,GAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA,GAAI,SAAS;AACvD,UAAU,CAAC,GAAG;;AAEd,QAAQ,IAAI,CAAC,WAAW,EAAE;AAC1B,UAAU,OAAO,IAAI,QAAQ;AAC7B,YAAY,iGAAiG;AAC7G,YAAY,EAAE,MAAM,EAAE,GAAA,EAAK;AAC3B,WAAW;AACX,QAAQ;;AAER,QAAQ,OAAO,mBAAmB,CAAC;AACnC,UAAU,OAAO;AACjB,UAAU,WAAW;AACrB,SAAS,CAAC;AACV,MAAM,CAAC;AACP,KAAK;AACL,GAAG;AACH;;;;"}
1
+ {"version":3,"file":"tunnelRoute.js","sources":["../../../src/server/tunnelRoute.ts"],"sourcesContent":["import { dsnToString, getClient, handleTunnelRequest } from '@sentry/core';\n\nexport interface CreateSentryTunnelRouteOptions {\n allowedDsns?: string[];\n}\n\ntype SentryTunnelRouteHandlerContext = {\n request: Request;\n};\n\ntype SentryTunnelRoute = {\n handlers: {\n POST: (context: SentryTunnelRouteHandlerContext) => Promise<Response>;\n };\n};\n\n/**\n * Creates a TanStack Start server route configuration for tunneling Sentry envelopes.\n *\n * @example\n * ```ts\n * import { createFileRoute } from '@tanstack/react-router';\n * import * as Sentry from '@sentry/tanstackstart-react';\n *\n * export const Route = createFileRoute('/monitoring')({\n * server: Sentry.createSentryTunnelRoute({\n * allowedDsns: ['https://public@o0.ingest.sentry.io/0'],\n * }),\n * });\n * ```\n */\nexport function createSentryTunnelRoute(options: CreateSentryTunnelRouteOptions): SentryTunnelRoute {\n return {\n handlers: {\n POST: async ({ request }) => {\n const allowedDsnsFromOptions = options.allowedDsns?.length ? options.allowedDsns : undefined;\n\n const allowedDsns =\n allowedDsnsFromOptions ??\n (() => {\n const client = getClient();\n const dsn = client?.getDsn();\n return dsn ? [dsnToString(dsn)] : undefined;\n })();\n\n if (!allowedDsns) {\n return new Response(\n 'Tunnel route requires Sentry server SDK initialized with a DSN, or pass allowedDsns explicitly.',\n { status: 500 },\n );\n }\n\n return handleTunnelRequest({\n request,\n allowedDsns,\n });\n },\n },\n };\n}\n"],"names":[],"mappings":";;AA+BO,SAAS,wBAAwB,OAAA,EAA4D;AAClG,EAAA,OAAO;AAAA,IACL,QAAA,EAAU;AAAA,MACR,IAAA,EAAM,OAAO,EAAE,OAAA,EAAQ,KAAM;AAC3B,QAAA,MAAM,sBAAA,GAAyB,OAAA,CAAQ,WAAA,EAAa,MAAA,GAAS,QAAQ,WAAA,GAAc,MAAA;AAEnF,QAAA,MAAM,WAAA,GACJ,2BACC,MAAM;AACL,UAAA,MAAM,SAAS,SAAA,EAAU;AACzB,UAAA,MAAM,GAAA,GAAM,QAAQ,MAAA,EAAO;AAC3B,UAAA,OAAO,GAAA,GAAM,CAAC,WAAA,CAAY,GAAG,CAAC,CAAA,GAAI,MAAA;AAAA,QACpC,CAAA,GAAG;AAEL,QAAA,IAAI,CAAC,WAAA,EAAa;AAChB,UAAA,OAAO,IAAI,QAAA;AAAA,YACT,iGAAA;AAAA,YACA,EAAE,QAAQ,GAAA;AAAI,WAChB;AAAA,QACF;AAEA,QAAA,OAAO,mBAAA,CAAoB;AAAA,UACzB,OAAA;AAAA,UACA;AAAA,SACD,CAAA;AAAA,MACH;AAAA;AACF,GACF;AACF;;;;"}
@@ -1,29 +1,17 @@
1
1
  import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/node';
2
2
 
3
- /**
4
- * Extracts the SHA-256 hash from a server function pathname.
5
- * Server function pathnames are structured as `/_serverFn/<hash>`.
6
- * This function matches the pattern and returns the hash if found.
7
- *
8
- * @param pathname - the pathname of the server function
9
- * @returns the sha256 of the server function
10
- */
11
3
  function extractServerFunctionSha256(pathname) {
12
4
  const serverFnMatch = pathname.match(/\/_serverFn\/([a-f0-9]{64})/i);
13
- return serverFnMatch?.[1] ?? 'unknown';
5
+ return serverFnMatch?.[1] ?? "unknown";
14
6
  }
15
-
16
- /**
17
- * Returns span options for TanStack Start middleware spans.
18
- */
19
7
  function getMiddlewareSpanOptions(name) {
20
8
  return {
21
- op: 'middleware.tanstackstart',
9
+ op: "middleware.tanstackstart",
22
10
  name,
23
11
  attributes: {
24
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.middleware.tanstackstart',
25
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'middleware.tanstackstart',
26
- },
12
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.middleware.tanstackstart",
13
+ [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "middleware.tanstackstart"
14
+ }
27
15
  };
28
16
  }
29
17
 
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../../src/server/utils.ts"],"sourcesContent":["import type { StartSpanOptions } from '@sentry/core';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/node';\n\n/**\n * Extracts the SHA-256 hash from a server function pathname.\n * Server function pathnames are structured as `/_serverFn/<hash>`.\n * This function matches the pattern and returns the hash if found.\n *\n * @param pathname - the pathname of the server function\n * @returns the sha256 of the server function\n */\nexport function extractServerFunctionSha256(pathname: string): string {\n const serverFnMatch = pathname.match(/\\/_serverFn\\/([a-f0-9]{64})/i);\n return serverFnMatch?.[1] ?? 'unknown';\n}\n\n/**\n * Returns span options for TanStack Start middleware spans.\n */\nexport function getMiddlewareSpanOptions(name: string): StartSpanOptions {\n return {\n op: 'middleware.tanstackstart',\n name,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.middleware.tanstackstart',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'middleware.tanstackstart',\n },\n };\n}\n"],"names":[],"mappings":";;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,2BAA2B,CAAC,QAAQ,EAAkB;AACtE,EAAE,MAAM,gBAAgB,QAAQ,CAAC,KAAK,CAAC,8BAA8B,CAAC;AACtE,EAAE,OAAO,aAAa,GAAG,CAAC,CAAA,IAAK,SAAS;AACxC;;AAEA;AACA;AACA;AACO,SAAS,wBAAwB,CAAC,IAAI,EAA4B;AACzE,EAAE,OAAO;AACT,IAAI,EAAE,EAAE,0BAA0B;AAClC,IAAI,IAAI;AACR,IAAI,UAAU,EAAE;AAChB,MAAM,CAAC,gCAAgC,GAAG,+BAA+B;AACzE,MAAM,CAAC,4BAA4B,GAAG,0BAA0B;AAChE,KAAK;AACL,GAAG;AACH;;;;"}
1
+ {"version":3,"file":"utils.js","sources":["../../../src/server/utils.ts"],"sourcesContent":["import type { StartSpanOptions } from '@sentry/core';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/node';\n\n/**\n * Extracts the SHA-256 hash from a server function pathname.\n * Server function pathnames are structured as `/_serverFn/<hash>`.\n * This function matches the pattern and returns the hash if found.\n *\n * @param pathname - the pathname of the server function\n * @returns the sha256 of the server function\n */\nexport function extractServerFunctionSha256(pathname: string): string {\n const serverFnMatch = pathname.match(/\\/_serverFn\\/([a-f0-9]{64})/i);\n return serverFnMatch?.[1] ?? 'unknown';\n}\n\n/**\n * Returns span options for TanStack Start middleware spans.\n */\nexport function getMiddlewareSpanOptions(name: string): StartSpanOptions {\n return {\n op: 'middleware.tanstackstart',\n name,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.middleware.tanstackstart',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'middleware.tanstackstart',\n },\n };\n}\n"],"names":[],"mappings":";;AAWO,SAAS,4BAA4B,QAAA,EAA0B;AACpE,EAAA,MAAM,aAAA,GAAgB,QAAA,CAAS,KAAA,CAAM,8BAA8B,CAAA;AACnE,EAAA,OAAO,aAAA,GAAgB,CAAC,CAAA,IAAK,SAAA;AAC/B;AAKO,SAAS,yBAAyB,IAAA,EAAgC;AACvE,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,0BAAA;AAAA,IACJ,IAAA;AAAA,IACA,UAAA,EAAY;AAAA,MACV,CAAC,gCAAgC,GAAG,+BAAA;AAAA,MACpC,CAAC,4BAA4B,GAAG;AAAA;AAClC,GACF;AACF;;;;"}
@@ -2,30 +2,6 @@ import { flushIfServerless } from '@sentry/core';
2
2
  import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startSpan } from '@sentry/node';
3
3
  import { extractServerFunctionSha256 } from './utils.js';
4
4
 
5
- /**
6
- * This function can be used to wrap the server entry request handler to add tracing to server-side functionality.
7
- * You must explicitly define a server entry point in your application for this to work. This is done by passing the request handler to the `createServerEntry` function.
8
- * For more information about the server entry point, see the [TanStack Start documentation](https://tanstack.com/start/docs/server-entry).
9
- *
10
- * @example
11
- * ```ts
12
- * import { wrapFetchWithSentry } from '@sentry/tanstackstart-react';
13
- *
14
- * import handler, { createServerEntry } from '@tanstack/react-start/server-entry';
15
- * import type { ServerEntry } from '@tanstack/react-start/server-entry';
16
- *
17
- * const requestHandler: ServerEntry = wrapFetchWithSentry({
18
- * fetch(request: Request) {
19
- * return handler.fetch(request);
20
- * },
21
- * });
22
- *
23
- * export default serverEntry = createServerEntry(requestHandler);
24
- * ```
25
- *
26
- * @param serverEntry - request handler to wrap
27
- * @returns - wrapped request handler
28
- */
29
5
  function wrapFetchWithSentry(serverEntry) {
30
6
  if (serverEntry.fetch) {
31
7
  serverEntry.fetch = new Proxy(serverEntry.fetch, {
@@ -33,36 +9,31 @@ function wrapFetchWithSentry(serverEntry) {
33
9
  try {
34
10
  const request = args[0];
35
11
  const url = new URL(request.url);
36
- const method = request.method || 'GET';
37
-
38
- // instrument server functions
39
- if (url.pathname.includes('_serverFn') || url.pathname.includes('createServerFn')) {
12
+ const method = request.method || "GET";
13
+ if (url.pathname.includes("_serverFn") || url.pathname.includes("createServerFn")) {
40
14
  const functionSha256 = extractServerFunctionSha256(url.pathname);
41
- const op = 'function.tanstackstart';
42
-
15
+ const op = "function.tanstackstart";
43
16
  const serverFunctionSpanAttributes = {
44
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.tanstackstart.server',
17
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.tanstackstart.server",
45
18
  [SEMANTIC_ATTRIBUTE_SENTRY_OP]: op,
46
- 'tanstackstart.function.hash.sha256': functionSha256,
19
+ "tanstackstart.function.hash.sha256": functionSha256
47
20
  };
48
-
49
21
  return await startSpan(
50
22
  {
51
- op: op,
23
+ op,
52
24
  name: `${method} ${url.pathname}`,
53
- attributes: serverFunctionSpanAttributes,
25
+ attributes: serverFunctionSpanAttributes
54
26
  },
55
27
  async () => {
56
28
  return target.apply(thisArg, args);
57
- },
29
+ }
58
30
  );
59
31
  }
60
-
61
32
  return await target.apply(thisArg, args);
62
33
  } finally {
63
34
  await flushIfServerless();
64
35
  }
65
- },
36
+ }
66
37
  });
67
38
  }
68
39
  return serverEntry;
@@ -1 +1 @@
1
- {"version":3,"file":"wrapFetchWithSentry.js","sources":["../../../src/server/wrapFetchWithSentry.ts"],"sourcesContent":["import { flushIfServerless } from '@sentry/core';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startSpan } from '@sentry/node';\nimport { extractServerFunctionSha256 } from './utils';\n\nexport type ServerEntry = {\n fetch: (request: Request, opts?: unknown) => Promise<Response> | Response;\n};\n\n/**\n * This function can be used to wrap the server entry request handler to add tracing to server-side functionality.\n * You must explicitly define a server entry point in your application for this to work. This is done by passing the request handler to the `createServerEntry` function.\n * For more information about the server entry point, see the [TanStack Start documentation](https://tanstack.com/start/docs/server-entry).\n *\n * @example\n * ```ts\n * import { wrapFetchWithSentry } from '@sentry/tanstackstart-react';\n *\n * import handler, { createServerEntry } from '@tanstack/react-start/server-entry';\n * import type { ServerEntry } from '@tanstack/react-start/server-entry';\n *\n * const requestHandler: ServerEntry = wrapFetchWithSentry({\n * fetch(request: Request) {\n * return handler.fetch(request);\n * },\n * });\n *\n * export default serverEntry = createServerEntry(requestHandler);\n * ```\n *\n * @param serverEntry - request handler to wrap\n * @returns - wrapped request handler\n */\nexport function wrapFetchWithSentry(serverEntry: ServerEntry): ServerEntry {\n if (serverEntry.fetch) {\n serverEntry.fetch = new Proxy<typeof serverEntry.fetch>(serverEntry.fetch, {\n async apply(target, thisArg, args) {\n try {\n const request: Request = args[0];\n const url = new URL(request.url);\n const method = request.method || 'GET';\n\n // instrument server functions\n if (url.pathname.includes('_serverFn') || url.pathname.includes('createServerFn')) {\n const functionSha256 = extractServerFunctionSha256(url.pathname);\n const op = 'function.tanstackstart';\n\n const serverFunctionSpanAttributes = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.tanstackstart.server',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: op,\n 'tanstackstart.function.hash.sha256': functionSha256,\n };\n\n return await startSpan(\n {\n op: op,\n name: `${method} ${url.pathname}`,\n attributes: serverFunctionSpanAttributes,\n },\n async () => {\n return target.apply(thisArg, args);\n },\n );\n }\n\n return await target.apply(thisArg, args);\n } finally {\n await flushIfServerless();\n }\n },\n });\n }\n return serverEntry;\n}\n"],"names":[],"mappings":";;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,mBAAmB,CAAC,WAAW,EAA4B;AAC3E,EAAE,IAAI,WAAW,CAAC,KAAK,EAAE;AACzB,IAAI,WAAW,CAAC,KAAA,GAAQ,IAAI,KAAK,CAA2B,WAAW,CAAC,KAAK,EAAE;AAC/E,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;AACzC,QAAQ,IAAI;AACZ,UAAU,MAAM,OAAO,GAAY,IAAI,CAAC,CAAC,CAAC;AAC1C,UAAU,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC;AAC1C,UAAU,MAAM,MAAA,GAAS,OAAO,CAAC,MAAA,IAAU,KAAK;;AAEhD;AACA,UAAU,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,KAAK,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE;AAC7F,YAAY,MAAM,iBAAiB,2BAA2B,CAAC,GAAG,CAAC,QAAQ,CAAC;AAC5E,YAAY,MAAM,EAAA,GAAK,wBAAwB;;AAE/C,YAAY,MAAM,+BAA+B;AACjD,cAAc,CAAC,gCAAgC,GAAG,oCAAoC;AACtF,cAAc,CAAC,4BAA4B,GAAG,EAAE;AAChD,cAAc,oCAAoC,EAAE,cAAc;AAClE,aAAa;;AAEb,YAAY,OAAO,MAAM,SAAS;AAClC,cAAc;AACd,gBAAgB,EAAE,EAAE,EAAE;AACtB,gBAAgB,IAAI,EAAE,CAAC,EAAA,MAAA,CAAA,CAAA,EAAA,GAAA,CAAA,QAAA,CAAA,CAAA;AACA,gBAAA,UAAA,EAAA,4BAAA;AACA,eAAA;AACA,cAAA,YAAA;AACA,gBAAA,OAAA,MAAA,CAAA,KAAA,CAAA,OAAA,EAAA,IAAA,CAAA;AACA,cAAA,CAAA;AACA,aAAA;AACA,UAAA;;AAEA,UAAA,OAAA,MAAA,MAAA,CAAA,KAAA,CAAA,OAAA,EAAA,IAAA,CAAA;AACA,QAAA,CAAA,SAAA;AACA,UAAA,MAAA,iBAAA,EAAA;AACA,QAAA;AACA,MAAA,CAAA;AACA,KAAA,CAAA;AACA,EAAA;AACA,EAAA,OAAA,WAAA;AACA;;;;"}
1
+ {"version":3,"file":"wrapFetchWithSentry.js","sources":["../../../src/server/wrapFetchWithSentry.ts"],"sourcesContent":["import { flushIfServerless } from '@sentry/core';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startSpan } from '@sentry/node';\nimport { extractServerFunctionSha256 } from './utils';\n\nexport type ServerEntry = {\n fetch: (request: Request, opts?: unknown) => Promise<Response> | Response;\n};\n\n/**\n * This function can be used to wrap the server entry request handler to add tracing to server-side functionality.\n * You must explicitly define a server entry point in your application for this to work. This is done by passing the request handler to the `createServerEntry` function.\n * For more information about the server entry point, see the [TanStack Start documentation](https://tanstack.com/start/docs/server-entry).\n *\n * @example\n * ```ts\n * import { wrapFetchWithSentry } from '@sentry/tanstackstart-react';\n *\n * import handler, { createServerEntry } from '@tanstack/react-start/server-entry';\n * import type { ServerEntry } from '@tanstack/react-start/server-entry';\n *\n * const requestHandler: ServerEntry = wrapFetchWithSentry({\n * fetch(request: Request) {\n * return handler.fetch(request);\n * },\n * });\n *\n * export default serverEntry = createServerEntry(requestHandler);\n * ```\n *\n * @param serverEntry - request handler to wrap\n * @returns - wrapped request handler\n */\nexport function wrapFetchWithSentry(serverEntry: ServerEntry): ServerEntry {\n if (serverEntry.fetch) {\n serverEntry.fetch = new Proxy<typeof serverEntry.fetch>(serverEntry.fetch, {\n async apply(target, thisArg, args) {\n try {\n const request: Request = args[0];\n const url = new URL(request.url);\n const method = request.method || 'GET';\n\n // instrument server functions\n if (url.pathname.includes('_serverFn') || url.pathname.includes('createServerFn')) {\n const functionSha256 = extractServerFunctionSha256(url.pathname);\n const op = 'function.tanstackstart';\n\n const serverFunctionSpanAttributes = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.tanstackstart.server',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: op,\n 'tanstackstart.function.hash.sha256': functionSha256,\n };\n\n return await startSpan(\n {\n op: op,\n name: `${method} ${url.pathname}`,\n attributes: serverFunctionSpanAttributes,\n },\n async () => {\n return target.apply(thisArg, args);\n },\n );\n }\n\n return await target.apply(thisArg, args);\n } finally {\n await flushIfServerless();\n }\n },\n });\n }\n return serverEntry;\n}\n"],"names":[],"mappings":";;;;AAgCO,SAAS,oBAAoB,WAAA,EAAuC;AACzE,EAAA,IAAI,YAAY,KAAA,EAAO;AACrB,IAAA,WAAA,CAAY,KAAA,GAAQ,IAAI,KAAA,CAAgC,WAAA,CAAY,KAAA,EAAO;AAAA,MACzE,MAAM,KAAA,CAAM,MAAA,EAAQ,OAAA,EAAS,IAAA,EAAM;AACjC,QAAA,IAAI;AACF,UAAA,MAAM,OAAA,GAAmB,KAAK,CAAC,CAAA;AAC/B,UAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAA;AAC/B,UAAA,MAAM,MAAA,GAAS,QAAQ,MAAA,IAAU,KAAA;AAGjC,UAAA,IAAI,GAAA,CAAI,SAAS,QAAA,CAAS,WAAW,KAAK,GAAA,CAAI,QAAA,CAAS,QAAA,CAAS,gBAAgB,CAAA,EAAG;AACjF,YAAA,MAAM,cAAA,GAAiB,2BAAA,CAA4B,GAAA,CAAI,QAAQ,CAAA;AAC/D,YAAA,MAAM,EAAA,GAAK,wBAAA;AAEX,YAAA,MAAM,4BAAA,GAA+B;AAAA,cACnC,CAAC,gCAAgC,GAAG,oCAAA;AAAA,cACpC,CAAC,4BAA4B,GAAG,EAAA;AAAA,cAChC,oCAAA,EAAsC;AAAA,aACxC;AAEA,YAAA,OAAO,MAAM,SAAA;AAAA,cACX;AAAA,gBACE,EAAA;AAAA,gBACA,IAAA,EAAM,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,IAAI,QAAQ,CAAA,CAAA;AAAA,gBAC/B,UAAA,EAAY;AAAA,eACd;AAAA,cACA,YAAY;AACV,gBAAA,OAAO,MAAA,CAAO,KAAA,CAAM,OAAA,EAAS,IAAI,CAAA;AAAA,cACnC;AAAA,aACF;AAAA,UACF;AAEA,UAAA,OAAO,MAAM,MAAA,CAAO,KAAA,CAAM,OAAA,EAAS,IAAI,CAAA;AAAA,QACzC,CAAA,SAAE;AACA,UAAA,MAAM,iBAAA,EAAkB;AAAA,QAC1B;AAAA,MACF;AAAA,KACD,CAAA;AAAA,EACH;AACA,EAAA,OAAO,WAAA;AACT;;;;"}
@@ -1,116 +1,68 @@
1
- /**
2
- * Core function that wraps middleware arrays matching the given regex.
3
- */
4
1
  function wrapMiddlewareArrays(code, id, debug, regex) {
5
2
  const skipped = [];
6
3
  let didWrap = false;
7
-
8
4
  const transformed = code.replace(regex, (match, key, contents) => {
9
5
  const objContents = arrayToObjectShorthand(contents);
10
6
  if (objContents) {
11
7
  didWrap = true;
12
8
  if (debug) {
13
- // eslint-disable-next-line no-console
14
9
  console.log(`[Sentry] Auto-wrapping ${key} in ${id}`);
15
10
  }
16
- // Handle method call syntax like `.middleware([...])` vs object property syntax like `middleware: [...]`
17
- if (key.endsWith('(')) {
11
+ if (key.endsWith("(")) {
18
12
  return `${key}wrapMiddlewaresWithSentry(${objContents}))`;
19
13
  }
20
14
  return `${key}: wrapMiddlewaresWithSentry(${objContents})`;
21
15
  }
22
- // Track middlewares that couldn't be auto-wrapped
23
- // Skip if we matched whitespace only
24
16
  if (contents.trim()) {
25
17
  skipped.push(key);
26
18
  }
27
19
  return match;
28
20
  });
29
-
30
21
  return { code: transformed, didWrap, skipped };
31
22
  }
32
-
33
- /**
34
- * Wraps global middleware arrays (requestMiddleware, functionMiddleware) in createStart() files.
35
- */
36
23
  function wrapGlobalMiddleware(code, id, debug) {
37
24
  return wrapMiddlewareArrays(code, id, debug, /(requestMiddleware|functionMiddleware)\s*:\s*\[([^\]]*)\]/g);
38
25
  }
39
-
40
- /**
41
- * Wraps route middleware arrays in createFileRoute() files.
42
- */
43
26
  function wrapRouteMiddleware(code, id, debug) {
44
27
  return wrapMiddlewareArrays(code, id, debug, /(middleware)\s*:\s*\[([^\]]*)\]/g);
45
28
  }
46
-
47
- /**
48
- * Wraps middleware arrays in createServerFn().middleware([...]) calls.
49
- */
50
29
  function wrapServerFnMiddleware(code, id, debug) {
51
30
  return wrapMiddlewareArrays(code, id, debug, /(\.middleware\s*\()\s*\[([^\]]*)\]\s*\)/g);
52
31
  }
53
-
54
- /**
55
- * Applies a wrap function to the current state and returns the updated state.
56
- */
57
- function applyWrap(
58
- state,
59
- wrapFn,
60
- id,
61
- debug,
62
- ) {
32
+ function applyWrap(state, wrapFn, id, debug) {
63
33
  const result = wrapFn(state.code, id, debug);
64
34
  return {
65
35
  code: result.code,
66
36
  needsImport: state.needsImport || result.didWrap,
67
- skippedMiddlewares: [...state.skippedMiddlewares, ...result.skipped],
37
+ skippedMiddlewares: [...state.skippedMiddlewares, ...result.skipped]
68
38
  };
69
39
  }
70
-
71
- /**
72
- * A Vite plugin that automatically instruments TanStack Start middlewares:
73
- * - `requestMiddleware` and `functionMiddleware` arrays in `createStart()`
74
- * - `middleware` arrays in `createFileRoute()` route definitions
75
- */
76
40
  function makeAutoInstrumentMiddlewarePlugin(options = {}) {
77
41
  const { enabled = true, debug = false } = options;
78
-
79
42
  return {
80
- name: 'sentry-tanstack-middleware-auto-instrument',
81
- enforce: 'pre',
82
-
43
+ name: "sentry-tanstack-middleware-auto-instrument",
44
+ enforce: "pre",
83
45
  transform(code, id) {
84
46
  if (!enabled) {
85
47
  return null;
86
48
  }
87
-
88
- // Skip if not a TS/JS file
89
49
  if (!/\.(ts|tsx|js|jsx|mjs|mts)$/.test(id)) {
90
50
  return null;
91
51
  }
92
-
93
- // Detect file types that should be instrumented
94
- const isStartFile = id.includes('start') && code.includes('createStart(');
95
- const isRouteFile = code.includes('createFileRoute(') && /middleware\s*:\s*\[/.test(code);
96
- const isServerFnFile = code.includes('createServerFn') && /\.middleware\s*\(\s*\[/.test(code);
97
-
52
+ const isStartFile = id.includes("start") && code.includes("createStart(");
53
+ const isRouteFile = code.includes("createFileRoute(") && /middleware\s*:\s*\[/.test(code);
54
+ const isServerFnFile = code.includes("createServerFn") && /\.middleware\s*\(\s*\[/.test(code);
98
55
  if (!isStartFile && !isRouteFile && !isServerFnFile) {
99
56
  return null;
100
57
  }
101
-
102
- // Skip if the user already did some manual wrapping
103
- if (code.includes('wrapMiddlewaresWithSentry')) {
58
+ if (code.includes("wrapMiddlewaresWithSentry")) {
104
59
  return null;
105
60
  }
106
-
107
61
  let fileTransformState = {
108
62
  code,
109
63
  needsImport: false,
110
- skippedMiddlewares: [],
64
+ skippedMiddlewares: []
111
65
  };
112
-
113
- // Wrap middlewares
114
66
  if (isStartFile) {
115
67
  fileTransformState = applyWrap(fileTransformState, wrapGlobalMiddleware, id, debug);
116
68
  }
@@ -120,70 +72,36 @@ function makeAutoInstrumentMiddlewarePlugin(options = {}) {
120
72
  if (isServerFnFile) {
121
73
  fileTransformState = applyWrap(fileTransformState, wrapServerFnMiddleware, id, debug);
122
74
  }
123
-
124
- // Warn about middlewares that couldn't be auto-wrapped
125
75
  if (fileTransformState.skippedMiddlewares.length > 0) {
126
- // eslint-disable-next-line no-console
127
76
  console.warn(
128
- `[Sentry] Could not auto-instrument ${fileTransformState.skippedMiddlewares.join(' and ')} in ${id}. ` +
129
- 'To instrument these middlewares, use wrapMiddlewaresWithSentry() manually. ',
77
+ `[Sentry] Could not auto-instrument ${fileTransformState.skippedMiddlewares.join(" and ")} in ${id}. To instrument these middlewares, use wrapMiddlewaresWithSentry() manually. `
130
78
  );
131
79
  }
132
-
133
- // We didn't wrap any middlewares, so we don't need to import the wrapMiddlewaresWithSentry function
134
80
  if (!fileTransformState.needsImport) {
135
81
  return null;
136
82
  }
137
-
138
83
  return { code: addSentryImport(fileTransformState.code), map: null };
139
- },
84
+ }
140
85
  };
141
86
  }
142
-
143
- /**
144
- * Convert array contents to object shorthand syntax.
145
- * e.g., "foo, bar, baz" → "{ foo, bar, baz }"
146
- *
147
- * Returns null if contents contain non-identifier expressions (function calls, etc.)
148
- * which cannot be converted to object shorthand.
149
- */
150
87
  function arrayToObjectShorthand(contents) {
151
- const items = contents
152
- .split(',')
153
- .map(s => s.trim())
154
- .filter(Boolean);
155
-
156
- // Only convert if all items are valid identifiers (no complex expressions)
157
- const allIdentifiers = items.every(item => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(item));
88
+ const items = contents.split(",").map((s) => s.trim()).filter(Boolean);
89
+ const allIdentifiers = items.every((item) => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(item));
158
90
  if (!allIdentifiers || items.length === 0) {
159
91
  return null;
160
92
  }
161
-
162
- // Deduplicate to avoid invalid syntax like { foo, foo }
163
93
  const uniqueItems = [...new Set(items)];
164
-
165
- return `{ ${uniqueItems.join(', ')} }`;
94
+ return `{ ${uniqueItems.join(", ")} }`;
166
95
  }
167
-
168
- /**
169
- * Adds the wrapMiddlewaresWithSentry import to the code.
170
- * Handles 'use client' and 'use server' directives by inserting the import after them.
171
- */
172
96
  function addSentryImport(code) {
173
97
  const sentryImport = "import { wrapMiddlewaresWithSentry } from '@sentry/tanstackstart-react';\n";
174
-
175
- // Don't add the import if it already exists
176
98
  if (code.includes(sentryImport.trimEnd())) {
177
99
  return code;
178
100
  }
179
-
180
- // Check for 'use server' or 'use client' directives, these need to be before any imports
181
101
  const directiveMatch = code.match(/^(['"])use (client|server)\1;?\s*\n?/);
182
-
183
102
  if (!directiveMatch) {
184
103
  return sentryImport + code;
185
104
  }
186
-
187
105
  const directive = directiveMatch[0];
188
106
  return directive + sentryImport + code.slice(directive.length);
189
107
  }