@sentry/wizard 4.4.0 → 4.6.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 (228) hide show
  1. package/CHANGELOG.md +23 -1
  2. package/README.md +23 -19
  3. package/dist/bin.js +13 -0
  4. package/dist/bin.js.map +1 -1
  5. package/dist/e2e-tests/tests/nextjs-14.test.js +4 -5
  6. package/dist/e2e-tests/tests/nextjs-14.test.js.map +1 -1
  7. package/dist/e2e-tests/tests/nextjs-15.test.js +3 -5
  8. package/dist/e2e-tests/tests/nextjs-15.test.js.map +1 -1
  9. package/dist/e2e-tests/utils/index.d.ts +1 -1
  10. package/dist/e2e-tests/utils/index.js +20 -2
  11. package/dist/e2e-tests/utils/index.js.map +1 -1
  12. package/dist/lib/Constants.d.ts +2 -0
  13. package/dist/lib/Constants.js.map +1 -1
  14. package/dist/lib/Helper/File.d.ts +1 -1
  15. package/dist/lib/Helper/File.js +1 -3
  16. package/dist/lib/Helper/File.js.map +1 -1
  17. package/dist/lib/Helper/Logging.d.ts +3 -0
  18. package/dist/lib/Helper/Logging.js +3 -0
  19. package/dist/lib/Helper/Logging.js.map +1 -1
  20. package/dist/lib/Helper/Package.d.ts +5 -3
  21. package/dist/lib/Helper/Package.js +2 -2
  22. package/dist/lib/Helper/Package.js.map +1 -1
  23. package/dist/lib/Helper/SentryCli.d.ts +20 -7
  24. package/dist/lib/Helper/SentryCli.js +21 -13
  25. package/dist/lib/Helper/SentryCli.js.map +1 -1
  26. package/dist/lib/Helper/Wizard.js +9 -5
  27. package/dist/lib/Helper/Wizard.js.map +1 -1
  28. package/dist/lib/Helper/__tests__/SentryCli.js +21 -4
  29. package/dist/lib/Helper/__tests__/SentryCli.js.map +1 -1
  30. package/dist/lib/Setup.d.ts +3 -1
  31. package/dist/lib/Setup.js.map +1 -1
  32. package/dist/lib/Steps/Integrations/BaseIntegration.js +1 -2
  33. package/dist/lib/Steps/Integrations/BaseIntegration.js.map +1 -1
  34. package/dist/lib/Steps/Integrations/Cordova.js +14 -10
  35. package/dist/lib/Steps/Integrations/Cordova.js.map +1 -1
  36. package/dist/lib/Steps/Integrations/Electron.d.ts +4 -1
  37. package/dist/lib/Steps/Integrations/Electron.js +1 -1
  38. package/dist/lib/Steps/Integrations/Electron.js.map +1 -1
  39. package/dist/lib/Steps/Integrations/MobileProject.d.ts +3 -1
  40. package/dist/lib/Steps/Integrations/MobileProject.js +1 -1
  41. package/dist/lib/Steps/Integrations/MobileProject.js.map +1 -1
  42. package/dist/lib/Steps/PromptForParameters.d.ts +4 -1
  43. package/dist/lib/Steps/PromptForParameters.js.map +1 -1
  44. package/dist/lib/Steps/SentryProjectSelector.d.ts +42 -1
  45. package/dist/lib/Steps/SentryProjectSelector.js +1 -1
  46. package/dist/lib/Steps/SentryProjectSelector.js.map +1 -1
  47. package/dist/lib/Steps/WaitForSentry.d.ts +3 -1
  48. package/dist/lib/Steps/WaitForSentry.js +4 -4
  49. package/dist/lib/Steps/WaitForSentry.js.map +1 -1
  50. package/dist/lib/Types.d.ts +14 -0
  51. package/dist/lib/Types.js +3 -0
  52. package/dist/lib/Types.js.map +1 -0
  53. package/dist/lib/__tests__/Env.js +6 -13
  54. package/dist/lib/__tests__/Env.js.map +1 -1
  55. package/dist/src/android/android-wizard.js +15 -12
  56. package/dist/src/android/android-wizard.js.map +1 -1
  57. package/dist/src/android/code-tools.js +1 -1
  58. package/dist/src/android/code-tools.js.map +1 -1
  59. package/dist/src/android/gradle.js +4 -4
  60. package/dist/src/android/gradle.js.map +1 -1
  61. package/dist/src/android/manifest.js +1 -1
  62. package/dist/src/android/manifest.js.map +1 -1
  63. package/dist/src/apple/apple-wizard.d.ts +2 -2
  64. package/dist/src/apple/apple-wizard.js +37 -118
  65. package/dist/src/apple/apple-wizard.js.map +1 -1
  66. package/dist/src/apple/check-installed-cli.d.ts +1 -0
  67. package/dist/src/apple/check-installed-cli.js +60 -0
  68. package/dist/src/apple/check-installed-cli.js.map +1 -0
  69. package/dist/src/apple/cocoapod.js +1 -1
  70. package/dist/src/apple/cocoapod.js.map +1 -1
  71. package/dist/src/apple/code-tools.js +1 -1
  72. package/dist/src/apple/code-tools.js.map +1 -1
  73. package/dist/src/apple/configure-fastlane.d.ts +5 -0
  74. package/dist/src/apple/configure-fastlane.js +66 -0
  75. package/dist/src/apple/configure-fastlane.js.map +1 -0
  76. package/dist/src/apple/fastlane.d.ts +1 -1
  77. package/dist/src/apple/fastlane.js +5 -5
  78. package/dist/src/apple/fastlane.js.map +1 -1
  79. package/dist/src/apple/lookup-xcode-project.d.ts +7 -0
  80. package/dist/src/apple/lookup-xcode-project.js +98 -0
  81. package/dist/src/apple/lookup-xcode-project.js.map +1 -0
  82. package/dist/src/apple/options.d.ts +4 -0
  83. package/dist/src/apple/options.js +3 -0
  84. package/dist/src/apple/options.js.map +1 -0
  85. package/dist/src/apple/search-xcode-project-at-path.d.ts +1 -0
  86. package/dist/src/apple/search-xcode-project-at-path.js +70 -0
  87. package/dist/src/apple/search-xcode-project-at-path.js.map +1 -0
  88. package/dist/src/apple/xcode-manager.js +1 -1
  89. package/dist/src/apple/xcode-manager.js.map +1 -1
  90. package/dist/src/flutter/code-tools.js +3 -3
  91. package/dist/src/flutter/code-tools.js.map +1 -1
  92. package/dist/src/flutter/flutter-wizard.js +21 -15
  93. package/dist/src/flutter/flutter-wizard.js.map +1 -1
  94. package/dist/src/flutter/templates.js +4 -4
  95. package/dist/src/flutter/templates.js.map +1 -1
  96. package/dist/src/nextjs/nextjs-wizard.js +118 -67
  97. package/dist/src/nextjs/nextjs-wizard.js.map +1 -1
  98. package/dist/src/nextjs/templates.d.ts +11 -3
  99. package/dist/src/nextjs/templates.js +193 -71
  100. package/dist/src/nextjs/templates.js.map +1 -1
  101. package/dist/src/nuxt/nuxt-wizard.js +21 -16
  102. package/dist/src/nuxt/nuxt-wizard.js.map +1 -1
  103. package/dist/src/nuxt/sdk-example.js +3 -3
  104. package/dist/src/nuxt/sdk-example.js.map +1 -1
  105. package/dist/src/nuxt/sdk-setup.js +9 -9
  106. package/dist/src/nuxt/sdk-setup.js.map +1 -1
  107. package/dist/src/nuxt/templates.js +173 -58
  108. package/dist/src/nuxt/templates.js.map +1 -1
  109. package/dist/src/nuxt/utils.js +6 -3
  110. package/dist/src/nuxt/utils.js.map +1 -1
  111. package/dist/src/react-native/expo-env-file.js +1 -1
  112. package/dist/src/react-native/expo-env-file.js.map +1 -1
  113. package/dist/src/react-native/expo-metro.js +4 -4
  114. package/dist/src/react-native/expo-metro.js.map +1 -1
  115. package/dist/src/react-native/expo.js +4 -4
  116. package/dist/src/react-native/expo.js.map +1 -1
  117. package/dist/src/react-native/javascript.js +7 -7
  118. package/dist/src/react-native/javascript.js.map +1 -1
  119. package/dist/src/react-native/metro.js +8 -8
  120. package/dist/src/react-native/metro.js.map +1 -1
  121. package/dist/src/react-native/react-native-wizard.d.ts +1 -1
  122. package/dist/src/react-native/react-native-wizard.js +36 -31
  123. package/dist/src/react-native/react-native-wizard.js.map +1 -1
  124. package/dist/src/react-native/uninstall.js +8 -5
  125. package/dist/src/react-native/uninstall.js.map +1 -1
  126. package/dist/src/react-native/xcode.d.ts +2 -1
  127. package/dist/src/react-native/xcode.js +1 -2
  128. package/dist/src/react-native/xcode.js.map +1 -1
  129. package/dist/src/remix/codemods/handle-error.js +4 -1
  130. package/dist/src/remix/codemods/handle-error.js.map +1 -1
  131. package/dist/src/remix/remix-wizard.js +23 -18
  132. package/dist/src/remix/remix-wizard.js.map +1 -1
  133. package/dist/src/remix/sdk-example.js +163 -64
  134. package/dist/src/remix/sdk-example.js.map +1 -1
  135. package/dist/src/remix/sdk-setup.js +11 -7
  136. package/dist/src/remix/sdk-setup.js.map +1 -1
  137. package/dist/src/run.d.ts +3 -1
  138. package/dist/src/run.js +29 -9
  139. package/dist/src/run.js.map +1 -1
  140. package/dist/src/sourcemaps/sourcemaps-wizard.js +30 -28
  141. package/dist/src/sourcemaps/sourcemaps-wizard.js.map +1 -1
  142. package/dist/src/sourcemaps/tools/angular.js +3 -3
  143. package/dist/src/sourcemaps/tools/angular.js.map +1 -1
  144. package/dist/src/sourcemaps/tools/create-react-app.js +3 -3
  145. package/dist/src/sourcemaps/tools/create-react-app.js.map +1 -1
  146. package/dist/src/sourcemaps/tools/esbuild.js +6 -6
  147. package/dist/src/sourcemaps/tools/esbuild.js.map +1 -1
  148. package/dist/src/sourcemaps/tools/nextjs.js +5 -5
  149. package/dist/src/sourcemaps/tools/nextjs.js.map +1 -1
  150. package/dist/src/sourcemaps/tools/remix.js +4 -4
  151. package/dist/src/sourcemaps/tools/remix.js.map +1 -1
  152. package/dist/src/sourcemaps/tools/rollup.js +6 -6
  153. package/dist/src/sourcemaps/tools/rollup.js.map +1 -1
  154. package/dist/src/sourcemaps/tools/sentry-cli.js +23 -16
  155. package/dist/src/sourcemaps/tools/sentry-cli.js.map +1 -1
  156. package/dist/src/sourcemaps/tools/tsc.js +6 -6
  157. package/dist/src/sourcemaps/tools/tsc.js.map +1 -1
  158. package/dist/src/sourcemaps/tools/vite.js +12 -12
  159. package/dist/src/sourcemaps/tools/vite.js.map +1 -1
  160. package/dist/src/sourcemaps/tools/webpack.js +10 -10
  161. package/dist/src/sourcemaps/tools/webpack.js.map +1 -1
  162. package/dist/src/sourcemaps/utils/detect-tool.js +2 -2
  163. package/dist/src/sourcemaps/utils/detect-tool.js.map +1 -1
  164. package/dist/src/sourcemaps/utils/other-wizards.js +5 -5
  165. package/dist/src/sourcemaps/utils/other-wizards.js.map +1 -1
  166. package/dist/src/sourcemaps/utils/sdk-version.js +7 -7
  167. package/dist/src/sourcemaps/utils/sdk-version.js.map +1 -1
  168. package/dist/src/sveltekit/sdk-example.js +1 -1
  169. package/dist/src/sveltekit/sdk-example.js.map +1 -1
  170. package/dist/src/sveltekit/sdk-setup.js +15 -14
  171. package/dist/src/sveltekit/sdk-setup.js.map +1 -1
  172. package/dist/src/sveltekit/sveltekit-wizard.js +25 -20
  173. package/dist/src/sveltekit/sveltekit-wizard.js.map +1 -1
  174. package/dist/src/sveltekit/templates.js +126 -37
  175. package/dist/src/sveltekit/templates.js.map +1 -1
  176. package/dist/src/telemetry.js +11 -0
  177. package/dist/src/telemetry.js.map +1 -1
  178. package/dist/src/utils/{clack-utils.d.ts → clack/index.d.ts} +54 -15
  179. package/dist/src/utils/{clack-utils.js → clack/index.js} +107 -24
  180. package/dist/src/utils/clack/index.js.map +1 -0
  181. package/dist/src/utils/debug.js +1 -1
  182. package/dist/src/utils/debug.js.map +1 -1
  183. package/dist/src/utils/find-files-with-extension.d.ts +1 -0
  184. package/dist/src/utils/find-files-with-extension.js +39 -0
  185. package/dist/src/utils/find-files-with-extension.js.map +1 -0
  186. package/dist/src/utils/package-manager.d.ts +6 -1
  187. package/dist/src/utils/package-manager.js +32 -27
  188. package/dist/src/utils/package-manager.js.map +1 -1
  189. package/dist/src/utils/sentrycli-utils.js +0 -1
  190. package/dist/src/utils/sentrycli-utils.js.map +1 -1
  191. package/dist/src/utils/types.d.ts +4 -0
  192. package/dist/src/utils/types.js.map +1 -1
  193. package/dist/src/version.d.ts +1 -1
  194. package/dist/src/version.js +1 -1
  195. package/dist/src/version.js.map +1 -1
  196. package/dist/test/android/code-tools.test.js +0 -1
  197. package/dist/test/android/code-tools.test.js.map +1 -1
  198. package/dist/test/apple/cocoapod.test.js +1 -1
  199. package/dist/test/apple/cocoapod.test.js.map +1 -1
  200. package/dist/test/apple/code-tools.test.js +1 -1
  201. package/dist/test/apple/code-tools.test.js.map +1 -1
  202. package/dist/test/apple/fastfile.test.js +1 -1
  203. package/dist/test/apple/fastfile.test.js.map +1 -1
  204. package/dist/test/apple/xcode-manager.test.js +26 -2
  205. package/dist/test/apple/xcode-manager.test.js.map +1 -1
  206. package/dist/test/flutter/code-tools.test.js +0 -2
  207. package/dist/test/flutter/code-tools.test.js.map +1 -1
  208. package/dist/test/flutter/templates.test.js +23 -23
  209. package/dist/test/flutter/templates.test.js.map +1 -1
  210. package/dist/test/nextjs/templates.test.js +127 -133
  211. package/dist/test/nextjs/templates.test.js.map +1 -1
  212. package/dist/test/react-native/expo-metro.test.js +1 -1
  213. package/dist/test/react-native/expo-metro.test.js.map +1 -1
  214. package/dist/test/react-native/javascript.test.js +1 -1
  215. package/dist/test/react-native/javascript.test.js.map +1 -1
  216. package/dist/test/react-native/metro.test.js +1 -1
  217. package/dist/test/react-native/metro.test.js.map +1 -1
  218. package/dist/test/sourcemaps/tools/sentry-cli.test.js +14 -3
  219. package/dist/test/sourcemaps/tools/sentry-cli.test.js.map +1 -1
  220. package/dist/test/utils/{clack-utils.test.js → clack/index.test.js} +131 -41
  221. package/dist/test/utils/clack/index.test.js.map +1 -0
  222. package/dist/test/utils/package-manager.test.d.ts +1 -0
  223. package/dist/test/utils/package-manager.test.js +29 -0
  224. package/dist/test/utils/package-manager.test.js.map +1 -0
  225. package/package.json +1 -1
  226. package/dist/src/utils/clack-utils.js.map +0 -1
  227. package/dist/test/utils/clack-utils.test.js.map +0 -1
  228. /package/dist/test/utils/{clack-utils.test.d.ts → clack/index.test.d.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"javascript.test.js","sourceRoot":"","sources":["../../../test/react-native/javascript.test.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n addSentryInitWithSdkImport,\n checkAndWrapRootComponent,\n doesContainSentryWrap,\n doesJsCodeIncludeSdkSentryImport,\n SentryWrapResult,\n} from '../../src/react-native/javascript';\n// @ts-ignore - magicast is ESM and TS complains about that. It works though\nimport { generateCode, parseModule } from 'magicast';\nimport * as t from '@babel/types';\n\ndescribe('react-native javascript', () => {\n describe('addSentryInitWithSdkImport', () => {\n it('adds sdk import and sentry init under last import in the file', () => {\n const input = `import * as React from 'react';\n\nconst test = 'test';\n\nimport { View } from 'react-native';\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default App;`;\n\n const expectedOutput = `import * as React from 'react';\n\nconst test = 'test';\n\nimport { View } from 'react-native';\nimport * 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\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default App;`;\n\n expect(addSentryInitWithSdkImport(input, { dsn: 'dsn' })).toBe(\n expectedOutput,\n );\n });\n\n it('does not add sdk import and sentry init in the file without imports', () => {\n const input = `export const test = 'test';`;\n expect(addSentryInitWithSdkImport(input, { dsn: 'dsn' })).toBe(input);\n });\n\n it('does not add sdk import and sentry init in the empty file', () => {\n const input = '';\n expect(addSentryInitWithSdkImport(input, { dsn: 'dsn' })).toBe(input);\n });\n });\n\n describe('doesJsCodeIncludeSdkSentryImport', () => {\n it('returns true if code has sdk import', () => {\n const input = `import * as React from 'react';\n\nconst test = 'test';\n\nimport { View } from 'react-native';\nimport * as Sentry from '@sentry/react-native';\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default App;`;\n\n expect(\n doesJsCodeIncludeSdkSentryImport(input, {\n sdkPackageName: '@sentry/react-native',\n }),\n ).toBe(true);\n });\n\n it('returns true if code has sdk require', () => {\n const input = `import * as React from 'react';\n\nconst test = 'test';\n\nimport { View } from 'react-native';\nconst Sentry = require('@sentry/react-native');\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default App;`;\n\n expect(\n doesJsCodeIncludeSdkSentryImport(input, {\n sdkPackageName: '@sentry/react-native',\n }),\n ).toBe(true);\n });\n\n it('returns false if code does not have sdk import', () => {\n const input = `export const test = 'test';`;\n expect(\n doesJsCodeIncludeSdkSentryImport(input, {\n sdkPackageName: '@sentry/react-native',\n }),\n ).toBe(false);\n });\n\n it('returns false for empty file', () => {\n const input = '';\n expect(\n doesJsCodeIncludeSdkSentryImport(input, {\n sdkPackageName: '@sentry/react-native',\n }),\n ).toBe(false);\n });\n });\n\n describe('addSentryWrap', () => {\n it('wraps the root app component', () => {\n const mod = parseModule(`import * as React from 'react';\nimport * as Sentry from '@sentry/react-native';\n\nimport { View } from 'react-native';\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default App;`);\n\n const expectedOutput = `import * as React from 'react';\nimport * as Sentry from '@sentry/react-native';\n\nimport { View } from 'react-native';\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default Sentry.wrap(App);`;\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.Success);\n expect(generateCode(mod.$ast).code).toBe(expectedOutput);\n });\n\n it('wraps a wrapped root app component', () => {\n const mod = parseModule(`import * as React from 'react';\nimport * as Sentry from '@sentry/react-native';\n\nimport { View } from 'react-native';\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default AnotheWrapper.wrap(App);`);\n\n const expectedOutput = `import * as React from 'react';\nimport * as Sentry from '@sentry/react-native';\n\nimport { View } from 'react-native';\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default Sentry.wrap(AnotheWrapper.wrap(App));`;\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.Success);\n expect(generateCode(mod.$ast).code).toBe(expectedOutput);\n });\n\n it('wraps a root app named function', () => {\n const mod = parseModule(`import * as Sentry from '@sentry/react-native';\n\nexport default function RootLayout() {\n return (\n <View>\n Test App\n </View>\n );\n}`);\n\n const expectedOutput = `import * as Sentry from '@sentry/react-native';\n\nexport default Sentry.wrap(function RootLayout() {\n return (\n <View>\n Test App\n </View>\n );\n});`;\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.Success);\n expect(generateCode(mod.$ast).code).toBe(expectedOutput);\n });\n\n it('wraps a wrapped root app named function', () => {\n const mod = parseModule(`import * as Sentry from '@sentry/react-native';\n\nexport default Another.wrapper(function RootLayout() {\n return (\n <View>\n Test App\n </View>\n );\n});`);\n\n const expectedOutput = `import * as Sentry from '@sentry/react-native';\n\nexport default Sentry.wrap(Another.wrapper(function RootLayout() {\n return (\n <View>\n Test App\n </View>\n );\n}));`;\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.Success);\n expect(generateCode(mod.$ast).code).toBe(expectedOutput);\n });\n\n it('wraps a root app anonymous function', () => {\n const mod = parseModule(`import * as Sentry from '@sentry/react-native';\n\nexport default () => {\n return (\n <View>\n Test App\n </View>\n );\n}`);\n\n const expectedOutput = `import * as Sentry from '@sentry/react-native';\n\nexport default Sentry.wrap(() => {\n return (\n <View>\n Test App\n </View>\n );\n});`;\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.Success);\n expect(generateCode(mod.$ast).code).toBe(expectedOutput);\n });\n\n it('wraps a wrapped root app anonymous function', () => {\n const mod = parseModule(`import * as Sentry from '@sentry/react-native';\n\nexport default Another.wrap(() => {\n return (\n <View>\n Test App\n </View>\n );\n});`);\n\n const expectedOutput = `import * as Sentry from '@sentry/react-native';\n\nexport default Sentry.wrap(Another.wrap(() => {\n return (\n <View>\n Test App\n </View>\n );\n}));`;\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.Success);\n expect(generateCode(mod.$ast).code).toBe(expectedOutput);\n });\n\n it('wraps a complex root function', () => {\n // This is the default export for a new Expo 52 project\n const mod =\n parseModule(`import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';\nimport { useFonts } from 'expo-font';\nimport { Stack } from 'expo-router';\nimport * as SplashScreen from 'expo-splash-screen';\nimport { StatusBar } from 'expo-status-bar';\nimport { useEffect } from 'react';\nimport 'react-native-reanimated';\n\nimport { useColorScheme } from '@/hooks/useColorScheme';\nimport * as Sentry from '@sentry/react-native';\n\nSentry.init({\n dsn: 'https://sentry.io/123',\n\n // uncomment the line below to enable Spotlight (https://spotlightjs.com)\n // spotlight: __DEV__,\n});\n\n// Prevent the splash screen from auto-hiding before asset loading is complete.\nSplashScreen.preventAutoHideAsync();\n\nexport default function RootLayout() {\n const colorScheme = useColorScheme();\n const [loaded] = useFonts({\n SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),\n });\n\n useEffect(() => {\n if (loaded) {\n SplashScreen.hideAsync();\n }\n }, [loaded]);\n\n if (!loaded) {\n return null;\n }\n\n return (\n <ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>\n <Stack>\n <Stack.Screen name=\"(tabs)\" options={{ headerShown: false }} />\n <Stack.Screen name=\"+not-found\" />\n </Stack>\n <StatusBar style=\"auto\" />\n </ThemeProvider>\n );\n}\n`);\n\n const expectedOutput = `import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';\nimport { useFonts } from 'expo-font';\nimport { Stack } from 'expo-router';\nimport * as SplashScreen from 'expo-splash-screen';\nimport { StatusBar } from 'expo-status-bar';\nimport { useEffect } from 'react';\nimport 'react-native-reanimated';\n\nimport { useColorScheme } from '@/hooks/useColorScheme';\nimport * as Sentry from '@sentry/react-native';\n\nSentry.init({\n dsn: 'https://sentry.io/123',\n\n // uncomment the line below to enable Spotlight (https://spotlightjs.com)\n // spotlight: __DEV__,\n});\n\n// Prevent the splash screen from auto-hiding before asset loading is complete.\nSplashScreen.preventAutoHideAsync();\n\nexport default Sentry.wrap(function RootLayout() {\n const colorScheme = useColorScheme();\n const [loaded] = useFonts({\n SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),\n });\n\n useEffect(() => {\n if (loaded) {\n SplashScreen.hideAsync();\n }\n }, [loaded]);\n\n if (!loaded) {\n return null;\n }\n\n return (\n <ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>\n <Stack>\n <Stack.Screen name=\"(tabs)\" options={{ headerShown: false }} />\n <Stack.Screen name=\"+not-found\" />\n </Stack>\n <StatusBar style=\"auto\" />\n </ThemeProvider>\n );\n});`;\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.Success);\n expect(generateCode(mod.$ast).code).toBe(expectedOutput);\n });\n\n it('wraps a root app anonymous complex function', () => {\n const mod = parseModule(`import * as Sentry from '@sentry/react-native';\n\nexport default () => {\n const colorScheme = useColorScheme();\n const [loaded] = useFonts({\n SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),\n });\n\n useEffect(() => {\n if (loaded) {\n SplashScreen.hideAsync();\n }\n }, [loaded]);\n\n if (!loaded) {\n return null;\n }\n\n return (\n <ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>\n <Stack>\n <Stack.Screen name=\"(tabs)\" options={{ headerShown: false }} />\n <Stack.Screen name=\"+not-found\" />\n </Stack>\n <StatusBar style=\"auto\" />\n </ThemeProvider>\n );\n}`);\n\n const expectedOutput = `import * as Sentry from '@sentry/react-native';\n\nexport default Sentry.wrap(() => {\n const colorScheme = useColorScheme();\n const [loaded] = useFonts({\n SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),\n });\n\n useEffect(() => {\n if (loaded) {\n SplashScreen.hideAsync();\n }\n }, [loaded]);\n\n if (!loaded) {\n return null;\n }\n\n return (\n <ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>\n <Stack>\n <Stack.Screen name=\"(tabs)\" options={{ headerShown: false }} />\n <Stack.Screen name=\"+not-found\" />\n </Stack>\n <StatusBar style=\"auto\" />\n </ThemeProvider>\n );\n});`;\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.Success);\n expect(generateCode(mod.$ast).code).toBe(expectedOutput);\n });\n\n it('wraps a default class export', () => {\n const mod = parseModule(`import * as Sentry from '@sentry/react-native';\n\nexport default class RootLayout extends React.Component {\n render() {\n return (\n <View>\n Test App\n </View>\n );\n }\n}`);\n\n const expectedOutput = `import * as Sentry from '@sentry/react-native';\n\nexport default Sentry.wrap(class RootLayout extends React.Component {\n render() {\n return (\n <View>\n Test App\n </View>\n );\n }\n});`;\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.Success);\n expect(generateCode(mod.$ast).code).toBe(expectedOutput);\n });\n\n it('does not wrap a root app component if not found', () => {\n const input = `import * as React from 'react';\n\nimport { View } from 'react-native';\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport { App };`;\n const mod = parseModule(input);\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.NotFound);\n expect(generateCode(mod.$ast).code).toBe(input);\n });\n\n it('does not wrap a root app component if already wrapped', () => {\n const input = `import * as React from 'react';\nimport * as Sentry from '@sentry/react-native';\n\nimport { View } from 'react-native';\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default Sentry.wrap(App);`;\n const mod = parseModule(input);\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.AlreadyWrapped);\n expect(generateCode(mod.$ast).code).toBe(input);\n });\n\n it('does not wrap the root app component in an empty file', () => {\n const mod = parseModule(``);\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.NotFound);\n expect(generateCode(mod.$ast).code).toBe(``);\n });\n });\n\n it('does detect Sentry.wrap if exists', () => {\n const mod = parseModule(`export default Sentry.wrap(App);`);\n\n const result = doesContainSentryWrap(mod.$ast as t.Program);\n\n expect(result).toBeTruthy();\n });\n\n it('does not detect Sentry.wrap if not present', () => {\n const mod = parseModule(`export default App;`);\n\n const result = doesContainSentryWrap(mod.$ast as t.Program);\n\n expect(result).toBeFalsy();\n });\n});\n"]}
1
+ {"version":3,"file":"javascript.test.js","sourceRoot":"","sources":["../../../test/react-native/javascript.test.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n addSentryInitWithSdkImport,\n checkAndWrapRootComponent,\n doesContainSentryWrap,\n doesJsCodeIncludeSdkSentryImport,\n SentryWrapResult,\n} from '../../src/react-native/javascript';\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport { generateCode, parseModule } from 'magicast';\nimport * as t from '@babel/types';\n\ndescribe('react-native javascript', () => {\n describe('addSentryInitWithSdkImport', () => {\n it('adds sdk import and sentry init under last import in the file', () => {\n const input = `import * as React from 'react';\n\nconst test = 'test';\n\nimport { View } from 'react-native';\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default App;`;\n\n const expectedOutput = `import * as React from 'react';\n\nconst test = 'test';\n\nimport { View } from 'react-native';\nimport * 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\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default App;`;\n\n expect(addSentryInitWithSdkImport(input, { dsn: 'dsn' })).toBe(\n expectedOutput,\n );\n });\n\n it('does not add sdk import and sentry init in the file without imports', () => {\n const input = `export const test = 'test';`;\n expect(addSentryInitWithSdkImport(input, { dsn: 'dsn' })).toBe(input);\n });\n\n it('does not add sdk import and sentry init in the empty file', () => {\n const input = '';\n expect(addSentryInitWithSdkImport(input, { dsn: 'dsn' })).toBe(input);\n });\n });\n\n describe('doesJsCodeIncludeSdkSentryImport', () => {\n it('returns true if code has sdk import', () => {\n const input = `import * as React from 'react';\n\nconst test = 'test';\n\nimport { View } from 'react-native';\nimport * as Sentry from '@sentry/react-native';\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default App;`;\n\n expect(\n doesJsCodeIncludeSdkSentryImport(input, {\n sdkPackageName: '@sentry/react-native',\n }),\n ).toBe(true);\n });\n\n it('returns true if code has sdk require', () => {\n const input = `import * as React from 'react';\n\nconst test = 'test';\n\nimport { View } from 'react-native';\nconst Sentry = require('@sentry/react-native');\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default App;`;\n\n expect(\n doesJsCodeIncludeSdkSentryImport(input, {\n sdkPackageName: '@sentry/react-native',\n }),\n ).toBe(true);\n });\n\n it('returns false if code does not have sdk import', () => {\n const input = `export const test = 'test';`;\n expect(\n doesJsCodeIncludeSdkSentryImport(input, {\n sdkPackageName: '@sentry/react-native',\n }),\n ).toBe(false);\n });\n\n it('returns false for empty file', () => {\n const input = '';\n expect(\n doesJsCodeIncludeSdkSentryImport(input, {\n sdkPackageName: '@sentry/react-native',\n }),\n ).toBe(false);\n });\n });\n\n describe('addSentryWrap', () => {\n it('wraps the root app component', () => {\n const mod = parseModule(`import * as React from 'react';\nimport * as Sentry from '@sentry/react-native';\n\nimport { View } from 'react-native';\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default App;`);\n\n const expectedOutput = `import * as React from 'react';\nimport * as Sentry from '@sentry/react-native';\n\nimport { View } from 'react-native';\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default Sentry.wrap(App);`;\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.Success);\n expect(generateCode(mod.$ast).code).toBe(expectedOutput);\n });\n\n it('wraps a wrapped root app component', () => {\n const mod = parseModule(`import * as React from 'react';\nimport * as Sentry from '@sentry/react-native';\n\nimport { View } from 'react-native';\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default AnotheWrapper.wrap(App);`);\n\n const expectedOutput = `import * as React from 'react';\nimport * as Sentry from '@sentry/react-native';\n\nimport { View } from 'react-native';\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default Sentry.wrap(AnotheWrapper.wrap(App));`;\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.Success);\n expect(generateCode(mod.$ast).code).toBe(expectedOutput);\n });\n\n it('wraps a root app named function', () => {\n const mod = parseModule(`import * as Sentry from '@sentry/react-native';\n\nexport default function RootLayout() {\n return (\n <View>\n Test App\n </View>\n );\n}`);\n\n const expectedOutput = `import * as Sentry from '@sentry/react-native';\n\nexport default Sentry.wrap(function RootLayout() {\n return (\n <View>\n Test App\n </View>\n );\n});`;\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.Success);\n expect(generateCode(mod.$ast).code).toBe(expectedOutput);\n });\n\n it('wraps a wrapped root app named function', () => {\n const mod = parseModule(`import * as Sentry from '@sentry/react-native';\n\nexport default Another.wrapper(function RootLayout() {\n return (\n <View>\n Test App\n </View>\n );\n});`);\n\n const expectedOutput = `import * as Sentry from '@sentry/react-native';\n\nexport default Sentry.wrap(Another.wrapper(function RootLayout() {\n return (\n <View>\n Test App\n </View>\n );\n}));`;\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.Success);\n expect(generateCode(mod.$ast).code).toBe(expectedOutput);\n });\n\n it('wraps a root app anonymous function', () => {\n const mod = parseModule(`import * as Sentry from '@sentry/react-native';\n\nexport default () => {\n return (\n <View>\n Test App\n </View>\n );\n}`);\n\n const expectedOutput = `import * as Sentry from '@sentry/react-native';\n\nexport default Sentry.wrap(() => {\n return (\n <View>\n Test App\n </View>\n );\n});`;\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.Success);\n expect(generateCode(mod.$ast).code).toBe(expectedOutput);\n });\n\n it('wraps a wrapped root app anonymous function', () => {\n const mod = parseModule(`import * as Sentry from '@sentry/react-native';\n\nexport default Another.wrap(() => {\n return (\n <View>\n Test App\n </View>\n );\n});`);\n\n const expectedOutput = `import * as Sentry from '@sentry/react-native';\n\nexport default Sentry.wrap(Another.wrap(() => {\n return (\n <View>\n Test App\n </View>\n );\n}));`;\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.Success);\n expect(generateCode(mod.$ast).code).toBe(expectedOutput);\n });\n\n it('wraps a complex root function', () => {\n // This is the default export for a new Expo 52 project\n const mod =\n parseModule(`import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';\nimport { useFonts } from 'expo-font';\nimport { Stack } from 'expo-router';\nimport * as SplashScreen from 'expo-splash-screen';\nimport { StatusBar } from 'expo-status-bar';\nimport { useEffect } from 'react';\nimport 'react-native-reanimated';\n\nimport { useColorScheme } from '@/hooks/useColorScheme';\nimport * as Sentry from '@sentry/react-native';\n\nSentry.init({\n dsn: 'https://sentry.io/123',\n\n // uncomment the line below to enable Spotlight (https://spotlightjs.com)\n // spotlight: __DEV__,\n});\n\n// Prevent the splash screen from auto-hiding before asset loading is complete.\nSplashScreen.preventAutoHideAsync();\n\nexport default function RootLayout() {\n const colorScheme = useColorScheme();\n const [loaded] = useFonts({\n SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),\n });\n\n useEffect(() => {\n if (loaded) {\n SplashScreen.hideAsync();\n }\n }, [loaded]);\n\n if (!loaded) {\n return null;\n }\n\n return (\n <ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>\n <Stack>\n <Stack.Screen name=\"(tabs)\" options={{ headerShown: false }} />\n <Stack.Screen name=\"+not-found\" />\n </Stack>\n <StatusBar style=\"auto\" />\n </ThemeProvider>\n );\n}\n`);\n\n const expectedOutput = `import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';\nimport { useFonts } from 'expo-font';\nimport { Stack } from 'expo-router';\nimport * as SplashScreen from 'expo-splash-screen';\nimport { StatusBar } from 'expo-status-bar';\nimport { useEffect } from 'react';\nimport 'react-native-reanimated';\n\nimport { useColorScheme } from '@/hooks/useColorScheme';\nimport * as Sentry from '@sentry/react-native';\n\nSentry.init({\n dsn: 'https://sentry.io/123',\n\n // uncomment the line below to enable Spotlight (https://spotlightjs.com)\n // spotlight: __DEV__,\n});\n\n// Prevent the splash screen from auto-hiding before asset loading is complete.\nSplashScreen.preventAutoHideAsync();\n\nexport default Sentry.wrap(function RootLayout() {\n const colorScheme = useColorScheme();\n const [loaded] = useFonts({\n SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),\n });\n\n useEffect(() => {\n if (loaded) {\n SplashScreen.hideAsync();\n }\n }, [loaded]);\n\n if (!loaded) {\n return null;\n }\n\n return (\n <ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>\n <Stack>\n <Stack.Screen name=\"(tabs)\" options={{ headerShown: false }} />\n <Stack.Screen name=\"+not-found\" />\n </Stack>\n <StatusBar style=\"auto\" />\n </ThemeProvider>\n );\n});`;\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.Success);\n expect(generateCode(mod.$ast).code).toBe(expectedOutput);\n });\n\n it('wraps a root app anonymous complex function', () => {\n const mod = parseModule(`import * as Sentry from '@sentry/react-native';\n\nexport default () => {\n const colorScheme = useColorScheme();\n const [loaded] = useFonts({\n SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),\n });\n\n useEffect(() => {\n if (loaded) {\n SplashScreen.hideAsync();\n }\n }, [loaded]);\n\n if (!loaded) {\n return null;\n }\n\n return (\n <ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>\n <Stack>\n <Stack.Screen name=\"(tabs)\" options={{ headerShown: false }} />\n <Stack.Screen name=\"+not-found\" />\n </Stack>\n <StatusBar style=\"auto\" />\n </ThemeProvider>\n );\n}`);\n\n const expectedOutput = `import * as Sentry from '@sentry/react-native';\n\nexport default Sentry.wrap(() => {\n const colorScheme = useColorScheme();\n const [loaded] = useFonts({\n SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),\n });\n\n useEffect(() => {\n if (loaded) {\n SplashScreen.hideAsync();\n }\n }, [loaded]);\n\n if (!loaded) {\n return null;\n }\n\n return (\n <ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>\n <Stack>\n <Stack.Screen name=\"(tabs)\" options={{ headerShown: false }} />\n <Stack.Screen name=\"+not-found\" />\n </Stack>\n <StatusBar style=\"auto\" />\n </ThemeProvider>\n );\n});`;\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.Success);\n expect(generateCode(mod.$ast).code).toBe(expectedOutput);\n });\n\n it('wraps a default class export', () => {\n const mod = parseModule(`import * as Sentry from '@sentry/react-native';\n\nexport default class RootLayout extends React.Component {\n render() {\n return (\n <View>\n Test App\n </View>\n );\n }\n}`);\n\n const expectedOutput = `import * as Sentry from '@sentry/react-native';\n\nexport default Sentry.wrap(class RootLayout extends React.Component {\n render() {\n return (\n <View>\n Test App\n </View>\n );\n }\n});`;\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.Success);\n expect(generateCode(mod.$ast).code).toBe(expectedOutput);\n });\n\n it('does not wrap a root app component if not found', () => {\n const input = `import * as React from 'react';\n\nimport { View } from 'react-native';\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport { App };`;\n const mod = parseModule(input);\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.NotFound);\n expect(generateCode(mod.$ast).code).toBe(input);\n });\n\n it('does not wrap a root app component if already wrapped', () => {\n const input = `import * as React from 'react';\nimport * as Sentry from '@sentry/react-native';\n\nimport { View } from 'react-native';\n\nconst App = () => {\n return (\n <View>\n Test App\n </View>\n );\n};\n\nexport default Sentry.wrap(App);`;\n const mod = parseModule(input);\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.AlreadyWrapped);\n expect(generateCode(mod.$ast).code).toBe(input);\n });\n\n it('does not wrap the root app component in an empty file', () => {\n const mod = parseModule(``);\n\n const result = checkAndWrapRootComponent(mod);\n\n expect(result).toBe(SentryWrapResult.NotFound);\n expect(generateCode(mod.$ast).code).toBe(``);\n });\n });\n\n it('does detect Sentry.wrap if exists', () => {\n const mod = parseModule(`export default Sentry.wrap(App);`);\n\n const result = doesContainSentryWrap(mod.$ast as t.Program);\n\n expect(result).toBeTruthy();\n });\n\n it('does not detect Sentry.wrap if not present', () => {\n const mod = parseModule(`export default App;`);\n\n const result = doesContainSentryWrap(mod.$ast as t.Program);\n\n expect(result).toBeFalsy();\n });\n});\n"]}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- // @ts-ignore - magicast is ESM and TS complains about that. It works though
3
+ // @ts-expect-error - magicast is ESM and TS complains about that. It works though
4
4
  const magicast_1 = require("magicast");
5
5
  const metro_1 = require("../../src/react-native/metro");
6
6
  describe('patch metro config - sentry serializer', () => {
@@ -1 +1 @@
1
- {"version":3,"file":"metro.test.js","sourceRoot":"","sources":["../../../test/react-native/metro.test.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-ignore - magicast is ESM and TS complains about that. It works though\nimport { generateCode, type ProxifiedModule, parseModule } from 'magicast';\n\nimport * as recast from 'recast';\nimport x = recast.types;\nimport t = x.namedTypes;\n\nimport {\n addSentrySerializerRequireToMetroConfig,\n addSentrySerializerToMetroConfig,\n getMetroConfigObject,\n patchMetroWithSentryConfigInMemory,\n removeSentryRequire,\n removeSentrySerializerFromMetroConfig,\n} from '../../src/react-native/metro';\n\ndescribe('patch metro config - sentry serializer', () => {\n describe('patchMetroWithSentryConfigInMemory', () => {\n it('patches react native 0.72 default metro config', async () => {\n const mod =\n parseModule(`const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');\n\n/**\n * Metro configuration\n * https://reactnative.dev/docs/metro\n *\n * @type {import('metro-config').MetroConfig}\n */\nconst config = {};\n\nmodule.exports = mergeConfig(getDefaultConfig(__dirname), config);`);\n\n const result = await patchMetroWithSentryConfigInMemory(mod, async () => {\n /* noop */\n });\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code)\n .toBe(`const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');\n\nconst {\n withSentryConfig\n} = require(\"@sentry/react-native/metro\");\n\n/**\n * Metro configuration\n * https://reactnative.dev/docs/metro\n *\n * @type {import('metro-config').MetroConfig}\n */\nconst config = {};\n\nmodule.exports = withSentryConfig(mergeConfig(getDefaultConfig(__dirname), config));`);\n });\n\n it('patches react native 0.65 default metro config', async () => {\n const mod = parseModule(`/**\n* Metro configuration for React Native\n* https://github.com/facebook/react-native\n*\n* @format\n*/\n\nmodule.exports = {\n transformer: {\n getTransformOptions: async () => ({\n transform: {\n experimentalImportSupport: false,\n inlineRequires: true,\n },\n }),\n },\n};`);\n\n const result = await patchMetroWithSentryConfigInMemory(mod, async () => {\n /* noop */\n });\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`const {\n withSentryConfig\n} = require(\"@sentry/react-native/metro\");\n\n/**\n* Metro configuration for React Native\n* https://github.com/facebook/react-native\n*\n* @format\n*/\n\nmodule.exports = withSentryConfig({\n transformer: {\n getTransformOptions: async () => ({\n transform: {\n experimentalImportSupport: false,\n inlineRequires: true,\n },\n }),\n },\n});`);\n });\n\n it('patches react native metro config exported variable', async () => {\n const mod = parseModule(`const testConfig = {};\n\nmodule.exports = testConfig;`);\n\n const result = await patchMetroWithSentryConfigInMemory(mod, async () => {\n /* noop */\n });\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`const {\n withSentryConfig\n} = require(\"@sentry/react-native/metro\");\n\nconst testConfig = {};\n\nmodule.exports = withSentryConfig(testConfig);`);\n });\n\n it('does not patch react native metro config exported as factory function', async () => {\n const mod = parseModule(`module.exports = () => ({});`);\n\n const result = await patchMetroWithSentryConfigInMemory(mod, async () => {\n /* noop */\n });\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(`module.exports = () => ({});`);\n });\n });\n\n describe('addSentrySerializerToMetroConfig', () => {\n it('add to empty config', () => {\n const mod = parseModule(`module.exports = {\n other: 'config'\n }`);\n const configObject = getModuleExportsObject(mod);\n const result = addSentrySerializerToMetroConfig(configObject);\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`module.exports = {\n other: 'config',\n\n serializer: {\n customSerializer: createSentryMetroSerializer()\n }\n}`);\n });\n\n it('add to existing serializer config', () => {\n const mod = parseModule(`module.exports = {\n other: 'config',\n serializer: {\n other: 'config'\n }\n}`);\n const configObject = getModuleExportsObject(mod);\n const result = addSentrySerializerToMetroConfig(configObject);\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`module.exports = {\n other: 'config',\n serializer: {\n other: 'config',\n customSerializer: createSentryMetroSerializer()\n }\n}`);\n });\n\n it('not add to existing customSerializer config', () => {\n const mod = parseModule(`module.exports = {\n other: 'config',\n serializer: {\n other: 'config',\n customSerializer: 'existing-serializer'\n }\n}`);\n const configObject = getModuleExportsObject(mod);\n const result = addSentrySerializerToMetroConfig(configObject);\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(`module.exports = {\n other: 'config',\n serializer: {\n other: 'config',\n customSerializer: 'existing-serializer'\n }\n}`);\n });\n });\n\n describe('addSentrySerializerImportToMetroConfig', () => {\n it('add import', () => {\n const mod =\n parseModule(`const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');\n\nmodule.exports = {\n other: 'config'\n}`);\n const result = addSentrySerializerRequireToMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code)\n .toBe(`const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');\n\nconst {\n createSentryMetroSerializer\n} = require(\"@sentry/react-native/dist/js/tools/sentryMetroSerializer\");\n\nmodule.exports = {\n other: 'config'\n}`);\n });\n });\n\n describe('getMetroConfigObject', () => {\n it('get config object from variable called config', () => {\n const mod = parseModule(`var config = { some: 'config' };`);\n const configObject = getMetroConfigObject(mod.$ast as t.Program);\n expect(\n ((configObject?.properties[0] as t.ObjectProperty).key as t.Identifier)\n .name,\n ).toBe('some');\n expect(\n (\n (configObject?.properties[0] as t.ObjectProperty)\n .value as t.StringLiteral\n ).value,\n ).toBe('config');\n });\n\n it('get config object from const called config', () => {\n const mod = parseModule(`const config = { some: 'config' };`);\n const configObject = getMetroConfigObject(mod.$ast as t.Program);\n expect(\n ((configObject?.properties[0] as t.ObjectProperty).key as t.Identifier)\n .name,\n ).toBe('some');\n expect(\n (\n (configObject?.properties[0] as t.ObjectProperty)\n .value as t.StringLiteral\n ).value,\n ).toBe('config');\n });\n\n it('get config oject from let called config', () => {\n const mod = parseModule(`let config = { some: 'config' };`);\n const configObject = getMetroConfigObject(mod.$ast as t.Program);\n expect(\n ((configObject?.properties[0] as t.ObjectProperty).key as t.Identifier)\n .name,\n ).toBe('some');\n expect(\n (\n (configObject?.properties[0] as t.ObjectProperty)\n .value as t.StringLiteral\n ).value,\n ).toBe('config');\n });\n\n it('get config object from module.exports', () => {\n const mod = parseModule(`module.exports = { some: 'config' };`);\n const configObject = getMetroConfigObject(mod.$ast as t.Program);\n expect(\n ((configObject?.properties[0] as t.ObjectProperty).key as t.Identifier)\n .name,\n ).toBe('some');\n expect(\n (\n (configObject?.properties[0] as t.ObjectProperty)\n .value as t.StringLiteral\n ).value,\n ).toBe('config');\n });\n });\n\n describe('remove @sentry require', () => {\n it('nothing to remove', () => {\n const mod = parseModule(`let config = { some: 'config' };`);\n const result = removeSentryRequire(mod.$ast as t.Program);\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(\n `let config = { some: 'config' };`,\n );\n });\n\n it('remove metro serializer import', () => {\n const mod = parseModule(`const {\n createSentryMetroSerializer,\n} = require('@sentry/react-native/dist/js/tools/sentryMetroSerializer');\nlet config = { some: 'config' };`);\n const result = removeSentryRequire(mod.$ast as t.Program);\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(\n `let config = { some: 'config' };`,\n );\n });\n\n it('remove all sentry imports', () => {\n const mod = parseModule(`const {\n createSentryMetroSerializer,\n} = require('@sentry/react-native/dist/js/tools/sentryMetroSerializer');\nvar Sentry = require('@sentry/react-native');\nlet SentryIntegrations = require('@sentry/integrations');\n\nlet config = { some: 'config' };`);\n const result = removeSentryRequire(mod.$ast as t.Program);\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(\n `let config = { some: 'config' };`,\n );\n });\n });\n\n describe('remove sentryMetroSerializer', () => {\n it('no custom serializer to remove', () => {\n const mod = parseModule(`let config = { some: 'config' };`);\n const result = removeSentrySerializerFromMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(\n `let config = { some: 'config' };`,\n );\n });\n\n it('no Sentry custom serializer to remove', () => {\n const mod = parseModule(`let config = {\n serializer: {\n customSerializer: 'existing-serializer',\n other: 'config',\n },\n other: 'config',\n};`);\n const result = removeSentrySerializerFromMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(`let config = {\n serializer: {\n customSerializer: 'existing-serializer',\n other: 'config',\n },\n other: 'config',\n};`);\n });\n\n it('Sentry serializer to remove', () => {\n const mod = parseModule(`let config = {\n serializer: {\n customSerializer: createSentryMetroSerializer(),\n other: 'config',\n },\n other: 'config',\n};`);\n const result = removeSentrySerializerFromMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`let config = {\n serializer: {\n other: 'config'\n },\n other: 'config',\n};`);\n });\n\n it('Sentry serializer to remove with wrapped serializer', () => {\n const mod = parseModule(`let config = {\n serializer: {\n customSerializer: createSentryMetroSerializer(wrappedSerializer()),\n other: 'config',\n },\n other: 'config',\n};`);\n const result = removeSentrySerializerFromMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`let config = {\n serializer: {\n customSerializer: wrappedSerializer(),\n other: 'config',\n },\n other: 'config',\n};`);\n });\n });\n});\n\nfunction getModuleExportsObject(\n mod: ProxifiedModule,\n index = 0,\n): t.ObjectExpression {\n return (\n ((mod.$ast as t.Program).body[index] as t.ExpressionStatement)\n .expression as t.AssignmentExpression\n ).right as t.ObjectExpression;\n}\n"]}
1
+ {"version":3,"file":"metro.test.js","sourceRoot":"","sources":["../../../test/react-native/metro.test.ts"],"names":[],"mappings":";;AAAA,kFAAkF;AAClF,uCAA2E;AAM3E,wDAOsC;AAEtC,QAAQ,CAAC,wCAAwC,EAAE,GAAG,EAAE;IACtD,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAClD,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;YAC9D,MAAM,GAAG,GACP,IAAA,sBAAW,EAAC;;;;;;;;;;mEAU+C,CAAC,CAAC;YAE/D,MAAM,MAAM,GAAG,MAAM,IAAA,0CAAkC,EAAC,GAAG,EAAE,KAAK,IAAI,EAAE;gBACtE,UAAU;YACZ,CAAC,CAAC,CAAC;YACH,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1B,MAAM,CAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;iBAChC,IAAI,CAAC;;;;;;;;;;;;;;qFAcuE,CAAC,CAAC;QACnF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;YAC9D,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC;;;;;;;;;;;;;;;;GAgB3B,CAAC,CAAC;YAEC,MAAM,MAAM,GAAG,MAAM,IAAA,0CAAkC,EAAC,GAAG,EAAE,KAAK,IAAI,EAAE;gBACtE,UAAU;YACZ,CAAC,CAAC,CAAC;YACH,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1B,MAAM,CAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;IAoB3C,CAAC,CAAC;QACF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;YACnE,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC;;6BAED,CAAC,CAAC;YAEzB,MAAM,MAAM,GAAG,MAAM,IAAA,0CAAkC,EAAC,GAAG,EAAE,KAAK,IAAI,EAAE;gBACtE,UAAU;YACZ,CAAC,CAAC,CAAC;YACH,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1B,MAAM,CAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;;;;;;+CAMA,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uEAAuE,EAAE,KAAK,IAAI,EAAE;YACrF,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC,8BAA8B,CAAC,CAAC;YAExD,MAAM,MAAM,GAAG,MAAM,IAAA,0CAAkC,EAAC,GAAG,EAAE,KAAK,IAAI,EAAE;gBACtE,UAAU;YACZ,CAAC,CAAC,CAAC;YACH,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3B,MAAM,CAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC3E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAChD,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;YAC7B,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC;;QAEtB,CAAC,CAAC;YACJ,MAAM,YAAY,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC;YACjD,MAAM,MAAM,GAAG,IAAA,wCAAgC,EAAC,YAAY,CAAC,CAAC;YAC9D,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1B,MAAM,CAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;;;;;;EAM7C,CAAC,CAAC;QACA,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;YAC3C,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC;;;;;EAK5B,CAAC,CAAC;YACE,MAAM,YAAY,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC;YACjD,MAAM,MAAM,GAAG,IAAA,wCAAgC,EAAC,YAAY,CAAC,CAAC;YAC9D,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1B,MAAM,CAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;;;;;;EAM7C,CAAC,CAAC;QACA,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;YACrD,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC;;;;;;EAM5B,CAAC,CAAC;YACE,MAAM,YAAY,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC;YACjD,MAAM,MAAM,GAAG,IAAA,wCAAgC,EAAC,YAAY,CAAC,CAAC;YAC9D,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3B,MAAM,CAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;;;;;;EAM7C,CAAC,CAAC;QACA,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,wCAAwC,EAAE,GAAG,EAAE;QACtD,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE;YACpB,MAAM,GAAG,GACP,IAAA,sBAAW,EAAC;;;;EAIlB,CAAC,CAAC;YACE,MAAM,MAAM,GAAG,IAAA,+CAAuC,EACpD,GAAG,CAAC,IAAiB,CACtB,CAAC;YACF,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1B,MAAM,CAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;iBAChC,IAAI,CAAC;;;;;;;;EAQZ,CAAC,CAAC;QACA,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACpC,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;YACvD,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC,kCAAkC,CAAC,CAAC;YAC5D,MAAM,YAAY,GAAG,IAAA,4BAAoB,EAAC,GAAG,CAAC,IAAiB,CAAC,CAAC;YACjE,MAAM,CACH,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAsB,CAAA,CAAC,GAAoB;iBACpE,IAAI,CACR,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACf,MAAM,CAEF,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAsB,CAAA;iBAC9C,KACJ,CAAC,KAAK,CACR,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;YACpD,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC,oCAAoC,CAAC,CAAC;YAC9D,MAAM,YAAY,GAAG,IAAA,4BAAoB,EAAC,GAAG,CAAC,IAAiB,CAAC,CAAC;YACjE,MAAM,CACH,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAsB,CAAA,CAAC,GAAoB;iBACpE,IAAI,CACR,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACf,MAAM,CAEF,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAsB,CAAA;iBAC9C,KACJ,CAAC,KAAK,CACR,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC,kCAAkC,CAAC,CAAC;YAC5D,MAAM,YAAY,GAAG,IAAA,4BAAoB,EAAC,GAAG,CAAC,IAAiB,CAAC,CAAC;YACjE,MAAM,CACH,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAsB,CAAA,CAAC,GAAoB;iBACpE,IAAI,CACR,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACf,MAAM,CAEF,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAsB,CAAA;iBAC9C,KACJ,CAAC,KAAK,CACR,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC,sCAAsC,CAAC,CAAC;YAChE,MAAM,YAAY,GAAG,IAAA,4BAAoB,EAAC,GAAG,CAAC,IAAiB,CAAC,CAAC;YACjE,MAAM,CACH,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAsB,CAAA,CAAC,GAAoB;iBACpE,IAAI,CACR,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACf,MAAM,CAEF,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAsB,CAAA;iBAC9C,KACJ,CAAC,KAAK,CACR,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;QACtC,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;YAC3B,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC,kCAAkC,CAAC,CAAC;YAC5D,MAAM,MAAM,GAAG,IAAA,2BAAmB,EAAC,GAAG,CAAC,IAAiB,CAAC,CAAC;YAC1D,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3B,MAAM,CAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CACtC,kCAAkC,CACnC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC;;;iCAGG,CAAC,CAAC;YAC7B,MAAM,MAAM,GAAG,IAAA,2BAAmB,EAAC,GAAG,CAAC,IAAiB,CAAC,CAAC;YAC1D,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1B,MAAM,CAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CACtC,kCAAkC,CACnC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;YACnC,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC;;;;;;iCAMG,CAAC,CAAC;YAC7B,MAAM,MAAM,GAAG,IAAA,2BAAmB,EAAC,GAAG,CAAC,IAAiB,CAAC,CAAC;YAC1D,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1B,MAAM,CAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CACtC,kCAAkC,CACnC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;QAC5C,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC,kCAAkC,CAAC,CAAC;YAC5D,MAAM,MAAM,GAAG,IAAA,6CAAqC,EAClD,GAAG,CAAC,IAAiB,CACtB,CAAC;YACF,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3B,MAAM,CAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CACtC,kCAAkC,CACnC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC;;;;;;GAM3B,CAAC,CAAC;YACC,MAAM,MAAM,GAAG,IAAA,6CAAqC,EAClD,GAAG,CAAC,IAAiB,CACtB,CAAC;YACF,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3B,MAAM,CAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;;;;;;GAM5C,CAAC,CAAC;QACD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;YACrC,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC;;;;;;GAM3B,CAAC,CAAC;YACC,MAAM,MAAM,GAAG,IAAA,6CAAqC,EAClD,GAAG,CAAC,IAAiB,CACtB,CAAC;YACF,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1B,MAAM,CAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;;;;;GAK5C,CAAC,CAAC;QACD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;YAC7D,MAAM,GAAG,GAAG,IAAA,sBAAW,EAAC;;;;;;GAM3B,CAAC,CAAC;YACC,MAAM,MAAM,GAAG,IAAA,6CAAqC,EAClD,GAAG,CAAC,IAAiB,CACtB,CAAC;YACF,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1B,MAAM,CAAC,IAAA,uBAAY,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;;;;;;GAM5C,CAAC,CAAC;QACD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,SAAS,sBAAsB,CAC7B,GAAoB,EACpB,KAAK,GAAG,CAAC;IAET,OACI,GAAG,CAAC,IAAkB,CAAC,IAAI,CAAC,KAAK,CAA2B;SAC3D,UACJ,CAAC,KAA2B,CAAC;AAChC,CAAC","sourcesContent":["// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport { generateCode, type ProxifiedModule, parseModule } from 'magicast';\n\nimport * as recast from 'recast';\nimport x = recast.types;\nimport t = x.namedTypes;\n\nimport {\n addSentrySerializerRequireToMetroConfig,\n addSentrySerializerToMetroConfig,\n getMetroConfigObject,\n patchMetroWithSentryConfigInMemory,\n removeSentryRequire,\n removeSentrySerializerFromMetroConfig,\n} from '../../src/react-native/metro';\n\ndescribe('patch metro config - sentry serializer', () => {\n describe('patchMetroWithSentryConfigInMemory', () => {\n it('patches react native 0.72 default metro config', async () => {\n const mod =\n parseModule(`const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');\n\n/**\n * Metro configuration\n * https://reactnative.dev/docs/metro\n *\n * @type {import('metro-config').MetroConfig}\n */\nconst config = {};\n\nmodule.exports = mergeConfig(getDefaultConfig(__dirname), config);`);\n\n const result = await patchMetroWithSentryConfigInMemory(mod, async () => {\n /* noop */\n });\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code)\n .toBe(`const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');\n\nconst {\n withSentryConfig\n} = require(\"@sentry/react-native/metro\");\n\n/**\n * Metro configuration\n * https://reactnative.dev/docs/metro\n *\n * @type {import('metro-config').MetroConfig}\n */\nconst config = {};\n\nmodule.exports = withSentryConfig(mergeConfig(getDefaultConfig(__dirname), config));`);\n });\n\n it('patches react native 0.65 default metro config', async () => {\n const mod = parseModule(`/**\n* Metro configuration for React Native\n* https://github.com/facebook/react-native\n*\n* @format\n*/\n\nmodule.exports = {\n transformer: {\n getTransformOptions: async () => ({\n transform: {\n experimentalImportSupport: false,\n inlineRequires: true,\n },\n }),\n },\n};`);\n\n const result = await patchMetroWithSentryConfigInMemory(mod, async () => {\n /* noop */\n });\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`const {\n withSentryConfig\n} = require(\"@sentry/react-native/metro\");\n\n/**\n* Metro configuration for React Native\n* https://github.com/facebook/react-native\n*\n* @format\n*/\n\nmodule.exports = withSentryConfig({\n transformer: {\n getTransformOptions: async () => ({\n transform: {\n experimentalImportSupport: false,\n inlineRequires: true,\n },\n }),\n },\n});`);\n });\n\n it('patches react native metro config exported variable', async () => {\n const mod = parseModule(`const testConfig = {};\n\nmodule.exports = testConfig;`);\n\n const result = await patchMetroWithSentryConfigInMemory(mod, async () => {\n /* noop */\n });\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`const {\n withSentryConfig\n} = require(\"@sentry/react-native/metro\");\n\nconst testConfig = {};\n\nmodule.exports = withSentryConfig(testConfig);`);\n });\n\n it('does not patch react native metro config exported as factory function', async () => {\n const mod = parseModule(`module.exports = () => ({});`);\n\n const result = await patchMetroWithSentryConfigInMemory(mod, async () => {\n /* noop */\n });\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(`module.exports = () => ({});`);\n });\n });\n\n describe('addSentrySerializerToMetroConfig', () => {\n it('add to empty config', () => {\n const mod = parseModule(`module.exports = {\n other: 'config'\n }`);\n const configObject = getModuleExportsObject(mod);\n const result = addSentrySerializerToMetroConfig(configObject);\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`module.exports = {\n other: 'config',\n\n serializer: {\n customSerializer: createSentryMetroSerializer()\n }\n}`);\n });\n\n it('add to existing serializer config', () => {\n const mod = parseModule(`module.exports = {\n other: 'config',\n serializer: {\n other: 'config'\n }\n}`);\n const configObject = getModuleExportsObject(mod);\n const result = addSentrySerializerToMetroConfig(configObject);\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`module.exports = {\n other: 'config',\n serializer: {\n other: 'config',\n customSerializer: createSentryMetroSerializer()\n }\n}`);\n });\n\n it('not add to existing customSerializer config', () => {\n const mod = parseModule(`module.exports = {\n other: 'config',\n serializer: {\n other: 'config',\n customSerializer: 'existing-serializer'\n }\n}`);\n const configObject = getModuleExportsObject(mod);\n const result = addSentrySerializerToMetroConfig(configObject);\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(`module.exports = {\n other: 'config',\n serializer: {\n other: 'config',\n customSerializer: 'existing-serializer'\n }\n}`);\n });\n });\n\n describe('addSentrySerializerImportToMetroConfig', () => {\n it('add import', () => {\n const mod =\n parseModule(`const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');\n\nmodule.exports = {\n other: 'config'\n}`);\n const result = addSentrySerializerRequireToMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code)\n .toBe(`const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');\n\nconst {\n createSentryMetroSerializer\n} = require(\"@sentry/react-native/dist/js/tools/sentryMetroSerializer\");\n\nmodule.exports = {\n other: 'config'\n}`);\n });\n });\n\n describe('getMetroConfigObject', () => {\n it('get config object from variable called config', () => {\n const mod = parseModule(`var config = { some: 'config' };`);\n const configObject = getMetroConfigObject(mod.$ast as t.Program);\n expect(\n ((configObject?.properties[0] as t.ObjectProperty).key as t.Identifier)\n .name,\n ).toBe('some');\n expect(\n (\n (configObject?.properties[0] as t.ObjectProperty)\n .value as t.StringLiteral\n ).value,\n ).toBe('config');\n });\n\n it('get config object from const called config', () => {\n const mod = parseModule(`const config = { some: 'config' };`);\n const configObject = getMetroConfigObject(mod.$ast as t.Program);\n expect(\n ((configObject?.properties[0] as t.ObjectProperty).key as t.Identifier)\n .name,\n ).toBe('some');\n expect(\n (\n (configObject?.properties[0] as t.ObjectProperty)\n .value as t.StringLiteral\n ).value,\n ).toBe('config');\n });\n\n it('get config oject from let called config', () => {\n const mod = parseModule(`let config = { some: 'config' };`);\n const configObject = getMetroConfigObject(mod.$ast as t.Program);\n expect(\n ((configObject?.properties[0] as t.ObjectProperty).key as t.Identifier)\n .name,\n ).toBe('some');\n expect(\n (\n (configObject?.properties[0] as t.ObjectProperty)\n .value as t.StringLiteral\n ).value,\n ).toBe('config');\n });\n\n it('get config object from module.exports', () => {\n const mod = parseModule(`module.exports = { some: 'config' };`);\n const configObject = getMetroConfigObject(mod.$ast as t.Program);\n expect(\n ((configObject?.properties[0] as t.ObjectProperty).key as t.Identifier)\n .name,\n ).toBe('some');\n expect(\n (\n (configObject?.properties[0] as t.ObjectProperty)\n .value as t.StringLiteral\n ).value,\n ).toBe('config');\n });\n });\n\n describe('remove @sentry require', () => {\n it('nothing to remove', () => {\n const mod = parseModule(`let config = { some: 'config' };`);\n const result = removeSentryRequire(mod.$ast as t.Program);\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(\n `let config = { some: 'config' };`,\n );\n });\n\n it('remove metro serializer import', () => {\n const mod = parseModule(`const {\n createSentryMetroSerializer,\n} = require('@sentry/react-native/dist/js/tools/sentryMetroSerializer');\nlet config = { some: 'config' };`);\n const result = removeSentryRequire(mod.$ast as t.Program);\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(\n `let config = { some: 'config' };`,\n );\n });\n\n it('remove all sentry imports', () => {\n const mod = parseModule(`const {\n createSentryMetroSerializer,\n} = require('@sentry/react-native/dist/js/tools/sentryMetroSerializer');\nvar Sentry = require('@sentry/react-native');\nlet SentryIntegrations = require('@sentry/integrations');\n\nlet config = { some: 'config' };`);\n const result = removeSentryRequire(mod.$ast as t.Program);\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(\n `let config = { some: 'config' };`,\n );\n });\n });\n\n describe('remove sentryMetroSerializer', () => {\n it('no custom serializer to remove', () => {\n const mod = parseModule(`let config = { some: 'config' };`);\n const result = removeSentrySerializerFromMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(\n `let config = { some: 'config' };`,\n );\n });\n\n it('no Sentry custom serializer to remove', () => {\n const mod = parseModule(`let config = {\n serializer: {\n customSerializer: 'existing-serializer',\n other: 'config',\n },\n other: 'config',\n};`);\n const result = removeSentrySerializerFromMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(false);\n expect(generateCode(mod.$ast).code).toBe(`let config = {\n serializer: {\n customSerializer: 'existing-serializer',\n other: 'config',\n },\n other: 'config',\n};`);\n });\n\n it('Sentry serializer to remove', () => {\n const mod = parseModule(`let config = {\n serializer: {\n customSerializer: createSentryMetroSerializer(),\n other: 'config',\n },\n other: 'config',\n};`);\n const result = removeSentrySerializerFromMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`let config = {\n serializer: {\n other: 'config'\n },\n other: 'config',\n};`);\n });\n\n it('Sentry serializer to remove with wrapped serializer', () => {\n const mod = parseModule(`let config = {\n serializer: {\n customSerializer: createSentryMetroSerializer(wrappedSerializer()),\n other: 'config',\n },\n other: 'config',\n};`);\n const result = removeSentrySerializerFromMetroConfig(\n mod.$ast as t.Program,\n );\n expect(result).toBe(true);\n expect(generateCode(mod.$ast).code).toBe(`let config = {\n serializer: {\n customSerializer: wrappedSerializer(),\n other: 'config',\n },\n other: 'config',\n};`);\n });\n });\n});\n\nfunction getModuleExportsObject(\n mod: ProxifiedModule,\n index = 0,\n): t.ObjectExpression {\n return (\n ((mod.$ast as t.Program).body[index] as t.ExpressionStatement)\n .expression as t.AssignmentExpression\n ).right as t.ObjectExpression;\n}\n"]}
@@ -26,6 +26,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
26
26
  const fs = __importStar(require("fs"));
27
27
  const sentry_cli_1 = require("../../../src/sourcemaps/tools/sentry-cli");
28
28
  const packageManagerHelpers = __importStar(require("../../../src/utils/package-manager"));
29
+ const clack_1 = require("../../../src/utils/clack");
29
30
  const writeFileSpy = jest
30
31
  .spyOn(fs.promises, 'writeFile')
31
32
  .mockImplementation(() => Promise.resolve());
@@ -40,8 +41,8 @@ jest.mock('@clack/prompts', () => {
40
41
  };
41
42
  });
42
43
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
43
- jest.mock('../../../src/utils/clack-utils', () => ({
44
- ...jest.requireActual('../../../src/utils/clack-utils'),
44
+ jest.mock('../../../src/utils/clack', () => ({
45
+ ...jest.requireActual('../../../src/utils/clack'),
45
46
  getPackageDotJson: jest.fn().mockResolvedValue({
46
47
  scripts: {
47
48
  build: 'tsc',
@@ -63,10 +64,20 @@ describe('addSentryCommandToBuildCommand', () => {
63
64
  ],
64
65
  ])('adds the cli command to the script command (%s)', async (_, pacMan) => {
65
66
  jest
66
- .spyOn(packageManagerHelpers, 'detectPackageManger')
67
+ .spyOn(packageManagerHelpers, '_detectPackageManger')
67
68
  .mockReturnValue(pacMan);
68
69
  await (0, sentry_cli_1.addSentryCommandToBuildCommand)();
69
70
  expect(writeFileSpy).toHaveBeenCalledWith(expect.stringContaining('package.json'), expect.stringContaining(`tsc && ${pacMan.runScriptCommand} sentry:sourcemaps`));
70
71
  });
72
+ it('does not add the cli command to the script command if it is already in there', async () => {
73
+ jest.mocked(clack_1.getPackageDotJson).mockResolvedValue({
74
+ scripts: {
75
+ build: 'tsc && sentry:sourcemaps',
76
+ },
77
+ version: '1.0.0',
78
+ });
79
+ await (0, sentry_cli_1.addSentryCommandToBuildCommand)();
80
+ expect(writeFileSpy).not.toHaveBeenCalled();
81
+ });
71
82
  });
72
83
  //# sourceMappingURL=sentry-cli.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sentry-cli.test.js","sourceRoot":"","sources":["../../../../test/sourcemaps/tools/sentry-cli.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AAEzB,yEAA0F;AAE1F,0FAA4E;AAE5E,MAAM,YAAY,GAAG,IAAI;KACtB,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC;KAC/B,kBAAkB,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;AAE/C,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC/B,OAAO;QACL,GAAG,EAAE;YACH,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;YACf,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE;SACnB;QACD,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC;QAC1C,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC;KAC3C,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,+DAA+D;AAC/D,IAAI,CAAC,IAAI,CAAC,gCAAgC,EAAE,GAAG,EAAE,CAAC,CAAC;IACjD,GAAG,IAAI,CAAC,aAAa,CAAC,gCAAgC,CAAC;IACvD,iBAAiB,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;QAC7C,OAAO,EAAE;YACP,KAAK,EAAE,KAAK;SACb;QACD,OAAO,EAAE,OAAO;KACjB,CAAC;CACH,CAAC,CAAC,CAAC;AAEJ,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,IAAI,CAAC;QACN;YACE,qBAAqB,CAAC,GAAG;YACzB,qBAAqB,CAAC,IAAI;YAC1B,qBAAqB,CAAC,OAAO;YAC7B,qBAAqB,CAAC,OAAO;YAC7B,qBAAqB,CAAC,GAAG;SAC1B;KACF,CAAC,CAAC,iDAAiD,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE;QACxE,IAAI;aACD,KAAK,CAAC,qBAAqB,EAAE,qBAAqB,CAAC;aACnD,eAAe,CAAC,MAAM,CAAC,CAAC;QAC3B,MAAM,IAAA,2CAA8B,GAAE,CAAC;QACvC,MAAM,CAAC,YAAY,CAAC,CAAC,oBAAoB,CACvC,MAAM,CAAC,gBAAgB,CAAC,cAAc,CAAC,EACvC,MAAM,CAAC,gBAAgB,CACrB,UAAU,MAAM,CAAC,gBAAgB,oBAAoB,CACtD,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import * as fs from 'fs';\n\nimport { addSentryCommandToBuildCommand } from '../../../src/sourcemaps/tools/sentry-cli';\n\nimport * as packageManagerHelpers from '../../../src/utils/package-manager';\n\nconst writeFileSpy = jest\n .spyOn(fs.promises, 'writeFile')\n .mockImplementation(() => Promise.resolve());\n\njest.mock('@clack/prompts', () => {\n return {\n log: {\n info: jest.fn(),\n success: jest.fn(),\n },\n confirm: jest.fn().mockResolvedValue(true),\n isCancel: jest.fn().mockReturnValue(false),\n };\n});\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-return\njest.mock('../../../src/utils/clack-utils', () => ({\n ...jest.requireActual('../../../src/utils/clack-utils'),\n getPackageDotJson: jest.fn().mockResolvedValue({\n scripts: {\n build: 'tsc',\n },\n version: '1.0.0',\n }),\n}));\n\ndescribe('addSentryCommandToBuildCommand', () => {\n afterEach(() => {\n jest.clearAllMocks();\n });\n it.each([\n [\n packageManagerHelpers.NPM,\n packageManagerHelpers.PNPM,\n packageManagerHelpers.YARN_V1,\n packageManagerHelpers.YARN_V2,\n packageManagerHelpers.BUN,\n ],\n ])('adds the cli command to the script command (%s)', async (_, pacMan) => {\n jest\n .spyOn(packageManagerHelpers, 'detectPackageManger')\n .mockReturnValue(pacMan);\n await addSentryCommandToBuildCommand();\n expect(writeFileSpy).toHaveBeenCalledWith(\n expect.stringContaining('package.json'),\n expect.stringContaining(\n `tsc && ${pacMan.runScriptCommand} sentry:sourcemaps`,\n ),\n );\n });\n});\n"]}
1
+ {"version":3,"file":"sentry-cli.test.js","sourceRoot":"","sources":["../../../../test/sourcemaps/tools/sentry-cli.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AAEzB,yEAA0F;AAE1F,0FAA4E;AAC5E,oDAA6D;AAC7D,MAAM,YAAY,GAAG,IAAI;KACtB,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC;KAC/B,kBAAkB,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;AAE/C,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC/B,OAAO;QACL,GAAG,EAAE;YACH,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;YACf,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE;SACnB;QACD,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC;QAC1C,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC;KAC3C,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,+DAA+D;AAC/D,IAAI,CAAC,IAAI,CAAC,0BAA0B,EAAE,GAAG,EAAE,CAAC,CAAC;IAC3C,GAAG,IAAI,CAAC,aAAa,CAAC,0BAA0B,CAAC;IACjD,iBAAiB,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;QAC7C,OAAO,EAAE;YACP,KAAK,EAAE,KAAK;SACb;QACD,OAAO,EAAE,OAAO;KACjB,CAAC;CACH,CAAC,CAAC,CAAC;AAEJ,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,IAAI,CAAC;QACN;YACE,qBAAqB,CAAC,GAAG;YACzB,qBAAqB,CAAC,IAAI;YAC1B,qBAAqB,CAAC,OAAO;YAC7B,qBAAqB,CAAC,OAAO;YAC7B,qBAAqB,CAAC,GAAG;SAC1B;KACF,CAAC,CAAC,iDAAiD,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE;QACxE,IAAI;aACD,KAAK,CAAC,qBAAqB,EAAE,sBAAsB,CAAC;aACpD,eAAe,CAAC,MAAM,CAAC,CAAC;QAC3B,MAAM,IAAA,2CAA8B,GAAE,CAAC;QACvC,MAAM,CAAC,YAAY,CAAC,CAAC,oBAAoB,CACvC,MAAM,CAAC,gBAAgB,CAAC,cAAc,CAAC,EACvC,MAAM,CAAC,gBAAgB,CACrB,UAAU,MAAM,CAAC,gBAAgB,oBAAoB,CACtD,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8EAA8E,EAAE,KAAK,IAAI,EAAE;QAC5F,IAAI,CAAC,MAAM,CAAC,yBAAiB,CAAC,CAAC,iBAAiB,CAAC;YAC/C,OAAO,EAAE;gBACP,KAAK,EAAE,0BAA0B;aAClC;YACD,OAAO,EAAE,OAAO;SACjB,CAAC,CAAC;QAEH,MAAM,IAAA,2CAA8B,GAAE,CAAC;QAEvC,MAAM,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import * as fs from 'fs';\n\nimport { addSentryCommandToBuildCommand } from '../../../src/sourcemaps/tools/sentry-cli';\n\nimport * as packageManagerHelpers from '../../../src/utils/package-manager';\nimport { getPackageDotJson } from '../../../src/utils/clack';\nconst writeFileSpy = jest\n .spyOn(fs.promises, 'writeFile')\n .mockImplementation(() => Promise.resolve());\n\njest.mock('@clack/prompts', () => {\n return {\n log: {\n info: jest.fn(),\n success: jest.fn(),\n },\n confirm: jest.fn().mockResolvedValue(true),\n isCancel: jest.fn().mockReturnValue(false),\n };\n});\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-return\njest.mock('../../../src/utils/clack', () => ({\n ...jest.requireActual('../../../src/utils/clack'),\n getPackageDotJson: jest.fn().mockResolvedValue({\n scripts: {\n build: 'tsc',\n },\n version: '1.0.0',\n }),\n}));\n\ndescribe('addSentryCommandToBuildCommand', () => {\n afterEach(() => {\n jest.clearAllMocks();\n });\n it.each([\n [\n packageManagerHelpers.NPM,\n packageManagerHelpers.PNPM,\n packageManagerHelpers.YARN_V1,\n packageManagerHelpers.YARN_V2,\n packageManagerHelpers.BUN,\n ],\n ])('adds the cli command to the script command (%s)', async (_, pacMan) => {\n jest\n .spyOn(packageManagerHelpers, '_detectPackageManger')\n .mockReturnValue(pacMan);\n await addSentryCommandToBuildCommand();\n expect(writeFileSpy).toHaveBeenCalledWith(\n expect.stringContaining('package.json'),\n expect.stringContaining(\n `tsc && ${pacMan.runScriptCommand} sentry:sourcemaps`,\n ),\n );\n });\n\n it('does not add the cli command to the script command if it is already in there', async () => {\n jest.mocked(getPackageDotJson).mockResolvedValue({\n scripts: {\n build: 'tsc && sentry:sourcemaps',\n },\n version: '1.0.0',\n });\n\n await addSentryCommandToBuildCommand();\n\n expect(writeFileSpy).not.toHaveBeenCalled();\n });\n});\n"]}
@@ -26,11 +26,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- const clack_utils_1 = require("../../src/utils/clack-utils");
29
+ const clack_1 = require("../../../src/utils/clack/");
30
30
  const fs = __importStar(require("node:fs"));
31
31
  const ChildProcess = __importStar(require("node:child_process"));
32
+ const PackageManagerUtils = __importStar(require("../../../src/utils/package-manager"));
33
+ const package_manager_1 = require("../../../src/utils/package-manager");
32
34
  const axios_1 = __importDefault(require("axios"));
33
- // @ts-ignore - clack is ESM and TS complains about that. It works though
35
+ // @ts-expect-error - clack is ESM and TS complains about that. It works though
34
36
  const clack = __importStar(require("@clack/prompts"));
35
37
  const Sentry = __importStar(require("@sentry/node"));
36
38
  jest.mock('node:child_process', () => ({
@@ -53,6 +55,7 @@ jest.mock('@clack/prompts', () => ({
53
55
  spinner: jest
54
56
  .fn()
55
57
  .mockImplementation(() => ({ start: jest.fn(), stop: jest.fn() })),
58
+ select: jest.fn(),
56
59
  }));
57
60
  const clackMock = clack;
58
61
  jest.mock('axios');
@@ -67,8 +70,9 @@ describe('askForToolConfigPath', () => {
67
70
  });
68
71
  it('returns undefined if users have no config file', async () => {
69
72
  mockUserResponse(clack.confirm, false);
70
- const result = await (0, clack_utils_1.askForToolConfigPath)('Webpack', 'webpack.config.js');
73
+ const result = await (0, clack_1.askForToolConfigPath)('Webpack', 'webpack.config.js');
71
74
  expect(clack.confirm).toHaveBeenCalledWith(expect.objectContaining({
75
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
72
76
  message: expect.stringContaining('have a Webpack config file'),
73
77
  }));
74
78
  expect(result).toBeUndefined();
@@ -76,11 +80,13 @@ describe('askForToolConfigPath', () => {
76
80
  it('returns the path if users have a config file and the entered path is valid', async () => {
77
81
  mockUserResponse(clack.confirm, true);
78
82
  mockUserResponse(clack.text, 'my.webpack.config.js');
79
- const result = await (0, clack_utils_1.askForToolConfigPath)('Webpack', 'webpack.config.js');
83
+ const result = await (0, clack_1.askForToolConfigPath)('Webpack', 'webpack.config.js');
80
84
  expect(clack.confirm).toHaveBeenCalledWith(expect.objectContaining({
85
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
81
86
  message: expect.stringContaining('have a Webpack config file'),
82
87
  }));
83
88
  expect(clack.text).toHaveBeenCalledWith(expect.objectContaining({
89
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
84
90
  message: expect.stringContaining('enter the path to your Webpack config file'),
85
91
  }));
86
92
  expect(result).toBe('my.webpack.config.js');
@@ -96,7 +102,7 @@ describe('createNewConfigFile', () => {
96
102
  .mockImplementation(jest.fn());
97
103
  const filename = '/webpack.config.js';
98
104
  const code = 'module.exports = {/*config...*/}';
99
- const result = await (0, clack_utils_1.createNewConfigFile)(filename, code);
105
+ const result = await (0, clack_1.createNewConfigFile)(filename, code);
100
106
  expect(result).toBe(true);
101
107
  expect(writeFileSpy).toHaveBeenCalledWith(filename, code);
102
108
  });
@@ -105,7 +111,7 @@ describe('createNewConfigFile', () => {
105
111
  const filename = '/webpack.config.js';
106
112
  const code = 'module.exports = {/*config...*/}';
107
113
  const moreInfo = 'More information...';
108
- await (0, clack_utils_1.createNewConfigFile)(filename, code, moreInfo);
114
+ await (0, clack_1.createNewConfigFile)(filename, code, moreInfo);
109
115
  expect(clack.log.info).toHaveBeenCalledTimes(1);
110
116
  expect(clack.log.info).toHaveBeenCalledWith(expect.stringContaining(moreInfo));
111
117
  });
@@ -115,13 +121,13 @@ describe('createNewConfigFile', () => {
115
121
  .mockImplementation(() => Promise.reject(new Error('Could not write')));
116
122
  const filename = '/webpack.config.js';
117
123
  const code = 'module.exports = {/*config...*/}';
118
- const result = await (0, clack_utils_1.createNewConfigFile)(filename, code);
124
+ const result = await (0, clack_1.createNewConfigFile)(filename, code);
119
125
  expect(result).toBe(false);
120
126
  expect(writeFileSpy).toHaveBeenCalledWith(filename, code);
121
127
  expect(clack.log.warn).toHaveBeenCalledTimes(1);
122
128
  });
123
129
  it('returns false if the passed path is not absolute', async () => {
124
- const result = await (0, clack_utils_1.createNewConfigFile)('./relative/webpack.config.js', '');
130
+ const result = await (0, clack_1.createNewConfigFile)('./relative/webpack.config.js', '');
125
131
  expect(result).toBe(false);
126
132
  });
127
133
  });
@@ -129,11 +135,24 @@ describe('installPackage', () => {
129
135
  afterEach(() => {
130
136
  jest.clearAllMocks();
131
137
  });
138
+ const spawnSpy = jest
139
+ .spyOn(ChildProcess, 'spawn')
140
+ // @ts-expect-error - ignoring complete typing
141
+ .mockImplementation(() => ({
142
+ // @ts-expect-error - not passing the full object but directly resolving
143
+ // to simulate a successful install
144
+ on: jest.fn((evt, cb) => {
145
+ if (evt === 'close') {
146
+ cb(0);
147
+ }
148
+ }),
149
+ stderr: { on: jest.fn() },
150
+ }));
132
151
  it('force-installs a package if the forceInstall flag is set', async () => {
133
152
  const packageManagerMock = {
134
153
  name: 'npm',
135
154
  label: 'NPM',
136
- installCommand: 'npm install',
155
+ installCommand: 'install',
137
156
  buildCommand: 'npm run build',
138
157
  runScriptCommand: 'npm run',
139
158
  flags: '',
@@ -141,30 +160,21 @@ describe('installPackage', () => {
141
160
  detect: jest.fn(),
142
161
  addOverride: jest.fn(),
143
162
  };
144
- const execSpy = jest
145
- .spyOn(ChildProcess, 'exec')
146
- // @ts-expect-error - don't care about the return value
147
- .mockImplementationOnce((cmd, cb) => {
148
- if (cb) {
149
- // @ts-expect-error - don't care about the options value
150
- cb(null, '', '');
151
- }
152
- });
153
- await (0, clack_utils_1.installPackage)({
163
+ await (0, clack_1.installPackage)({
154
164
  alreadyInstalled: false,
155
- packageName: '@sentry/sveltekit',
156
- packageNameDisplayLabel: '@sentry/sveltekit',
165
+ packageName: '@some/package',
166
+ packageNameDisplayLabel: '@some/package',
157
167
  forceInstall: true,
158
168
  askBeforeUpdating: false,
159
169
  packageManager: packageManagerMock,
160
170
  });
161
- expect(execSpy).toHaveBeenCalledWith('npm install @sentry/sveltekit --force', expect.any(Function));
171
+ expect(spawnSpy).toHaveBeenCalledWith('npm', ['install', '@some/package', '--force'], { shell: true, stdio: ['pipe', 'ignore', 'pipe'] });
162
172
  });
163
173
  it.each([false, undefined])("doesn't force-install a package if the forceInstall flag is %s", async (flag) => {
164
174
  const packageManagerMock = {
165
175
  name: 'npm',
166
176
  label: 'NPM',
167
- installCommand: 'npm install',
177
+ installCommand: 'install',
168
178
  buildCommand: 'npm run build',
169
179
  runScriptCommand: 'npm run',
170
180
  flags: '',
@@ -172,16 +182,7 @@ describe('installPackage', () => {
172
182
  detect: jest.fn(),
173
183
  addOverride: jest.fn(),
174
184
  };
175
- const execSpy = jest
176
- .spyOn(ChildProcess, 'exec')
177
- // @ts-expect-error - don't care about the return value
178
- .mockImplementationOnce((cmd, cb) => {
179
- if (cb) {
180
- // @ts-expect-error - don't care about the options value
181
- cb(null, '', '');
182
- }
183
- });
184
- await (0, clack_utils_1.installPackage)({
185
+ await (0, clack_1.installPackage)({
185
186
  alreadyInstalled: false,
186
187
  packageName: '@sentry/sveltekit',
187
188
  packageNameDisplayLabel: '@sentry/sveltekit',
@@ -189,7 +190,29 @@ describe('installPackage', () => {
189
190
  askBeforeUpdating: false,
190
191
  packageManager: packageManagerMock,
191
192
  });
192
- expect(execSpy).toHaveBeenCalledWith('npm install @sentry/sveltekit ', expect.any(Function));
193
+ expect(spawnSpy).toHaveBeenCalledWith('npm', ['install', '@sentry/sveltekit'], { shell: true, stdio: ['pipe', 'ignore', 'pipe'] });
194
+ });
195
+ it('adds install flags if defined', async () => {
196
+ const packageManagerMock = {
197
+ name: 'npm',
198
+ label: 'NPM',
199
+ installCommand: 'install',
200
+ buildCommand: 'npm run build',
201
+ runScriptCommand: 'npm run',
202
+ flags: '--ignore-workspace-root-check',
203
+ forceInstallFlag: '--force',
204
+ detect: jest.fn(),
205
+ addOverride: jest.fn(),
206
+ };
207
+ await (0, clack_1.installPackage)({
208
+ alreadyInstalled: false,
209
+ packageName: '@some/package',
210
+ packageNameDisplayLabel: '@some/package',
211
+ forceInstall: true,
212
+ askBeforeUpdating: false,
213
+ packageManager: packageManagerMock,
214
+ });
215
+ expect(spawnSpy).toHaveBeenCalledWith('npm', ['install', '@some/package', '--ignore-workspace-root-check', '--force'], { shell: true, stdio: ['pipe', 'ignore', 'pipe'] });
193
216
  });
194
217
  });
195
218
  describe('askForWizardLogin', () => {
@@ -213,8 +236,9 @@ describe('askForWizardLogin', () => {
213
236
  hash: 'mockedHash',
214
237
  },
215
238
  });
216
- await (0, clack_utils_1.askForWizardLogin)({ url: 'https://santry.io/' });
239
+ await (0, clack_1.askForWizardLogin)({ url: 'https://santry.io/' });
217
240
  expect(clack.confirm).toHaveBeenCalledWith(expect.objectContaining({
241
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
218
242
  message: expect.stringContaining('already have a Sentry account'),
219
243
  }));
220
244
  });
@@ -226,7 +250,7 @@ describe('askForWizardLogin', () => {
226
250
  hash: 'mockedHash',
227
251
  },
228
252
  });
229
- await (0, clack_utils_1.askForWizardLogin)({
253
+ await (0, clack_1.askForWizardLogin)({
230
254
  url: 'https://santry.io/',
231
255
  orgSlug: 'my-org',
232
256
  projectSlug: 'my-project',
@@ -260,10 +284,10 @@ describe('abort', () => {
260
284
  const flushSpy = jest.fn();
261
285
  jest.spyOn(Sentry, 'flush').mockImplementation(flushSpy);
262
286
  it('ends the process with an error exit code by default', async () => {
263
- // @ts-ignore - jest doesn't like the empty function
287
+ // @ts-expect-error - jest doesn't like the empty function
264
288
  // eslint-disable-next-line @typescript-eslint/no-empty-function
265
289
  const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => { });
266
- await (0, clack_utils_1.abort)();
290
+ await (0, clack_1.abort)();
267
291
  expect(exitSpy).toHaveBeenCalledWith(1);
268
292
  expect(clackMock.outro).toHaveBeenCalledTimes(1);
269
293
  expect(clackMock.outro).toHaveBeenCalledWith('Wizard setup cancelled.');
@@ -273,10 +297,10 @@ describe('abort', () => {
273
297
  expect(flushSpy).toHaveBeenLastCalledWith(3000);
274
298
  });
275
299
  it('ends the process with a custom exit code and message if provided', async () => {
276
- // @ts-ignore - jest doesn't like the empty function
300
+ // @ts-expect-error - jest doesn't like the empty function
277
301
  // eslint-disable-next-line @typescript-eslint/no-empty-function
278
302
  const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => { });
279
- await (0, clack_utils_1.abort)('Bye', 0);
303
+ await (0, clack_1.abort)('Bye', 0);
280
304
  expect(exitSpy).toHaveBeenCalledWith(0);
281
305
  expect(clackMock.outro).toHaveBeenCalledTimes(1);
282
306
  expect(clackMock.outro).toHaveBeenCalledWith('Bye');
@@ -286,4 +310,70 @@ describe('abort', () => {
286
310
  expect(flushSpy).toHaveBeenLastCalledWith(3000);
287
311
  });
288
312
  });
289
- //# sourceMappingURL=clack-utils.test.js.map
313
+ describe('getPackageManager', () => {
314
+ afterEach(() => {
315
+ jest.clearAllMocks();
316
+ // @ts-expect-error - this variable is set by the wizard
317
+ delete global.__sentry_wizard_cached_package_manager;
318
+ });
319
+ it('returns the auto-detected package manager', async () => {
320
+ const detectPacManSpy = jest
321
+ .spyOn(PackageManagerUtils, '_detectPackageManger')
322
+ .mockReturnValueOnce(package_manager_1.YARN_V1);
323
+ const packageManager = await (0, clack_1.getPackageManager)();
324
+ expect(detectPacManSpy).toHaveBeenCalledTimes(1);
325
+ expect(packageManager).toBe(package_manager_1.YARN_V1);
326
+ });
327
+ it('caches the auto-detected package manager', async () => {
328
+ const detectPacManSpy = jest
329
+ .spyOn(PackageManagerUtils, '_detectPackageManger')
330
+ .mockReturnValueOnce(package_manager_1.YARN_V1);
331
+ const packageManager1 = await (0, clack_1.getPackageManager)();
332
+ const packageManager2 = await (0, clack_1.getPackageManager)();
333
+ expect(detectPacManSpy).toHaveBeenCalledTimes(1);
334
+ expect(packageManager1).toBe(package_manager_1.YARN_V1);
335
+ expect(packageManager2).toBe(package_manager_1.YARN_V1);
336
+ });
337
+ describe('when auto detection fails', () => {
338
+ it('returns a fallback package manager if fallback is specified', async () => {
339
+ const detectPacManSpy = jest
340
+ .spyOn(PackageManagerUtils, '_detectPackageManger')
341
+ .mockReturnValueOnce(null);
342
+ const packageManager = await (0, clack_1.getPackageManager)(package_manager_1.YARN_V2);
343
+ expect(detectPacManSpy).toHaveBeenCalledTimes(1);
344
+ expect(packageManager).toBe(package_manager_1.YARN_V2);
345
+ });
346
+ it("doesn't cache the fallback package manager", async () => {
347
+ const detectPacManSpy = jest
348
+ .spyOn(PackageManagerUtils, '_detectPackageManger')
349
+ .mockReturnValue(null);
350
+ const packageManager1 = await (0, clack_1.getPackageManager)(package_manager_1.YARN_V2);
351
+ const packageManager2 = await (0, clack_1.getPackageManager)(package_manager_1.NPM);
352
+ expect(detectPacManSpy).toHaveBeenCalledTimes(2);
353
+ expect(packageManager1).toBe(package_manager_1.YARN_V2);
354
+ expect(packageManager2).toBe(package_manager_1.NPM);
355
+ });
356
+ it('returns the user-selected package manager if no fallback is provided', async () => {
357
+ const detectPacManSpy = jest
358
+ .spyOn(PackageManagerUtils, '_detectPackageManger')
359
+ .mockReturnValueOnce(null);
360
+ clackMock.select.mockReturnValueOnce(Promise.resolve(package_manager_1.PNPM));
361
+ const packageManager = await (0, clack_1.getPackageManager)();
362
+ expect(detectPacManSpy).toHaveBeenCalledTimes(1);
363
+ expect(packageManager).toBe(package_manager_1.PNPM);
364
+ });
365
+ it('caches the user-selected package manager', async () => {
366
+ const detectPacManSpy = jest
367
+ .spyOn(PackageManagerUtils, '_detectPackageManger')
368
+ .mockReturnValueOnce(null);
369
+ clackMock.select.mockReturnValueOnce(Promise.resolve(package_manager_1.PNPM));
370
+ const packageManager1 = await (0, clack_1.getPackageManager)();
371
+ const packageManager2 = await (0, clack_1.getPackageManager)();
372
+ expect(detectPacManSpy).toHaveBeenCalledTimes(1);
373
+ expect(clackMock.select).toHaveBeenCalledTimes(1);
374
+ expect(packageManager1).toBe(package_manager_1.PNPM);
375
+ expect(packageManager2).toBe(package_manager_1.PNPM);
376
+ });
377
+ });
378
+ });
379
+ //# sourceMappingURL=index.test.js.map