@sentry/wizard 6.10.0 → 6.12.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 (203) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/dist/ci-ensure-runtime-loaded.sh +82 -0
  3. package/dist/e2e-tests/tests/angular-17.test.js +72 -82
  4. package/dist/e2e-tests/tests/angular-17.test.js.map +1 -1
  5. package/dist/e2e-tests/tests/angular-19.test.js +71 -80
  6. package/dist/e2e-tests/tests/angular-19.test.js.map +1 -1
  7. package/dist/e2e-tests/tests/cloudflare-worker.test.d.ts +1 -0
  8. package/dist/e2e-tests/tests/cloudflare-worker.test.js +69 -0
  9. package/dist/e2e-tests/tests/cloudflare-worker.test.js.map +1 -0
  10. package/dist/e2e-tests/tests/cloudflare-wrangler-sourcemaps.test.js +2 -5
  11. package/dist/e2e-tests/tests/cloudflare-wrangler-sourcemaps.test.js.map +1 -1
  12. package/dist/e2e-tests/tests/expo.test.js +36 -61
  13. package/dist/e2e-tests/tests/expo.test.js.map +1 -1
  14. package/dist/e2e-tests/tests/flutter.test.js +63 -70
  15. package/dist/e2e-tests/tests/flutter.test.js.map +1 -1
  16. package/dist/e2e-tests/tests/help-message.test.js +2 -2
  17. package/dist/e2e-tests/tests/help-message.test.js.map +1 -1
  18. package/dist/e2e-tests/tests/nextjs-14.test.js +48 -76
  19. package/dist/e2e-tests/tests/nextjs-14.test.js.map +1 -1
  20. package/dist/e2e-tests/tests/nextjs-15.test.js +89 -99
  21. package/dist/e2e-tests/tests/nextjs-15.test.js.map +1 -1
  22. package/dist/e2e-tests/tests/nextjs-16.test.js +48 -45
  23. package/dist/e2e-tests/tests/nextjs-16.test.js.map +1 -1
  24. package/dist/e2e-tests/tests/nuxt-3.test.js +45 -58
  25. package/dist/e2e-tests/tests/nuxt-3.test.js.map +1 -1
  26. package/dist/e2e-tests/tests/nuxt-4.test.js +59 -73
  27. package/dist/e2e-tests/tests/nuxt-4.test.js.map +1 -1
  28. package/dist/e2e-tests/tests/pnpm-workspace.test.js +6 -8
  29. package/dist/e2e-tests/tests/pnpm-workspace.test.js.map +1 -1
  30. package/dist/e2e-tests/tests/react-native.test.js +44 -80
  31. package/dist/e2e-tests/tests/react-native.test.js.map +1 -1
  32. package/dist/e2e-tests/tests/react-router-instrumentation-api.test.d.ts +1 -0
  33. package/dist/e2e-tests/tests/react-router-instrumentation-api.test.js +96 -0
  34. package/dist/e2e-tests/tests/react-router-instrumentation-api.test.js.map +1 -0
  35. package/dist/e2e-tests/tests/react-router.test.js +165 -145
  36. package/dist/e2e-tests/tests/react-router.test.js.map +1 -1
  37. package/dist/e2e-tests/tests/remix.test.js +162 -132
  38. package/dist/e2e-tests/tests/remix.test.js.map +1 -1
  39. package/dist/e2e-tests/tests/sveltekit-hooks.test.js +48 -36
  40. package/dist/e2e-tests/tests/sveltekit-hooks.test.js.map +1 -1
  41. package/dist/e2e-tests/tests/sveltekit-tracing.test.js +5 -7
  42. package/dist/e2e-tests/tests/sveltekit-tracing.test.js.map +1 -1
  43. package/dist/e2e-tests/utils/index.d.ts +15 -43
  44. package/dist/e2e-tests/utils/index.js +95 -185
  45. package/dist/e2e-tests/utils/index.js.map +1 -1
  46. package/dist/get-e2e-test-matrix.mjs +11 -0
  47. package/dist/lib/Constants.d.ts +1 -0
  48. package/dist/lib/Constants.js +5 -0
  49. package/dist/lib/Constants.js.map +1 -1
  50. package/dist/src/android/android-wizard.js +2 -4
  51. package/dist/src/android/android-wizard.js.map +1 -1
  52. package/dist/src/angular/angular-wizard.js +4 -6
  53. package/dist/src/angular/angular-wizard.js.map +1 -1
  54. package/dist/src/angular/sdk-setup.js +1 -1
  55. package/dist/src/angular/sdk-setup.js.map +1 -1
  56. package/dist/src/apple/apple-wizard.js +2 -4
  57. package/dist/src/apple/apple-wizard.js.map +1 -1
  58. package/dist/src/apple/code-tools.js +17 -3
  59. package/dist/src/apple/code-tools.js.map +1 -1
  60. package/dist/src/apple/configure-package-manager.js +18 -5
  61. package/dist/src/apple/configure-package-manager.js.map +1 -1
  62. package/dist/src/cloudflare/cloudflare-wizard.d.ts +3 -0
  63. package/dist/src/cloudflare/cloudflare-wizard.js +104 -0
  64. package/dist/src/cloudflare/cloudflare-wizard.js.map +1 -0
  65. package/dist/src/cloudflare/sdk-setup.d.ts +8 -0
  66. package/dist/src/cloudflare/sdk-setup.js +47 -0
  67. package/dist/src/cloudflare/sdk-setup.js.map +1 -0
  68. package/dist/src/cloudflare/templates.d.ts +5 -0
  69. package/dist/src/cloudflare/templates.js +50 -0
  70. package/dist/src/cloudflare/templates.js.map +1 -0
  71. package/dist/src/cloudflare/wrangler/create-wrangler-config.d.ts +4 -0
  72. package/dist/src/cloudflare/wrangler/create-wrangler-config.js +27 -0
  73. package/dist/src/cloudflare/wrangler/create-wrangler-config.js.map +1 -0
  74. package/dist/src/cloudflare/wrangler/ensure-wrangler-config.d.ts +4 -0
  75. package/dist/src/cloudflare/wrangler/ensure-wrangler-config.js +25 -0
  76. package/dist/src/cloudflare/wrangler/ensure-wrangler-config.js.map +1 -0
  77. package/dist/src/cloudflare/wrangler/find-wrangler-config.d.ts +4 -0
  78. package/dist/src/cloudflare/wrangler/find-wrangler-config.js +23 -0
  79. package/dist/src/cloudflare/wrangler/find-wrangler-config.js.map +1 -0
  80. package/dist/src/cloudflare/wrangler/get-entry-point-from-wrangler-config.d.ts +6 -0
  81. package/dist/src/cloudflare/wrangler/get-entry-point-from-wrangler-config.js +52 -0
  82. package/dist/src/cloudflare/wrangler/get-entry-point-from-wrangler-config.js.map +1 -0
  83. package/dist/src/cloudflare/wrangler/update-wrangler-config.d.ts +17 -0
  84. package/dist/src/cloudflare/wrangler/update-wrangler-config.js +173 -0
  85. package/dist/src/cloudflare/wrangler/update-wrangler-config.js.map +1 -0
  86. package/dist/src/cloudflare/wrap-worker.d.ts +33 -0
  87. package/dist/src/cloudflare/wrap-worker.js +116 -0
  88. package/dist/src/cloudflare/wrap-worker.js.map +1 -0
  89. package/dist/src/flutter/flutter-wizard.js +3 -6
  90. package/dist/src/flutter/flutter-wizard.js.map +1 -1
  91. package/dist/src/nextjs/nextjs-wizard.js +0 -2
  92. package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
  93. package/dist/src/nuxt/nuxt-wizard.js +3 -5
  94. package/dist/src/nuxt/nuxt-wizard.js.map +1 -1
  95. package/dist/src/react-native/expo.d.ts +6 -0
  96. package/dist/src/react-native/expo.js +27 -1
  97. package/dist/src/react-native/expo.js.map +1 -1
  98. package/dist/src/react-native/git.d.ts +5 -0
  99. package/dist/src/react-native/git.js +32 -1
  100. package/dist/src/react-native/git.js.map +1 -1
  101. package/dist/src/react-native/javascript.js +3 -1
  102. package/dist/src/react-native/javascript.js.map +1 -1
  103. package/dist/src/react-native/react-native-wizard.js +14 -10
  104. package/dist/src/react-native/react-native-wizard.js.map +1 -1
  105. package/dist/src/react-router/codemods/client.entry.d.ts +1 -1
  106. package/dist/src/react-router/codemods/client.entry.js +69 -12
  107. package/dist/src/react-router/codemods/client.entry.js.map +1 -1
  108. package/dist/src/react-router/codemods/react-router-config.js +1 -1
  109. package/dist/src/react-router/codemods/react-router-config.js.map +1 -1
  110. package/dist/src/react-router/codemods/root.js +1 -2
  111. package/dist/src/react-router/codemods/root.js.map +1 -1
  112. package/dist/src/react-router/codemods/server-entry.d.ts +1 -1
  113. package/dist/src/react-router/codemods/server-entry.js +39 -4
  114. package/dist/src/react-router/codemods/server-entry.js.map +1 -1
  115. package/dist/src/react-router/codemods/vite.js +46 -1
  116. package/dist/src/react-router/codemods/vite.js.map +1 -1
  117. package/dist/src/react-router/react-router-wizard.js +55 -10
  118. package/dist/src/react-router/react-router-wizard.js.map +1 -1
  119. package/dist/src/react-router/sdk-setup.d.ts +5 -3
  120. package/dist/src/react-router/sdk-setup.js +35 -9
  121. package/dist/src/react-router/sdk-setup.js.map +1 -1
  122. package/dist/src/react-router/templates.d.ts +2 -2
  123. package/dist/src/react-router/templates.js +72 -2
  124. package/dist/src/react-router/templates.js.map +1 -1
  125. package/dist/src/remix/remix-wizard.js +2 -4
  126. package/dist/src/remix/remix-wizard.js.map +1 -1
  127. package/dist/src/run.d.ts +1 -1
  128. package/dist/src/run.js +5 -0
  129. package/dist/src/run.js.map +1 -1
  130. package/dist/src/sourcemaps/tools/vite.js +1 -1
  131. package/dist/src/sourcemaps/tools/vite.js.map +1 -1
  132. package/dist/src/sveltekit/sdk-setup/vite.js +1 -1
  133. package/dist/src/sveltekit/sdk-setup/vite.js.map +1 -1
  134. package/dist/src/sveltekit/sveltekit-wizard.js +2 -4
  135. package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
  136. package/dist/src/utils/abort-if-sportlight-not-supported.d.ts +5 -0
  137. package/dist/src/utils/abort-if-sportlight-not-supported.js +40 -0
  138. package/dist/src/utils/abort-if-sportlight-not-supported.js.map +1 -0
  139. package/dist/src/utils/ast-utils.d.ts +11 -1
  140. package/dist/src/utils/ast-utils.js +19 -1
  141. package/dist/src/utils/ast-utils.js.map +1 -1
  142. package/dist/src/utils/clack/index.d.ts +2 -2
  143. package/dist/src/utils/clack/index.js.map +1 -1
  144. package/dist/src/utils/clack/mcp-config.js +117 -59
  145. package/dist/src/utils/clack/mcp-config.js.map +1 -1
  146. package/dist/src/version.d.ts +1 -1
  147. package/dist/src/version.js +1 -1
  148. package/dist/src/version.js.map +1 -1
  149. package/dist/test/angular/angular-wizard.test.js +2 -4
  150. package/dist/test/angular/angular-wizard.test.js.map +1 -1
  151. package/dist/test/apple/code-tools.test.js +78 -0
  152. package/dist/test/apple/code-tools.test.js.map +1 -1
  153. package/dist/test/apple/configure-package-manager.test.d.ts +1 -0
  154. package/dist/test/apple/configure-package-manager.test.js +161 -0
  155. package/dist/test/apple/configure-package-manager.test.js.map +1 -0
  156. package/dist/test/cloudflare/create-wrangler-config.test.d.ts +1 -0
  157. package/dist/test/cloudflare/create-wrangler-config.test.js +48 -0
  158. package/dist/test/cloudflare/create-wrangler-config.test.js.map +1 -0
  159. package/dist/test/cloudflare/ensure-wrangler-config.test.d.ts +1 -0
  160. package/dist/test/cloudflare/ensure-wrangler-config.test.js +61 -0
  161. package/dist/test/cloudflare/ensure-wrangler-config.test.js.map +1 -0
  162. package/dist/test/cloudflare/find-wrangler-config.test.d.ts +1 -0
  163. package/dist/test/cloudflare/find-wrangler-config.test.js +77 -0
  164. package/dist/test/cloudflare/find-wrangler-config.test.js.map +1 -0
  165. package/dist/test/cloudflare/get-entry-point-from-wrangler-config.test.d.ts +1 -0
  166. package/dist/test/cloudflare/get-entry-point-from-wrangler-config.test.js +81 -0
  167. package/dist/test/cloudflare/get-entry-point-from-wrangler-config.test.js.map +1 -0
  168. package/dist/test/cloudflare/sdk-setup.test.d.ts +1 -0
  169. package/dist/test/cloudflare/sdk-setup.test.js +170 -0
  170. package/dist/test/cloudflare/sdk-setup.test.js.map +1 -0
  171. package/dist/test/cloudflare/templates.test.d.ts +1 -0
  172. package/dist/test/cloudflare/templates.test.js +122 -0
  173. package/dist/test/cloudflare/templates.test.js.map +1 -0
  174. package/dist/test/cloudflare/update-wrangler-config.test.d.ts +1 -0
  175. package/dist/test/cloudflare/update-wrangler-config.test.js +216 -0
  176. package/dist/test/cloudflare/update-wrangler-config.test.js.map +1 -0
  177. package/dist/test/cloudflare/wrap-worker.test.d.ts +1 -0
  178. package/dist/test/cloudflare/wrap-worker.test.js +206 -0
  179. package/dist/test/cloudflare/wrap-worker.test.js.map +1 -0
  180. package/dist/test/react-native/expo.test.js +140 -0
  181. package/dist/test/react-native/expo.test.js.map +1 -1
  182. package/dist/test/react-native/git.test.d.ts +1 -0
  183. package/dist/test/react-native/git.test.js +160 -0
  184. package/dist/test/react-native/git.test.js.map +1 -0
  185. package/dist/test/react-router/codemods/client-entry.test.js +29 -0
  186. package/dist/test/react-router/codemods/client-entry.test.js.map +1 -1
  187. package/dist/test/react-router/codemods/root.test.js +4 -0
  188. package/dist/test/react-router/codemods/root.test.js.map +1 -1
  189. package/dist/test/react-router/codemods/server-entry.test.js +70 -0
  190. package/dist/test/react-router/codemods/server-entry.test.js.map +1 -1
  191. package/dist/test/react-router/codemods/vite.test.js +89 -0
  192. package/dist/test/react-router/codemods/vite.test.js.map +1 -1
  193. package/dist/test/react-router/sdk-setup.test.js +64 -8
  194. package/dist/test/react-router/sdk-setup.test.js.map +1 -1
  195. package/dist/test/react-router/templates.test.js +50 -0
  196. package/dist/test/react-router/templates.test.js.map +1 -1
  197. package/dist/test/sourcemaps/tools/vite.test.js +12 -8
  198. package/dist/test/sourcemaps/tools/vite.test.js.map +1 -1
  199. package/dist/test/utils/ast-utils.test.js +22 -0
  200. package/dist/test/utils/ast-utils.test.js.map +1 -1
  201. package/dist/test/utils/clack/mcp-config.test.js +176 -51
  202. package/dist/test/utils/clack/mcp-config.test.js.map +1 -1
  203. package/package.json +6 -5
@@ -42,7 +42,7 @@ const magicast_1 = require("magicast");
42
42
  const debug_1 = require("../../utils/debug");
43
43
  const ast_utils_1 = require("../../utils/ast-utils");
44
44
  const utils_1 = require("./utils");
45
- async function instrumentServerEntry(serverEntryPath) {
45
+ async function instrumentServerEntry(serverEntryPath, useInstrumentationAPI = false) {
46
46
  const serverEntryAst = await (0, magicast_1.loadFile)(serverEntryPath);
47
47
  if (!(0, ast_utils_1.hasSentryContent)(serverEntryAst.$ast)) {
48
48
  serverEntryAst.imports.$add({
@@ -53,9 +53,39 @@ async function instrumentServerEntry(serverEntryPath) {
53
53
  }
54
54
  instrumentHandleError(serverEntryAst);
55
55
  instrumentHandleRequest(serverEntryAst);
56
+ if (useInstrumentationAPI) {
57
+ instrumentUnstableInstrumentations(serverEntryAst);
58
+ }
56
59
  await (0, magicast_1.writeFile)(serverEntryAst.$ast, serverEntryPath);
57
60
  }
58
61
  exports.instrumentServerEntry = instrumentServerEntry;
62
+ function instrumentUnstableInstrumentations(originalEntryServerMod) {
63
+ const originalEntryServerModAST = originalEntryServerMod.$ast;
64
+ const hasUnstableInstrumentations = originalEntryServerModAST.body.some((node) => {
65
+ if (node.type !== 'ExportNamedDeclaration' ||
66
+ node.declaration?.type !== 'VariableDeclaration') {
67
+ return false;
68
+ }
69
+ const declarations = node.declaration.declarations;
70
+ if (!declarations || declarations.length === 0) {
71
+ return false;
72
+ }
73
+ const firstDeclaration = declarations[0];
74
+ if (!firstDeclaration || firstDeclaration.type !== 'VariableDeclarator') {
75
+ return false;
76
+ }
77
+ const id = firstDeclaration.id;
78
+ return (id &&
79
+ id.type === 'Identifier' &&
80
+ id.name === 'unstable_instrumentations');
81
+ });
82
+ if (hasUnstableInstrumentations) {
83
+ (0, debug_1.debug)('unstable_instrumentations export already exists, skipping adding it again');
84
+ return;
85
+ }
86
+ const instrumentationsExport = recast.parse(`export const unstable_instrumentations = [Sentry.createSentryServerInstrumentation()];`).program.body[0];
87
+ originalEntryServerModAST.body.push(instrumentationsExport);
88
+ }
59
89
  function instrumentHandleRequest(originalEntryServerMod) {
60
90
  const originalEntryServerModAST = originalEntryServerMod.$ast;
61
91
  const defaultServerEntryExport = originalEntryServerModAST.body.find((node) => {
@@ -148,10 +178,15 @@ function instrumentHandleRequest(originalEntryServerMod) {
148
178
  this.traverse(path);
149
179
  },
150
180
  });
151
- // Replace the existing default export with the wrapped one
152
- originalEntryServerModAST.body.splice(defaultExportIndex, 1,
181
+ // Replace the existing default export with the unwrapped function declaration
153
182
  // @ts-expect-error - declaration works here because the AST is proxified by magicast
154
- defaultExportNode.declaration);
183
+ const funcDeclaration = defaultExportNode.declaration;
184
+ // Make non-async functions async so the return type matches wrapSentryHandleRequest
185
+ if (funcDeclaration.type === 'FunctionDeclaration' &&
186
+ !funcDeclaration.async) {
187
+ funcDeclaration.async = true;
188
+ }
189
+ originalEntryServerModAST.body.splice(defaultExportIndex, 1, funcDeclaration);
155
190
  // Adding our wrapped export
156
191
  originalEntryServerModAST.body.push(recast.types.builders.exportDefaultDeclaration(recast.types.builders.callExpression(recast.types.builders.memberExpression(recast.types.builders.identifier('Sentry'), recast.types.builders.identifier('wrapSentryHandleRequest')), [recast.types.builders.identifier('handleRequest')])));
157
192
  }
@@ -1 +1 @@
1
- {"version":3,"file":"server-entry.js","sourceRoot":"","sources":["../../../../src/react-router/codemods/server-entry.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-argument */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-return */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport type { ProxifiedModule } from 'magicast';\n\nimport * as recast from 'recast';\nimport type { namedTypes as t } from 'ast-types';\n\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\nimport chalk from 'chalk';\n\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport { generateCode, loadFile, writeFile } from 'magicast';\nimport { debug } from '../../utils/debug';\nimport {\n hasSentryContent,\n safeCalleeIdentifierMatch,\n safeGetIdentifierName,\n} from '../../utils/ast-utils';\nimport { getAfterImportsInsertionIndex } from './utils';\n\nexport async function instrumentServerEntry(\n serverEntryPath: string,\n): Promise<void> {\n const serverEntryAst = await loadFile(serverEntryPath);\n\n if (!hasSentryContent(serverEntryAst.$ast as t.Program)) {\n serverEntryAst.imports.$add({\n from: '@sentry/react-router',\n imported: '*',\n local: 'Sentry',\n });\n }\n\n instrumentHandleError(serverEntryAst);\n instrumentHandleRequest(serverEntryAst);\n\n await writeFile(serverEntryAst.$ast, serverEntryPath);\n}\n\nexport function instrumentHandleRequest(\n originalEntryServerMod: ProxifiedModule<any>,\n): void {\n const originalEntryServerModAST = originalEntryServerMod.$ast as t.Program;\n\n const defaultServerEntryExport = originalEntryServerModAST.body.find(\n (node) => {\n return node.type === 'ExportDefaultDeclaration';\n },\n );\n\n if (!defaultServerEntryExport) {\n clack.log.warn(\n `Could not find function ${chalk.cyan(\n 'handleRequest',\n )} in your server entry file. Creating one for you.`,\n );\n\n let foundServerRouterImport = false;\n let foundRenderToPipeableStreamImport = false;\n let foundCreateReadableStreamFromReadableImport = false;\n\n originalEntryServerMod.imports.$items.forEach((item) => {\n if (item.imported === 'ServerRouter' && item.from === 'react-router') {\n foundServerRouterImport = true;\n }\n if (\n item.imported === 'renderToPipeableStream' &&\n item.from === 'react-dom/server'\n ) {\n foundRenderToPipeableStreamImport = true;\n }\n if (\n item.imported === 'createReadableStreamFromReadable' &&\n item.from === '@react-router/node'\n ) {\n foundCreateReadableStreamFromReadableImport = true;\n }\n });\n\n if (!foundServerRouterImport) {\n originalEntryServerMod.imports.$add({\n from: 'react-router',\n imported: 'ServerRouter',\n local: 'ServerRouter',\n });\n }\n\n if (!foundRenderToPipeableStreamImport) {\n originalEntryServerMod.imports.$add({\n from: 'react-dom/server',\n imported: 'renderToPipeableStream',\n local: 'renderToPipeableStream',\n });\n }\n\n if (!foundCreateReadableStreamFromReadableImport) {\n originalEntryServerMod.imports.$add({\n from: '@react-router/node',\n imported: 'createReadableStreamFromReadable',\n local: 'createReadableStreamFromReadable',\n });\n }\n\n const implementation =\n recast.parse(`const handleRequest = Sentry.createSentryHandleRequest({\n ServerRouter,\n renderToPipeableStream,\n createReadableStreamFromReadable,\n})`).program.body[0];\n\n try {\n originalEntryServerModAST.body.splice(\n getAfterImportsInsertionIndex(originalEntryServerModAST),\n 0,\n implementation,\n );\n\n originalEntryServerModAST.body.push({\n type: 'ExportDefaultDeclaration',\n declaration: {\n type: 'Identifier',\n name: 'handleRequest',\n },\n });\n } catch (error) {\n debug('Failed to insert handleRequest implementation:', error);\n throw new Error(\n 'Could not automatically instrument handleRequest. Please add it manually.',\n );\n }\n } else if (\n defaultServerEntryExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(defaultServerEntryExport).code.includes(\n 'wrapSentryHandleRequest',\n )\n ) {\n debug('wrapSentryHandleRequest is already used, skipping wrapping again');\n clack.log.info(\n 'Sentry handleRequest wrapper already detected, skipping instrumentation.',\n );\n } else {\n let defaultExportNode: recast.types.namedTypes.ExportDefaultDeclaration | null =\n null;\n const defaultExportIndex = originalEntryServerModAST.body.findIndex(\n (node) => {\n const found = node.type === 'ExportDefaultDeclaration';\n\n if (found) {\n defaultExportNode = node;\n }\n\n return found;\n },\n );\n\n if (defaultExportIndex !== -1 && defaultExportNode !== null) {\n recast.visit(defaultExportNode, {\n visitCallExpression(path) {\n if (\n safeCalleeIdentifierMatch(path.value.callee, 'pipe') &&\n path.value.arguments.length &&\n path.value.arguments[0].type === 'Identifier' &&\n safeGetIdentifierName(path.value.arguments[0]) === 'body'\n ) {\n const wrapped = recast.types.builders.callExpression(\n recast.types.builders.memberExpression(\n recast.types.builders.identifier('Sentry'),\n recast.types.builders.identifier('getMetaTagTransformer'),\n ),\n [path.value.arguments[0]],\n );\n\n path.value.arguments[0] = wrapped;\n }\n\n this.traverse(path);\n },\n });\n\n // Replace the existing default export with the wrapped one\n originalEntryServerModAST.body.splice(\n defaultExportIndex,\n 1,\n // @ts-expect-error - declaration works here because the AST is proxified by magicast\n defaultExportNode.declaration,\n );\n\n // Adding our wrapped export\n originalEntryServerModAST.body.push(\n recast.types.builders.exportDefaultDeclaration(\n recast.types.builders.callExpression(\n recast.types.builders.memberExpression(\n recast.types.builders.identifier('Sentry'),\n recast.types.builders.identifier('wrapSentryHandleRequest'),\n ),\n [recast.types.builders.identifier('handleRequest')],\n ),\n ),\n );\n }\n }\n}\n\nexport function instrumentHandleError(\n originalEntryServerMod: ProxifiedModule<any>,\n): void {\n const originalEntryServerModAST = originalEntryServerMod.$ast as t.Program;\n\n const handleErrorFunctionExport = originalEntryServerModAST.body.find(\n (node) => {\n return (\n node.type === 'ExportNamedDeclaration' &&\n node.declaration?.type === 'FunctionDeclaration' &&\n node.declaration.id?.name === 'handleError'\n );\n },\n );\n\n const handleErrorFunctionVariableDeclarationExport =\n originalEntryServerModAST.body.find((node) => {\n if (\n node.type !== 'ExportNamedDeclaration' ||\n node.declaration?.type !== 'VariableDeclaration'\n ) {\n return false;\n }\n\n const declarations = node.declaration.declarations;\n if (!declarations || declarations.length === 0) {\n return false;\n }\n\n const firstDeclaration = declarations[0];\n if (!firstDeclaration || firstDeclaration.type !== 'VariableDeclarator') {\n return false;\n }\n\n const id = firstDeclaration.id;\n return id && id.type === 'Identifier' && id.name === 'handleError';\n });\n\n if (\n !handleErrorFunctionExport &&\n !handleErrorFunctionVariableDeclarationExport\n ) {\n clack.log.warn(\n `Could not find function ${chalk.cyan(\n 'handleError',\n )} in your server entry file. Creating one for you.`,\n );\n\n const implementation =\n recast.parse(`const handleError = Sentry.createSentryHandleError({\n logErrors: false\n})`).program.body[0];\n\n originalEntryServerModAST.body.splice(\n getAfterImportsInsertionIndex(originalEntryServerModAST),\n 0,\n recast.types.builders.exportNamedDeclaration(implementation),\n );\n } else if (\n (handleErrorFunctionExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(handleErrorFunctionExport).code.includes(\n 'captureException',\n )) ||\n (handleErrorFunctionVariableDeclarationExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(handleErrorFunctionVariableDeclarationExport).code.includes(\n 'captureException',\n ))\n ) {\n debug(\n 'Found captureException inside handleError, skipping adding it again',\n );\n } else if (\n (handleErrorFunctionExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(handleErrorFunctionExport).code.includes(\n 'createSentryHandleError',\n )) ||\n (handleErrorFunctionVariableDeclarationExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(handleErrorFunctionVariableDeclarationExport).code.includes(\n 'createSentryHandleError',\n ))\n ) {\n debug('createSentryHandleError is already used, skipping adding it again');\n } else if (handleErrorFunctionExport) {\n // Create the Sentry captureException call as an IfStatement\n const sentryCall = recast.parse(`if (!request.signal.aborted) {\n Sentry.captureException(error);\n}`).program.body[0];\n\n // Safely insert the Sentry call at the beginning of the handleError function body\n // @ts-expect-error - declaration works here because the AST is proxified by magicast\n const declaration = handleErrorFunctionExport.declaration;\n if (\n declaration &&\n declaration.body &&\n declaration.body.body &&\n Array.isArray(declaration.body.body)\n ) {\n declaration.body.body.unshift(sentryCall);\n } else {\n debug(\n 'Cannot safely access handleError function body, skipping instrumentation',\n );\n }\n } else if (handleErrorFunctionVariableDeclarationExport) {\n // Create the Sentry captureException call as an IfStatement\n const sentryCall = recast.parse(`if (!request.signal.aborted) {\n Sentry.captureException(error);\n}`).program.body[0];\n\n // Safe access to existing handle error implementation with proper null checks\n // We know this is ExportNamedDeclaration with VariableDeclaration from the earlier find\n const exportDeclaration =\n handleErrorFunctionVariableDeclarationExport as any;\n if (\n !exportDeclaration.declaration ||\n exportDeclaration.declaration.type !== 'VariableDeclaration' ||\n !exportDeclaration.declaration.declarations ||\n exportDeclaration.declaration.declarations.length === 0\n ) {\n debug(\n 'Cannot safely access handleError variable declaration, skipping instrumentation',\n );\n return;\n }\n\n const firstDeclaration = exportDeclaration.declaration.declarations[0];\n if (\n !firstDeclaration ||\n firstDeclaration.type !== 'VariableDeclarator' ||\n !firstDeclaration.init\n ) {\n debug(\n 'Cannot safely access handleError variable declarator init, skipping instrumentation',\n );\n return;\n }\n\n const existingHandleErrorImplementation = firstDeclaration.init;\n const existingParams = existingHandleErrorImplementation.params;\n const existingBody = existingHandleErrorImplementation.body;\n\n const requestParam = {\n ...recast.types.builders.property(\n 'init',\n recast.types.builders.identifier('request'), // key\n recast.types.builders.identifier('request'), // value\n ),\n shorthand: true,\n };\n // Add error and {request} parameters to handleError function if not present\n // When none of the parameters exist\n if (existingParams.length === 0) {\n existingParams.push(\n recast.types.builders.identifier('error'),\n recast.types.builders.objectPattern([requestParam]),\n );\n // When only error parameter exists\n } else if (existingParams.length === 1) {\n existingParams.push(recast.types.builders.objectPattern([requestParam]));\n // When both parameters exist, but request is not destructured\n } else if (\n existingParams[1].type === 'ObjectPattern' &&\n !existingParams[1].properties.some(\n (prop: t.ObjectProperty) =>\n safeGetIdentifierName(prop.key) === 'request',\n )\n ) {\n existingParams[1].properties.push(requestParam);\n }\n\n // Add the Sentry call to the function body\n existingBody.body.push(sentryCall);\n }\n}\n"]}
1
+ {"version":3,"file":"server-entry.js","sourceRoot":"","sources":["../../../../src/react-router/codemods/server-entry.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-argument */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-return */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport type { ProxifiedModule } from 'magicast';\n\nimport * as recast from 'recast';\nimport type { namedTypes as t } from 'ast-types';\n\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\nimport chalk from 'chalk';\n\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport { generateCode, loadFile, writeFile } from 'magicast';\nimport { debug } from '../../utils/debug';\nimport {\n hasSentryContent,\n safeCalleeIdentifierMatch,\n safeGetIdentifierName,\n} from '../../utils/ast-utils';\nimport { getAfterImportsInsertionIndex } from './utils';\n\nexport async function instrumentServerEntry(\n serverEntryPath: string,\n useInstrumentationAPI = false,\n): Promise<void> {\n const serverEntryAst = await loadFile(serverEntryPath);\n\n if (!hasSentryContent(serverEntryAst.$ast as t.Program)) {\n serverEntryAst.imports.$add({\n from: '@sentry/react-router',\n imported: '*',\n local: 'Sentry',\n });\n }\n\n instrumentHandleError(serverEntryAst);\n instrumentHandleRequest(serverEntryAst);\n\n if (useInstrumentationAPI) {\n instrumentUnstableInstrumentations(serverEntryAst);\n }\n\n await writeFile(serverEntryAst.$ast, serverEntryPath);\n}\n\nfunction instrumentUnstableInstrumentations(\n originalEntryServerMod: ProxifiedModule<any>,\n): void {\n const originalEntryServerModAST = originalEntryServerMod.$ast as t.Program;\n\n const hasUnstableInstrumentations = originalEntryServerModAST.body.some(\n (node) => {\n if (\n node.type !== 'ExportNamedDeclaration' ||\n node.declaration?.type !== 'VariableDeclaration'\n ) {\n return false;\n }\n\n const declarations = node.declaration.declarations;\n if (!declarations || declarations.length === 0) {\n return false;\n }\n\n const firstDeclaration = declarations[0];\n if (!firstDeclaration || firstDeclaration.type !== 'VariableDeclarator') {\n return false;\n }\n\n const id = firstDeclaration.id;\n return (\n id &&\n id.type === 'Identifier' &&\n id.name === 'unstable_instrumentations'\n );\n },\n );\n\n if (hasUnstableInstrumentations) {\n debug(\n 'unstable_instrumentations export already exists, skipping adding it again',\n );\n return;\n }\n\n const instrumentationsExport = recast.parse(\n `export const unstable_instrumentations = [Sentry.createSentryServerInstrumentation()];`,\n ).program.body[0];\n\n originalEntryServerModAST.body.push(instrumentationsExport);\n}\n\nexport function instrumentHandleRequest(\n originalEntryServerMod: ProxifiedModule<any>,\n): void {\n const originalEntryServerModAST = originalEntryServerMod.$ast as t.Program;\n\n const defaultServerEntryExport = originalEntryServerModAST.body.find(\n (node) => {\n return node.type === 'ExportDefaultDeclaration';\n },\n );\n\n if (!defaultServerEntryExport) {\n clack.log.warn(\n `Could not find function ${chalk.cyan(\n 'handleRequest',\n )} in your server entry file. Creating one for you.`,\n );\n\n let foundServerRouterImport = false;\n let foundRenderToPipeableStreamImport = false;\n let foundCreateReadableStreamFromReadableImport = false;\n\n originalEntryServerMod.imports.$items.forEach((item) => {\n if (item.imported === 'ServerRouter' && item.from === 'react-router') {\n foundServerRouterImport = true;\n }\n if (\n item.imported === 'renderToPipeableStream' &&\n item.from === 'react-dom/server'\n ) {\n foundRenderToPipeableStreamImport = true;\n }\n if (\n item.imported === 'createReadableStreamFromReadable' &&\n item.from === '@react-router/node'\n ) {\n foundCreateReadableStreamFromReadableImport = true;\n }\n });\n\n if (!foundServerRouterImport) {\n originalEntryServerMod.imports.$add({\n from: 'react-router',\n imported: 'ServerRouter',\n local: 'ServerRouter',\n });\n }\n\n if (!foundRenderToPipeableStreamImport) {\n originalEntryServerMod.imports.$add({\n from: 'react-dom/server',\n imported: 'renderToPipeableStream',\n local: 'renderToPipeableStream',\n });\n }\n\n if (!foundCreateReadableStreamFromReadableImport) {\n originalEntryServerMod.imports.$add({\n from: '@react-router/node',\n imported: 'createReadableStreamFromReadable',\n local: 'createReadableStreamFromReadable',\n });\n }\n\n const implementation =\n recast.parse(`const handleRequest = Sentry.createSentryHandleRequest({\n ServerRouter,\n renderToPipeableStream,\n createReadableStreamFromReadable,\n})`).program.body[0];\n\n try {\n originalEntryServerModAST.body.splice(\n getAfterImportsInsertionIndex(originalEntryServerModAST),\n 0,\n implementation,\n );\n\n originalEntryServerModAST.body.push({\n type: 'ExportDefaultDeclaration',\n declaration: {\n type: 'Identifier',\n name: 'handleRequest',\n },\n });\n } catch (error) {\n debug('Failed to insert handleRequest implementation:', error);\n throw new Error(\n 'Could not automatically instrument handleRequest. Please add it manually.',\n );\n }\n } else if (\n defaultServerEntryExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(defaultServerEntryExport).code.includes(\n 'wrapSentryHandleRequest',\n )\n ) {\n debug('wrapSentryHandleRequest is already used, skipping wrapping again');\n clack.log.info(\n 'Sentry handleRequest wrapper already detected, skipping instrumentation.',\n );\n } else {\n let defaultExportNode: recast.types.namedTypes.ExportDefaultDeclaration | null =\n null;\n const defaultExportIndex = originalEntryServerModAST.body.findIndex(\n (node) => {\n const found = node.type === 'ExportDefaultDeclaration';\n\n if (found) {\n defaultExportNode = node;\n }\n\n return found;\n },\n );\n\n if (defaultExportIndex !== -1 && defaultExportNode !== null) {\n recast.visit(defaultExportNode, {\n visitCallExpression(path) {\n if (\n safeCalleeIdentifierMatch(path.value.callee, 'pipe') &&\n path.value.arguments.length &&\n path.value.arguments[0].type === 'Identifier' &&\n safeGetIdentifierName(path.value.arguments[0]) === 'body'\n ) {\n const wrapped = recast.types.builders.callExpression(\n recast.types.builders.memberExpression(\n recast.types.builders.identifier('Sentry'),\n recast.types.builders.identifier('getMetaTagTransformer'),\n ),\n [path.value.arguments[0]],\n );\n\n path.value.arguments[0] = wrapped;\n }\n\n this.traverse(path);\n },\n });\n\n // Replace the existing default export with the unwrapped function declaration\n // @ts-expect-error - declaration works here because the AST is proxified by magicast\n const funcDeclaration = defaultExportNode.declaration;\n // Make non-async functions async so the return type matches wrapSentryHandleRequest\n if (\n funcDeclaration.type === 'FunctionDeclaration' &&\n !funcDeclaration.async\n ) {\n funcDeclaration.async = true;\n }\n originalEntryServerModAST.body.splice(\n defaultExportIndex,\n 1,\n funcDeclaration,\n );\n\n // Adding our wrapped export\n originalEntryServerModAST.body.push(\n recast.types.builders.exportDefaultDeclaration(\n recast.types.builders.callExpression(\n recast.types.builders.memberExpression(\n recast.types.builders.identifier('Sentry'),\n recast.types.builders.identifier('wrapSentryHandleRequest'),\n ),\n [recast.types.builders.identifier('handleRequest')],\n ),\n ),\n );\n }\n }\n}\n\nexport function instrumentHandleError(\n originalEntryServerMod: ProxifiedModule<any>,\n): void {\n const originalEntryServerModAST = originalEntryServerMod.$ast as t.Program;\n\n const handleErrorFunctionExport = originalEntryServerModAST.body.find(\n (node) => {\n return (\n node.type === 'ExportNamedDeclaration' &&\n node.declaration?.type === 'FunctionDeclaration' &&\n node.declaration.id?.name === 'handleError'\n );\n },\n );\n\n const handleErrorFunctionVariableDeclarationExport =\n originalEntryServerModAST.body.find((node) => {\n if (\n node.type !== 'ExportNamedDeclaration' ||\n node.declaration?.type !== 'VariableDeclaration'\n ) {\n return false;\n }\n\n const declarations = node.declaration.declarations;\n if (!declarations || declarations.length === 0) {\n return false;\n }\n\n const firstDeclaration = declarations[0];\n if (!firstDeclaration || firstDeclaration.type !== 'VariableDeclarator') {\n return false;\n }\n\n const id = firstDeclaration.id;\n return id && id.type === 'Identifier' && id.name === 'handleError';\n });\n\n if (\n !handleErrorFunctionExport &&\n !handleErrorFunctionVariableDeclarationExport\n ) {\n clack.log.warn(\n `Could not find function ${chalk.cyan(\n 'handleError',\n )} in your server entry file. Creating one for you.`,\n );\n\n const implementation =\n recast.parse(`const handleError = Sentry.createSentryHandleError({\n logErrors: false\n})`).program.body[0];\n\n originalEntryServerModAST.body.splice(\n getAfterImportsInsertionIndex(originalEntryServerModAST),\n 0,\n recast.types.builders.exportNamedDeclaration(implementation),\n );\n } else if (\n (handleErrorFunctionExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(handleErrorFunctionExport).code.includes(\n 'captureException',\n )) ||\n (handleErrorFunctionVariableDeclarationExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(handleErrorFunctionVariableDeclarationExport).code.includes(\n 'captureException',\n ))\n ) {\n debug(\n 'Found captureException inside handleError, skipping adding it again',\n );\n } else if (\n (handleErrorFunctionExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(handleErrorFunctionExport).code.includes(\n 'createSentryHandleError',\n )) ||\n (handleErrorFunctionVariableDeclarationExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(handleErrorFunctionVariableDeclarationExport).code.includes(\n 'createSentryHandleError',\n ))\n ) {\n debug('createSentryHandleError is already used, skipping adding it again');\n } else if (handleErrorFunctionExport) {\n // Create the Sentry captureException call as an IfStatement\n const sentryCall = recast.parse(`if (!request.signal.aborted) {\n Sentry.captureException(error);\n}`).program.body[0];\n\n // Safely insert the Sentry call at the beginning of the handleError function body\n // @ts-expect-error - declaration works here because the AST is proxified by magicast\n const declaration = handleErrorFunctionExport.declaration;\n if (\n declaration &&\n declaration.body &&\n declaration.body.body &&\n Array.isArray(declaration.body.body)\n ) {\n declaration.body.body.unshift(sentryCall);\n } else {\n debug(\n 'Cannot safely access handleError function body, skipping instrumentation',\n );\n }\n } else if (handleErrorFunctionVariableDeclarationExport) {\n // Create the Sentry captureException call as an IfStatement\n const sentryCall = recast.parse(`if (!request.signal.aborted) {\n Sentry.captureException(error);\n}`).program.body[0];\n\n // Safe access to existing handle error implementation with proper null checks\n // We know this is ExportNamedDeclaration with VariableDeclaration from the earlier find\n const exportDeclaration =\n handleErrorFunctionVariableDeclarationExport as any;\n if (\n !exportDeclaration.declaration ||\n exportDeclaration.declaration.type !== 'VariableDeclaration' ||\n !exportDeclaration.declaration.declarations ||\n exportDeclaration.declaration.declarations.length === 0\n ) {\n debug(\n 'Cannot safely access handleError variable declaration, skipping instrumentation',\n );\n return;\n }\n\n const firstDeclaration = exportDeclaration.declaration.declarations[0];\n if (\n !firstDeclaration ||\n firstDeclaration.type !== 'VariableDeclarator' ||\n !firstDeclaration.init\n ) {\n debug(\n 'Cannot safely access handleError variable declarator init, skipping instrumentation',\n );\n return;\n }\n\n const existingHandleErrorImplementation = firstDeclaration.init;\n const existingParams = existingHandleErrorImplementation.params;\n const existingBody = existingHandleErrorImplementation.body;\n\n const requestParam = {\n ...recast.types.builders.property(\n 'init',\n recast.types.builders.identifier('request'), // key\n recast.types.builders.identifier('request'), // value\n ),\n shorthand: true,\n };\n // Add error and {request} parameters to handleError function if not present\n // When none of the parameters exist\n if (existingParams.length === 0) {\n existingParams.push(\n recast.types.builders.identifier('error'),\n recast.types.builders.objectPattern([requestParam]),\n );\n // When only error parameter exists\n } else if (existingParams.length === 1) {\n existingParams.push(recast.types.builders.objectPattern([requestParam]));\n // When both parameters exist, but request is not destructured\n } else if (\n existingParams[1].type === 'ObjectPattern' &&\n !existingParams[1].properties.some(\n (prop: t.ObjectProperty) =>\n safeGetIdentifierName(prop.key) === 'request',\n )\n ) {\n existingParams[1].properties.push(requestParam);\n }\n\n // Add the Sentry call to the function body\n existingBody.body.push(sentryCall);\n }\n}\n"]}
@@ -36,6 +36,7 @@ const magicast_1 = require("magicast");
36
36
  const prompts_1 = __importDefault(require("@clack/prompts"));
37
37
  const chalk_1 = __importDefault(require("chalk"));
38
38
  const ast_utils_1 = require("../../utils/ast-utils");
39
+ const debug_1 = require("../../utils/debug");
39
40
  /**
40
41
  * Extracts ObjectExpression from function body.
41
42
  * Handles both arrow functions with object returns and block statements with explicit returns.
@@ -85,6 +86,48 @@ function createSentryPluginCall(orgSlug, projectSlug) {
85
86
  b.identifier('config'),
86
87
  ]);
87
88
  }
89
+ /** Adds @sentry/react-router to optimizeDeps.exclude to prevent 504 errors during dev. */
90
+ function addOptimizeDepsExclude(configObj) {
91
+ const b = recast.types.builders;
92
+ const optimizeDeps = (0, ast_utils_1.findProperty)(configObj, 'optimizeDeps');
93
+ const optimizeDepsObj = optimizeDeps?.type === 'ObjectProperty' &&
94
+ optimizeDeps.value?.type === 'ObjectExpression'
95
+ ? optimizeDeps.value
96
+ : null;
97
+ let targetDepsObj;
98
+ if (!optimizeDepsObj) {
99
+ if (optimizeDeps) {
100
+ (0, debug_1.debug)('optimizeDeps is not a static object, skipping exclude');
101
+ return;
102
+ }
103
+ targetDepsObj = b.objectExpression([]);
104
+ configObj.properties.push(b.objectProperty(b.identifier('optimizeDeps'), targetDepsObj));
105
+ }
106
+ else {
107
+ targetDepsObj = optimizeDepsObj;
108
+ }
109
+ const excludeProp = (0, ast_utils_1.findProperty)(targetDepsObj, 'exclude');
110
+ const excludeArr = excludeProp?.type === 'ObjectProperty' &&
111
+ excludeProp.value?.type === 'ArrayExpression'
112
+ ? excludeProp.value
113
+ : null;
114
+ let targetArr;
115
+ if (!excludeArr) {
116
+ if (excludeProp) {
117
+ (0, debug_1.debug)('optimizeDeps.exclude is not a static array, skipping');
118
+ return;
119
+ }
120
+ targetArr = b.arrayExpression([]);
121
+ targetDepsObj.properties.push(b.objectProperty(b.identifier('exclude'), targetArr));
122
+ }
123
+ else {
124
+ targetArr = excludeArr;
125
+ }
126
+ const isAlreadyExcluded = targetArr.elements.some((el) => el?.type === 'StringLiteral' && el.value === '@sentry/react-router');
127
+ if (!isAlreadyExcluded) {
128
+ targetArr.elements.push(b.stringLiteral('@sentry/react-router'));
129
+ }
130
+ }
88
131
  function addReactRouterPluginToViteConfig(program, orgSlug, projectSlug) {
89
132
  const b = recast.types.builders;
90
133
  let wasConverted = false;
@@ -135,6 +178,8 @@ function addReactRouterPluginToViteConfig(program, orgSlug, projectSlug) {
135
178
  else {
136
179
  return { success: false, wasConverted };
137
180
  }
181
+ // Prevent 504 "Outdated Optimize Dep" errors in dev (https://github.com/vitejs/vite/issues/13506)
182
+ addOptimizeDepsExclude(configObj);
138
183
  return { success: true, wasConverted };
139
184
  }
140
185
  exports.addReactRouterPluginToViteConfig = addReactRouterPluginToViteConfig;
@@ -161,7 +206,7 @@ async function instrumentViteConfig(orgSlug, projectSlug) {
161
206
  if (!success) {
162
207
  throw new Error('Failed to modify Vite config structure');
163
208
  }
164
- const code = (0, magicast_1.generateCode)(mod.$ast).code;
209
+ const code = (0, ast_utils_1.preserveTrailingNewline)(configContent, (0, magicast_1.generateCode)(mod.$ast).code);
165
210
  await fs.promises.writeFile(configPath, code);
166
211
  return { wasConverted };
167
212
  }
@@ -1 +1 @@
1
- {"version":3,"file":"vite.js","sourceRoot":"","sources":["../../../../src/react-router/codemods/vite.ts"],"names":[],"mappings":"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","sourcesContent":["import type { namedTypes as t } from 'ast-types';\nimport * as recast from 'recast';\nimport * as path from 'path';\nimport * as fs from 'fs';\n\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport { parseModule, generateCode } from 'magicast';\n\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\nimport chalk from 'chalk';\n\nimport { hasSentryContent, findProperty } from '../../utils/ast-utils';\n\n/**\n * Extracts ObjectExpression from function body.\n * Handles both arrow functions with object returns and block statements with explicit returns.\n *\n * - Arrow with object-return: (config) => ({ ... })\n * - Arrow with block: (config) => { return { ... }; }\n * - Function with block: function(config) { return { ... }; }\n *\n * @param body - The function body to extract from\n * @returns The ObjectExpression if found, undefined otherwise\n */\nfunction extractFromFunctionBody(\n body: t.Expression | t.BlockStatement,\n): t.ObjectExpression | undefined {\n if (body.type === 'ObjectExpression') {\n return body as t.ObjectExpression;\n }\n\n if (body.type === 'BlockStatement') {\n const blockBody = body as t.BlockStatement;\n const returnStatement = blockBody.body.find(\n (stmt: t.Statement): stmt is t.ReturnStatement =>\n stmt.type === 'ReturnStatement',\n );\n\n return returnStatement?.argument?.type === 'ObjectExpression'\n ? returnStatement.argument\n : undefined;\n }\n\n return undefined;\n}\n\n/**\n * Creates the sentryReactRouter Vite plugin call expression.\n *\n * Generates AST for:\n * sentryReactRouter({\n * org: \"...\",\n * project: \"...\",\n * authToken: process.env.SENTRY_AUTH_TOKEN\n * }, config)\n *\n * @param orgSlug - Sentry organization slug\n * @param projectSlug - Sentry project slug\n * @returns CallExpression node for the Sentry Vite plugin\n */\nfunction createSentryPluginCall(\n orgSlug: string,\n projectSlug: string,\n): t.CallExpression {\n const b = recast.types.builders;\n return b.callExpression(b.identifier('sentryReactRouter'), [\n b.objectExpression([\n b.objectProperty(b.identifier('org'), b.stringLiteral(orgSlug)),\n b.objectProperty(b.identifier('project'), b.stringLiteral(projectSlug)),\n b.objectProperty(\n b.identifier('authToken'),\n b.memberExpression(\n b.memberExpression(b.identifier('process'), b.identifier('env')),\n b.identifier('SENTRY_AUTH_TOKEN'),\n ),\n ),\n ]),\n b.identifier('config'),\n ]);\n}\n\nexport function addReactRouterPluginToViteConfig(\n program: t.Program,\n orgSlug: string,\n projectSlug: string,\n): { success: boolean; wasConverted: boolean } {\n const b = recast.types.builders;\n let wasConverted = false;\n\n const defaultExport = program.body.find(\n (node) => node.type === 'ExportDefaultDeclaration',\n ) as t.ExportDefaultDeclaration | undefined;\n\n if (!defaultExport) {\n return { success: false, wasConverted: false };\n }\n\n let configObj: t.ObjectExpression | undefined;\n let defineConfigCall: t.CallExpression | undefined;\n\n if (\n defaultExport.declaration.type === 'CallExpression' &&\n defaultExport.declaration.callee.type === 'Identifier' &&\n defaultExport.declaration.callee.name === 'defineConfig'\n ) {\n defineConfigCall = defaultExport.declaration;\n\n // Early exit if not single argument\n if (defineConfigCall.arguments.length !== 1) {\n return { success: false, wasConverted: false };\n }\n\n const arg = defineConfigCall.arguments[0];\n\n if (arg.type === 'ObjectExpression') {\n configObj = arg;\n // Convert to function form\n const arrowFunction = b.arrowFunctionExpression(\n [b.identifier('config')],\n configObj,\n );\n defineConfigCall.arguments[0] = arrowFunction;\n wasConverted = true;\n } else if (\n arg.type === 'ArrowFunctionExpression' ||\n arg.type === 'FunctionExpression'\n ) {\n configObj = extractFromFunctionBody(arg.body);\n }\n }\n\n if (!configObj) {\n return { success: false, wasConverted };\n }\n\n const pluginsProp = findProperty(configObj, 'plugins');\n const sentryPluginCall = createSentryPluginCall(orgSlug, projectSlug);\n\n if (!pluginsProp) {\n configObj.properties.push(\n b.objectProperty(\n b.identifier('plugins'),\n b.arrayExpression([sentryPluginCall]),\n ),\n );\n } else if (\n pluginsProp.value.type === 'ArrayExpression' &&\n pluginsProp.type === 'ObjectProperty'\n ) {\n const arrayExpr = pluginsProp.value;\n // Defensive: ensure elements array exists\n if (!arrayExpr.elements) {\n arrayExpr.elements = [];\n }\n arrayExpr.elements.push(sentryPluginCall);\n } else {\n return { success: false, wasConverted };\n }\n\n return { success: true, wasConverted };\n}\n\nexport async function instrumentViteConfig(\n orgSlug: string,\n projectSlug: string,\n): Promise<{ wasConverted: boolean }> {\n const configPath = fs.existsSync(path.join(process.cwd(), 'vite.config.ts'))\n ? path.join(process.cwd(), 'vite.config.ts')\n : path.join(process.cwd(), 'vite.config.js');\n\n if (!fs.existsSync(configPath)) {\n throw new Error('Could not find vite.config.ts or vite.config.js');\n }\n\n const configContent = await fs.promises.readFile(configPath, 'utf-8');\n const filename = chalk.cyan(path.basename(configPath));\n\n const mod = parseModule(configContent);\n\n if (hasSentryContent(mod.$ast as t.Program)) {\n clack.log.info(`${filename} already contains sentryReactRouter plugin.`);\n return { wasConverted: false };\n }\n\n mod.imports.$add({\n from: '@sentry/react-router',\n imported: 'sentryReactRouter',\n local: 'sentryReactRouter',\n });\n\n const { success, wasConverted } = addReactRouterPluginToViteConfig(\n mod.$ast as t.Program,\n orgSlug,\n projectSlug,\n );\n\n if (!success) {\n throw new Error('Failed to modify Vite config structure');\n }\n\n const code = generateCode(mod.$ast).code;\n await fs.promises.writeFile(configPath, code);\n\n return { wasConverted };\n}\n"]}
1
+ {"version":3,"file":"vite.js","sourceRoot":"","sources":["../../../../src/react-router/codemods/vite.ts"],"names":[],"mappings":"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","sourcesContent":["import type { namedTypes as t } from 'ast-types';\nimport * as recast from 'recast';\nimport * as path from 'path';\nimport * as fs from 'fs';\n\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport { parseModule, generateCode } from 'magicast';\n\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\nimport chalk from 'chalk';\n\nimport {\n hasSentryContent,\n findProperty,\n preserveTrailingNewline,\n} from '../../utils/ast-utils';\nimport { debug } from '../../utils/debug';\n\n/**\n * Extracts ObjectExpression from function body.\n * Handles both arrow functions with object returns and block statements with explicit returns.\n *\n * - Arrow with object-return: (config) => ({ ... })\n * - Arrow with block: (config) => { return { ... }; }\n * - Function with block: function(config) { return { ... }; }\n *\n * @param body - The function body to extract from\n * @returns The ObjectExpression if found, undefined otherwise\n */\nfunction extractFromFunctionBody(\n body: t.Expression | t.BlockStatement,\n): t.ObjectExpression | undefined {\n if (body.type === 'ObjectExpression') {\n return body as t.ObjectExpression;\n }\n\n if (body.type === 'BlockStatement') {\n const blockBody = body as t.BlockStatement;\n const returnStatement = blockBody.body.find(\n (stmt: t.Statement): stmt is t.ReturnStatement =>\n stmt.type === 'ReturnStatement',\n );\n\n return returnStatement?.argument?.type === 'ObjectExpression'\n ? returnStatement.argument\n : undefined;\n }\n\n return undefined;\n}\n\n/**\n * Creates the sentryReactRouter Vite plugin call expression.\n *\n * Generates AST for:\n * sentryReactRouter({\n * org: \"...\",\n * project: \"...\",\n * authToken: process.env.SENTRY_AUTH_TOKEN\n * }, config)\n *\n * @param orgSlug - Sentry organization slug\n * @param projectSlug - Sentry project slug\n * @returns CallExpression node for the Sentry Vite plugin\n */\nfunction createSentryPluginCall(\n orgSlug: string,\n projectSlug: string,\n): t.CallExpression {\n const b = recast.types.builders;\n return b.callExpression(b.identifier('sentryReactRouter'), [\n b.objectExpression([\n b.objectProperty(b.identifier('org'), b.stringLiteral(orgSlug)),\n b.objectProperty(b.identifier('project'), b.stringLiteral(projectSlug)),\n b.objectProperty(\n b.identifier('authToken'),\n b.memberExpression(\n b.memberExpression(b.identifier('process'), b.identifier('env')),\n b.identifier('SENTRY_AUTH_TOKEN'),\n ),\n ),\n ]),\n b.identifier('config'),\n ]);\n}\n\n/** Adds @sentry/react-router to optimizeDeps.exclude to prevent 504 errors during dev. */\nfunction addOptimizeDepsExclude(configObj: t.ObjectExpression): void {\n const b = recast.types.builders;\n\n const optimizeDeps = findProperty(configObj, 'optimizeDeps');\n const optimizeDepsObj =\n optimizeDeps?.type === 'ObjectProperty' &&\n optimizeDeps.value?.type === 'ObjectExpression'\n ? optimizeDeps.value\n : null;\n\n let targetDepsObj: t.ObjectExpression;\n if (!optimizeDepsObj) {\n if (optimizeDeps) {\n debug('optimizeDeps is not a static object, skipping exclude');\n return;\n }\n targetDepsObj = b.objectExpression([]);\n configObj.properties.push(\n b.objectProperty(b.identifier('optimizeDeps'), targetDepsObj),\n );\n } else {\n targetDepsObj = optimizeDepsObj;\n }\n\n const excludeProp = findProperty(targetDepsObj, 'exclude');\n const excludeArr =\n excludeProp?.type === 'ObjectProperty' &&\n excludeProp.value?.type === 'ArrayExpression'\n ? excludeProp.value\n : null;\n\n let targetArr: t.ArrayExpression;\n if (!excludeArr) {\n if (excludeProp) {\n debug('optimizeDeps.exclude is not a static array, skipping');\n return;\n }\n targetArr = b.arrayExpression([]);\n targetDepsObj.properties.push(\n b.objectProperty(b.identifier('exclude'), targetArr),\n );\n } else {\n targetArr = excludeArr;\n }\n\n const isAlreadyExcluded = targetArr.elements.some(\n (el) => el?.type === 'StringLiteral' && el.value === '@sentry/react-router',\n );\n if (!isAlreadyExcluded) {\n targetArr.elements.push(b.stringLiteral('@sentry/react-router'));\n }\n}\n\nexport function addReactRouterPluginToViteConfig(\n program: t.Program,\n orgSlug: string,\n projectSlug: string,\n): { success: boolean; wasConverted: boolean } {\n const b = recast.types.builders;\n let wasConverted = false;\n\n const defaultExport = program.body.find(\n (node) => node.type === 'ExportDefaultDeclaration',\n ) as t.ExportDefaultDeclaration | undefined;\n\n if (!defaultExport) {\n return { success: false, wasConverted: false };\n }\n\n let configObj: t.ObjectExpression | undefined;\n let defineConfigCall: t.CallExpression | undefined;\n\n if (\n defaultExport.declaration.type === 'CallExpression' &&\n defaultExport.declaration.callee.type === 'Identifier' &&\n defaultExport.declaration.callee.name === 'defineConfig'\n ) {\n defineConfigCall = defaultExport.declaration;\n\n // Early exit if not single argument\n if (defineConfigCall.arguments.length !== 1) {\n return { success: false, wasConverted: false };\n }\n\n const arg = defineConfigCall.arguments[0];\n\n if (arg.type === 'ObjectExpression') {\n configObj = arg;\n // Convert to function form\n const arrowFunction = b.arrowFunctionExpression(\n [b.identifier('config')],\n configObj,\n );\n defineConfigCall.arguments[0] = arrowFunction;\n wasConverted = true;\n } else if (\n arg.type === 'ArrowFunctionExpression' ||\n arg.type === 'FunctionExpression'\n ) {\n configObj = extractFromFunctionBody(arg.body);\n }\n }\n\n if (!configObj) {\n return { success: false, wasConverted };\n }\n\n const pluginsProp = findProperty(configObj, 'plugins');\n const sentryPluginCall = createSentryPluginCall(orgSlug, projectSlug);\n\n if (!pluginsProp) {\n configObj.properties.push(\n b.objectProperty(\n b.identifier('plugins'),\n b.arrayExpression([sentryPluginCall]),\n ),\n );\n } else if (\n pluginsProp.value.type === 'ArrayExpression' &&\n pluginsProp.type === 'ObjectProperty'\n ) {\n const arrayExpr = pluginsProp.value;\n // Defensive: ensure elements array exists\n if (!arrayExpr.elements) {\n arrayExpr.elements = [];\n }\n arrayExpr.elements.push(sentryPluginCall);\n } else {\n return { success: false, wasConverted };\n }\n\n // Prevent 504 \"Outdated Optimize Dep\" errors in dev (https://github.com/vitejs/vite/issues/13506)\n addOptimizeDepsExclude(configObj);\n\n return { success: true, wasConverted };\n}\n\nexport async function instrumentViteConfig(\n orgSlug: string,\n projectSlug: string,\n): Promise<{ wasConverted: boolean }> {\n const configPath = fs.existsSync(path.join(process.cwd(), 'vite.config.ts'))\n ? path.join(process.cwd(), 'vite.config.ts')\n : path.join(process.cwd(), 'vite.config.js');\n\n if (!fs.existsSync(configPath)) {\n throw new Error('Could not find vite.config.ts or vite.config.js');\n }\n\n const configContent = await fs.promises.readFile(configPath, 'utf-8');\n const filename = chalk.cyan(path.basename(configPath));\n\n const mod = parseModule(configContent);\n\n if (hasSentryContent(mod.$ast as t.Program)) {\n clack.log.info(`${filename} already contains sentryReactRouter plugin.`);\n return { wasConverted: false };\n }\n\n mod.imports.$add({\n from: '@sentry/react-router',\n imported: 'sentryReactRouter',\n local: 'sentryReactRouter',\n });\n\n const { success, wasConverted } = addReactRouterPluginToViteConfig(\n mod.$ast as t.Program,\n orgSlug,\n projectSlug,\n );\n\n if (!success) {\n throw new Error('Failed to modify Vite config structure');\n }\n\n const code = preserveTrailingNewline(\n configContent,\n generateCode(mod.$ast).code,\n );\n await fs.promises.writeFile(configPath, code);\n\n return { wasConverted };\n}\n"]}
@@ -1,4 +1,27 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
27
  };
@@ -7,6 +30,7 @@ exports.runReactRouterWizard = void 0;
7
30
  // @ts-expect-error - clack is ESM and TS complains about that. It works though
8
31
  const prompts_1 = __importDefault(require("@clack/prompts"));
9
32
  const chalk_1 = __importDefault(require("chalk"));
33
+ const Sentry = __importStar(require("@sentry/node"));
10
34
  const telemetry_1 = require("../telemetry");
11
35
  const clack_1 = require("../utils/clack");
12
36
  const mcp_config_1 = require("../utils/clack/mcp-config");
@@ -15,6 +39,7 @@ const debug_1 = require("../utils/debug");
15
39
  const sdk_example_1 = require("./sdk-example");
16
40
  const sdk_setup_1 = require("./sdk-setup");
17
41
  const templates_1 = require("./templates");
42
+ const abort_if_sportlight_not_supported_1 = require("../utils/abort-if-sportlight-not-supported");
18
43
  async function runReactRouterWizard(options) {
19
44
  return (0, telemetry_1.withTelemetry)({
20
45
  enabled: options.telemetryEnabled,
@@ -45,10 +70,7 @@ async function runReactRouterWizardWithTelemetry(options) {
45
70
  const sentryAlreadyInstalled = (0, package_json_1.hasPackageInstalled)('@sentry/react-router', packageJson);
46
71
  const projectData = await (0, clack_1.getOrAskForProjectData)(options, 'javascript-react-router');
47
72
  if (projectData.spotlight) {
48
- prompts_1.default.log.warn('Spotlight mode is not yet supported for React Router.');
49
- prompts_1.default.log.info('Spotlight is currently only available for Next.js.');
50
- await (0, clack_1.abort)('Exiting wizard', 0);
51
- return;
73
+ return (0, abort_if_sportlight_not_supported_1.abortIfSpotlightNotSupported)('React Router');
52
74
  }
53
75
  const { selectedProject, authToken, selfHosted, sentryUrl } = projectData;
54
76
  await (0, clack_1.installPackage)({
@@ -77,6 +99,18 @@ async function runReactRouterWizardWithTelemetry(options) {
77
99
  enabledHint: 'recommended for production debugging',
78
100
  },
79
101
  ]);
102
+ // Only ask about Instrumentation API when Tracing is enabled, since it depends on it
103
+ let instrumentationAPISelected = false;
104
+ if (featureSelection.performance) {
105
+ const instrumentationAPISelection = await (0, clack_1.featureSelectionPrompt)([
106
+ {
107
+ id: 'instrumentationAPI',
108
+ prompt: `Do you want to use the ${chalk_1.default.bold('Instrumentation API')} for automatic tracing of loaders, actions, and middleware?`,
109
+ enabledHint: 'recommended',
110
+ },
111
+ ]);
112
+ instrumentationAPISelected = instrumentationAPISelection.instrumentationAPI;
113
+ }
80
114
  if (featureSelection.profiling) {
81
115
  const profilingAlreadyInstalled = (0, package_json_1.hasPackageInstalled)('@sentry/profiling-node', packageJson);
82
116
  await (0, clack_1.installPackage)({
@@ -87,7 +121,7 @@ async function runReactRouterWizardWithTelemetry(options) {
87
121
  const createExamplePageSelection = await (0, clack_1.askShouldCreateExamplePage)();
88
122
  (0, telemetry_1.traceStep)('Reveal missing entry files', () => {
89
123
  try {
90
- (0, sdk_setup_1.runReactRouterReveal)(typeScriptDetected);
124
+ (0, sdk_setup_1.runReactRouterReveal)();
91
125
  prompts_1.default.log.success('Entry files are ready for instrumentation');
92
126
  }
93
127
  catch (e) {
@@ -96,14 +130,25 @@ Please create your entry files manually using React Router v7 commands.`);
96
130
  (0, debug_1.debug)(e);
97
131
  }
98
132
  });
133
+ Sentry.setTag('instrumentation-api-selected', instrumentationAPISelected);
134
+ let useInstrumentationAPI = instrumentationAPISelected;
135
+ if (useInstrumentationAPI && !(0, sdk_setup_1.supportsInstrumentationAPI)(packageJson)) {
136
+ Sentry.setTag('instrumentation-api-version-guard', true);
137
+ const detectedVersion = (0, sdk_setup_1.getReactRouterVersion)(packageJson) ?? 'unknown';
138
+ prompts_1.default.log.warn(`The Instrumentation API requires React Router ${chalk_1.default.cyan('>=7.9.5')} (detected ${chalk_1.default.cyan(detectedVersion)}). Your version does not meet this requirement.\n` +
139
+ `Continuing without the Instrumentation API. Please upgrade React Router to use this feature:\n` +
140
+ chalk_1.default.dim('https://docs.sentry.io/platforms/javascript/guides/react-router/'));
141
+ useInstrumentationAPI = false;
142
+ }
143
+ Sentry.setTag('use-instrumentation-api', useInstrumentationAPI);
99
144
  await (0, telemetry_1.traceStep)('Initialize Sentry on client entry', async () => {
100
145
  try {
101
- await (0, sdk_setup_1.initializeSentryOnEntryClient)(selectedProject.keys[0].dsn.public, featureSelection.performance, featureSelection.replay, featureSelection.logs, typeScriptDetected);
146
+ await (0, sdk_setup_1.initializeSentryOnEntryClient)(selectedProject.keys[0].dsn.public, featureSelection.performance, featureSelection.replay, featureSelection.logs, typeScriptDetected, useInstrumentationAPI);
102
147
  }
103
148
  catch (e) {
104
149
  prompts_1.default.log.warn(`Could not initialize Sentry on client entry automatically.`);
105
150
  const clientEntryFilename = `entry.client.${typeScriptDetected ? 'tsx' : 'jsx'}`;
106
- const manualClientContent = (0, templates_1.getManualClientEntryContent)(selectedProject.keys[0].dsn.public, featureSelection.performance, featureSelection.replay, featureSelection.logs);
151
+ const manualClientContent = (0, templates_1.getManualClientEntryContent)(selectedProject.keys[0].dsn.public, featureSelection.performance, featureSelection.replay, featureSelection.logs, useInstrumentationAPI);
107
152
  await (0, clack_1.showCopyPasteInstructions)({
108
153
  filename: clientEntryFilename,
109
154
  codeSnippet: manualClientContent,
@@ -130,12 +175,12 @@ Please create your entry files manually using React Router v7 commands.`);
130
175
  });
131
176
  await (0, telemetry_1.traceStep)('Instrument server entry', async () => {
132
177
  try {
133
- await (0, sdk_setup_1.instrumentSentryOnEntryServer)(typeScriptDetected);
178
+ await (0, sdk_setup_1.instrumentSentryOnEntryServer)(typeScriptDetected, useInstrumentationAPI);
134
179
  }
135
180
  catch (e) {
136
181
  prompts_1.default.log.warn(`Could not initialize Sentry on server entry automatically.`);
137
182
  const serverEntryFilename = `entry.server.${typeScriptDetected ? 'tsx' : 'jsx'}`;
138
- const manualServerContent = (0, templates_1.getManualServerEntryContent)();
183
+ const manualServerContent = (0, templates_1.getManualServerEntryContent)(useInstrumentationAPI);
139
184
  await (0, clack_1.showCopyPasteInstructions)({
140
185
  filename: serverEntryFilename,
141
186
  codeSnippet: manualServerContent,
@@ -176,7 +221,7 @@ Please create your entry files manually using React Router v7 commands.`);
176
221
  return unchanged(`{
177
222
  scripts: {
178
223
  ${minus('"start": "react-router dev"')}
179
- ${plus('"start": "NODE_OPTIONS=\'--import ./instrument.server.mjs\' react-router-serve ./build/server/index.js"')}
224
+ ${plus('"start": "NODE_ENV=production NODE_OPTIONS=\'--import ./instrument.server.mjs\' react-router-serve ./build/server/index.js"')}
180
225
  ${minus('"dev": "react-router dev"')}
181
226
  ${plus('"dev": "NODE_OPTIONS=\'--import ./instrument.server.mjs\' react-router dev"')}
182
227
  },
@@ -1 +1 @@
1
- {"version":3,"file":"react-router-wizard.js","sourceRoot":"","sources":["../../../src/react-router/react-router-wizard.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\nimport chalk from 'chalk';\n\nimport type { WizardOptions } from '../utils/types';\nimport { withTelemetry, traceStep } from '../telemetry';\nimport {\n abort,\n askShouldCreateExamplePage,\n confirmContinueIfNoOrDirtyGitRepo,\n featureSelectionPrompt,\n getOrAskForProjectData,\n getPackageDotJson,\n isUsingTypeScript,\n printWelcome,\n installPackage,\n addDotEnvSentryBuildPluginFile,\n showCopyPasteInstructions,\n makeCodeSnippet,\n runPrettierIfInstalled,\n} from '../utils/clack';\nimport { offerProjectScopedMcpConfig } from '../utils/clack/mcp-config';\nimport { hasPackageInstalled } from '../utils/package-json';\nimport { debug } from '../utils/debug';\nimport { createExamplePage } from './sdk-example';\nimport {\n isReactRouterV7,\n runReactRouterReveal,\n initializeSentryOnEntryClient,\n instrumentRootRoute,\n createServerInstrumentationFile,\n updatePackageJsonScripts,\n instrumentSentryOnEntryServer,\n configureReactRouterConfig,\n configureReactRouterVitePlugin,\n} from './sdk-setup';\nimport {\n getManualClientEntryContent,\n getManualServerEntryContent,\n getManualRootContent,\n getManualServerInstrumentContent,\n getManualReactRouterConfigContent,\n getManualViteConfigContent,\n} from './templates';\n\nexport async function runReactRouterWizard(\n options: WizardOptions,\n): Promise<void> {\n return withTelemetry(\n {\n enabled: options.telemetryEnabled,\n integration: 'reactRouter',\n wizardOptions: options,\n },\n () => runReactRouterWizardWithTelemetry(options),\n );\n}\n\nasync function runReactRouterWizardWithTelemetry(\n options: WizardOptions,\n): Promise<void> {\n printWelcome({\n wizardName: 'Sentry React Router Wizard',\n promoCode: options.promoCode,\n });\n\n const packageJson = await getPackageDotJson();\n\n if (!packageJson) {\n clack.log.error(\n 'Could not find a package.json file in the current directory',\n );\n return;\n }\n\n const typeScriptDetected = isUsingTypeScript();\n\n if (!isReactRouterV7(packageJson)) {\n clack.log.error(\n 'This wizard requires React Router v7. Please upgrade your React Router version to v7.0.0 or higher.\\n\\nFor upgrade instructions, visit: https://react-router.dev/upgrade/v7',\n );\n return;\n }\n\n await confirmContinueIfNoOrDirtyGitRepo({\n ignoreGitChanges: options.ignoreGitChanges,\n cwd: undefined,\n });\n\n const sentryAlreadyInstalled = hasPackageInstalled(\n '@sentry/react-router',\n packageJson,\n );\n\n const projectData = await getOrAskForProjectData(\n options,\n 'javascript-react-router',\n );\n\n if (projectData.spotlight) {\n clack.log.warn('Spotlight mode is not yet supported for React Router.');\n clack.log.info('Spotlight is currently only available for Next.js.');\n await abort('Exiting wizard', 0);\n return;\n }\n\n const { selectedProject, authToken, selfHosted, sentryUrl } = projectData;\n\n await installPackage({\n packageName: '@sentry/react-router',\n alreadyInstalled: sentryAlreadyInstalled,\n });\n\n const featureSelection = await featureSelectionPrompt([\n {\n id: 'performance',\n prompt: `Do you want to enable ${chalk.bold(\n 'Tracing',\n )} to track the performance of your application?`,\n enabledHint: 'recommended',\n },\n {\n id: 'replay',\n prompt: `Do you want to enable ${chalk.bold(\n 'Session Replay',\n )} to get a video-like reproduction of errors during a user session?`,\n enabledHint: 'recommended, but increases bundle size',\n },\n {\n id: 'logs',\n prompt: `Do you want to enable ${chalk.bold(\n 'Logs',\n )} to send your application logs to Sentry?`,\n enabledHint: 'recommended',\n },\n {\n id: 'profiling',\n prompt: `Do you want to enable ${chalk.bold(\n 'Profiling',\n )} to track application performance in detail?`,\n enabledHint: 'recommended for production debugging',\n },\n ]);\n\n if (featureSelection.profiling) {\n const profilingAlreadyInstalled = hasPackageInstalled(\n '@sentry/profiling-node',\n packageJson,\n );\n\n await installPackage({\n packageName: '@sentry/profiling-node',\n alreadyInstalled: profilingAlreadyInstalled,\n });\n }\n\n const createExamplePageSelection = await askShouldCreateExamplePage();\n\n traceStep('Reveal missing entry files', () => {\n try {\n runReactRouterReveal(typeScriptDetected);\n clack.log.success('Entry files are ready for instrumentation');\n } catch (e) {\n clack.log.warn(`Could not run 'npx react-router reveal'.\nPlease create your entry files manually using React Router v7 commands.`);\n debug(e);\n }\n });\n\n await traceStep('Initialize Sentry on client entry', async () => {\n try {\n await initializeSentryOnEntryClient(\n selectedProject.keys[0].dsn.public,\n featureSelection.performance,\n featureSelection.replay,\n featureSelection.logs,\n typeScriptDetected,\n );\n } catch (e) {\n clack.log.warn(\n `Could not initialize Sentry on client entry automatically.`,\n );\n\n const clientEntryFilename = `entry.client.${\n typeScriptDetected ? 'tsx' : 'jsx'\n }`;\n\n const manualClientContent = getManualClientEntryContent(\n selectedProject.keys[0].dsn.public,\n featureSelection.performance,\n featureSelection.replay,\n featureSelection.logs,\n );\n\n await showCopyPasteInstructions({\n filename: clientEntryFilename,\n codeSnippet: manualClientContent,\n hint: 'This enables error tracking and performance monitoring for your React Router app',\n });\n\n debug(e);\n }\n });\n\n await traceStep('Instrument root route', async () => {\n try {\n await instrumentRootRoute(typeScriptDetected);\n } catch (e) {\n clack.log.warn(`Could not instrument root route automatically.`);\n\n const rootFilename = `app/root.${typeScriptDetected ? 'tsx' : 'jsx'}`;\n const manualRootContent = getManualRootContent(typeScriptDetected);\n\n await showCopyPasteInstructions({\n filename: rootFilename,\n codeSnippet: manualRootContent,\n hint: 'This adds error boundary integration to capture exceptions in your React Router app',\n });\n\n debug(e);\n }\n });\n\n await traceStep('Instrument server entry', async () => {\n try {\n await instrumentSentryOnEntryServer(typeScriptDetected);\n } catch (e) {\n clack.log.warn(\n `Could not initialize Sentry on server entry automatically.`,\n );\n\n const serverEntryFilename = `entry.server.${\n typeScriptDetected ? 'tsx' : 'jsx'\n }`;\n const manualServerContent = getManualServerEntryContent();\n\n await showCopyPasteInstructions({\n filename: serverEntryFilename,\n codeSnippet: manualServerContent,\n hint: 'This configures server-side request handling and error tracking',\n });\n\n debug(e);\n }\n });\n\n await traceStep('Create server instrumentation file', async () => {\n try {\n createServerInstrumentationFile(selectedProject.keys[0].dsn.public, {\n performance: featureSelection.performance,\n replay: featureSelection.replay,\n logs: featureSelection.logs,\n profiling: featureSelection.profiling,\n });\n } catch (e) {\n clack.log.warn(\n 'Could not create a server instrumentation file automatically.',\n );\n\n const manualServerInstrumentContent = getManualServerInstrumentContent(\n selectedProject.keys[0].dsn.public,\n featureSelection.performance,\n featureSelection.profiling,\n featureSelection.logs,\n );\n\n await showCopyPasteInstructions({\n filename: 'instrument.server.mjs',\n codeSnippet: manualServerInstrumentContent,\n hint: 'Create the file if it does not exist - this initializes Sentry before your application starts',\n });\n\n debug(e);\n }\n });\n\n await traceStep('Update package.json scripts', async () => {\n try {\n await updatePackageJsonScripts();\n } catch (e) {\n clack.log.warn('Could not update start script automatically.');\n\n await showCopyPasteInstructions({\n filename: 'package.json',\n codeSnippet: makeCodeSnippet(true, (unchanged, plus, minus) => {\n return unchanged(`{\n scripts: {\n ${minus('\"start\": \"react-router dev\"')}\n ${plus(\n '\"start\": \"NODE_OPTIONS=\\'--import ./instrument.server.mjs\\' react-router-serve ./build/server/index.js\"',\n )}\n ${minus('\"dev\": \"react-router dev\"')}\n ${plus(\n '\"dev\": \"NODE_OPTIONS=\\'--import ./instrument.server.mjs\\' react-router dev\"',\n )}\n },\n // ... rest of your package.json\n }`);\n }),\n });\n\n debug(e);\n }\n });\n\n await traceStep('Create build plugin env file', async () => {\n try {\n await addDotEnvSentryBuildPluginFile(authToken);\n } catch (e) {\n clack.log.warn(\n 'Could not create .env.sentry-build-plugin file. Please create it manually.',\n );\n debug(e);\n }\n });\n\n // Validate auth token before configuring sourcemap uploads\n if (!authToken) {\n clack.log.warn(\n `${chalk.yellow(\n 'Warning:',\n )} No auth token found. Sourcemap uploads will not work without ${chalk.cyan(\n 'SENTRY_AUTH_TOKEN',\n )}.\\n` +\n `Please set ${chalk.cyan('SENTRY_AUTH_TOKEN')} in your ${chalk.cyan(\n '.env.sentry-build-plugin',\n )} file or environment variables.`,\n );\n }\n\n // Configure Vite plugin for sourcemap uploads\n await traceStep('Configure Vite plugin for sourcemap uploads', async () => {\n try {\n await configureReactRouterVitePlugin(\n selectedProject.organization.slug,\n selectedProject.slug,\n );\n } catch (e) {\n clack.log.warn(\n `Could not configure Vite plugin for sourcemap uploads automatically.`,\n );\n\n await showCopyPasteInstructions({\n filename: `vite.config.${typeScriptDetected ? 'ts' : 'js'}`,\n codeSnippet: getManualViteConfigContent(\n selectedProject.organization.slug,\n selectedProject.slug,\n ),\n hint: 'This enables automatic sourcemap uploads during build for better error tracking',\n });\n\n debug(e);\n }\n });\n\n // Configure React Router config for build hook\n await traceStep('Configure React Router build hook', async () => {\n try {\n await configureReactRouterConfig(typeScriptDetected);\n } catch (e) {\n clack.log.warn(\n `Could not configure React Router build hook automatically.`,\n );\n\n await showCopyPasteInstructions({\n filename: `react-router.config.${typeScriptDetected ? 'ts' : 'js'}`,\n codeSnippet: getManualReactRouterConfigContent(typeScriptDetected),\n hint: 'This enables automatic sourcemap uploads at the end of the build process',\n });\n\n debug(e);\n }\n });\n\n // Create example page if requested\n if (createExamplePageSelection) {\n await traceStep('Create example page', async () => {\n await createExamplePage({\n selfHosted,\n orgSlug: selectedProject.organization.slug,\n projectId: selectedProject.id,\n url: sentryUrl,\n isTS: typeScriptDetected,\n projectDir: process.cwd(),\n });\n });\n }\n\n await runPrettierIfInstalled({ cwd: undefined });\n\n // Offer optional project-scoped MCP config for Sentry with org and project scope\n await offerProjectScopedMcpConfig(\n selectedProject.organization.slug,\n selectedProject.slug,\n );\n\n clack.outro(\n `${chalk.green('Successfully installed the Sentry React Router SDK!')}${\n createExamplePageSelection\n ? `\\n\\nYou can validate your setup by visiting ${chalk.cyan(\n '\"/sentry-example-page\"',\n )} in your application.`\n : ''\n }`,\n );\n}\n"]}
1
+ {"version":3,"file":"react-router-wizard.js","sourceRoot":"","sources":["../../../src/react-router/react-router-wizard.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\nimport chalk from 'chalk';\nimport * as Sentry from '@sentry/node';\n\nimport type { WizardOptions } from '../utils/types';\nimport { withTelemetry, traceStep } from '../telemetry';\nimport {\n askShouldCreateExamplePage,\n confirmContinueIfNoOrDirtyGitRepo,\n featureSelectionPrompt,\n getOrAskForProjectData,\n getPackageDotJson,\n isUsingTypeScript,\n printWelcome,\n installPackage,\n addDotEnvSentryBuildPluginFile,\n showCopyPasteInstructions,\n makeCodeSnippet,\n runPrettierIfInstalled,\n} from '../utils/clack';\nimport { offerProjectScopedMcpConfig } from '../utils/clack/mcp-config';\nimport { hasPackageInstalled } from '../utils/package-json';\nimport { debug } from '../utils/debug';\nimport { createExamplePage } from './sdk-example';\nimport {\n isReactRouterV7,\n getReactRouterVersion,\n supportsInstrumentationAPI,\n runReactRouterReveal,\n initializeSentryOnEntryClient,\n instrumentRootRoute,\n createServerInstrumentationFile,\n updatePackageJsonScripts,\n instrumentSentryOnEntryServer,\n configureReactRouterConfig,\n configureReactRouterVitePlugin,\n} from './sdk-setup';\nimport {\n getManualClientEntryContent,\n getManualServerEntryContent,\n getManualRootContent,\n getManualServerInstrumentContent,\n getManualReactRouterConfigContent,\n getManualViteConfigContent,\n} from './templates';\nimport { abortIfSpotlightNotSupported } from '../utils/abort-if-sportlight-not-supported';\n\nexport async function runReactRouterWizard(\n options: WizardOptions,\n): Promise<void> {\n return withTelemetry(\n {\n enabled: options.telemetryEnabled,\n integration: 'reactRouter',\n wizardOptions: options,\n },\n () => runReactRouterWizardWithTelemetry(options),\n );\n}\n\nasync function runReactRouterWizardWithTelemetry(\n options: WizardOptions,\n): Promise<void> {\n printWelcome({\n wizardName: 'Sentry React Router Wizard',\n promoCode: options.promoCode,\n });\n\n const packageJson = await getPackageDotJson();\n\n if (!packageJson) {\n clack.log.error(\n 'Could not find a package.json file in the current directory',\n );\n return;\n }\n\n const typeScriptDetected = isUsingTypeScript();\n\n if (!isReactRouterV7(packageJson)) {\n clack.log.error(\n 'This wizard requires React Router v7. Please upgrade your React Router version to v7.0.0 or higher.\\n\\nFor upgrade instructions, visit: https://react-router.dev/upgrade/v7',\n );\n return;\n }\n\n await confirmContinueIfNoOrDirtyGitRepo({\n ignoreGitChanges: options.ignoreGitChanges,\n cwd: undefined,\n });\n\n const sentryAlreadyInstalled = hasPackageInstalled(\n '@sentry/react-router',\n packageJson,\n );\n\n const projectData = await getOrAskForProjectData(\n options,\n 'javascript-react-router',\n );\n\n if (projectData.spotlight) {\n return abortIfSpotlightNotSupported('React Router');\n }\n\n const { selectedProject, authToken, selfHosted, sentryUrl } = projectData;\n\n await installPackage({\n packageName: '@sentry/react-router',\n alreadyInstalled: sentryAlreadyInstalled,\n });\n\n const featureSelection = await featureSelectionPrompt([\n {\n id: 'performance',\n prompt: `Do you want to enable ${chalk.bold(\n 'Tracing',\n )} to track the performance of your application?`,\n enabledHint: 'recommended',\n },\n {\n id: 'replay',\n prompt: `Do you want to enable ${chalk.bold(\n 'Session Replay',\n )} to get a video-like reproduction of errors during a user session?`,\n enabledHint: 'recommended, but increases bundle size',\n },\n {\n id: 'logs',\n prompt: `Do you want to enable ${chalk.bold(\n 'Logs',\n )} to send your application logs to Sentry?`,\n enabledHint: 'recommended',\n },\n {\n id: 'profiling',\n prompt: `Do you want to enable ${chalk.bold(\n 'Profiling',\n )} to track application performance in detail?`,\n enabledHint: 'recommended for production debugging',\n },\n ]);\n\n // Only ask about Instrumentation API when Tracing is enabled, since it depends on it\n let instrumentationAPISelected = false;\n if (featureSelection.performance) {\n const instrumentationAPISelection = await featureSelectionPrompt([\n {\n id: 'instrumentationAPI',\n prompt: `Do you want to use the ${chalk.bold(\n 'Instrumentation API',\n )} for automatic tracing of loaders, actions, and middleware?`,\n enabledHint: 'recommended',\n },\n ]);\n instrumentationAPISelected = instrumentationAPISelection.instrumentationAPI;\n }\n\n if (featureSelection.profiling) {\n const profilingAlreadyInstalled = hasPackageInstalled(\n '@sentry/profiling-node',\n packageJson,\n );\n\n await installPackage({\n packageName: '@sentry/profiling-node',\n alreadyInstalled: profilingAlreadyInstalled,\n });\n }\n\n const createExamplePageSelection = await askShouldCreateExamplePage();\n\n traceStep('Reveal missing entry files', () => {\n try {\n runReactRouterReveal();\n clack.log.success('Entry files are ready for instrumentation');\n } catch (e) {\n clack.log.warn(`Could not run 'npx react-router reveal'.\nPlease create your entry files manually using React Router v7 commands.`);\n debug(e);\n }\n });\n\n Sentry.setTag('instrumentation-api-selected', instrumentationAPISelected);\n\n let useInstrumentationAPI = instrumentationAPISelected;\n\n if (useInstrumentationAPI && !supportsInstrumentationAPI(packageJson)) {\n Sentry.setTag('instrumentation-api-version-guard', true);\n const detectedVersion = getReactRouterVersion(packageJson) ?? 'unknown';\n clack.log.warn(\n `The Instrumentation API requires React Router ${chalk.cyan(\n '>=7.9.5',\n )} (detected ${chalk.cyan(\n detectedVersion,\n )}). Your version does not meet this requirement.\\n` +\n `Continuing without the Instrumentation API. Please upgrade React Router to use this feature:\\n` +\n chalk.dim(\n 'https://docs.sentry.io/platforms/javascript/guides/react-router/',\n ),\n );\n useInstrumentationAPI = false;\n }\n\n Sentry.setTag('use-instrumentation-api', useInstrumentationAPI);\n\n await traceStep('Initialize Sentry on client entry', async () => {\n try {\n await initializeSentryOnEntryClient(\n selectedProject.keys[0].dsn.public,\n featureSelection.performance,\n featureSelection.replay,\n featureSelection.logs,\n typeScriptDetected,\n useInstrumentationAPI,\n );\n } catch (e) {\n clack.log.warn(\n `Could not initialize Sentry on client entry automatically.`,\n );\n\n const clientEntryFilename = `entry.client.${\n typeScriptDetected ? 'tsx' : 'jsx'\n }`;\n\n const manualClientContent = getManualClientEntryContent(\n selectedProject.keys[0].dsn.public,\n featureSelection.performance,\n featureSelection.replay,\n featureSelection.logs,\n useInstrumentationAPI,\n );\n\n await showCopyPasteInstructions({\n filename: clientEntryFilename,\n codeSnippet: manualClientContent,\n hint: 'This enables error tracking and performance monitoring for your React Router app',\n });\n\n debug(e);\n }\n });\n\n await traceStep('Instrument root route', async () => {\n try {\n await instrumentRootRoute(typeScriptDetected);\n } catch (e) {\n clack.log.warn(`Could not instrument root route automatically.`);\n\n const rootFilename = `app/root.${typeScriptDetected ? 'tsx' : 'jsx'}`;\n const manualRootContent = getManualRootContent(typeScriptDetected);\n\n await showCopyPasteInstructions({\n filename: rootFilename,\n codeSnippet: manualRootContent,\n hint: 'This adds error boundary integration to capture exceptions in your React Router app',\n });\n\n debug(e);\n }\n });\n\n await traceStep('Instrument server entry', async () => {\n try {\n await instrumentSentryOnEntryServer(\n typeScriptDetected,\n useInstrumentationAPI,\n );\n } catch (e) {\n clack.log.warn(\n `Could not initialize Sentry on server entry automatically.`,\n );\n\n const serverEntryFilename = `entry.server.${\n typeScriptDetected ? 'tsx' : 'jsx'\n }`;\n const manualServerContent = getManualServerEntryContent(\n useInstrumentationAPI,\n );\n\n await showCopyPasteInstructions({\n filename: serverEntryFilename,\n codeSnippet: manualServerContent,\n hint: 'This configures server-side request handling and error tracking',\n });\n\n debug(e);\n }\n });\n\n await traceStep('Create server instrumentation file', async () => {\n try {\n createServerInstrumentationFile(selectedProject.keys[0].dsn.public, {\n performance: featureSelection.performance,\n replay: featureSelection.replay,\n logs: featureSelection.logs,\n profiling: featureSelection.profiling,\n });\n } catch (e) {\n clack.log.warn(\n 'Could not create a server instrumentation file automatically.',\n );\n\n const manualServerInstrumentContent = getManualServerInstrumentContent(\n selectedProject.keys[0].dsn.public,\n featureSelection.performance,\n featureSelection.profiling,\n featureSelection.logs,\n );\n\n await showCopyPasteInstructions({\n filename: 'instrument.server.mjs',\n codeSnippet: manualServerInstrumentContent,\n hint: 'Create the file if it does not exist - this initializes Sentry before your application starts',\n });\n\n debug(e);\n }\n });\n\n await traceStep('Update package.json scripts', async () => {\n try {\n await updatePackageJsonScripts();\n } catch (e) {\n clack.log.warn('Could not update start script automatically.');\n\n await showCopyPasteInstructions({\n filename: 'package.json',\n codeSnippet: makeCodeSnippet(true, (unchanged, plus, minus) => {\n return unchanged(`{\n scripts: {\n ${minus('\"start\": \"react-router dev\"')}\n ${plus(\n '\"start\": \"NODE_ENV=production NODE_OPTIONS=\\'--import ./instrument.server.mjs\\' react-router-serve ./build/server/index.js\"',\n )}\n ${minus('\"dev\": \"react-router dev\"')}\n ${plus(\n '\"dev\": \"NODE_OPTIONS=\\'--import ./instrument.server.mjs\\' react-router dev\"',\n )}\n },\n // ... rest of your package.json\n }`);\n }),\n });\n\n debug(e);\n }\n });\n\n await traceStep('Create build plugin env file', async () => {\n try {\n await addDotEnvSentryBuildPluginFile(authToken);\n } catch (e) {\n clack.log.warn(\n 'Could not create .env.sentry-build-plugin file. Please create it manually.',\n );\n debug(e);\n }\n });\n\n // Validate auth token before configuring sourcemap uploads\n if (!authToken) {\n clack.log.warn(\n `${chalk.yellow(\n 'Warning:',\n )} No auth token found. Sourcemap uploads will not work without ${chalk.cyan(\n 'SENTRY_AUTH_TOKEN',\n )}.\\n` +\n `Please set ${chalk.cyan('SENTRY_AUTH_TOKEN')} in your ${chalk.cyan(\n '.env.sentry-build-plugin',\n )} file or environment variables.`,\n );\n }\n\n // Configure Vite plugin for sourcemap uploads\n await traceStep('Configure Vite plugin for sourcemap uploads', async () => {\n try {\n await configureReactRouterVitePlugin(\n selectedProject.organization.slug,\n selectedProject.slug,\n );\n } catch (e) {\n clack.log.warn(\n `Could not configure Vite plugin for sourcemap uploads automatically.`,\n );\n\n await showCopyPasteInstructions({\n filename: `vite.config.${typeScriptDetected ? 'ts' : 'js'}`,\n codeSnippet: getManualViteConfigContent(\n selectedProject.organization.slug,\n selectedProject.slug,\n ),\n hint: 'This enables automatic sourcemap uploads during build for better error tracking',\n });\n\n debug(e);\n }\n });\n\n // Configure React Router config for build hook\n await traceStep('Configure React Router build hook', async () => {\n try {\n await configureReactRouterConfig(typeScriptDetected);\n } catch (e) {\n clack.log.warn(\n `Could not configure React Router build hook automatically.`,\n );\n\n await showCopyPasteInstructions({\n filename: `react-router.config.${typeScriptDetected ? 'ts' : 'js'}`,\n codeSnippet: getManualReactRouterConfigContent(typeScriptDetected),\n hint: 'This enables automatic sourcemap uploads at the end of the build process',\n });\n\n debug(e);\n }\n });\n\n // Create example page if requested\n if (createExamplePageSelection) {\n await traceStep('Create example page', async () => {\n await createExamplePage({\n selfHosted,\n orgSlug: selectedProject.organization.slug,\n projectId: selectedProject.id,\n url: sentryUrl,\n isTS: typeScriptDetected,\n projectDir: process.cwd(),\n });\n });\n }\n\n await runPrettierIfInstalled({ cwd: undefined });\n\n // Offer optional project-scoped MCP config for Sentry with org and project scope\n await offerProjectScopedMcpConfig(\n selectedProject.organization.slug,\n selectedProject.slug,\n );\n\n clack.outro(\n `${chalk.green('Successfully installed the Sentry React Router SDK!')}${\n createExamplePageSelection\n ? `\\n\\nYou can validate your setup by visiting ${chalk.cyan(\n '\"/sentry-example-page\"',\n )} in your application.`\n : ''\n }`,\n );\n}\n"]}
@@ -1,9 +1,11 @@
1
1
  import type { PackageDotJson } from '../utils/package-json';
2
2
  export declare function getRouteFilePath(filename: string, isTS: boolean): string;
3
3
  export declare function tryRevealAndGetManualInstructions(missingFilename: string, filePath: string): Promise<boolean>;
4
- export declare function runReactRouterReveal(force?: boolean): void;
4
+ export declare function runReactRouterReveal(): void;
5
5
  export declare function isReactRouterV7(packageJson: PackageDotJson): boolean;
6
- export declare function initializeSentryOnEntryClient(dsn: string, enableTracing: boolean, enableReplay: boolean, enableLogs: boolean, isTS: boolean): Promise<void>;
6
+ export declare function getReactRouterVersion(packageJson: PackageDotJson): string | undefined;
7
+ export declare function supportsInstrumentationAPI(packageJson: PackageDotJson): boolean;
8
+ export declare function initializeSentryOnEntryClient(dsn: string, enableTracing: boolean, enableReplay: boolean, enableLogs: boolean, isTS: boolean, useInstrumentationAPI?: boolean): Promise<void>;
7
9
  export declare function instrumentRootRoute(isTS: boolean): Promise<void>;
8
10
  export declare function createServerInstrumentationFile(dsn: string, selectedFeatures: {
9
11
  performance: boolean;
@@ -12,6 +14,6 @@ export declare function createServerInstrumentationFile(dsn: string, selectedFea
12
14
  profiling: boolean;
13
15
  }): string;
14
16
  export declare function updatePackageJsonScripts(): Promise<void>;
15
- export declare function instrumentSentryOnEntryServer(isTS: boolean): Promise<void>;
17
+ export declare function instrumentSentryOnEntryServer(isTS: boolean, useInstrumentationAPI?: boolean): Promise<void>;
16
18
  export declare function configureReactRouterVitePlugin(orgSlug: string, projectSlug: string): Promise<void>;
17
19
  export declare function configureReactRouterConfig(isTS: boolean): Promise<void>;