@sentry/wizard 4.6.0 → 4.8.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 (218) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +19 -19
  3. package/dist/bin.js +9 -0
  4. package/dist/bin.js.map +1 -1
  5. package/dist/e2e-tests/tests/angular-17.test.d.ts +1 -0
  6. package/dist/e2e-tests/tests/angular-17.test.js +196 -0
  7. package/dist/e2e-tests/tests/angular-17.test.js.map +1 -0
  8. package/dist/e2e-tests/tests/angular-19.test.d.ts +1 -0
  9. package/dist/e2e-tests/tests/angular-19.test.js +194 -0
  10. package/dist/e2e-tests/tests/angular-19.test.js.map +1 -0
  11. package/dist/e2e-tests/tests/expo.test.d.ts +1 -0
  12. package/dist/e2e-tests/tests/expo.test.js +95 -0
  13. package/dist/e2e-tests/tests/expo.test.js.map +1 -0
  14. package/dist/e2e-tests/tests/flutter.test.js +16 -16
  15. package/dist/e2e-tests/tests/flutter.test.js.map +1 -1
  16. package/dist/e2e-tests/tests/help-message.test.d.ts +1 -0
  17. package/dist/e2e-tests/tests/help-message.test.js +56 -0
  18. package/dist/e2e-tests/tests/help-message.test.js.map +1 -0
  19. package/dist/e2e-tests/tests/nextjs-14.test.js +15 -15
  20. package/dist/e2e-tests/tests/nextjs-14.test.js.map +1 -1
  21. package/dist/e2e-tests/tests/nextjs-15.test.js +15 -15
  22. package/dist/e2e-tests/tests/nextjs-15.test.js.map +1 -1
  23. package/dist/e2e-tests/tests/nuxt-3.test.js +13 -12
  24. package/dist/e2e-tests/tests/nuxt-3.test.js.map +1 -1
  25. package/dist/e2e-tests/tests/nuxt-4.test.js +13 -12
  26. package/dist/e2e-tests/tests/nuxt-4.test.js.map +1 -1
  27. package/dist/e2e-tests/tests/react-native.test.d.ts +1 -0
  28. package/dist/e2e-tests/tests/react-native.test.js +97 -0
  29. package/dist/e2e-tests/tests/react-native.test.js.map +1 -0
  30. package/dist/e2e-tests/tests/remix.test.js +24 -24
  31. package/dist/e2e-tests/tests/remix.test.js.map +1 -1
  32. package/dist/e2e-tests/tests/sveltekit.test.js +22 -22
  33. package/dist/e2e-tests/tests/sveltekit.test.js.map +1 -1
  34. package/dist/e2e-tests/utils/index.d.ts +7 -0
  35. package/dist/e2e-tests/utils/index.js +33 -12
  36. package/dist/e2e-tests/utils/index.js.map +1 -1
  37. package/dist/lib/Constants.d.ts +6 -1
  38. package/dist/lib/Constants.js +3 -0
  39. package/dist/lib/Constants.js.map +1 -1
  40. package/dist/lib/Helper/Logging.d.ts +1 -1
  41. package/dist/lib/Helper/Logging.js.map +1 -1
  42. package/dist/lib/Helper/__tests__/File.js +9 -9
  43. package/dist/lib/Helper/__tests__/File.js.map +1 -1
  44. package/dist/lib/Helper/__tests__/MergeConfig.js +17 -17
  45. package/dist/lib/Helper/__tests__/MergeConfig.js.map +1 -1
  46. package/dist/lib/Helper/__tests__/SentryCli.js +23 -22
  47. package/dist/lib/Helper/__tests__/SentryCli.js.map +1 -1
  48. package/dist/lib/Setup.d.ts +2 -1
  49. package/dist/lib/Setup.js +12 -2
  50. package/dist/lib/Setup.js.map +1 -1
  51. package/dist/lib/Steps/BaseStep.d.ts +1 -1
  52. package/dist/lib/Steps/BaseStep.js.map +1 -1
  53. package/dist/lib/Steps/Integrations/Cordova.js.map +1 -1
  54. package/dist/lib/Steps/Welcome.js +5 -0
  55. package/dist/lib/Steps/Welcome.js.map +1 -1
  56. package/dist/lib/__tests__/Env.js +4 -3
  57. package/dist/lib/__tests__/Env.js.map +1 -1
  58. package/dist/src/angular/angular-wizard.d.ts +3 -0
  59. package/dist/src/angular/angular-wizard.js +186 -0
  60. package/dist/src/angular/angular-wizard.js.map +1 -0
  61. package/dist/src/angular/codemods/app-config.d.ts +3 -0
  62. package/dist/src/angular/codemods/app-config.js +211 -0
  63. package/dist/src/angular/codemods/app-config.js.map +1 -0
  64. package/dist/src/angular/codemods/main.d.ts +20 -0
  65. package/dist/src/angular/codemods/main.js +62 -0
  66. package/dist/src/angular/codemods/main.js.map +1 -0
  67. package/dist/src/angular/codemods/sourcemaps.d.ts +21 -0
  68. package/dist/src/angular/codemods/sourcemaps.js +94 -0
  69. package/dist/src/angular/codemods/sourcemaps.js.map +1 -0
  70. package/dist/src/angular/example-component.d.ts +8 -0
  71. package/dist/src/angular/example-component.js +286 -0
  72. package/dist/src/angular/example-component.js.map +1 -0
  73. package/dist/src/angular/sdk-setup.d.ts +6 -0
  74. package/dist/src/angular/sdk-setup.js +99 -0
  75. package/dist/src/angular/sdk-setup.js.map +1 -0
  76. package/dist/src/apple/apple-wizard.js +24 -64
  77. package/dist/src/apple/apple-wizard.js.map +1 -1
  78. package/dist/src/apple/configure-package-manager.d.ts +5 -0
  79. package/dist/src/apple/configure-package-manager.js +68 -0
  80. package/dist/src/apple/configure-package-manager.js.map +1 -0
  81. package/dist/src/apple/configure-sentry-cli.d.ts +4 -0
  82. package/dist/src/apple/configure-sentry-cli.js +47 -0
  83. package/dist/src/apple/configure-sentry-cli.js.map +1 -0
  84. package/dist/src/apple/configure-xcode-project.d.ts +8 -0
  85. package/dist/src/apple/configure-xcode-project.js +11 -0
  86. package/dist/src/apple/configure-xcode-project.js.map +1 -0
  87. package/dist/src/apple/inject-code-snippet.d.ts +6 -0
  88. package/dist/src/apple/inject-code-snippet.js +54 -0
  89. package/dist/src/apple/inject-code-snippet.js.map +1 -0
  90. package/dist/src/apple/templates.js +11 -7
  91. package/dist/src/apple/templates.js.map +1 -1
  92. package/dist/src/apple/xcode-manager.js +3 -6
  93. package/dist/src/apple/xcode-manager.js.map +1 -1
  94. package/dist/src/flutter/flutter-wizard.js +10 -2
  95. package/dist/src/flutter/flutter-wizard.js.map +1 -1
  96. package/dist/src/nextjs/nextjs-wizard.js +26 -12
  97. package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
  98. package/dist/src/nextjs/templates.js +59 -8
  99. package/dist/src/nextjs/templates.js.map +1 -1
  100. package/dist/src/nuxt/templates.js +30 -0
  101. package/dist/src/nuxt/templates.js.map +1 -1
  102. package/dist/src/react-native/expo-metro.js +4 -1
  103. package/dist/src/react-native/expo-metro.js.map +1 -1
  104. package/dist/src/react-native/expo.js +5 -1
  105. package/dist/src/react-native/expo.js.map +1 -1
  106. package/dist/src/react-native/javascript.d.ts +6 -4
  107. package/dist/src/react-native/javascript.js +33 -10
  108. package/dist/src/react-native/javascript.js.map +1 -1
  109. package/dist/src/react-native/metro.js +8 -2
  110. package/dist/src/react-native/metro.js.map +1 -1
  111. package/dist/src/react-native/react-native-wizard.d.ts +4 -0
  112. package/dist/src/react-native/react-native-wizard.js +30 -5
  113. package/dist/src/react-native/react-native-wizard.js.map +1 -1
  114. package/dist/src/react-native/xcode.d.ts +7 -3
  115. package/dist/src/react-native/xcode.js +68 -20
  116. package/dist/src/react-native/xcode.js.map +1 -1
  117. package/dist/src/remix/sdk-example.js +30 -1
  118. package/dist/src/remix/sdk-example.js.map +1 -1
  119. package/dist/src/remix/sdk-setup.js +11 -5
  120. package/dist/src/remix/sdk-setup.js.map +1 -1
  121. package/dist/src/run.d.ts +1 -1
  122. package/dist/src/run.js +7 -2
  123. package/dist/src/run.js.map +1 -1
  124. package/dist/src/sourcemaps/sourcemaps-wizard.d.ts +1 -1
  125. package/dist/src/sourcemaps/sourcemaps-wizard.js +35 -20
  126. package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
  127. package/dist/src/sourcemaps/tools/angular.d.ts +1 -0
  128. package/dist/src/sourcemaps/tools/angular.js +7 -7
  129. package/dist/src/sourcemaps/tools/angular.js.map +1 -1
  130. package/dist/src/sourcemaps/tools/sentry-cli.d.ts +5 -1
  131. package/dist/src/sourcemaps/tools/sentry-cli.js +6 -3
  132. package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
  133. package/dist/src/sourcemaps/tools/tsc.js +5 -1
  134. package/dist/src/sourcemaps/tools/tsc.js.map +1 -1
  135. package/dist/src/sourcemaps/tools/vite.js +4 -1
  136. package/dist/src/sourcemaps/tools/vite.js.map +1 -1
  137. package/dist/src/sourcemaps/tools/webpack.js +4 -1
  138. package/dist/src/sourcemaps/tools/webpack.js.map +1 -1
  139. package/dist/src/sveltekit/sdk-example.js +1 -1
  140. package/dist/src/sveltekit/sdk-example.js.map +1 -1
  141. package/dist/src/sveltekit/sveltekit-wizard.js +2 -2
  142. package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
  143. package/dist/src/sveltekit/templates.js +28 -1
  144. package/dist/src/sveltekit/templates.js.map +1 -1
  145. package/dist/src/utils/clack/index.d.ts +11 -3
  146. package/dist/src/utils/clack/index.js +12 -4
  147. package/dist/src/utils/clack/index.js.map +1 -1
  148. package/dist/src/utils/package-manager.d.ts +2 -0
  149. package/dist/src/utils/package-manager.js +55 -5
  150. package/dist/src/utils/package-manager.js.map +1 -1
  151. package/dist/src/version.d.ts +1 -1
  152. package/dist/src/version.js +1 -1
  153. package/dist/src/version.js.map +1 -1
  154. package/dist/test/android/code-tools.test.js +13 -12
  155. package/dist/test/android/code-tools.test.js.map +1 -1
  156. package/dist/test/angular/angular-wizard.test.d.ts +1 -0
  157. package/dist/test/angular/angular-wizard.test.js +27 -0
  158. package/dist/test/angular/angular-wizard.test.js.map +1 -0
  159. package/dist/test/angular/codemods/sourcemaps.test.d.ts +1 -0
  160. package/dist/test/angular/codemods/sourcemaps.test.js +237 -0
  161. package/dist/test/angular/codemods/sourcemaps.test.js.map +1 -0
  162. package/dist/test/angular/example-component.test.d.ts +1 -0
  163. package/dist/test/angular/example-component.test.js +105 -0
  164. package/dist/test/angular/example-component.test.js.map +1 -0
  165. package/dist/test/apple/cocoapod.test.js +77 -72
  166. package/dist/test/apple/cocoapod.test.js.map +1 -1
  167. package/dist/test/apple/code-tools.test.js +173 -166
  168. package/dist/test/apple/code-tools.test.js.map +1 -1
  169. package/dist/test/apple/fastfile.test.js +86 -83
  170. package/dist/test/apple/fastfile.test.js.map +1 -1
  171. package/dist/test/apple/templates.test.js +32 -27
  172. package/dist/test/apple/templates.test.js.map +1 -1
  173. package/dist/test/apple/xcode-manager.test.js +182 -183
  174. package/dist/test/apple/xcode-manager.test.js.map +1 -1
  175. package/dist/test/flutter/code-tools.test.js +29 -28
  176. package/dist/test/flutter/code-tools.test.js.map +1 -1
  177. package/dist/test/flutter/templates.test.js +15 -14
  178. package/dist/test/flutter/templates.test.js.map +1 -1
  179. package/dist/test/nextjs/templates.test.js +43 -36
  180. package/dist/test/nextjs/templates.test.js.map +1 -1
  181. package/dist/test/nuxt/templates.test.js +25 -24
  182. package/dist/test/nuxt/templates.test.js.map +1 -1
  183. package/dist/test/react-native/expo-metro.test.js +11 -10
  184. package/dist/test/react-native/expo-metro.test.js.map +1 -1
  185. package/dist/test/react-native/expo.test.js +11 -10
  186. package/dist/test/react-native/expo.test.js.map +1 -1
  187. package/dist/test/react-native/gradle.test.js +27 -26
  188. package/dist/test/react-native/gradle.test.js.map +1 -1
  189. package/dist/test/react-native/javascript.test.js +108 -58
  190. package/dist/test/react-native/javascript.test.js.map +1 -1
  191. package/dist/test/react-native/metro.test.js +178 -64
  192. package/dist/test/react-native/metro.test.js.map +1 -1
  193. package/dist/test/react-native/xcode.test.js +138 -37
  194. package/dist/test/react-native/xcode.test.js.map +1 -1
  195. package/dist/test/remix/client-entry.test.js +18 -17
  196. package/dist/test/remix/client-entry.test.js.map +1 -1
  197. package/dist/test/remix/server-instrumentation.test.js +6 -5
  198. package/dist/test/remix/server-instrumentation.test.js.map +1 -1
  199. package/dist/test/sourcemaps/tools/sentry-cli.test.js +20 -20
  200. package/dist/test/sourcemaps/tools/sentry-cli.test.js.map +1 -1
  201. package/dist/test/sourcemaps/tools/tsc.test.js +13 -14
  202. package/dist/test/sourcemaps/tools/tsc.test.js.map +1 -1
  203. package/dist/test/sourcemaps/tools/vite.test.js +13 -14
  204. package/dist/test/sourcemaps/tools/vite.test.js.map +1 -1
  205. package/dist/test/sourcemaps/tools/webpack.test.js +19 -20
  206. package/dist/test/sourcemaps/tools/webpack.test.js.map +1 -1
  207. package/dist/test/sveltekit/templates.test.js +13 -12
  208. package/dist/test/sveltekit/templates.test.js.map +1 -1
  209. package/dist/test/utils/ast-utils.test.js +45 -44
  210. package/dist/test/utils/ast-utils.test.js.map +1 -1
  211. package/dist/test/utils/clack/index.test.js +140 -144
  212. package/dist/test/utils/clack/index.test.js.map +1 -1
  213. package/dist/test/utils/package-manager.test.js +8 -7
  214. package/dist/test/utils/package-manager.test.js.map +1 -1
  215. package/package.json +10 -38
  216. package/dist/e2e-tests/jest.config.d.ts +0 -17
  217. package/dist/e2e-tests/jest.config.js +0 -23
  218. package/dist/e2e-tests/jest.config.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/nextjs/templates.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAC1B,0CAAiD;AAUjD,SAAgB,kCAAkC,CAAC,EACjD,OAAO,EACP,WAAW,EACX,UAAU,EACV,WAAW,EACX,SAAS,GACe;IACxB,OAAO;;;;YAIG,OAAO;gBACH,WAAW,KACvB,UAAU,CAAC,CAAC,CAAC,qBAAqB,SAAS,IAAI,CAAC,CAAC,CAAC,EACpD;;;;;;;;;;;SAYI,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,oBAC1B;;;;MAIE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK;;;;;;;;;;IAU1B,CAAC;AACL,CAAC;AA1CD,gFA0CC;AAED,SAAgB,0BAA0B,CACxC,+BAAuC;IAEvC,OAAO;;;;;;;IAOL,+BAA+B;;CAElC,CAAC;AACF,CAAC;AAbD,gEAaC;AAED,SAAgB,0BAA0B,CACxC,+BAAuC;IAEvC,OAAO;;;;;;;IAOL,+BAA+B;;CAElC,CAAC;AACF,CAAC;AAbD,gEAaC;AAED,SAAgB,0BAA0B,CACxC,+BAAuC;IAEvC,OAAO;;;;;;;;IAQL,+BAA+B;;CAElC,CAAC;AACF,CAAC;AAdD,gEAcC;AAED,SAAgB,kCAAkC,CAChD,+BAAuC;IAEvC,OAAO;;;;;;;IAOL,+BAA+B;;CAElC,CAAC;AACF,CAAC;AAbD,gFAaC;AAED,SAAS,4BAA4B,CAAC,QAA6B;IACjE,IAAI,QAAQ,CAAC,MAAM,EAAE;QACnB,OAAO;;;;;KAKN,CAAC;KACH;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAgB,iCAAiC,CAC/C,GAAW,EACX,MAAyB,EACzB,mBAGC;IAED,IAAI,MAAM,CAAC;IACX,IAAI,MAAM,KAAK,QAAQ,EAAE;QACvB,MAAM,GAAG;;8DAEiD,CAAC;KAC5D;SAAM,IAAI,MAAM,KAAK,MAAM,EAAE;QAC5B,MAAM,GAAG;;;8DAGiD,CAAC;KAC5D;IAED,IAAI,kBAAkB,GAAG,EAAE,CAAC;IAC5B,IAAI,mBAAmB,CAAC,WAAW,EAAE;QACnC,kBAAkB,IAAI;;;uBAGH,CAAC;KACrB;IAED,4EAA4E;IAC5E,OAAO,GAAG,MAAM;;;;;UAKR,GAAG,KAAK,kBAAkB;;;;;CAKnC,CAAC;AACF,CAAC;AAxCD,8EAwCC;AAED,SAAgB,oCAAoC,CAClD,GAAW,EACX,mBAGC;IAED,MAAM,mBAAmB,GAAG,4BAA4B,CAAC;QACvD,MAAM,EAAE,mBAAmB,CAAC,MAAM;KACnC,CAAC,CAAC;IAEH,IAAI,aAAa,GAAG,EAAE,CAAC;IAEvB,IAAI,mBAAmB,CAAC,MAAM,EAAE;QAC9B,aAAa,IAAI;;;;;;;;iCAQY,CAAC;KAC/B;IAED,IAAI,kBAAkB,GAAG,EAAE,CAAC;IAC5B,IAAI,mBAAmB,CAAC,WAAW,EAAE;QACnC,kBAAkB,IAAI;;;uBAGH,CAAC;KACrB;IAED,OAAO;;;;;;;UAOC,GAAG,KAAK,mBAAmB,GAAG,kBAAkB,GAAG,aAAa;;;;IAItE,CAAC;AACL,CAAC;AA7CD,oFA6CC;AAED,SAAgB,4BAA4B,CAAC,OAM5C;IACC,MAAM,cAAc,GAAG,OAAO,CAAC,UAAU;QACvC,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,iBAAiB,OAAO,CAAC,OAAO,oBAAoB,OAAO,CAAC,SAAS,EAAE;QAC7F,CAAC,CAAC,WAAW,OAAO,CAAC,OAAO,8BAA8B,OAAO,CAAC,SAAS,EAAE,CAAC;IAEhF,OAAO,GACL,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAC5C;;;;;;;;;;;;;;;;;;;;;;;;qGAwBmG,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyIlH,CAAC;AACF,CAAC;AA/KD,oEA+KC;AAED,SAAgB,gCAAgC;IAC9C,OAAO;;;;;CAKR,CAAC;AACF,CAAC;AAPD,4EAOC;AAED,SAAgB,8BAA8B;IAC5C,OAAO;;;;;;;;;CASR,CAAC;AACF,CAAC;AAXD,wEAWC;AAED,SAAgB,mCAAmC;IACjD,OAAO;;;;;;;;;;;;;;;;;CAiBR,CAAC;AACF,CAAC;AAnBD,kFAmBC;AAED,SAAgB,wCAAwC;IACtD,OAAO;EACP,eAAK,CAAC,KAAK,CAAC,2CAA2C,CAAC;EACxD,eAAK,CAAC,KAAK,CAAC,iCAAiC,CAAC;;EAE9C,eAAK,CAAC,GAAG,CACT,yEAAyE,CAC1E;oDACmD,eAAK,CAAC,KAAK,CAC3D,aAAa,CACd;IACC,eAAK,CAAC,KAAK,CAAC,4DAA4D,CAAC;;IAEzE,eAAK,CAAC,GAAG,CAAC,kCAAkC,CAAC;;;;CAIhD,CAAC;AACF,CAAC;AAlBD,4FAkBC;AAED,SAAgB,sCAAsC,CAAC,IAAa;IAClE,OAAO;2CAEL,IAAI,CAAC,CAAC,CAAC,gDAAgD,CAAC,CAAC,CAAC,EAC5D;;;EAGA,eAAK,CAAC,GAAG,CACT,yEAAyE,CAC1E;+DAEG,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAC/B;;;;;CAKD,CAAC;AACF,CAAC;AAlBD,wFAkBC;AAED,SAAgB,6BAA6B,CAC3C,2BAA2C;IAE3C,OAAO;;;;oBAKH,2BAA2B,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IACjD;;;;oBAKE,2BAA2B,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IACjD;;;;;CAKH,CAAC;AACF,CAAC;AArBD,sEAqBC;AAED,SAAgB,sCAAsC,CACpD,2BAA2C;IAE3C,OAAO,IAAA,uBAAe,EAAC,IAAI,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE;QAC/C,OAAO,SAAS,CAAC,GAAG,IAAI,CAAC,2CAA2C,CAAC;;SAEhE,IAAI,CAAC,OAAO,CAAC;IAClB,IAAI,CAAC;oBAEH,2BAA2B,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IACjD;;;;oBAKE,2BAA2B,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IACjD;IACA,CAAC;;;EAGH,IAAI,CAAC,2DAA2D,CAAC;CAClE,CAAC,CAAC;IACD,CAAC,CAAC,CAAC;AACL,CAAC;AAvBD,wFAuBC;AAED,SAAgB,4CAA4C,CAC1D,GAAW,EACX,mBAGC;IAED,OAAO,IAAA,uBAAe,EAAC,IAAI,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE;QAC/C,OAAO,IAAI,CAAC,oCAAoC,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;AACL,CAAC;AAVD,oGAUC;AAED,SAAgB,+BAA+B,CAAC,IAAa;IAC3D,OAAO,IAAI;QACT,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;EAsBJ;QACE,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;CAuBL,CAAC;AACF,CAAC;AAjDD,0EAiDC;AAED,SAAgB,8BAA8B,CAAC,IAAa;IAC1D,IAAI,IAAI,EAAE;QACR,OAAO;;EAET,eAAK,CAAC,KAAK,CAAC,2CAA2C,CAAC;EACxD,eAAK,CAAC,KAAK,CAAC,iCAAiC,CAAC;EAC9C,eAAK,CAAC,KAAK,CAAC,oCAAoC,CAAC;;sCAEb,eAAK,CAAC,KAAK,CAC3C,6BAA6B,CAC9B;IACD,eAAK,CAAC,KAAK,CAAC;;eAED,CAAC;;;;;;;;;;CAUf,CAAC;KACC;IACD,OAAO;;EAEP,eAAK,CAAC,KAAK,CAAC,2CAA2C,CAAC;EACxD,eAAK,CAAC,KAAK,CAAC,iCAAiC,CAAC;EAC9C,eAAK,CAAC,KAAK,CAAC,oCAAoC,CAAC;;sCAEb,eAAK,CAAC,KAAK,CAAC,WAAW,CAAC;IAC1D,eAAK,CAAC,KAAK,CAAC;;eAED,CAAC;;;;;;;;;;CAUf,CAAC;AACF,CAAC;AA7CD,wEA6CC;AAEM,MAAM,aAAa,GAAG,CAC3B,IAAa,EACb,EAAE,CAAC;;;;;;;;;;GAWH,IAAI;IACF,CAAC,CAAC;;EAEJ;IACE,CAAC,CAAC,EACN;;;;;;;CAOC,CAAC;AAzBW,QAAA,aAAa,iBAyBxB","sourcesContent":["import chalk from 'chalk';\nimport { makeCodeSnippet } from '../utils/clack';\n\ntype WithSentryConfigOptions = {\n orgSlug: string;\n projectSlug: string;\n selfHosted: boolean;\n sentryUrl: string;\n tunnelRoute: boolean;\n};\n\nexport function getWithSentryConfigOptionsTemplate({\n orgSlug,\n projectSlug,\n selfHosted,\n tunnelRoute,\n sentryUrl,\n}: WithSentryConfigOptions): string {\n return `{\n // For all available options, see:\n // https://www.npmjs.com/package/@sentry/webpack-plugin#options\n\n org: \"${orgSlug}\",\n project: \"${projectSlug}\",${\n selfHosted ? `\\n sentryUrl: \"${sentryUrl}\",` : ''\n }\n\n // Only print logs for uploading source maps in CI\n silent: !process.env.CI,\n\n // For all available options, see:\n // https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/\n\n // Upload a larger set of source maps for prettier stack traces (increases build time)\n widenClientFileUpload: true,\n\n // ${\n tunnelRoute ? 'Route' : 'Uncomment to route'\n } browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.\n // This can increase your server load as well as your hosting bill.\n // Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-\n // side errors will fail.\n ${tunnelRoute ? '' : '// '}tunnelRoute: \"/monitoring\",\n\n // Automatically tree-shake Sentry logger statements to reduce bundle size\n disableLogger: true,\n\n // Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.)\n // See the following for more information:\n // https://docs.sentry.io/product/crons/\n // https://vercel.com/docs/cron-jobs\n automaticVercelMonitors: true,\n }`;\n}\n\nexport function getNextjsConfigCjsTemplate(\n withSentryConfigOptionsTemplate: string,\n): string {\n return `const { withSentryConfig } = require(\"@sentry/nextjs\");\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {};\n\nmodule.exports = withSentryConfig(\n nextConfig,\n ${withSentryConfigOptionsTemplate}\n);\n`;\n}\n\nexport function getNextjsConfigMjsTemplate(\n withSentryConfigOptionsTemplate: string,\n): string {\n return `import { withSentryConfig } from \"@sentry/nextjs\";\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {};\n\nexport default withSentryConfig(\n nextConfig,\n ${withSentryConfigOptionsTemplate}\n);\n`;\n}\n\nexport function getNextjsConfigCjsAppendix(\n withSentryConfigOptionsTemplate: string,\n): string {\n return `\n\n// Injected content via Sentry wizard below\n\nconst { withSentryConfig } = require(\"@sentry/nextjs\");\n\nmodule.exports = withSentryConfig(\n module.exports,\n ${withSentryConfigOptionsTemplate}\n);\n`;\n}\n\nexport function getNextjsConfigEsmCopyPasteSnippet(\n withSentryConfigOptionsTemplate: string,\n): string {\n return `\n\n// next.config.mjs\nimport { withSentryConfig } from \"@sentry/nextjs\";\n\nexport default withSentryConfig(\n yourNextConfig,\n ${withSentryConfigOptionsTemplate}\n);\n`;\n}\n\nfunction getClientIntegrationsSnippet(features: { replay: boolean }) {\n if (features.replay) {\n return `\n\n // Add optional integrations for additional features\n integrations: [\n Sentry.replayIntegration(),\n ],`;\n }\n\n return '';\n}\n\nexport function getSentryServersideConfigContents(\n dsn: string,\n config: 'server' | 'edge',\n selectedFeaturesMap: {\n replay: boolean;\n performance: boolean;\n },\n): string {\n let primer;\n if (config === 'server') {\n primer = `// This file configures the initialization of Sentry on the server.\n// The config you add here will be used whenever the server handles a request.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;\n } else if (config === 'edge') {\n primer = `// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on).\n// The config you add here will be used whenever one of the edge features is loaded.\n// Note that this config is unrelated to the Vercel Edge Runtime and is also required when running locally.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;\n }\n\n let performanceOptions = '';\n if (selectedFeaturesMap.performance) {\n performanceOptions += `\n\n // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.\n tracesSampleRate: 1,`;\n }\n\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n return `${primer}\n\nimport * as Sentry from \"@sentry/nextjs\";\n\nSentry.init({\n dsn: \"${dsn}\",${performanceOptions}\n\n // Setting this option to true will print useful information to the console while you're setting up Sentry.\n debug: false,\n});\n`;\n}\n\nexport function getInstrumentationClientFileContents(\n dsn: string,\n selectedFeaturesMap: {\n replay: boolean;\n performance: boolean;\n },\n): string {\n const integrationsOptions = getClientIntegrationsSnippet({\n replay: selectedFeaturesMap.replay,\n });\n\n let replayOptions = '';\n\n if (selectedFeaturesMap.replay) {\n replayOptions += `\n\n // Define how likely Replay events are sampled.\n // This sets the sample rate to be 10%. You may want this to be 100% while\n // in development and sample at a lower rate in production\n replaysSessionSampleRate: 0.1,\n\n // Define how likely Replay events are sampled when an error occurs.\n replaysOnErrorSampleRate: 1.0,`;\n }\n\n let performanceOptions = '';\n if (selectedFeaturesMap.performance) {\n performanceOptions += `\n\n // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.\n tracesSampleRate: 1,`;\n }\n\n return `// This file configures the initialization of Sentry on the client.\n// The added config here will be used whenever a users loads a page in their browser.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/\n\nimport * as Sentry from \"@sentry/nextjs\";\n\nSentry.init({\n dsn: \"${dsn}\",${integrationsOptions}${performanceOptions}${replayOptions}\n\n // Setting this option to true will print useful information to the console while you're setting up Sentry.\n debug: false,\n});`;\n}\n\nexport function getSentryExamplePageContents(options: {\n selfHosted: boolean;\n sentryUrl: string;\n orgSlug: string;\n projectId: string;\n useClient: boolean;\n}): string {\n const issuesPageLink = options.selfHosted\n ? `${options.sentryUrl}organizations/${options.orgSlug}/issues/?project=${options.projectId}`\n : `https://${options.orgSlug}.sentry.io/issues/?project=${options.projectId}`;\n\n return `${\n options.useClient ? '\"use client\";\\n\\n' : ''\n }import Head from \"next/head\";\nimport * as Sentry from \"@sentry/nextjs\";\nimport { useState } from \"react\";\n\nexport default function Page() {\n const [hasSentError, setHasSentError] = useState(false);\n\n return (\n <div>\n <Head>\n <title>sentry-example-page</title>\n <meta name=\"description\" content=\"Test Sentry for your Next.js app!\" />\n </Head>\n\n <main>\n <div className=\"flex-spacer\" />\n <svg height=\"40\" width=\"40\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M21.85 2.995a3.698 3.698 0 0 1 1.353 1.354l16.303 28.278a3.703 3.703 0 0 1-1.354 5.053 3.694 3.694 0 0 1-1.848.496h-3.828a31.149 31.149 0 0 0 0-3.09h3.815a.61.61 0 0 0 .537-.917L20.523 5.893a.61.61 0 0 0-1.057 0l-3.739 6.494a28.948 28.948 0 0 1 9.63 10.453 28.988 28.988 0 0 1 3.499 13.78v1.542h-9.852v-1.544a19.106 19.106 0 0 0-2.182-8.85 19.08 19.08 0 0 0-6.032-6.829l-1.85 3.208a15.377 15.377 0 0 1 6.382 12.484v1.542H3.696A3.694 3.694 0 0 1 0 34.473c0-.648.17-1.286.494-1.849l2.33-4.074a8.562 8.562 0 0 1 2.689 1.536L3.158 34.17a.611.611 0 0 0 .538.917h8.448a12.481 12.481 0 0 0-6.037-9.09l-1.344-.772 4.908-8.545 1.344.77a22.16 22.16 0 0 1 7.705 7.444 22.193 22.193 0 0 1 3.316 10.193h3.699a25.892 25.892 0 0 0-3.811-12.033 25.856 25.856 0 0 0-9.046-8.796l-1.344-.772 5.269-9.136a3.698 3.698 0 0 1 3.2-1.849c.648 0 1.285.17 1.847.495Z\" fill=\"currentcolor\"/>\n </svg>\n <h1>\n sentry-example-page\n </h1>\n\n <p className=\"description\">\n Click the button below, and view the sample error on the Sentry <a target=\"_blank\" href=\"${issuesPageLink}\">Issues Page</a>.\n For more details about setting up Sentry, <a target=\"_blank\" href=\"https://docs.sentry.io/platforms/javascript/guides/nextjs/\">read our docs</a>.\n </p>\n\n <button\n type=\"button\"\n onClick={async () => {\n await Sentry.startSpan({\n name: 'Example Frontend Span',\n op: 'test'\n }, async () => {\n const res = await fetch(\"/api/sentry-example-api\");\n if (!res.ok) {\n setHasSentError(true);\n throw new Error(\"Sentry Example Frontend Error\");\n }\n });\n }}\n >\n <span>\n Throw Sample Error\n </span>\n </button>\n\n {hasSentError ? (\n <p className=\"success\">\n Sample error was sent to Sentry.\n </p>\n ) : (\n <div className=\"success_placeholder\" />\n )}\n\n <div className=\"flex-spacer\" />\n <p className=\"description\">\n Adblockers will prevent errors from being sent to Sentry.\n </p>\n </main>\n\n <style>{\\`\n main {\n display: flex;\n min-height: 100vh;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n gap: 16px;\n padding: 16px;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n\n h1 {\n padding: 0px 4px;\n border-radius: 4px;\n background-color: rgba(24, 20, 35, 0.03);\n font-family: monospace;\n font-size: 20px;\n line-height: 1.2;\n }\n\n p {\n margin: 0;\n font-size: 20px;\n }\n\n a {\n color: #6341F0;\n text-decoration: underline;\n cursor: pointer;\n\n @media (prefers-color-scheme: dark) {\n color: #B3A1FF;\n }\n }\n\n button {\n border-radius: 8px;\n color: white;\n cursor: pointer;\n background-color: #553DB8;\n border: none;\n padding: 0;\n margin-top: 4px;\n\n & > span {\n display: inline-block;\n padding: 12px 16px;\n border-radius: inherit;\n font-size: 20px;\n font-weight: bold;\n line-height: 1;\n background-color: #7553FF;\n border: 1px solid #553DB8;\n transform: translateY(-4px);\n }\n\n &:hover > span {\n transform: translateY(-8px);\n }\n\n &:active > span {\n transform: translateY(0);\n }\n }\n\n .description {\n text-align: center;\n color: #6E6C75;\n max-width: 500px;\n line-height: 1.5;\n font-size: 20px;\n\n @media (prefers-color-scheme: dark) {\n color: #A49FB5;\n }\n }\n\n .flex-spacer {\n flex: 1;\n }\n\n .success {\n padding: 12px 16px;\n border-radius: 8px;\n font-size: 20px;\n line-height: 1;\n background-color: #00F261;\n border: 1px solid #00BF4D;\n color: #181423;\n }\n\n .success_placeholder {\n height: 46px;\n }\n \\`}</style>\n </div>\n );\n}\n`;\n}\n\nexport function getSentryExamplePagesDirApiRoute() {\n return `// A faulty API route to test Sentry's error monitoring\nexport default function handler(_req, res) {\n throw new Error(\"Sentry Example API Route Error\");\n res.status(200).json({ name: \"John Doe\" });\n}\n`;\n}\n\nexport function getSentryExampleAppDirApiRoute() {\n return `import { NextResponse } from \"next/server\";\n\nexport const dynamic = \"force-dynamic\";\n\n// A faulty API route to test Sentry's error monitoring\nexport function GET() {\n throw new Error(\"Sentry Example API Route Error\");\n return NextResponse.json({ data: \"Testing Sentry Error...\" });\n}\n`;\n}\n\nexport function getSentryDefaultUnderscoreErrorPage() {\n return `import * as Sentry from \"@sentry/nextjs\";\nimport Error from \"next/error\";\n\nconst CustomErrorComponent = (props) => {\n return <Error statusCode={props.statusCode} />;\n};\n\nCustomErrorComponent.getInitialProps = async (contextData) => {\n // In case this is running in a serverless function, await this in order to give Sentry\n // time to send the error before the lambda exits\n await Sentry.captureUnderscoreErrorException(contextData);\n\n // This will contain the status code of the response\n return Error.getInitialProps(contextData);\n};\n\nexport default CustomErrorComponent;\n`;\n}\n\nexport function getSimpleUnderscoreErrorCopyPasteSnippet() {\n return `\n${chalk.green(`import * as Sentry from '@sentry/nextjs';`)}\n${chalk.green(`import Error from \"next/error\";`)}\n\n${chalk.dim(\n '// Replace \"YourCustomErrorComponent\" with your custom error component!',\n)}\nYourCustomErrorComponent.getInitialProps = async (${chalk.green(\n 'contextData',\n )}) => {\n ${chalk.green('await Sentry.captureUnderscoreErrorException(contextData);')}\n\n ${chalk.dim('// ...other getInitialProps code')}\n\n return Error.getInitialProps(contextData);\n};\n`;\n}\n\nexport function getFullUnderscoreErrorCopyPasteSnippet(isTs: boolean) {\n return `\nimport * as Sentry from '@sentry/nextjs';${\n isTs ? '\\nimport type { NextPageContext } from \"next\";' : ''\n }\nimport Error from \"next/error\";\n\n${chalk.dim(\n '// Replace \"YourCustomErrorComponent\" with your custom error component!',\n)}\nYourCustomErrorComponent.getInitialProps = async (contextData${\n isTs ? ': NextPageContext' : ''\n }) => {\n await Sentry.captureUnderscoreErrorException(contextData);\n\n return Error.getInitialProps(contextData);\n};\n`;\n}\n\nexport function getInstrumentationHookContent(\n instrumentationHookLocation: 'src' | 'root',\n) {\n return `import * as Sentry from '@sentry/nextjs';\n\nexport async function register() {\n if (process.env.NEXT_RUNTIME === 'nodejs') {\n await import('${\n instrumentationHookLocation === 'root' ? '.' : '..'\n }/sentry.server.config');\n }\n\n if (process.env.NEXT_RUNTIME === 'edge') {\n await import('${\n instrumentationHookLocation === 'root' ? '.' : '..'\n }/sentry.edge.config');\n }\n}\n\nexport const onRequestError = Sentry.captureRequestError;\n`;\n}\n\nexport function getInstrumentationHookCopyPasteSnippet(\n instrumentationHookLocation: 'src' | 'root',\n) {\n return makeCodeSnippet(true, (unchanged, plus) => {\n return unchanged(`${plus(\"import * as Sentry from '@sentry/nextjs';\")}\n\nexport ${plus('async')} function register() {\n ${plus(`if (process.env.NEXT_RUNTIME === 'nodejs') {\n await import('${\n instrumentationHookLocation === 'root' ? '.' : '..'\n }/sentry.server.config');\n }\n\n if (process.env.NEXT_RUNTIME === 'edge') {\n await import('${\n instrumentationHookLocation === 'root' ? '.' : '..'\n }/sentry.edge.config');\n }`)}\n}\n\n${plus('export const onRequestError = Sentry.captureRequestError;')}\n`);\n });\n}\n\nexport function getInstrumentationClientHookCopyPasteSnippet(\n dsn: string,\n selectedFeaturesMap: {\n replay: boolean;\n performance: boolean;\n },\n) {\n return makeCodeSnippet(true, (unchanged, plus) => {\n return plus(getInstrumentationClientFileContents(dsn, selectedFeaturesMap));\n });\n}\n\nexport function getSentryDefaultGlobalErrorPage(isTs: boolean) {\n return isTs\n ? `\"use client\";\n\nimport * as Sentry from \"@sentry/nextjs\";\nimport NextError from \"next/error\";\nimport { useEffect } from \"react\";\n\nexport default function GlobalError({ error }: { error: Error & { digest?: string } }) {\n useEffect(() => {\n Sentry.captureException(error);\n }, [error]);\n\n return (\n <html>\n <body>\n {/* \\`NextError\\` is the default Next.js error page component. Its type\n definition requires a \\`statusCode\\` prop. However, since the App Router\n does not expose status codes for errors, we simply pass 0 to render a\n generic error message. */}\n <NextError statusCode={0} />\n </body>\n </html>\n );\n}`\n : `\"use client\";\n\nimport * as Sentry from \"@sentry/nextjs\";\nimport NextError from \"next/error\";\nimport { useEffect } from \"react\";\n\nexport default function GlobalError({ error }) {\n useEffect(() => {\n Sentry.captureException(error);\n }, [error]);\n\n return (\n <html>\n <body>\n {/* \\`NextError\\` is the default Next.js error page component. Its type\n definition requires a \\`statusCode\\` prop. However, since the App Router\n does not expose status codes for errors, we simply pass 0 to render a\n generic error message. */}\n <NextError statusCode={0} />\n </body>\n </html>\n );\n}\n`;\n}\n\nexport function getGlobalErrorCopyPasteSnippet(isTs: boolean) {\n if (isTs) {\n return `\"use client\";\n\n${chalk.green('import * as Sentry from \"@sentry/nextjs\";')}\n${chalk.green('import Error from \"next/error\";')}\n${chalk.green('import { useEffect } from \"react\";')}\n\nexport default function GlobalError(${chalk.green(\n '{ error }: { error: Error }',\n )}) {\n ${chalk.green(`useEffect(() => {\n Sentry.captureException(error);\n }, [error]);`)}\n\n return (\n <html>\n <body>\n {/* Your Error component here... */}\n </body>\n </html>\n );\n}\n`;\n }\n return `\"use client\";\n\n${chalk.green('import * as Sentry from \"@sentry/nextjs\";')}\n${chalk.green('import Error from \"next/error\";')}\n${chalk.green('import { useEffect } from \"react\";')}\n\nexport default function GlobalError(${chalk.green('{ error }')}) {\n ${chalk.green(`useEffect(() => {\n Sentry.captureException(error);\n }, [error]);`)}\n\n return (\n <html>\n <body>\n {/* Your Error component here... */}\n </body>\n </html>\n );\n}\n`;\n}\n\nexport const getRootLayout = (\n isTs: boolean,\n) => `// This file was generated by the Sentry wizard because we couldn't find a root layout file.\n// You can delete this file at any time.\n\nexport const metadata = {\n title: 'Sentry NextJS Example',\n description: 'Generated by Sentry',\n}\n\nexport default function RootLayout({\n children,\n}${\n isTs\n ? `: {\n children: React.ReactNode\n}`\n : ''\n}) {\n return (\n <html lang=\"en\">\n <body>{children}</body>\n </html>\n )\n}\n`;\n"]}
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/nextjs/templates.ts"],"names":[],"mappings":"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","sourcesContent":["import chalk from 'chalk';\nimport { makeCodeSnippet } from '../utils/clack';\n\ntype WithSentryConfigOptions = {\n orgSlug: string;\n projectSlug: string;\n selfHosted: boolean;\n sentryUrl: string;\n tunnelRoute: boolean;\n};\n\nexport function getWithSentryConfigOptionsTemplate({\n orgSlug,\n projectSlug,\n selfHosted,\n tunnelRoute,\n sentryUrl,\n}: WithSentryConfigOptions): string {\n return `{\n // For all available options, see:\n // https://www.npmjs.com/package/@sentry/webpack-plugin#options\n\n org: \"${orgSlug}\",\n project: \"${projectSlug}\",${\n selfHosted ? `\\n sentryUrl: \"${sentryUrl}\",` : ''\n }\n\n // Only print logs for uploading source maps in CI\n silent: !process.env.CI,\n\n // For all available options, see:\n // https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/\n\n // Upload a larger set of source maps for prettier stack traces (increases build time)\n widenClientFileUpload: true,\n\n // ${\n tunnelRoute ? 'Route' : 'Uncomment to route'\n } browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.\n // This can increase your server load as well as your hosting bill.\n // Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-\n // side errors will fail.\n ${tunnelRoute ? '' : '// '}tunnelRoute: \"/monitoring\",\n\n // Automatically tree-shake Sentry logger statements to reduce bundle size\n disableLogger: true,\n\n // Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.)\n // See the following for more information:\n // https://docs.sentry.io/product/crons/\n // https://vercel.com/docs/cron-jobs\n automaticVercelMonitors: true,\n }`;\n}\n\nexport function getNextjsConfigCjsTemplate(\n withSentryConfigOptionsTemplate: string,\n): string {\n return `const { withSentryConfig } = require(\"@sentry/nextjs\");\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {};\n\nmodule.exports = withSentryConfig(\n nextConfig,\n ${withSentryConfigOptionsTemplate}\n);\n`;\n}\n\nexport function getNextjsConfigMjsTemplate(\n withSentryConfigOptionsTemplate: string,\n): string {\n return `import { withSentryConfig } from \"@sentry/nextjs\";\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {};\n\nexport default withSentryConfig(\n nextConfig,\n ${withSentryConfigOptionsTemplate}\n);\n`;\n}\n\nexport function getNextjsConfigCjsAppendix(\n withSentryConfigOptionsTemplate: string,\n): string {\n return `\n\n// Injected content via Sentry wizard below\n\nconst { withSentryConfig } = require(\"@sentry/nextjs\");\n\nmodule.exports = withSentryConfig(\n module.exports,\n ${withSentryConfigOptionsTemplate}\n);\n`;\n}\n\nexport function getNextjsConfigEsmCopyPasteSnippet(\n withSentryConfigOptionsTemplate: string,\n): string {\n return `\n\n// next.config.mjs\nimport { withSentryConfig } from \"@sentry/nextjs\";\n\nexport default withSentryConfig(\n yourNextConfig,\n ${withSentryConfigOptionsTemplate}\n);\n`;\n}\n\nfunction getClientIntegrationsSnippet(features: { replay: boolean }) {\n if (features.replay) {\n return `\n\n // Add optional integrations for additional features\n integrations: [\n Sentry.replayIntegration(),\n ],`;\n }\n\n return '';\n}\n\nexport function getSentryServersideConfigContents(\n dsn: string,\n config: 'server' | 'edge',\n selectedFeaturesMap: {\n replay: boolean;\n performance: boolean;\n },\n): string {\n let primer;\n if (config === 'server') {\n primer = `// This file configures the initialization of Sentry on the server.\n// The config you add here will be used whenever the server handles a request.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;\n } else if (config === 'edge') {\n primer = `// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on).\n// The config you add here will be used whenever one of the edge features is loaded.\n// Note that this config is unrelated to the Vercel Edge Runtime and is also required when running locally.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;\n }\n\n let performanceOptions = '';\n if (selectedFeaturesMap.performance) {\n performanceOptions += `\n\n // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.\n tracesSampleRate: 1,`;\n }\n\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n return `${primer}\n\nimport * as Sentry from \"@sentry/nextjs\";\n\nSentry.init({\n dsn: \"${dsn}\",${performanceOptions}\n\n // Setting this option to true will print useful information to the console while you're setting up Sentry.\n debug: false,\n});\n`;\n}\n\nexport function getInstrumentationClientFileContents(\n dsn: string,\n selectedFeaturesMap: {\n replay: boolean;\n performance: boolean;\n },\n): string {\n const integrationsOptions = getClientIntegrationsSnippet({\n replay: selectedFeaturesMap.replay,\n });\n\n let replayOptions = '';\n\n if (selectedFeaturesMap.replay) {\n replayOptions += `\n\n // Define how likely Replay events are sampled.\n // This sets the sample rate to be 10%. You may want this to be 100% while\n // in development and sample at a lower rate in production\n replaysSessionSampleRate: 0.1,\n\n // Define how likely Replay events are sampled when an error occurs.\n replaysOnErrorSampleRate: 1.0,`;\n }\n\n let performanceOptions = '';\n if (selectedFeaturesMap.performance) {\n performanceOptions += `\n\n // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.\n tracesSampleRate: 1,`;\n }\n\n return `// This file configures the initialization of Sentry on the client.\n// The added config here will be used whenever a users loads a page in their browser.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/\n\nimport * as Sentry from \"@sentry/nextjs\";\n\nSentry.init({\n dsn: \"${dsn}\",${integrationsOptions}${performanceOptions}${replayOptions}\n\n // Setting this option to true will print useful information to the console while you're setting up Sentry.\n debug: false,\n});\n\nexport const onRouterTransitionStart = Sentry.captureRouterTransitionStart;`;\n}\n\nexport function getSentryExamplePageContents(options: {\n selfHosted: boolean;\n sentryUrl: string;\n orgSlug: string;\n projectId: string;\n useClient: boolean;\n}): string {\n const issuesPageLink = options.selfHosted\n ? `${options.sentryUrl}organizations/${options.orgSlug}/issues/?project=${options.projectId}`\n : `https://${options.orgSlug}.sentry.io/issues/?project=${options.projectId}`;\n\n return `${\n options.useClient ? '\"use client\";\\n\\n' : ''\n }import Head from \"next/head\";\nimport * as Sentry from \"@sentry/nextjs\";\nimport { useState, useEffect } from \"react\";\n\nclass SentryExampleFrontendError extends Error {\n constructor(message: string | undefined) {\n super(message);\n this.name = \"SentryExampleFrontendError\";\n }\n}\n\nexport default function Page() {\n const [hasSentError, setHasSentError] = useState(false);\n const [isConnected, setIsConnected] = useState(true);\n \n useEffect(() => {\n async function checkConnectivity() {\n const result = await Sentry.diagnoseSdkConnectivity();\n setIsConnected(result !== 'sentry-unreachable');\n }\n checkConnectivity();\n }, []);\n\n return (\n <div>\n <Head>\n <title>sentry-example-page</title>\n <meta name=\"description\" content=\"Test Sentry for your Next.js app!\" />\n </Head>\n\n <main>\n <div className=\"flex-spacer\" />\n <svg height=\"40\" width=\"40\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M21.85 2.995a3.698 3.698 0 0 1 1.353 1.354l16.303 28.278a3.703 3.703 0 0 1-1.354 5.053 3.694 3.694 0 0 1-1.848.496h-3.828a31.149 31.149 0 0 0 0-3.09h3.815a.61.61 0 0 0 .537-.917L20.523 5.893a.61.61 0 0 0-1.057 0l-3.739 6.494a28.948 28.948 0 0 1 9.63 10.453 28.988 28.988 0 0 1 3.499 13.78v1.542h-9.852v-1.544a19.106 19.106 0 0 0-2.182-8.85 19.08 19.08 0 0 0-6.032-6.829l-1.85 3.208a15.377 15.377 0 0 1 6.382 12.484v1.542H3.696A3.694 3.694 0 0 1 0 34.473c0-.648.17-1.286.494-1.849l2.33-4.074a8.562 8.562 0 0 1 2.689 1.536L3.158 34.17a.611.611 0 0 0 .538.917h8.448a12.481 12.481 0 0 0-6.037-9.09l-1.344-.772 4.908-8.545 1.344.77a22.16 22.16 0 0 1 7.705 7.444 22.193 22.193 0 0 1 3.316 10.193h3.699a25.892 25.892 0 0 0-3.811-12.033 25.856 25.856 0 0 0-9.046-8.796l-1.344-.772 5.269-9.136a3.698 3.698 0 0 1 3.2-1.849c.648 0 1.285.17 1.847.495Z\" fill=\"currentcolor\"/>\n </svg>\n <h1>\n sentry-example-page\n </h1>\n\n <p className=\"description\">\n Click the button below, and view the sample error on the Sentry <a target=\"_blank\" href=\"${issuesPageLink}\">Issues Page</a>.\n For more details about setting up Sentry, <a target=\"_blank\" href=\"https://docs.sentry.io/platforms/javascript/guides/nextjs/\">read our docs</a>.\n </p>\n\n <button\n type=\"button\"\n onClick={async () => {\n await Sentry.startSpan({\n name: 'Example Frontend Span',\n op: 'test'\n }, async () => {\n const res = await fetch(\"/api/sentry-example-api\");\n if (!res.ok) {\n setHasSentError(true);\n throw new SentryExampleFrontendError(\"This error is raised on the frontend of the example page.\");\n }\n });\n }}\n >\n <span>\n Throw Sample Error\n </span>\n </button>\n\n {hasSentError ? (\n <p className=\"success\">\n Sample error was sent to Sentry.\n </p>\n ) : !isConnected ? (\n <div className=\"connectivity-error\">\n <p>The Sentry SDK is not able to reach Sentry right now - this may be due to an adblocker. For more information, see <a target=\"_blank\" href=\"https://docs.sentry.io/platforms/javascript/guides/nextjs/troubleshooting/#the-sdk-is-not-sending-any-data\">the troubleshooting guide</a>.</p>\n </div>\n ) : (\n <div className=\"success_placeholder\" />\n )}\n\n <div className=\"flex-spacer\" />\n \n <p className=\"description\">\n Adblockers will prevent errors from being sent to Sentry.\n </p>\n </main>\n\n <style>{\\`\n main {\n display: flex;\n min-height: 100vh;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n gap: 16px;\n padding: 16px;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n\n h1 {\n padding: 0px 4px;\n border-radius: 4px;\n background-color: rgba(24, 20, 35, 0.03);\n font-family: monospace;\n font-size: 20px;\n line-height: 1.2;\n }\n\n p {\n margin: 0;\n font-size: 20px;\n }\n\n a {\n color: #6341F0;\n text-decoration: underline;\n cursor: pointer;\n\n @media (prefers-color-scheme: dark) {\n color: #B3A1FF;\n }\n }\n\n button {\n border-radius: 8px;\n color: white;\n cursor: pointer;\n background-color: #553DB8;\n border: none;\n padding: 0;\n margin-top: 4px;\n\n & > span {\n display: inline-block;\n padding: 12px 16px;\n border-radius: inherit;\n font-size: 20px;\n font-weight: bold;\n line-height: 1;\n background-color: #7553FF;\n border: 1px solid #553DB8;\n transform: translateY(-4px);\n }\n\n &:hover > span {\n transform: translateY(-8px);\n }\n\n &:active > span {\n transform: translateY(0);\n }\n }\n\n .description {\n text-align: center;\n color: #6E6C75;\n max-width: 500px;\n line-height: 1.5;\n font-size: 20px;\n\n @media (prefers-color-scheme: dark) {\n color: #A49FB5;\n }\n }\n\n .flex-spacer {\n flex: 1;\n }\n\n .success {\n padding: 12px 16px;\n border-radius: 8px;\n font-size: 20px;\n line-height: 1;\n background-color: #00F261;\n border: 1px solid #00BF4D;\n color: #181423;\n }\n\n .success_placeholder {\n height: 46px;\n }\n\n .connectivity-error {\n padding: 12px 16px;\n background-color: #E50045;\n border-radius: 8px;\n width: 500px;\n color: #FFFFFF;\n border: 1px solid #A80033;\n text-align: center;\n margin: 0;\n }\n \n .connectivity-error a {\n color: #FFFFFF;\n text-decoration: underline;\n }\n \\`}</style>\n </div>\n );\n}\n`;\n}\n\nexport function getSentryExamplePagesDirApiRoute() {\n return `// Custom error class for Sentry testing\nclass SentryExampleAPIError extends Error {\n constructor(message: string | undefined) {\n super(message);\n this.name = \"SentryExampleAPIError\";\n }\n}\n// A faulty API route to test Sentry's error monitoring\nexport default function handler(_req, res) {\nthrow new SentryExampleAPIError(\"This error is raised on the backend called by the example page.\");\nres.status(200).json({ name: \"John Doe\" });\n}\n`;\n}\n\nexport function getSentryExampleAppDirApiRoute() {\n return `import { NextResponse } from \"next/server\";\n\nexport const dynamic = \"force-dynamic\";\nclass SentryExampleAPIError extends Error {\n constructor(message: string | undefined) {\n super(message);\n this.name = \"SentryExampleAPIError\";\n }\n}\n// A faulty API route to test Sentry's error monitoring\nexport function GET() {\n throw new SentryExampleAPIError(\"This error is raised on the backend called by the example page.\");\n return NextResponse.json({ data: \"Testing Sentry Error...\" });\n}\n`;\n}\n\nexport function getSentryDefaultUnderscoreErrorPage() {\n return `import * as Sentry from \"@sentry/nextjs\";\nimport Error from \"next/error\";\n\nconst CustomErrorComponent = (props) => {\n return <Error statusCode={props.statusCode} />;\n};\n\nCustomErrorComponent.getInitialProps = async (contextData) => {\n // In case this is running in a serverless function, await this in order to give Sentry\n // time to send the error before the lambda exits\n await Sentry.captureUnderscoreErrorException(contextData);\n\n // This will contain the status code of the response\n return Error.getInitialProps(contextData);\n};\n\nexport default CustomErrorComponent;\n`;\n}\n\nexport function getSimpleUnderscoreErrorCopyPasteSnippet() {\n return `\n${chalk.green(`import * as Sentry from '@sentry/nextjs';`)}\n${chalk.green(`import Error from \"next/error\";`)}\n\n${chalk.dim(\n '// Replace \"YourCustomErrorComponent\" with your custom error component!',\n)}\nYourCustomErrorComponent.getInitialProps = async (${chalk.green(\n 'contextData',\n )}) => {\n ${chalk.green('await Sentry.captureUnderscoreErrorException(contextData);')}\n\n ${chalk.dim('// ...other getInitialProps code')}\n\n return Error.getInitialProps(contextData);\n};\n`;\n}\n\nexport function getFullUnderscoreErrorCopyPasteSnippet(isTs: boolean) {\n return `\nimport * as Sentry from '@sentry/nextjs';${\n isTs ? '\\nimport type { NextPageContext } from \"next\";' : ''\n }\nimport Error from \"next/error\";\n\n${chalk.dim(\n '// Replace \"YourCustomErrorComponent\" with your custom error component!',\n)}\nYourCustomErrorComponent.getInitialProps = async (contextData${\n isTs ? ': NextPageContext' : ''\n }) => {\n await Sentry.captureUnderscoreErrorException(contextData);\n\n return Error.getInitialProps(contextData);\n};\n`;\n}\n\nexport function getInstrumentationHookContent(\n instrumentationHookLocation: 'src' | 'root',\n) {\n return `import * as Sentry from '@sentry/nextjs';\n\nexport async function register() {\n if (process.env.NEXT_RUNTIME === 'nodejs') {\n await import('${\n instrumentationHookLocation === 'root' ? '.' : '..'\n }/sentry.server.config');\n }\n\n if (process.env.NEXT_RUNTIME === 'edge') {\n await import('${\n instrumentationHookLocation === 'root' ? '.' : '..'\n }/sentry.edge.config');\n }\n}\n\nexport const onRequestError = Sentry.captureRequestError;\n`;\n}\n\nexport function getInstrumentationHookCopyPasteSnippet(\n instrumentationHookLocation: 'src' | 'root',\n) {\n return makeCodeSnippet(true, (unchanged, plus) => {\n return unchanged(`${plus(\"import * as Sentry from '@sentry/nextjs';\")}\n\nexport ${plus('async')} function register() {\n ${plus(`if (process.env.NEXT_RUNTIME === 'nodejs') {\n await import('${\n instrumentationHookLocation === 'root' ? '.' : '..'\n }/sentry.server.config');\n }\n\n if (process.env.NEXT_RUNTIME === 'edge') {\n await import('${\n instrumentationHookLocation === 'root' ? '.' : '..'\n }/sentry.edge.config');\n }`)}\n}\n\n${plus('export const onRequestError = Sentry.captureRequestError;')}\n`);\n });\n}\n\nexport function getInstrumentationClientHookCopyPasteSnippet(\n dsn: string,\n selectedFeaturesMap: {\n replay: boolean;\n performance: boolean;\n },\n) {\n return makeCodeSnippet(true, (unchanged, plus) => {\n return plus(getInstrumentationClientFileContents(dsn, selectedFeaturesMap));\n });\n}\n\nexport function getSentryDefaultGlobalErrorPage(isTs: boolean) {\n return isTs\n ? `\"use client\";\n\nimport * as Sentry from \"@sentry/nextjs\";\nimport NextError from \"next/error\";\nimport { useEffect } from \"react\";\n\nexport default function GlobalError({ error }: { error: Error & { digest?: string } }) {\n useEffect(() => {\n Sentry.captureException(error);\n }, [error]);\n\n return (\n <html>\n <body>\n {/* \\`NextError\\` is the default Next.js error page component. Its type\n definition requires a \\`statusCode\\` prop. However, since the App Router\n does not expose status codes for errors, we simply pass 0 to render a\n generic error message. */}\n <NextError statusCode={0} />\n </body>\n </html>\n );\n}`\n : `\"use client\";\n\nimport * as Sentry from \"@sentry/nextjs\";\nimport NextError from \"next/error\";\nimport { useEffect } from \"react\";\n\nexport default function GlobalError({ error }) {\n useEffect(() => {\n Sentry.captureException(error);\n }, [error]);\n\n return (\n <html>\n <body>\n {/* \\`NextError\\` is the default Next.js error page component. Its type\n definition requires a \\`statusCode\\` prop. However, since the App Router\n does not expose status codes for errors, we simply pass 0 to render a\n generic error message. */}\n <NextError statusCode={0} />\n </body>\n </html>\n );\n}\n`;\n}\n\nexport function getGlobalErrorCopyPasteSnippet(isTs: boolean) {\n if (isTs) {\n return `\"use client\";\n\n${chalk.green('import * as Sentry from \"@sentry/nextjs\";')}\n${chalk.green('import Error from \"next/error\";')}\n${chalk.green('import { useEffect } from \"react\";')}\n\nexport default function GlobalError(${chalk.green(\n '{ error }: { error: Error }',\n )}) {\n ${chalk.green(`useEffect(() => {\n Sentry.captureException(error);\n }, [error]);`)}\n\n return (\n <html>\n <body>\n {/* Your Error component here... */}\n </body>\n </html>\n );\n}\n`;\n }\n return `\"use client\";\n\n${chalk.green('import * as Sentry from \"@sentry/nextjs\";')}\n${chalk.green('import Error from \"next/error\";')}\n${chalk.green('import { useEffect } from \"react\";')}\n\nexport default function GlobalError(${chalk.green('{ error }')}) {\n ${chalk.green(`useEffect(() => {\n Sentry.captureException(error);\n }, [error]);`)}\n\n return (\n <html>\n <body>\n {/* Your Error component here... */}\n </body>\n </html>\n );\n}\n`;\n}\n\nexport const getRootLayout = (\n isTs: boolean,\n) => `// This file was generated by the Sentry wizard because we couldn't find a root layout file.\n// You can delete this file at any time.\n\nexport const metadata = {\n title: 'Sentry NextJS Example',\n description: 'Generated by Sentry',\n}\n\nexport default function RootLayout({\n children,\n}${\n isTs\n ? `: {\n children: React.ReactNode\n}`\n : ''\n}) {\n return (\n <html lang=\"en\">\n <body>{children}</body>\n </html>\n )\n}\n`;\n"]}
@@ -116,6 +116,16 @@ Feel free to delete this file.
116
116
  import { useFetch} from '#imports'
117
117
 
118
118
  const hasSentError = ref(false);
119
+ const isConnected = ref(true);
120
+
121
+ onMounted(async () => {
122
+ try {
123
+ const result = await Sentry.diagnoseSdkConnectivity();
124
+ isConnected.value = result !== 'sentry-unreachable';
125
+ } catch (error) {
126
+ isConnected.value = false;
127
+ }
128
+ });
119
129
 
120
130
  function getSentryData() {
121
131
  Sentry.startSpan(
@@ -163,6 +173,9 @@ Feel free to delete this file.
163
173
  <p v-if="hasSentError" class="success">
164
174
  Sample error was sent to Sentry.
165
175
  </p>
176
+ <div v-else-if="!isConnected" class="connectivity-error">
177
+ <p>The Sentry SDK is not able to reach Sentry right now - this may be due to an adblocker. For more information, see <a target="_blank" href="https://docs.sentry.io/platforms/javascript/guides/nuxt/troubleshooting/#the-sdk-is-not-sending-any-data">the troubleshooting guide</a>.</p>
178
+ </div>
166
179
  <div v-else class="success_placeholder" />
167
180
 
168
181
  <div class="flex-spacer" />
@@ -279,7 +292,24 @@ Feel free to delete this file.
279
292
  .success_placeholder {
280
293
  height: 46px;
281
294
  }
295
+
296
+ .connectivity-error {
297
+ padding: 12px 16px;
298
+ background-color: #E50045;
299
+ border-radius: 8px;
300
+ width: 500px;
301
+ color: #FFFFFF;
302
+ border: 1px solid #A80033;
303
+ text-align: center;
304
+ margin: 0;
305
+ }
306
+
307
+ .connectivity-error a {
308
+ color: #FFFFFF;
309
+ text-decoration: underline;
310
+ }
282
311
  </style>
312
+
283
313
  `;
284
314
  }
285
315
  exports.getSentryExamplePageTemplate = getSentryExamplePageTemplate;
@@ -1 +1 @@
1
- {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/nuxt/templates.ts"],"names":[],"mappings":"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","sourcesContent":["import { getIssueStreamUrl } from '../utils/url';\n\ntype SelectedSentryFeatures = {\n performance: boolean;\n replay: boolean;\n};\n\nexport function getDefaultNuxtConfig(): string {\n return `// https://nuxt.com/docs/api/configuration/nuxt-config\nexport default defineNuxtConfig({\n compatibilityDate: '2024-04-03',\n devtools: { enabled: true }\n})\n`;\n}\n\nexport function getNuxtModuleFallbackTemplate(\n options: {\n org: string;\n project: string;\n url: string;\n selfHosted: boolean;\n },\n shouldTopLevelImport: boolean,\n): string {\n return ` modules: [\"@sentry/nuxt/module\"],\n sentry: {\n sourceMapsUploadOptions: {\n org: \"${options.org}\",\n project: \"${options.project}\",${\n options.selfHosted ? `\\n url: \"${options.url}\",` : ''\n }\n },${\n shouldTopLevelImport\n ? `\\n autoInjectServerSentry: \"top-level-import\",`\n : ''\n }\n },\n sourcemap: { client: \"hidden\" },`;\n}\n\nexport function getSentryConfigContents(\n dsn: string,\n config: 'client' | 'server',\n selectedFeatures: SelectedSentryFeatures,\n): string {\n if (config === 'client') {\n return getSentryClientConfigContents(dsn, selectedFeatures);\n }\n\n return getSentryServerConfigContents(dsn, selectedFeatures);\n}\n\nconst featuresConfigMap: Record<keyof SelectedSentryFeatures, string> = {\n performance: [\n ' // We recommend adjusting this value in production, or using tracesSampler',\n ' // for finer control',\n ' tracesSampleRate: 1.0,',\n ].join('\\n'),\n replay: [\n ' // This sets the sample rate to be 10%. You may want this to be 100% while',\n ' // in development and sample at a lower rate in production',\n ' replaysSessionSampleRate: 0.1,',\n ' ',\n ' // If the entire session is not sampled, use the below sample rate to sample',\n ' // sessions when an error occurs.',\n ' replaysOnErrorSampleRate: 1.0,',\n ' ',\n \" // If you don't want to use Session Replay, just remove the line below:\",\n ' integrations: [Sentry.replayIntegration()],',\n ].join('\\n'),\n};\n\nconst featuresMap: Record<\n 'client' | 'server',\n Array<keyof SelectedSentryFeatures>\n> = {\n client: ['performance', 'replay'],\n server: ['performance'],\n};\n\nexport function getConfigBody(\n dsn: string,\n variant: 'client' | 'server',\n selectedFeatures: SelectedSentryFeatures,\n) {\n return [\n `dsn: \"${dsn}\",`,\n Object.entries(selectedFeatures)\n .map(([feature, activated]: [keyof SelectedSentryFeatures, boolean]) => {\n return featuresMap[variant].includes(feature) && activated\n ? featuresConfigMap[feature]\n : null;\n })\n .filter(Boolean)\n .join('\\n\\n'),\n ]\n .filter(Boolean)\n .join('\\n\\n');\n}\n\nfunction getSentryClientConfigContents(\n dsn: string,\n selectedFeatures: SelectedSentryFeatures,\n): string {\n return `import * as Sentry from \"@sentry/nuxt\";\n\nSentry.init({\n // If set up, you can use your runtime config here\n // dsn: useRuntimeConfig().public.sentry.dsn,\n ${getConfigBody(dsn, 'client', selectedFeatures)}\n \n // Setting this option to true will print useful information to the console while you're setting up Sentry.\n debug: false,\n});\n`;\n}\n\nfunction getSentryServerConfigContents(\n dsn: string,\n selectedFeatures: SelectedSentryFeatures,\n): string {\n return `import * as Sentry from \"@sentry/nuxt\";\n \nSentry.init({\n ${getConfigBody(dsn, 'server', selectedFeatures)}\n \n // Setting this option to true will print useful information to the console while you're setting up Sentry.\n debug: false,\n});\n`;\n}\n\nexport function getIndexRouteTemplate(): string {\n return `<!--\nThis is just to verify the sentry-example-page.\nFeel free to delete this file.\n-->\n\n<template></template>`;\n}\n\nexport function getSentryExamplePageTemplate(options: {\n url: string;\n org: string;\n projectId: string;\n}): string {\n const { url, org, projectId } = options;\n const issuesPageLink = getIssueStreamUrl({ url, orgSlug: org, projectId });\n\n return `<!--\nThis is just a very simple page with a button to throw an example error.\nFeel free to delete this file.\n-->\n\n<script setup>\n import * as Sentry from '@sentry/nuxt';\n import { useFetch} from '#imports'\n\n const hasSentError = ref(false);\n \n function getSentryData() {\n Sentry.startSpan(\n {\n name: 'Example Frontend Span',\n op: 'test'\n },\n async () => {\n const { error } = await useFetch('/api/sentry-example-api');\n if (error.value) {\n hasSentError.value = true;\n throw new Error('Sentry Example Frontend Error');\n }\n }\n )\n }\n</script>\n\n<template>\n <title>Sentry Onboarding</title>\n <div>\n <main>\n <div class=\"flex-spacer\" />\n <svg height=\"40\" width=\"40\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M21.85 2.995a3.698 3.698 0 0 1 1.353 1.354l16.303 28.278a3.703 3.703 0 0 1-1.354 5.053 3.694 3.694 0 0 1-1.848.496h-3.828a31.149 31.149 0 0 0 0-3.09h3.815a.61.61 0 0 0 .537-.917L20.523 5.893a.61.61 0 0 0-1.057 0l-3.739 6.494a28.948 28.948 0 0 1 9.63 10.453 28.988 28.988 0 0 1 3.499 13.78v1.542h-9.852v-1.544a19.106 19.106 0 0 0-2.182-8.85 19.08 19.08 0 0 0-6.032-6.829l-1.85 3.208a15.377 15.377 0 0 1 6.382 12.484v1.542H3.696A3.694 3.694 0 0 1 0 34.473c0-.648.17-1.286.494-1.849l2.33-4.074a8.562 8.562 0 0 1 2.689 1.536L3.158 34.17a.611.611 0 0 0 .538.917h8.448a12.481 12.481 0 0 0-6.037-9.09l-1.344-.772 4.908-8.545 1.344.77a22.16 22.16 0 0 1 7.705 7.444 22.193 22.193 0 0 1 3.316 10.193h3.699a25.892 25.892 0 0 0-3.811-12.033 25.856 25.856 0 0 0-9.046-8.796l-1.344-.772 5.269-9.136a3.698 3.698 0 0 1 3.2-1.849c.648 0 1.285.17 1.847.495Z\" fill=\"currentcolor\"/>\n </svg>\n <h1>\n sentry-example-page\n </h1>\n\n <p class=\"description\">\n Click the button below, and view the sample error on the Sentry <a target=\"_blank\" href=\"${issuesPageLink}\">Issues Page</a>. \n For more details about setting up Sentry, <a target=\"_blank\" href=\"https://docs.sentry.io/platforms/javascript/guides/nuxt/\">read our docs</a>.\n </p>\n\n <button\n type=\"button\"\n @click=\"getSentryData\"\n >\n <span>\n Throw Sample Error\n </span>\n </button>\n\n <p v-if=\"hasSentError\" class=\"success\">\n Sample error was sent to Sentry.\n </p>\n <div v-else class=\"success_placeholder\" />\n\n <div class=\"flex-spacer\" />\n <p class=\"description\">\n Adblockers will prevent errors from being sent to Sentry.\n </p>\n </main>\n </div>\n</template>\n\n<style scoped>\n :global(body) {\n margin: 0;\n\n @media (prefers-color-scheme: dark) {\n color: #ededed;\n background-color: #0a0a0a;\n }\n }\n\n main {\n display: flex;\n min-height: 100vh;\n box-sizing: border-box;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n gap: 16px;\n padding: 16px;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n\n h1 {\n padding: 0px 4px;\n margin: 0;\n border-radius: 4px;\n background-color: rgba(24, 20, 35, 0.03);\n font-family: monospace;\n font-size: 20px;\n line-height: 1.2;\n }\n\n p {\n margin: 0;\n font-size: 20px;\n }\n\n a {\n color: #6341F0;\n text-decoration: underline;\n cursor: pointer;\n\n @media (prefers-color-scheme: dark) {\n color: #B3A1FF;\n }\n }\n\n button {\n border-radius: 8px;\n color: white;\n cursor: pointer;\n background-color: #553DB8;\n border: none;\n padding: 0;\n margin-top: 4px;\n\n & > span {\n display: inline-block;\n padding: 12px 16px;\n border-radius: inherit;\n font-size: 20px;\n font-weight: bold;\n line-height: 1;\n background-color: #7553FF;\n border: 1px solid #553DB8;\n transform: translateY(-4px);\n }\n\n &:hover > span {\n transform: translateY(-8px);\n }\n\n &:active > span {\n transform: translateY(0); \n }\n }\n\n .description {\n text-align: center;\n color: #6E6C75;\n max-width: 500px;\n line-height: 1.5;\n font-size: 20px;\n\n @media (prefers-color-scheme: dark) {\n color: #A49FB5;\n }\n }\n\n .flex-spacer {\n flex: 1;\n }\n\n .success {\n padding: 12px 16px;\n border-radius: 8px;\n font-size: 20px;\n line-height: 1;\n background-color: #00F261;\n border: 1px solid #00BF4D;\n color: #181423;\n }\n\n .success_placeholder {\n height: 46px;\n }\n</style>\n`;\n}\n\nexport function getSentryExampleApiTemplate() {\n return `// This is just a very simple API route that throws an example error.\n// Feel free to delete this file.\nimport { defineEventHandler } from '#imports';\n\nexport default defineEventHandler(() => {\n throw new Error(\"Sentry Example API Route Error\");\n});\n`;\n}\n\nexport function getSentryErrorButtonTemplate() {\n return `<!--\nThis is just a very simple component that throws an example error.\nFeel free to delete this file.\n-->\n\n<script setup>\n import * as Sentry from '@sentry/nuxt';\n\n const hasSentError = ref(false);\n \n const throwError = () => {\n Sentry.startSpan(\n {\n name: 'Example Frontend Span',\n op: 'test'\n },\n () => {\n hasSentError.value = true;\n throw new Error('Sentry Example Error');\n }\n )\n };\n</script>\n\n<template>\n <div v-if=\"hasSentError\" class=\"success\">\n Sample error was sent to Sentry.\n </div>\n <button v-else @click=\"throwError\">\n <span>Throw Sample Error</span>\n </button>\n</template>\n\n<style scoped>\n button {\n border-radius: 8px;\n color: white;\n cursor: pointer;\n background-color: #553DB8;\n border: none;\n padding: 0;\n margin-top: 4px;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n\n & > span {\n display: inline-block;\n padding: 12px 16px;\n border-radius: inherit;\n font-size: 20px;\n font-weight: bold;\n line-height: 1;\n background-color: #7553FF;\n border: 1px solid #553DB8;\n transform: translateY(-4px);\n }\n\n &:hover > span {\n transform: translateY(-8px);\n }\n\n &:active > span {\n transform: translateY(0);\n }\n }\n\n .success {\n width: max-content;\n padding: 12px 16px;\n border-radius: 8px;\n font-size: 20px;\n line-height: 1;\n background-color: #00F261;\n border: 1px solid #00BF4D;\n color: #181423;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n</style>\n`;\n}\n"]}
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/nuxt/templates.ts"],"names":[],"mappings":"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","sourcesContent":["import { getIssueStreamUrl } from '../utils/url';\n\ntype SelectedSentryFeatures = {\n performance: boolean;\n replay: boolean;\n};\n\nexport function getDefaultNuxtConfig(): string {\n return `// https://nuxt.com/docs/api/configuration/nuxt-config\nexport default defineNuxtConfig({\n compatibilityDate: '2024-04-03',\n devtools: { enabled: true }\n})\n`;\n}\n\nexport function getNuxtModuleFallbackTemplate(\n options: {\n org: string;\n project: string;\n url: string;\n selfHosted: boolean;\n },\n shouldTopLevelImport: boolean,\n): string {\n return ` modules: [\"@sentry/nuxt/module\"],\n sentry: {\n sourceMapsUploadOptions: {\n org: \"${options.org}\",\n project: \"${options.project}\",${\n options.selfHosted ? `\\n url: \"${options.url}\",` : ''\n }\n },${\n shouldTopLevelImport\n ? `\\n autoInjectServerSentry: \"top-level-import\",`\n : ''\n }\n },\n sourcemap: { client: \"hidden\" },`;\n}\n\nexport function getSentryConfigContents(\n dsn: string,\n config: 'client' | 'server',\n selectedFeatures: SelectedSentryFeatures,\n): string {\n if (config === 'client') {\n return getSentryClientConfigContents(dsn, selectedFeatures);\n }\n\n return getSentryServerConfigContents(dsn, selectedFeatures);\n}\n\nconst featuresConfigMap: Record<keyof SelectedSentryFeatures, string> = {\n performance: [\n ' // We recommend adjusting this value in production, or using tracesSampler',\n ' // for finer control',\n ' tracesSampleRate: 1.0,',\n ].join('\\n'),\n replay: [\n ' // This sets the sample rate to be 10%. You may want this to be 100% while',\n ' // in development and sample at a lower rate in production',\n ' replaysSessionSampleRate: 0.1,',\n ' ',\n ' // If the entire session is not sampled, use the below sample rate to sample',\n ' // sessions when an error occurs.',\n ' replaysOnErrorSampleRate: 1.0,',\n ' ',\n \" // If you don't want to use Session Replay, just remove the line below:\",\n ' integrations: [Sentry.replayIntegration()],',\n ].join('\\n'),\n};\n\nconst featuresMap: Record<\n 'client' | 'server',\n Array<keyof SelectedSentryFeatures>\n> = {\n client: ['performance', 'replay'],\n server: ['performance'],\n};\n\nexport function getConfigBody(\n dsn: string,\n variant: 'client' | 'server',\n selectedFeatures: SelectedSentryFeatures,\n) {\n return [\n `dsn: \"${dsn}\",`,\n Object.entries(selectedFeatures)\n .map(([feature, activated]: [keyof SelectedSentryFeatures, boolean]) => {\n return featuresMap[variant].includes(feature) && activated\n ? featuresConfigMap[feature]\n : null;\n })\n .filter(Boolean)\n .join('\\n\\n'),\n ]\n .filter(Boolean)\n .join('\\n\\n');\n}\n\nfunction getSentryClientConfigContents(\n dsn: string,\n selectedFeatures: SelectedSentryFeatures,\n): string {\n return `import * as Sentry from \"@sentry/nuxt\";\n\nSentry.init({\n // If set up, you can use your runtime config here\n // dsn: useRuntimeConfig().public.sentry.dsn,\n ${getConfigBody(dsn, 'client', selectedFeatures)}\n \n // Setting this option to true will print useful information to the console while you're setting up Sentry.\n debug: false,\n});\n`;\n}\n\nfunction getSentryServerConfigContents(\n dsn: string,\n selectedFeatures: SelectedSentryFeatures,\n): string {\n return `import * as Sentry from \"@sentry/nuxt\";\n \nSentry.init({\n ${getConfigBody(dsn, 'server', selectedFeatures)}\n \n // Setting this option to true will print useful information to the console while you're setting up Sentry.\n debug: false,\n});\n`;\n}\n\nexport function getIndexRouteTemplate(): string {\n return `<!--\nThis is just to verify the sentry-example-page.\nFeel free to delete this file.\n-->\n\n<template></template>`;\n}\n\nexport function getSentryExamplePageTemplate(options: {\n url: string;\n org: string;\n projectId: string;\n}): string {\n const { url, org, projectId } = options;\n const issuesPageLink = getIssueStreamUrl({ url, orgSlug: org, projectId });\n\n return `<!--\nThis is just a very simple page with a button to throw an example error.\nFeel free to delete this file.\n-->\n\n<script setup>\n import * as Sentry from '@sentry/nuxt';\n import { useFetch} from '#imports'\n\n const hasSentError = ref(false);\n const isConnected = ref(true);\n \n onMounted(async () => {\n try {\n const result = await Sentry.diagnoseSdkConnectivity();\n isConnected.value = result !== 'sentry-unreachable';\n } catch (error) {\n isConnected.value = false;\n }\n });\n \n function getSentryData() {\n Sentry.startSpan(\n {\n name: 'Example Frontend Span',\n op: 'test'\n },\n async () => {\n const { error } = await useFetch('/api/sentry-example-api');\n if (error.value) {\n hasSentError.value = true;\n throw new Error('Sentry Example Frontend Error');\n }\n }\n )\n }\n</script>\n\n<template>\n <title>Sentry Onboarding</title>\n <div>\n <main>\n <div class=\"flex-spacer\" />\n <svg height=\"40\" width=\"40\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M21.85 2.995a3.698 3.698 0 0 1 1.353 1.354l16.303 28.278a3.703 3.703 0 0 1-1.354 5.053 3.694 3.694 0 0 1-1.848.496h-3.828a31.149 31.149 0 0 0 0-3.09h3.815a.61.61 0 0 0 .537-.917L20.523 5.893a.61.61 0 0 0-1.057 0l-3.739 6.494a28.948 28.948 0 0 1 9.63 10.453 28.988 28.988 0 0 1 3.499 13.78v1.542h-9.852v-1.544a19.106 19.106 0 0 0-2.182-8.85 19.08 19.08 0 0 0-6.032-6.829l-1.85 3.208a15.377 15.377 0 0 1 6.382 12.484v1.542H3.696A3.694 3.694 0 0 1 0 34.473c0-.648.17-1.286.494-1.849l2.33-4.074a8.562 8.562 0 0 1 2.689 1.536L3.158 34.17a.611.611 0 0 0 .538.917h8.448a12.481 12.481 0 0 0-6.037-9.09l-1.344-.772 4.908-8.545 1.344.77a22.16 22.16 0 0 1 7.705 7.444 22.193 22.193 0 0 1 3.316 10.193h3.699a25.892 25.892 0 0 0-3.811-12.033 25.856 25.856 0 0 0-9.046-8.796l-1.344-.772 5.269-9.136a3.698 3.698 0 0 1 3.2-1.849c.648 0 1.285.17 1.847.495Z\" fill=\"currentcolor\"/>\n </svg>\n <h1>\n sentry-example-page\n </h1>\n\n <p class=\"description\">\n Click the button below, and view the sample error on the Sentry <a target=\"_blank\" href=\"${issuesPageLink}\">Issues Page</a>. \n For more details about setting up Sentry, <a target=\"_blank\" href=\"https://docs.sentry.io/platforms/javascript/guides/nuxt/\">read our docs</a>.\n </p>\n\n <button\n type=\"button\"\n @click=\"getSentryData\"\n >\n <span>\n Throw Sample Error\n </span>\n </button>\n\n <p v-if=\"hasSentError\" class=\"success\">\n Sample error was sent to Sentry.\n </p>\n <div v-else-if=\"!isConnected\" class=\"connectivity-error\">\n <p>The Sentry SDK is not able to reach Sentry right now - this may be due to an adblocker. For more information, see <a target=\"_blank\" href=\"https://docs.sentry.io/platforms/javascript/guides/nuxt/troubleshooting/#the-sdk-is-not-sending-any-data\">the troubleshooting guide</a>.</p>\n </div>\n <div v-else class=\"success_placeholder\" />\n\n <div class=\"flex-spacer\" />\n <p class=\"description\">\n Adblockers will prevent errors from being sent to Sentry.\n </p>\n </main>\n </div>\n</template>\n\n<style scoped>\n :global(body) {\n margin: 0;\n\n @media (prefers-color-scheme: dark) {\n color: #ededed;\n background-color: #0a0a0a;\n }\n }\n\n main {\n display: flex;\n min-height: 100vh;\n box-sizing: border-box;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n gap: 16px;\n padding: 16px;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n\n h1 {\n padding: 0px 4px;\n margin: 0;\n border-radius: 4px;\n background-color: rgba(24, 20, 35, 0.03);\n font-family: monospace;\n font-size: 20px;\n line-height: 1.2;\n }\n\n p {\n margin: 0;\n font-size: 20px;\n }\n\n a {\n color: #6341F0;\n text-decoration: underline;\n cursor: pointer;\n\n @media (prefers-color-scheme: dark) {\n color: #B3A1FF;\n }\n }\n\n button {\n border-radius: 8px;\n color: white;\n cursor: pointer;\n background-color: #553DB8;\n border: none;\n padding: 0;\n margin-top: 4px;\n\n & > span {\n display: inline-block;\n padding: 12px 16px;\n border-radius: inherit;\n font-size: 20px;\n font-weight: bold;\n line-height: 1;\n background-color: #7553FF;\n border: 1px solid #553DB8;\n transform: translateY(-4px);\n }\n\n &:hover > span {\n transform: translateY(-8px);\n }\n\n &:active > span {\n transform: translateY(0); \n }\n }\n\n .description {\n text-align: center;\n color: #6E6C75;\n max-width: 500px;\n line-height: 1.5;\n font-size: 20px;\n\n @media (prefers-color-scheme: dark) {\n color: #A49FB5;\n }\n }\n\n .flex-spacer {\n flex: 1;\n }\n\n .success {\n padding: 12px 16px;\n border-radius: 8px;\n font-size: 20px;\n line-height: 1;\n background-color: #00F261;\n border: 1px solid #00BF4D;\n color: #181423;\n }\n\n .success_placeholder {\n height: 46px;\n }\n \n .connectivity-error {\n padding: 12px 16px;\n background-color: #E50045;\n border-radius: 8px;\n width: 500px;\n color: #FFFFFF;\n border: 1px solid #A80033;\n text-align: center;\n margin: 0;\n }\n \n .connectivity-error a {\n color: #FFFFFF;\n text-decoration: underline;\n }\n</style>\n\n`;\n}\n\nexport function getSentryExampleApiTemplate() {\n return `// This is just a very simple API route that throws an example error.\n// Feel free to delete this file.\nimport { defineEventHandler } from '#imports';\n\nexport default defineEventHandler(() => {\n throw new Error(\"Sentry Example API Route Error\");\n});\n`;\n}\n\nexport function getSentryErrorButtonTemplate() {\n return `<!--\nThis is just a very simple component that throws an example error.\nFeel free to delete this file.\n-->\n\n<script setup>\n import * as Sentry from '@sentry/nuxt';\n\n const hasSentError = ref(false);\n \n const throwError = () => {\n Sentry.startSpan(\n {\n name: 'Example Frontend Span',\n op: 'test'\n },\n () => {\n hasSentError.value = true;\n throw new Error('Sentry Example Error');\n }\n )\n };\n</script>\n\n<template>\n <div v-if=\"hasSentError\" class=\"success\">\n Sample error was sent to Sentry.\n </div>\n <button v-else @click=\"throwError\">\n <span>Throw Sample Error</span>\n </button>\n</template>\n\n<style scoped>\n button {\n border-radius: 8px;\n color: white;\n cursor: pointer;\n background-color: #553DB8;\n border: none;\n padding: 0;\n margin-top: 4px;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n\n & > span {\n display: inline-block;\n padding: 12px 16px;\n border-radius: inherit;\n font-size: 20px;\n font-weight: bold;\n line-height: 1;\n background-color: #7553FF;\n border: 1px solid #553DB8;\n transform: translateY(-4px);\n }\n\n &:hover > span {\n transform: translateY(-8px);\n }\n\n &:active > span {\n transform: translateY(0);\n }\n }\n\n .success {\n width: max-content;\n padding: 12px 16px;\n border-radius: 8px;\n font-size: 20px;\n line-height: 1;\n background-color: #00F261;\n border: 1px solid #00BF4D;\n color: #181423;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n</style>\n`;\n}\n"]}
@@ -167,7 +167,10 @@ module.exports = config;
167
167
  return true;
168
168
  }
169
169
  function showInstructions() {
170
- return (0, clack_1.showCopyPasteInstructions)(metro_1.metroConfigPath, getMetroWithSentryExpoConfigSnippet(true));
170
+ return (0, clack_1.showCopyPasteInstructions)({
171
+ filename: metro_1.metroConfigPath,
172
+ codeSnippet: getMetroWithSentryExpoConfigSnippet(true),
173
+ });
171
174
  }
172
175
  function getMetroWithSentryExpoConfigSnippet(colors) {
173
176
  return (0, clack_1.makeCodeSnippet)(colors, (unchanged, plus, minus) => unchanged(`${minus(`// const { getDefaultConfig } = require("expo/metro-config");`)}
@@ -1 +1 @@
1
- {"version":3,"file":"expo-metro.js","sourceRoot":"","sources":["../../../src/react-native/expo-metro.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'node:fs';\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport type { ProxifiedModule } from 'magicast';\nimport chalk from 'chalk';\nimport * as Sentry from '@sentry/node';\n\nimport { getLastRequireIndex, hasSentryContent } from '../utils/ast-utils';\nimport { makeCodeSnippet, showCopyPasteInstructions } from '../utils/clack';\n\nimport { metroConfigPath, parseMetroConfig, writeMetroConfig } from './metro';\n\nimport * as recast from 'recast';\nimport x = recast.types;\nimport t = x.namedTypes;\n\nconst b = recast.types.builders;\n\nexport async function addSentryToExpoMetroConfig() {\n if (!fs.existsSync(metroConfigPath)) {\n const success = await createSentryExpoMetroConfig();\n if (!success) {\n Sentry.setTag('expo-metro-config', 'create-new-error');\n return await showInstructions();\n }\n Sentry.setTag('expo-metro-config', 'created-new');\n return undefined;\n }\n\n const mod = await parseMetroConfig();\n\n let didPatch = false;\n try {\n didPatch = patchMetroInMemory(mod);\n } catch (e) {\n // noop\n }\n if (!didPatch) {\n Sentry.setTag('expo-metro-config', 'patch-error');\n clack.log.error(\n `Could not patch ${chalk.cyan(\n metroConfigPath,\n )} with Sentry configuration.`,\n );\n return await showInstructions();\n }\n\n const saved = await writeMetroConfig(mod);\n if (saved) {\n Sentry.setTag('expo-metro-config', 'patch-saved');\n clack.log.success(\n chalk.green(`${chalk.cyan(metroConfigPath)} changes saved.`),\n );\n } else {\n Sentry.setTag('expo-metro-config', 'patch-save-error');\n clack.log.warn(\n `Could not save changes to ${chalk.cyan(\n metroConfigPath,\n )}, please follow the manual steps.`,\n );\n return await showInstructions();\n }\n}\n\nexport function patchMetroInMemory(mod: ProxifiedModule): boolean {\n const ast = mod.$ast as t.Program;\n\n if (hasSentryContent(ast)) {\n clack.log.warn(\n `The ${chalk.cyan(\n metroConfigPath,\n )} file already has Sentry configuration.`,\n );\n return false;\n }\n\n let didReplaceDefaultConfigCall = false;\n\n recast.visit(ast, {\n visitVariableDeclaration(path) {\n const { node } = path;\n\n if (\n // path is require(\"expo/metro-config\")\n // and only getDefaultConfig is being destructured\n // then remove the entire declaration\n node.declarations.length > 0 &&\n node.declarations[0].type === 'VariableDeclarator' &&\n node.declarations[0].init &&\n node.declarations[0].init.type === 'CallExpression' &&\n node.declarations[0].init.callee &&\n node.declarations[0].init.callee.type === 'Identifier' &&\n node.declarations[0].init.callee.name === 'require' &&\n node.declarations[0].init.arguments[0].type === 'StringLiteral' &&\n node.declarations[0].init.arguments[0].value === 'expo/metro-config' &&\n node.declarations[0].id.type === 'ObjectPattern' &&\n node.declarations[0].id.properties.length === 1 &&\n node.declarations[0].id.properties[0].type === 'ObjectProperty' &&\n node.declarations[0].id.properties[0].key.type === 'Identifier' &&\n node.declarations[0].id.properties[0].key.name === 'getDefaultConfig'\n ) {\n path.prune();\n return false;\n }\n\n this.traverse(path);\n },\n\n visitCallExpression(path) {\n const { node } = path;\n if (\n // path is getDefaultConfig\n // then rename it to getSentryExpoConfig\n node.callee.type === 'Identifier' &&\n node.callee.name === 'getDefaultConfig'\n ) {\n node.callee.name = 'getSentryExpoConfig';\n didReplaceDefaultConfigCall = true;\n return false;\n }\n\n this.traverse(path);\n },\n });\n\n if (!didReplaceDefaultConfigCall) {\n clack.log.warn(\n `Could not find \\`getDefaultConfig\\` in ${chalk.cyan(metroConfigPath)}.`,\n );\n return false;\n }\n\n addSentryExpoConfigRequire(ast);\n\n return true;\n}\n\nexport function addSentryExpoConfigRequire(program: t.Program) {\n const lastRequireIndex = getLastRequireIndex(program);\n const sentryExpoConfigRequire = createSentryExpoConfigRequire();\n program.body.splice(lastRequireIndex + 1, 0, sentryExpoConfigRequire);\n}\n\n/**\n * Creates const { getSentryExpoConfig } = require(\"@sentry/react-native/metro\");\n */\nfunction createSentryExpoConfigRequire() {\n return b.variableDeclaration('const', [\n b.variableDeclarator(\n b.objectPattern([\n b.objectProperty.from({\n key: b.identifier('getSentryExpoConfig'),\n value: b.identifier('getSentryExpoConfig'),\n shorthand: true,\n }),\n ]),\n b.callExpression(b.identifier('require'), [\n b.literal('@sentry/react-native/metro'),\n ]),\n ),\n ]);\n}\n\nasync function createSentryExpoMetroConfig(): Promise<boolean> {\n const snippet = `const { getSentryExpoConfig } = require(\"@sentry/react-native/metro\");\n\nconst config = getSentryExpoConfig(__dirname);\n\nmodule.exports = config;\n`;\n try {\n await fs.promises.writeFile(metroConfigPath, snippet);\n } catch (e) {\n clack.log.error(\n `Could not create ${chalk.cyan(\n metroConfigPath,\n )} with Sentry configuration.`,\n );\n return false;\n }\n clack.log.success(\n `Created ${chalk.cyan(metroConfigPath)} with Sentry configuration.`,\n );\n return true;\n}\n\nfunction showInstructions() {\n return showCopyPasteInstructions(\n metroConfigPath,\n getMetroWithSentryExpoConfigSnippet(true),\n );\n}\n\nfunction getMetroWithSentryExpoConfigSnippet(colors: boolean): string {\n return makeCodeSnippet(colors, (unchanged, plus, minus) =>\n unchanged(`${minus(\n `// const { getDefaultConfig } = require(\"expo/metro-config\");`,\n )}\n${plus(\n `const { getSentryExpoConfig } = require(\"@sentry/react-native/metro\");`,\n)}\n\n${minus(`// const config = getDefaultConfig(__dirname);`)}\n${plus(`const config = getSentryExpoConfig(__dirname);`)}\n\nmodule.exports = config;`),\n );\n}\n"]}
1
+ {"version":3,"file":"expo-metro.js","sourceRoot":"","sources":["../../../src/react-native/expo-metro.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4CAA8B;AAC9B,+EAA+E;AAC/E,sDAAwC;AAGxC,kDAA0B;AAC1B,qDAAuC;AAEvC,kDAA2E;AAC3E,0CAA4E;AAE5E,mCAA8E;AAE9E,+CAAiC;AAIjC,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;AAEzB,KAAK,UAAU,0BAA0B;IAC9C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,uBAAe,CAAC,EAAE;QACnC,MAAM,OAAO,GAAG,MAAM,2BAA2B,EAAE,CAAC;QACpD,IAAI,CAAC,OAAO,EAAE;YACZ,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC;YACvD,OAAO,MAAM,gBAAgB,EAAE,CAAC;SACjC;QACD,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,aAAa,CAAC,CAAC;QAClD,OAAO,SAAS,CAAC;KAClB;IAED,MAAM,GAAG,GAAG,MAAM,IAAA,wBAAgB,GAAE,CAAC;IAErC,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI;QACF,QAAQ,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;KACpC;IAAC,OAAO,CAAC,EAAE;QACV,OAAO;KACR;IACD,IAAI,CAAC,QAAQ,EAAE;QACb,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,aAAa,CAAC,CAAC;QAClD,KAAK,CAAC,GAAG,CAAC,KAAK,CACb,mBAAmB,eAAK,CAAC,IAAI,CAC3B,uBAAe,CAChB,6BAA6B,CAC/B,CAAC;QACF,OAAO,MAAM,gBAAgB,EAAE,CAAC;KACjC;IAED,MAAM,KAAK,GAAG,MAAM,IAAA,wBAAgB,EAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,KAAK,EAAE;QACT,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,aAAa,CAAC,CAAC;QAClD,KAAK,CAAC,GAAG,CAAC,OAAO,CACf,eAAK,CAAC,KAAK,CAAC,GAAG,eAAK,CAAC,IAAI,CAAC,uBAAe,CAAC,iBAAiB,CAAC,CAC7D,CAAC;KACH;SAAM;QACL,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,kBAAkB,CAAC,CAAC;QACvD,KAAK,CAAC,GAAG,CAAC,IAAI,CACZ,6BAA6B,eAAK,CAAC,IAAI,CACrC,uBAAe,CAChB,mCAAmC,CACrC,CAAC;QACF,OAAO,MAAM,gBAAgB,EAAE,CAAC;KACjC;AACH,CAAC;AA5CD,gEA4CC;AAED,SAAgB,kBAAkB,CAAC,GAAoB;IACrD,MAAM,GAAG,GAAG,GAAG,CAAC,IAAiB,CAAC;IAElC,IAAI,IAAA,4BAAgB,EAAC,GAAG,CAAC,EAAE;QACzB,KAAK,CAAC,GAAG,CAAC,IAAI,CACZ,OAAO,eAAK,CAAC,IAAI,CACf,uBAAe,CAChB,yCAAyC,CAC3C,CAAC;QACF,OAAO,KAAK,CAAC;KACd;IAED,IAAI,2BAA2B,GAAG,KAAK,CAAC;IAExC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE;QAChB,wBAAwB,CAAC,IAAI;YAC3B,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;YAEtB;YACE,uCAAuC;YACvC,kDAAkD;YAClD,qCAAqC;YACrC,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;gBAC5B,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,oBAAoB;gBAClD,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI;gBACzB,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,gBAAgB;gBACnD,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM;gBAChC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY;gBACtD,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS;gBACnD,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe;gBAC/D,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,mBAAmB;gBACpE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,KAAK,eAAe;gBAChD,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC;gBAC/C,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB;gBAC/D,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,YAAY;gBAC/D,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,kBAAkB,EACrE;gBACA,IAAI,CAAC,KAAK,EAAE,CAAC;gBACb,OAAO,KAAK,CAAC;aACd;YAED,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;QAED,mBAAmB,CAAC,IAAI;YACtB,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;YACtB;YACE,2BAA2B;YAC3B,wCAAwC;YACxC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY;gBACjC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,kBAAkB,EACvC;gBACA,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,qBAAqB,CAAC;gBACzC,2BAA2B,GAAG,IAAI,CAAC;gBACnC,OAAO,KAAK,CAAC;aACd;YAED,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,2BAA2B,EAAE;QAChC,KAAK,CAAC,GAAG,CAAC,IAAI,CACZ,0CAA0C,eAAK,CAAC,IAAI,CAAC,uBAAe,CAAC,GAAG,CACzE,CAAC;QACF,OAAO,KAAK,CAAC;KACd;IAED,0BAA0B,CAAC,GAAG,CAAC,CAAC;IAEhC,OAAO,IAAI,CAAC;AACd,CAAC;AAvED,gDAuEC;AAED,SAAgB,0BAA0B,CAAC,OAAkB;IAC3D,MAAM,gBAAgB,GAAG,IAAA,+BAAmB,EAAC,OAAO,CAAC,CAAC;IACtD,MAAM,uBAAuB,GAAG,6BAA6B,EAAE,CAAC;IAChE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,GAAG,CAAC,EAAE,CAAC,EAAE,uBAAuB,CAAC,CAAC;AACxE,CAAC;AAJD,gEAIC;AAED;;GAEG;AACH,SAAS,6BAA6B;IACpC,OAAO,CAAC,CAAC,mBAAmB,CAAC,OAAO,EAAE;QACpC,CAAC,CAAC,kBAAkB,CAClB,CAAC,CAAC,aAAa,CAAC;YACd,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC;gBACpB,GAAG,EAAE,CAAC,CAAC,UAAU,CAAC,qBAAqB,CAAC;gBACxC,KAAK,EAAE,CAAC,CAAC,UAAU,CAAC,qBAAqB,CAAC;gBAC1C,SAAS,EAAE,IAAI;aAChB,CAAC;SACH,CAAC,EACF,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE;YACxC,CAAC,CAAC,OAAO,CAAC,4BAA4B,CAAC;SACxC,CAAC,CACH;KACF,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,2BAA2B;IACxC,MAAM,OAAO,GAAG;;;;;CAKjB,CAAC;IACA,IAAI;QACF,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,uBAAe,EAAE,OAAO,CAAC,CAAC;KACvD;IAAC,OAAO,CAAC,EAAE;QACV,KAAK,CAAC,GAAG,CAAC,KAAK,CACb,oBAAoB,eAAK,CAAC,IAAI,CAC5B,uBAAe,CAChB,6BAA6B,CAC/B,CAAC;QACF,OAAO,KAAK,CAAC;KACd;IACD,KAAK,CAAC,GAAG,CAAC,OAAO,CACf,WAAW,eAAK,CAAC,IAAI,CAAC,uBAAe,CAAC,6BAA6B,CACpE,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,gBAAgB;IACvB,OAAO,IAAA,iCAAyB,EAAC;QAC/B,QAAQ,EAAE,uBAAe;QACzB,WAAW,EAAE,mCAAmC,CAAC,IAAI,CAAC;KACvD,CAAC,CAAC;AACL,CAAC;AAED,SAAS,mCAAmC,CAAC,MAAe;IAC1D,OAAO,IAAA,uBAAe,EAAC,MAAM,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,CACxD,SAAS,CAAC,GAAG,KAAK,CAChB,+DAA+D,CAChE;EACH,IAAI,CACJ,wEAAwE,CACzE;;EAEC,KAAK,CAAC,gDAAgD,CAAC;EACvD,IAAI,CAAC,gDAAgD,CAAC;;yBAE/B,CAAC,CACvB,CAAC;AACJ,CAAC","sourcesContent":["import * as fs from 'node:fs';\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport type { ProxifiedModule } from 'magicast';\nimport chalk from 'chalk';\nimport * as Sentry from '@sentry/node';\n\nimport { getLastRequireIndex, hasSentryContent } from '../utils/ast-utils';\nimport { makeCodeSnippet, showCopyPasteInstructions } from '../utils/clack';\n\nimport { metroConfigPath, parseMetroConfig, writeMetroConfig } from './metro';\n\nimport * as recast from 'recast';\nimport x = recast.types;\nimport t = x.namedTypes;\n\nconst b = recast.types.builders;\n\nexport async function addSentryToExpoMetroConfig() {\n if (!fs.existsSync(metroConfigPath)) {\n const success = await createSentryExpoMetroConfig();\n if (!success) {\n Sentry.setTag('expo-metro-config', 'create-new-error');\n return await showInstructions();\n }\n Sentry.setTag('expo-metro-config', 'created-new');\n return undefined;\n }\n\n const mod = await parseMetroConfig();\n\n let didPatch = false;\n try {\n didPatch = patchMetroInMemory(mod);\n } catch (e) {\n // noop\n }\n if (!didPatch) {\n Sentry.setTag('expo-metro-config', 'patch-error');\n clack.log.error(\n `Could not patch ${chalk.cyan(\n metroConfigPath,\n )} with Sentry configuration.`,\n );\n return await showInstructions();\n }\n\n const saved = await writeMetroConfig(mod);\n if (saved) {\n Sentry.setTag('expo-metro-config', 'patch-saved');\n clack.log.success(\n chalk.green(`${chalk.cyan(metroConfigPath)} changes saved.`),\n );\n } else {\n Sentry.setTag('expo-metro-config', 'patch-save-error');\n clack.log.warn(\n `Could not save changes to ${chalk.cyan(\n metroConfigPath,\n )}, please follow the manual steps.`,\n );\n return await showInstructions();\n }\n}\n\nexport function patchMetroInMemory(mod: ProxifiedModule): boolean {\n const ast = mod.$ast as t.Program;\n\n if (hasSentryContent(ast)) {\n clack.log.warn(\n `The ${chalk.cyan(\n metroConfigPath,\n )} file already has Sentry configuration.`,\n );\n return false;\n }\n\n let didReplaceDefaultConfigCall = false;\n\n recast.visit(ast, {\n visitVariableDeclaration(path) {\n const { node } = path;\n\n if (\n // path is require(\"expo/metro-config\")\n // and only getDefaultConfig is being destructured\n // then remove the entire declaration\n node.declarations.length > 0 &&\n node.declarations[0].type === 'VariableDeclarator' &&\n node.declarations[0].init &&\n node.declarations[0].init.type === 'CallExpression' &&\n node.declarations[0].init.callee &&\n node.declarations[0].init.callee.type === 'Identifier' &&\n node.declarations[0].init.callee.name === 'require' &&\n node.declarations[0].init.arguments[0].type === 'StringLiteral' &&\n node.declarations[0].init.arguments[0].value === 'expo/metro-config' &&\n node.declarations[0].id.type === 'ObjectPattern' &&\n node.declarations[0].id.properties.length === 1 &&\n node.declarations[0].id.properties[0].type === 'ObjectProperty' &&\n node.declarations[0].id.properties[0].key.type === 'Identifier' &&\n node.declarations[0].id.properties[0].key.name === 'getDefaultConfig'\n ) {\n path.prune();\n return false;\n }\n\n this.traverse(path);\n },\n\n visitCallExpression(path) {\n const { node } = path;\n if (\n // path is getDefaultConfig\n // then rename it to getSentryExpoConfig\n node.callee.type === 'Identifier' &&\n node.callee.name === 'getDefaultConfig'\n ) {\n node.callee.name = 'getSentryExpoConfig';\n didReplaceDefaultConfigCall = true;\n return false;\n }\n\n this.traverse(path);\n },\n });\n\n if (!didReplaceDefaultConfigCall) {\n clack.log.warn(\n `Could not find \\`getDefaultConfig\\` in ${chalk.cyan(metroConfigPath)}.`,\n );\n return false;\n }\n\n addSentryExpoConfigRequire(ast);\n\n return true;\n}\n\nexport function addSentryExpoConfigRequire(program: t.Program) {\n const lastRequireIndex = getLastRequireIndex(program);\n const sentryExpoConfigRequire = createSentryExpoConfigRequire();\n program.body.splice(lastRequireIndex + 1, 0, sentryExpoConfigRequire);\n}\n\n/**\n * Creates const { getSentryExpoConfig } = require(\"@sentry/react-native/metro\");\n */\nfunction createSentryExpoConfigRequire() {\n return b.variableDeclaration('const', [\n b.variableDeclarator(\n b.objectPattern([\n b.objectProperty.from({\n key: b.identifier('getSentryExpoConfig'),\n value: b.identifier('getSentryExpoConfig'),\n shorthand: true,\n }),\n ]),\n b.callExpression(b.identifier('require'), [\n b.literal('@sentry/react-native/metro'),\n ]),\n ),\n ]);\n}\n\nasync function createSentryExpoMetroConfig(): Promise<boolean> {\n const snippet = `const { getSentryExpoConfig } = require(\"@sentry/react-native/metro\");\n\nconst config = getSentryExpoConfig(__dirname);\n\nmodule.exports = config;\n`;\n try {\n await fs.promises.writeFile(metroConfigPath, snippet);\n } catch (e) {\n clack.log.error(\n `Could not create ${chalk.cyan(\n metroConfigPath,\n )} with Sentry configuration.`,\n );\n return false;\n }\n clack.log.success(\n `Created ${chalk.cyan(metroConfigPath)} with Sentry configuration.`,\n );\n return true;\n}\n\nfunction showInstructions() {\n return showCopyPasteInstructions({\n filename: metroConfigPath,\n codeSnippet: getMetroWithSentryExpoConfigSnippet(true),\n });\n}\n\nfunction getMetroWithSentryExpoConfigSnippet(colors: boolean): string {\n return makeCodeSnippet(colors, (unchanged, plus, minus) =>\n unchanged(`${minus(\n `// const { getDefaultConfig } = require(\"expo/metro-config\");`,\n )}\n${plus(\n `const { getSentryExpoConfig } = require(\"@sentry/react-native/metro\");`,\n)}\n\n${minus(`// const config = getDefaultConfig(__dirname);`)}\n${plus(`const config = getSentryExpoConfig(__dirname);`)}\n\nmodule.exports = config;`),\n );\n}\n"]}
@@ -49,7 +49,11 @@ exports.printSentryExpoMigrationOutro = printSentryExpoMigrationOutro;
49
49
  */
50
50
  async function patchExpoAppConfig(options) {
51
51
  function showInstructions() {
52
- return (0, clack_1.showCopyPasteInstructions)(APP_CONFIG_JSON, getSentryAppConfigJsonCodeSnippet(options), 'This ensures auto upload of source maps during native app build.');
52
+ return (0, clack_1.showCopyPasteInstructions)({
53
+ filename: APP_CONFIG_JSON,
54
+ codeSnippet: getSentryAppConfigJsonCodeSnippet(options),
55
+ hint: 'This ensures auto upload of source maps during native app build.',
56
+ });
53
57
  }
54
58
  const appConfigJsonExists = fs.existsSync(APP_CONFIG_JSON);
55
59
  Sentry.setTag('app-config-file-status', appConfigJsonExists ? 'found' : 'not-found');
@@ -1 +1 @@
1
- {"version":3,"file":"expo.js","sourceRoot":"","sources":["../../../src/react-native/expo.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\nimport chalk from 'chalk';\nimport * as fs from 'fs';\nimport { EOL } from 'os';\n\nimport { isPlainObject } from '@sentry/utils';\nimport * as Sentry from '@sentry/node';\nimport { makeCodeSnippet, showCopyPasteInstructions } from '../utils/clack';\nimport { RNCliSetupConfigContent } from './react-native-wizard';\nimport { traceStep } from '../telemetry';\n\nexport const SENTRY_EXPO_PLUGIN_NAME = '@sentry/react-native/expo';\nexport const DEPRECATED_SENTRY_EXPO_PLUGIN_NAME = 'sentry-expo';\n\nexport const SENTRY_PLUGIN_FUNCTION_NAME = 'withSentry';\n\nconst APP_CONFIG_JSON = `app.json`;\n\nexport interface AppConfigJson {\n expo?: {\n plugins?: Array<[string, undefined | Record<string, unknown>]>;\n };\n}\n\nexport function printSentryExpoMigrationOutro(): void {\n clack.outro(\n `Deprecated ${chalk.cyan(\n 'sentry-expo',\n )} package installed in your dependencies. Please follow the migration guide at ${chalk.cyan(\n 'https://docs.sentry.io/platforms/react-native/migration/sentry-expo/',\n )}`,\n );\n}\n\n/**\n * Finds app.json in the project root and add Sentry Expo `withSentry` plugin.\n */\nexport async function patchExpoAppConfig(options: RNCliSetupConfigContent) {\n function showInstructions() {\n return showCopyPasteInstructions(\n APP_CONFIG_JSON,\n getSentryAppConfigJsonCodeSnippet(options),\n 'This ensures auto upload of source maps during native app build.',\n );\n }\n\n const appConfigJsonExists = fs.existsSync(APP_CONFIG_JSON);\n\n Sentry.setTag(\n 'app-config-file-status',\n appConfigJsonExists ? 'found' : 'not-found',\n );\n if (!appConfigJsonExists) {\n return await showInstructions();\n }\n\n const patched = await patchAppConfigJson(APP_CONFIG_JSON, options);\n if (!patched) {\n return await showInstructions();\n }\n}\n\nasync function patchAppConfigJson(\n path: string,\n options: RNCliSetupConfigContent,\n): Promise<boolean> {\n const appConfigContent = (\n await fs.promises.readFile(path, { encoding: 'utf-8' })\n ).toString();\n const patchedContent = traceStep('app-config-json-patch', () =>\n addWithSentryToAppConfigJson(appConfigContent, options),\n );\n if (patchedContent === null) {\n return false;\n }\n\n try {\n await fs.promises.writeFile(path, patchedContent);\n } catch (error) {\n Sentry.setTag('app-config-file-status', 'json-write-error');\n clack.log.error(`Unable to write ${chalk.cyan('app.config.json')}.`);\n return false;\n }\n Sentry.setTag('app-config-file-status', 'json-write-success');\n clack.log.success(\n `Added Sentry Expo plugin to ${chalk.cyan('app.config.json')}.`,\n );\n return true;\n}\n\nexport function addWithSentryToAppConfigJson(\n appConfigContent: string,\n options: RNCliSetupConfigContent,\n): string | null {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const parsedAppConfig: AppConfigJson = JSON.parse(appConfigContent);\n const includesWithSentry =\n appConfigContent.includes(SENTRY_EXPO_PLUGIN_NAME) ||\n appConfigContent.includes(DEPRECATED_SENTRY_EXPO_PLUGIN_NAME);\n\n if (includesWithSentry) {\n Sentry.setTag('app-config-file-status', 'already-patched');\n clack.log.warn(\n `Your ${chalk.cyan(\n 'app.config.json',\n )} already includes the Sentry Expo plugin.`,\n );\n return null;\n }\n\n if (\n parsedAppConfig.expo !== undefined &&\n !isPlainObject(parsedAppConfig.expo)\n ) {\n Sentry.setTag('app-config-file-status', 'invalid-json');\n return null;\n }\n if (\n parsedAppConfig.expo &&\n parsedAppConfig.expo.plugins !== undefined &&\n !Array.isArray(parsedAppConfig.expo.plugins)\n ) {\n Sentry.setTag('app-config-file-status', 'invalid-json');\n return null;\n }\n\n parsedAppConfig.expo = parsedAppConfig.expo ?? {};\n parsedAppConfig.expo.plugins = parsedAppConfig.expo.plugins ?? [];\n parsedAppConfig.expo.plugins.push([\n SENTRY_EXPO_PLUGIN_NAME,\n {\n url: options.url,\n project: options.project,\n organization: options.org,\n },\n ]);\n\n return JSON.stringify(parsedAppConfig, null, 2) + EOL;\n } catch (error) {\n Sentry.setTag('app-config-file-status', 'invalid-json');\n clack.log.error(\n `Unable to parse your ${chalk.cyan(\n 'app.config.json',\n )}. Make sure it has a valid format!`,\n );\n return null;\n }\n}\n\nexport function getSentryAppConfigJsonCodeSnippet({\n url,\n project,\n org,\n}: Omit<RNCliSetupConfigContent, 'authToken'>) {\n return makeCodeSnippet(true, (unchanged, plus, _minus) => {\n return unchanged(`{\n \"name\": \"my app\",\n \"plugins\": [\n ${plus(`[\n \"@sentry/react-native/expo\",\n {\n \"url\": \"${url}\",\n \"project\": \"${project}\",\n \"organization\": \"${org}\"\n }\n ]`)}\n ],\n}`);\n });\n}\n"]}
1
+ {"version":3,"file":"expo.js","sourceRoot":"","sources":["../../../src/react-native/expo.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport * as clack from '@clack/prompts';\nimport chalk from 'chalk';\nimport * as fs from 'fs';\nimport { EOL } from 'os';\n\nimport { isPlainObject } from '@sentry/utils';\nimport * as Sentry from '@sentry/node';\nimport { makeCodeSnippet, showCopyPasteInstructions } from '../utils/clack';\nimport { RNCliSetupConfigContent } from './react-native-wizard';\nimport { traceStep } from '../telemetry';\n\nexport const SENTRY_EXPO_PLUGIN_NAME = '@sentry/react-native/expo';\nexport const DEPRECATED_SENTRY_EXPO_PLUGIN_NAME = 'sentry-expo';\n\nexport const SENTRY_PLUGIN_FUNCTION_NAME = 'withSentry';\n\nconst APP_CONFIG_JSON = `app.json`;\n\nexport interface AppConfigJson {\n expo?: {\n plugins?: Array<[string, undefined | Record<string, unknown>]>;\n };\n}\n\nexport function printSentryExpoMigrationOutro(): void {\n clack.outro(\n `Deprecated ${chalk.cyan(\n 'sentry-expo',\n )} package installed in your dependencies. Please follow the migration guide at ${chalk.cyan(\n 'https://docs.sentry.io/platforms/react-native/migration/sentry-expo/',\n )}`,\n );\n}\n\n/**\n * Finds app.json in the project root and add Sentry Expo `withSentry` plugin.\n */\nexport async function patchExpoAppConfig(options: RNCliSetupConfigContent) {\n function showInstructions() {\n return showCopyPasteInstructions({\n filename: APP_CONFIG_JSON,\n codeSnippet: getSentryAppConfigJsonCodeSnippet(options),\n hint: 'This ensures auto upload of source maps during native app build.',\n });\n }\n\n const appConfigJsonExists = fs.existsSync(APP_CONFIG_JSON);\n\n Sentry.setTag(\n 'app-config-file-status',\n appConfigJsonExists ? 'found' : 'not-found',\n );\n if (!appConfigJsonExists) {\n return await showInstructions();\n }\n\n const patched = await patchAppConfigJson(APP_CONFIG_JSON, options);\n if (!patched) {\n return await showInstructions();\n }\n}\n\nasync function patchAppConfigJson(\n path: string,\n options: RNCliSetupConfigContent,\n): Promise<boolean> {\n const appConfigContent = (\n await fs.promises.readFile(path, { encoding: 'utf-8' })\n ).toString();\n const patchedContent = traceStep('app-config-json-patch', () =>\n addWithSentryToAppConfigJson(appConfigContent, options),\n );\n if (patchedContent === null) {\n return false;\n }\n\n try {\n await fs.promises.writeFile(path, patchedContent);\n } catch (error) {\n Sentry.setTag('app-config-file-status', 'json-write-error');\n clack.log.error(`Unable to write ${chalk.cyan('app.config.json')}.`);\n return false;\n }\n Sentry.setTag('app-config-file-status', 'json-write-success');\n clack.log.success(\n `Added Sentry Expo plugin to ${chalk.cyan('app.config.json')}.`,\n );\n return true;\n}\n\nexport function addWithSentryToAppConfigJson(\n appConfigContent: string,\n options: RNCliSetupConfigContent,\n): string | null {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const parsedAppConfig: AppConfigJson = JSON.parse(appConfigContent);\n const includesWithSentry =\n appConfigContent.includes(SENTRY_EXPO_PLUGIN_NAME) ||\n appConfigContent.includes(DEPRECATED_SENTRY_EXPO_PLUGIN_NAME);\n\n if (includesWithSentry) {\n Sentry.setTag('app-config-file-status', 'already-patched');\n clack.log.warn(\n `Your ${chalk.cyan(\n 'app.config.json',\n )} already includes the Sentry Expo plugin.`,\n );\n return null;\n }\n\n if (\n parsedAppConfig.expo !== undefined &&\n !isPlainObject(parsedAppConfig.expo)\n ) {\n Sentry.setTag('app-config-file-status', 'invalid-json');\n return null;\n }\n if (\n parsedAppConfig.expo &&\n parsedAppConfig.expo.plugins !== undefined &&\n !Array.isArray(parsedAppConfig.expo.plugins)\n ) {\n Sentry.setTag('app-config-file-status', 'invalid-json');\n return null;\n }\n\n parsedAppConfig.expo = parsedAppConfig.expo ?? {};\n parsedAppConfig.expo.plugins = parsedAppConfig.expo.plugins ?? [];\n parsedAppConfig.expo.plugins.push([\n SENTRY_EXPO_PLUGIN_NAME,\n {\n url: options.url,\n project: options.project,\n organization: options.org,\n },\n ]);\n\n return JSON.stringify(parsedAppConfig, null, 2) + EOL;\n } catch (error) {\n Sentry.setTag('app-config-file-status', 'invalid-json');\n clack.log.error(\n `Unable to parse your ${chalk.cyan(\n 'app.config.json',\n )}. Make sure it has a valid format!`,\n );\n return null;\n }\n}\n\nexport function getSentryAppConfigJsonCodeSnippet({\n url,\n project,\n org,\n}: Omit<RNCliSetupConfigContent, 'authToken'>) {\n return makeCodeSnippet(true, (unchanged, plus, _minus) => {\n return unchanged(`{\n \"name\": \"my app\",\n \"plugins\": [\n ${plus(`[\n \"@sentry/react-native/expo\",\n {\n \"url\": \"${url}\",\n \"project\": \"${project}\",\n \"organization\": \"${org}\"\n }\n ]`)}\n ],\n}`);\n });\n}\n"]}
@@ -1,16 +1,18 @@
1
1
  import { ProxifiedModule } from 'magicast';
2
2
  import * as t from '@babel/types';
3
- export declare function addSentryInit({ dsn }: {
3
+ export declare function addSentryInit({ dsn, enableSessionReplay, }: {
4
4
  dsn: string;
5
+ enableSessionReplay?: boolean;
5
6
  }): Promise<void>;
6
- export declare function addSentryInitWithSdkImport(js: string, { dsn }: {
7
+ export declare function addSentryInitWithSdkImport(js: string, { dsn, enableSessionReplay, }: {
7
8
  dsn: string;
9
+ enableSessionReplay?: boolean;
8
10
  }): string;
9
11
  export declare function doesJsCodeIncludeSdkSentryImport(js: string, { sdkPackageName }: {
10
12
  sdkPackageName: string;
11
13
  }): boolean;
12
- export declare function getSentryInitColoredCodeSnippet(dsn: string): string;
13
- export declare function getSentryInitPlainTextSnippet(dsn: string): string;
14
+ export declare function getSentryInitColoredCodeSnippet(dsn: string, enableSessionReplay?: boolean): string;
15
+ export declare function getSentryInitPlainTextSnippet(dsn: string, enableSessionReplay?: boolean): string;
14
16
  /**
15
17
  * This step should be executed after `addSentryInit`
16
18
  */
@@ -42,12 +42,18 @@ const react_native_wizard_1 = require("./react-native-wizard");
42
42
  // @ts-expect-error - magicast is ESM and TS complains about that. It works though
43
43
  const magicast_1 = require("magicast");
44
44
  const t = __importStar(require("@babel/types"));
45
- async function addSentryInit({ dsn }) {
45
+ const sessionReplaySampleRate = 0.1;
46
+ const sessionReplayOnErrorSampleRate = 1.0;
47
+ async function addSentryInit({ dsn, enableSessionReplay = false, }) {
46
48
  const jsPath = getMainAppFilePath();
47
49
  Sentry.setTag('app-js-file-status', jsPath ? 'found' : 'not-found');
48
50
  if (!jsPath) {
49
51
  prompts_1.default.log.warn(`Could not find main App file. Place the following code snippet close to the Apps Root component.`);
50
- await (0, clack_1.showCopyPasteInstructions)('App.js or _layout.tsx', getSentryInitColoredCodeSnippet(dsn), 'This ensures the Sentry SDK is ready to capture errors.');
52
+ await (0, clack_1.showCopyPasteInstructions)({
53
+ filename: 'App.js or _layout.tsx',
54
+ codeSnippet: getSentryInitColoredCodeSnippet(dsn, enableSessionReplay),
55
+ hint: 'This ensures the Sentry SDK is ready to capture errors.',
56
+ });
51
57
  return;
52
58
  }
53
59
  const jsRelativePath = path.relative(process.cwd(), jsPath);
@@ -60,8 +66,15 @@ async function addSentryInit({ dsn }) {
60
66
  prompts_1.default.log.warn(`${chalk_1.default.cyan(jsRelativePath)} already includes Sentry. We wont't add it again.`);
61
67
  return;
62
68
  }
69
+ if (enableSessionReplay) {
70
+ prompts_1.default.log.info(`Session Replay will be enabled with default settings (replaysSessionSampleRate: ${sessionReplaySampleRate}, replaysOnErrorSampleRate: ${sessionReplayOnErrorSampleRate}).`);
71
+ prompts_1.default.log.message('By default, all text content, images, and webviews will be masked for privacy. You can customize this in your code later.');
72
+ }
63
73
  (0, telemetry_1.traceStep)('add-sentry-init', () => {
64
- const newContent = addSentryInitWithSdkImport(js, { dsn });
74
+ const newContent = addSentryInitWithSdkImport(js, {
75
+ dsn,
76
+ enableSessionReplay,
77
+ });
65
78
  prompts_1.default.log.success(`Added ${chalk_1.default.cyan('Sentry.init')} to ${chalk_1.default.cyan(jsRelativePath)}.`);
66
79
  fs.writeFileSync(jsPath, newContent, 'utf-8');
67
80
  });
@@ -69,27 +82,34 @@ async function addSentryInit({ dsn }) {
69
82
  prompts_1.default.log.success(chalk_1.default.green(`${chalk_1.default.cyan(jsRelativePath)} changes saved.`));
70
83
  }
71
84
  exports.addSentryInit = addSentryInit;
72
- function addSentryInitWithSdkImport(js, { dsn }) {
85
+ function addSentryInitWithSdkImport(js, { dsn, enableSessionReplay = false, }) {
73
86
  return js.replace(/^([^]*)(import\s+[^;]*?;$)/m, (match) => `${match}
74
- ${getSentryInitPlainTextSnippet(dsn)}`);
87
+ ${getSentryInitPlainTextSnippet(dsn, enableSessionReplay)}`);
75
88
  }
76
89
  exports.addSentryInitWithSdkImport = addSentryInitWithSdkImport;
77
90
  function doesJsCodeIncludeSdkSentryImport(js, { sdkPackageName }) {
78
91
  return !!js.match(sdkPackageName);
79
92
  }
80
93
  exports.doesJsCodeIncludeSdkSentryImport = doesJsCodeIncludeSdkSentryImport;
81
- function getSentryInitColoredCodeSnippet(dsn) {
94
+ function getSentryInitColoredCodeSnippet(dsn, enableSessionReplay = false) {
82
95
  return (0, clack_1.makeCodeSnippet)(true, (_unchanged, plus, _minus) => {
83
- return plus(getSentryInitPlainTextSnippet(dsn));
96
+ return plus(getSentryInitPlainTextSnippet(dsn, enableSessionReplay));
84
97
  });
85
98
  }
86
99
  exports.getSentryInitColoredCodeSnippet = getSentryInitColoredCodeSnippet;
87
- function getSentryInitPlainTextSnippet(dsn) {
100
+ function getSentryInitPlainTextSnippet(dsn, enableSessionReplay = false) {
88
101
  return `import * as Sentry from '@sentry/react-native';
89
102
 
90
103
  Sentry.init({
91
104
  dsn: '${dsn}',
92
-
105
+ ${enableSessionReplay
106
+ ? `
107
+ // Configure Session Replay
108
+ replaysSessionSampleRate: ${sessionReplaySampleRate},
109
+ replaysOnErrorSampleRate: ${sessionReplayOnErrorSampleRate},
110
+ integrations: [Sentry.mobileReplayIntegration()],
111
+ `
112
+ : ''}
93
113
  // uncomment the line below to enable Spotlight (https://spotlightjs.com)
94
114
  // spotlight: __DEV__,
95
115
  });`;
@@ -107,7 +127,10 @@ function getMainAppFilePath() {
107
127
  * This step should be executed after `addSentryInit`
108
128
  */
109
129
  async function wrapRootComponent() {
110
- const showInstructions = () => (0, clack_1.showCopyPasteInstructions)('App.js or _layout.tsx', getSentryWrapColoredCodeSnippet());
130
+ const showInstructions = () => (0, clack_1.showCopyPasteInstructions)({
131
+ filename: 'App.js or _layout.tsx',
132
+ codeSnippet: getSentryWrapColoredCodeSnippet(),
133
+ });
111
134
  const jsPath = getMainAppFilePath();
112
135
  Sentry.setTag('app-js-file-status', jsPath ? 'found' : 'not-found');
113
136
  if (!jsPath) {
@@ -1 +1 @@
1
- {"version":3,"file":"javascript.js","sourceRoot":"","sources":["../../../src/react-native/javascript.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable max-lines */\n// @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 path from 'path';\nimport * as process from 'process';\nimport * as fs from 'fs';\nimport * as Sentry from '@sentry/node';\n\nimport { traceStep } from '../telemetry';\nimport { makeCodeSnippet, showCopyPasteInstructions } from '../utils/clack';\nimport { getFirstMatchedPath } from './glob';\nimport { RN_SDK_PACKAGE } from './react-native-wizard';\n\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport { generateCode, ProxifiedModule, parseModule } from 'magicast';\nimport * as t from '@babel/types';\n\nexport async function addSentryInit({ dsn }: { dsn: string }) {\n const jsPath = getMainAppFilePath();\n Sentry.setTag('app-js-file-status', jsPath ? 'found' : 'not-found');\n if (!jsPath) {\n clack.log.warn(\n `Could not find main App file. Place the following code snippet close to the Apps Root component.`,\n );\n await showCopyPasteInstructions(\n 'App.js or _layout.tsx',\n getSentryInitColoredCodeSnippet(dsn),\n 'This ensures the Sentry SDK is ready to capture errors.',\n );\n return;\n }\n const jsRelativePath = path.relative(process.cwd(), jsPath);\n\n const js = fs.readFileSync(jsPath, 'utf-8');\n const includesSentry = doesJsCodeIncludeSdkSentryImport(js, {\n sdkPackageName: RN_SDK_PACKAGE,\n });\n if (includesSentry) {\n Sentry.setTag('app-js-file-status', 'already-includes-sentry');\n clack.log.warn(\n `${chalk.cyan(\n jsRelativePath,\n )} already includes Sentry. We wont't add it again.`,\n );\n return;\n }\n\n traceStep('add-sentry-init', () => {\n const newContent = addSentryInitWithSdkImport(js, { dsn });\n\n clack.log.success(\n `Added ${chalk.cyan('Sentry.init')} to ${chalk.cyan(jsRelativePath)}.`,\n );\n\n fs.writeFileSync(jsPath, newContent, 'utf-8');\n });\n\n Sentry.setTag('app-js-file-status', 'added-sentry-init');\n clack.log.success(\n chalk.green(`${chalk.cyan(jsRelativePath)} changes saved.`),\n );\n}\n\nexport function addSentryInitWithSdkImport(\n js: string,\n { dsn }: { dsn: string },\n): string {\n return js.replace(\n /^([^]*)(import\\s+[^;]*?;$)/m,\n (match: string) => `${match}\n${getSentryInitPlainTextSnippet(dsn)}`,\n );\n}\n\nexport function doesJsCodeIncludeSdkSentryImport(\n js: string,\n { sdkPackageName }: { sdkPackageName: string },\n): boolean {\n return !!js.match(sdkPackageName);\n}\n\nexport function getSentryInitColoredCodeSnippet(dsn: string) {\n return makeCodeSnippet(true, (_unchanged, plus, _minus) => {\n return plus(getSentryInitPlainTextSnippet(dsn));\n });\n}\n\nexport function getSentryInitPlainTextSnippet(dsn: string) {\n return `import * as Sentry from '@sentry/react-native';\n\nSentry.init({\n dsn: '${dsn}',\n\n // uncomment the line below to enable Spotlight (https://spotlightjs.com)\n // spotlight: __DEV__,\n});`;\n}\n\nfunction getMainAppFilePath(): string | undefined {\n const prefixGlob = '{.,./src,./app}';\n const suffixGlob = '@(j|t|cj|mj)s?(x)';\n const universalGlob = `@(App|_layout).${suffixGlob}`;\n const jsFileGlob = `${prefixGlob}/+(${universalGlob})`;\n const jsPath = traceStep('find-app-js-file', () =>\n getFirstMatchedPath(jsFileGlob),\n );\n return jsPath;\n}\n\n/**\n * This step should be executed after `addSentryInit`\n */\nexport async function wrapRootComponent() {\n const showInstructions = () =>\n showCopyPasteInstructions(\n 'App.js or _layout.tsx',\n getSentryWrapColoredCodeSnippet(),\n );\n\n const jsPath = getMainAppFilePath();\n Sentry.setTag('app-js-file-status', jsPath ? 'found' : 'not-found');\n if (!jsPath) {\n clack.log.warn(\n `Could not find main App file. Please wrap your App's Root component.`,\n );\n await showInstructions();\n return;\n }\n\n const jsRelativePath = path.relative(process.cwd(), jsPath);\n\n const js = fs.readFileSync(jsPath, 'utf-8');\n\n const mod = parseModule(js);\n const result = checkAndWrapRootComponent(mod);\n\n if (result === SentryWrapResult.AlreadyWrapped) {\n Sentry.setTag('app-js-file-status', 'already-includes-sentry-wrap');\n clack.log.warn(\n `${chalk.cyan(\n jsRelativePath,\n )} already includes Sentry.wrap. We wont't add it again.`,\n );\n return;\n }\n\n if (result === SentryWrapResult.NotFound) {\n clack.log.warn(\n `Could not find your App's Root component. Please wrap your App's Root component manually.`,\n );\n await showInstructions();\n return;\n }\n\n traceStep('add-sentry-wrap', () => {\n clack.log.success(\n `Added ${chalk.cyan('Sentry.wrap')} to ${chalk.cyan(jsRelativePath)}.`,\n );\n\n fs.writeFileSync(jsPath, generateCode(mod.$ast).code, 'utf-8');\n });\n\n Sentry.setTag('app-js-file-status', 'added-sentry-wrap');\n clack.log.success(\n chalk.green(`${chalk.cyan(jsRelativePath)} changes saved.`),\n );\n}\n\nexport enum SentryWrapResult {\n NotFound = 'RootComponentNotFound',\n AlreadyWrapped = 'AlreadyWrapped',\n Success = 'Success',\n}\n\nexport function checkAndWrapRootComponent(\n mod: ProxifiedModule,\n): SentryWrapResult {\n if (doesContainSentryWrap(mod.$ast as t.Program)) {\n return SentryWrapResult.AlreadyWrapped;\n }\n\n const defaultExport = getDefaultExport(mod.$ast as t.Program);\n if (!defaultExport) {\n return SentryWrapResult.NotFound;\n }\n\n const wrappedConfig = wrapWithSentry(defaultExport);\n\n const replacedDefaultExport = replaceDefaultExport(\n mod.$ast as t.Program,\n wrappedConfig,\n );\n\n if (!replacedDefaultExport) {\n return SentryWrapResult.NotFound;\n }\n\n return SentryWrapResult.Success;\n}\n\nexport function getDefaultExport(\n program: t.Program,\n):\n | t.Identifier\n | t.CallExpression\n | t.ObjectExpression\n | t.FunctionDeclaration\n | t.ArrowFunctionExpression\n | t.ClassDeclaration\n | undefined {\n for (const node of program.body) {\n if (\n t.isExportDefaultDeclaration(node) &&\n (t.isIdentifier(node.declaration) ||\n t.isCallExpression(node.declaration) ||\n t.isObjectExpression(node.declaration) ||\n t.isFunctionDeclaration(node.declaration) ||\n t.isArrowFunctionExpression(node.declaration) ||\n t.isClassDeclaration(node.declaration))\n ) {\n Sentry.setTag('app-js-file-status', 'default-export');\n return node.declaration;\n }\n }\n\n Sentry.setTag('app-js-file-status', 'default-export-not-found');\n return undefined;\n}\n\nexport function wrapWithSentry(\n configObj:\n | t.Identifier\n | t.CallExpression\n | t.ObjectExpression\n | t.FunctionDeclaration\n | t.ArrowFunctionExpression\n | t.ClassDeclaration,\n): t.CallExpression {\n if (t.isFunctionDeclaration(configObj)) {\n return t.callExpression(\n t.memberExpression(t.identifier('Sentry'), t.identifier('wrap')),\n [\n t.functionExpression(\n configObj.id,\n configObj.params,\n configObj.body,\n configObj.generator,\n configObj.async,\n ),\n ],\n );\n }\n\n if (t.isArrowFunctionExpression(configObj)) {\n return t.callExpression(\n t.memberExpression(t.identifier('Sentry'), t.identifier('wrap')),\n [configObj],\n );\n }\n\n if (t.isClassDeclaration(configObj)) {\n return t.callExpression(\n t.memberExpression(t.identifier('Sentry'), t.identifier('wrap')),\n [\n t.classExpression(\n configObj.id,\n configObj.superClass,\n configObj.body,\n configObj.decorators,\n ),\n ],\n );\n }\n\n return t.callExpression(\n t.memberExpression(t.identifier('Sentry'), t.identifier('wrap')),\n [configObj],\n );\n}\n\nexport function replaceDefaultExport(\n program: t.Program,\n wrappedDefaultExport: t.CallExpression,\n): boolean {\n for (const node of program.body) {\n if (t.isExportDefaultDeclaration(node)) {\n node.declaration = wrappedDefaultExport;\n return true;\n }\n }\n return false;\n}\n\nexport function doesContainSentryWrap(program: t.Program): boolean {\n for (const node of program.body) {\n if (t.isExportDefaultDeclaration(node)) {\n const declaration = node.declaration;\n if (t.isCallExpression(declaration)) {\n const callExpr = declaration;\n if (t.isMemberExpression(callExpr.callee)) {\n const callee = callExpr.callee;\n if (\n t.isIdentifier(callee.object) &&\n callee.object.name === 'Sentry' &&\n t.isIdentifier(callee.property) &&\n callee.property.name === 'wrap'\n ) {\n return true;\n }\n }\n }\n }\n }\n return false;\n}\n\nfunction getSentryWrapColoredCodeSnippet() {\n return makeCodeSnippet(true, (_unchanged, plus, _minus) => {\n return plus(`import * as Sentry from '@sentry/react-native';\n\nexport default Sentry.wrap(App);`);\n });\n}\n"]}
1
+ {"version":3,"file":"javascript.js","sourceRoot":"","sources":["../../../src/react-native/javascript.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable max-lines */\n// @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 path from 'path';\nimport * as process from 'process';\nimport * as fs from 'fs';\nimport * as Sentry from '@sentry/node';\n\nimport { traceStep } from '../telemetry';\nimport { makeCodeSnippet, showCopyPasteInstructions } from '../utils/clack';\nimport { getFirstMatchedPath } from './glob';\nimport { RN_SDK_PACKAGE } from './react-native-wizard';\n\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport { generateCode, ProxifiedModule, parseModule } from 'magicast';\nimport * as t from '@babel/types';\n\nconst sessionReplaySampleRate = 0.1;\nconst sessionReplayOnErrorSampleRate = 1.0;\n\nexport async function addSentryInit({\n dsn,\n enableSessionReplay = false,\n}: {\n dsn: string;\n enableSessionReplay?: boolean;\n}) {\n const jsPath = getMainAppFilePath();\n Sentry.setTag('app-js-file-status', jsPath ? 'found' : 'not-found');\n if (!jsPath) {\n clack.log.warn(\n `Could not find main App file. Place the following code snippet close to the Apps Root component.`,\n );\n await showCopyPasteInstructions({\n filename: 'App.js or _layout.tsx',\n codeSnippet: getSentryInitColoredCodeSnippet(dsn, enableSessionReplay),\n hint: 'This ensures the Sentry SDK is ready to capture errors.',\n });\n return;\n }\n const jsRelativePath = path.relative(process.cwd(), jsPath);\n\n const js = fs.readFileSync(jsPath, 'utf-8');\n const includesSentry = doesJsCodeIncludeSdkSentryImport(js, {\n sdkPackageName: RN_SDK_PACKAGE,\n });\n if (includesSentry) {\n Sentry.setTag('app-js-file-status', 'already-includes-sentry');\n clack.log.warn(\n `${chalk.cyan(\n jsRelativePath,\n )} already includes Sentry. We wont't add it again.`,\n );\n return;\n }\n\n if (enableSessionReplay) {\n clack.log.info(\n `Session Replay will be enabled with default settings (replaysSessionSampleRate: ${sessionReplaySampleRate}, replaysOnErrorSampleRate: ${sessionReplayOnErrorSampleRate}).`,\n );\n clack.log.message(\n 'By default, all text content, images, and webviews will be masked for privacy. You can customize this in your code later.',\n );\n }\n\n traceStep('add-sentry-init', () => {\n const newContent = addSentryInitWithSdkImport(js, {\n dsn,\n enableSessionReplay,\n });\n\n clack.log.success(\n `Added ${chalk.cyan('Sentry.init')} to ${chalk.cyan(jsRelativePath)}.`,\n );\n\n fs.writeFileSync(jsPath, newContent, 'utf-8');\n });\n\n Sentry.setTag('app-js-file-status', 'added-sentry-init');\n clack.log.success(\n chalk.green(`${chalk.cyan(jsRelativePath)} changes saved.`),\n );\n}\n\nexport function addSentryInitWithSdkImport(\n js: string,\n {\n dsn,\n enableSessionReplay = false,\n }: { dsn: string; enableSessionReplay?: boolean },\n): string {\n return js.replace(\n /^([^]*)(import\\s+[^;]*?;$)/m,\n (match: string) => `${match}\n${getSentryInitPlainTextSnippet(dsn, enableSessionReplay)}`,\n );\n}\n\nexport function doesJsCodeIncludeSdkSentryImport(\n js: string,\n { sdkPackageName }: { sdkPackageName: string },\n): boolean {\n return !!js.match(sdkPackageName);\n}\n\nexport function getSentryInitColoredCodeSnippet(\n dsn: string,\n enableSessionReplay = false,\n) {\n return makeCodeSnippet(true, (_unchanged, plus, _minus) => {\n return plus(getSentryInitPlainTextSnippet(dsn, enableSessionReplay));\n });\n}\n\nexport function getSentryInitPlainTextSnippet(\n dsn: string,\n enableSessionReplay = false,\n) {\n return `import * as Sentry from '@sentry/react-native';\n\nSentry.init({\n dsn: '${dsn}',\n${\n enableSessionReplay\n ? `\n // Configure Session Replay\n replaysSessionSampleRate: ${sessionReplaySampleRate},\n replaysOnErrorSampleRate: ${sessionReplayOnErrorSampleRate},\n integrations: [Sentry.mobileReplayIntegration()],\n`\n : ''\n}\n // uncomment the line below to enable Spotlight (https://spotlightjs.com)\n // spotlight: __DEV__,\n});`;\n}\n\nfunction getMainAppFilePath(): string | undefined {\n const prefixGlob = '{.,./src,./app}';\n const suffixGlob = '@(j|t|cj|mj)s?(x)';\n const universalGlob = `@(App|_layout).${suffixGlob}`;\n const jsFileGlob = `${prefixGlob}/+(${universalGlob})`;\n const jsPath = traceStep('find-app-js-file', () =>\n getFirstMatchedPath(jsFileGlob),\n );\n return jsPath;\n}\n\n/**\n * This step should be executed after `addSentryInit`\n */\nexport async function wrapRootComponent() {\n const showInstructions = () =>\n showCopyPasteInstructions({\n filename: 'App.js or _layout.tsx',\n codeSnippet: getSentryWrapColoredCodeSnippet(),\n });\n\n const jsPath = getMainAppFilePath();\n Sentry.setTag('app-js-file-status', jsPath ? 'found' : 'not-found');\n if (!jsPath) {\n clack.log.warn(\n `Could not find main App file. Please wrap your App's Root component.`,\n );\n await showInstructions();\n return;\n }\n\n const jsRelativePath = path.relative(process.cwd(), jsPath);\n\n const js = fs.readFileSync(jsPath, 'utf-8');\n\n const mod = parseModule(js);\n const result = checkAndWrapRootComponent(mod);\n\n if (result === SentryWrapResult.AlreadyWrapped) {\n Sentry.setTag('app-js-file-status', 'already-includes-sentry-wrap');\n clack.log.warn(\n `${chalk.cyan(\n jsRelativePath,\n )} already includes Sentry.wrap. We wont't add it again.`,\n );\n return;\n }\n\n if (result === SentryWrapResult.NotFound) {\n clack.log.warn(\n `Could not find your App's Root component. Please wrap your App's Root component manually.`,\n );\n await showInstructions();\n return;\n }\n\n traceStep('add-sentry-wrap', () => {\n clack.log.success(\n `Added ${chalk.cyan('Sentry.wrap')} to ${chalk.cyan(jsRelativePath)}.`,\n );\n\n fs.writeFileSync(jsPath, generateCode(mod.$ast).code, 'utf-8');\n });\n\n Sentry.setTag('app-js-file-status', 'added-sentry-wrap');\n clack.log.success(\n chalk.green(`${chalk.cyan(jsRelativePath)} changes saved.`),\n );\n}\n\nexport enum SentryWrapResult {\n NotFound = 'RootComponentNotFound',\n AlreadyWrapped = 'AlreadyWrapped',\n Success = 'Success',\n}\n\nexport function checkAndWrapRootComponent(\n mod: ProxifiedModule,\n): SentryWrapResult {\n if (doesContainSentryWrap(mod.$ast as t.Program)) {\n return SentryWrapResult.AlreadyWrapped;\n }\n\n const defaultExport = getDefaultExport(mod.$ast as t.Program);\n if (!defaultExport) {\n return SentryWrapResult.NotFound;\n }\n\n const wrappedConfig = wrapWithSentry(defaultExport);\n\n const replacedDefaultExport = replaceDefaultExport(\n mod.$ast as t.Program,\n wrappedConfig,\n );\n\n if (!replacedDefaultExport) {\n return SentryWrapResult.NotFound;\n }\n\n return SentryWrapResult.Success;\n}\n\nexport function getDefaultExport(\n program: t.Program,\n):\n | t.Identifier\n | t.CallExpression\n | t.ObjectExpression\n | t.FunctionDeclaration\n | t.ArrowFunctionExpression\n | t.ClassDeclaration\n | undefined {\n for (const node of program.body) {\n if (\n t.isExportDefaultDeclaration(node) &&\n (t.isIdentifier(node.declaration) ||\n t.isCallExpression(node.declaration) ||\n t.isObjectExpression(node.declaration) ||\n t.isFunctionDeclaration(node.declaration) ||\n t.isArrowFunctionExpression(node.declaration) ||\n t.isClassDeclaration(node.declaration))\n ) {\n Sentry.setTag('app-js-file-status', 'default-export');\n return node.declaration;\n }\n }\n\n Sentry.setTag('app-js-file-status', 'default-export-not-found');\n return undefined;\n}\n\nexport function wrapWithSentry(\n configObj:\n | t.Identifier\n | t.CallExpression\n | t.ObjectExpression\n | t.FunctionDeclaration\n | t.ArrowFunctionExpression\n | t.ClassDeclaration,\n): t.CallExpression {\n if (t.isFunctionDeclaration(configObj)) {\n return t.callExpression(\n t.memberExpression(t.identifier('Sentry'), t.identifier('wrap')),\n [\n t.functionExpression(\n configObj.id,\n configObj.params,\n configObj.body,\n configObj.generator,\n configObj.async,\n ),\n ],\n );\n }\n\n if (t.isArrowFunctionExpression(configObj)) {\n return t.callExpression(\n t.memberExpression(t.identifier('Sentry'), t.identifier('wrap')),\n [configObj],\n );\n }\n\n if (t.isClassDeclaration(configObj)) {\n return t.callExpression(\n t.memberExpression(t.identifier('Sentry'), t.identifier('wrap')),\n [\n t.classExpression(\n configObj.id,\n configObj.superClass,\n configObj.body,\n configObj.decorators,\n ),\n ],\n );\n }\n\n return t.callExpression(\n t.memberExpression(t.identifier('Sentry'), t.identifier('wrap')),\n [configObj],\n );\n}\n\nexport function replaceDefaultExport(\n program: t.Program,\n wrappedDefaultExport: t.CallExpression,\n): boolean {\n for (const node of program.body) {\n if (t.isExportDefaultDeclaration(node)) {\n node.declaration = wrappedDefaultExport;\n return true;\n }\n }\n return false;\n}\n\nexport function doesContainSentryWrap(program: t.Program): boolean {\n for (const node of program.body) {\n if (t.isExportDefaultDeclaration(node)) {\n const declaration = node.declaration;\n if (t.isCallExpression(declaration)) {\n const callExpr = declaration;\n if (t.isMemberExpression(callExpr.callee)) {\n const callee = callExpr.callee;\n if (\n t.isIdentifier(callee.object) &&\n callee.object.name === 'Sentry' &&\n t.isIdentifier(callee.property) &&\n callee.property.name === 'wrap'\n ) {\n return true;\n }\n }\n }\n }\n }\n return false;\n}\n\nfunction getSentryWrapColoredCodeSnippet() {\n return makeCodeSnippet(true, (_unchanged, plus, _minus) => {\n return plus(`import * as Sentry from '@sentry/react-native';\n\nexport default Sentry.wrap(App);`);\n });\n}\n"]}