@sentry/wizard 6.11.0 → 6.13.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.
- package/CHANGELOG.md +64 -0
- package/dist/bin.js +16 -1
- package/dist/bin.js.map +1 -1
- package/dist/e2e-tests/tests/angular-17.test.js +3 -4
- package/dist/e2e-tests/tests/angular-17.test.js.map +1 -1
- package/dist/e2e-tests/tests/angular-19.test.js +3 -4
- package/dist/e2e-tests/tests/angular-19.test.js.map +1 -1
- package/dist/e2e-tests/tests/cloudflare-worker.test.js +5 -0
- package/dist/e2e-tests/tests/cloudflare-worker.test.js.map +1 -1
- package/dist/e2e-tests/tests/flutter.test.js +60 -0
- package/dist/e2e-tests/tests/flutter.test.js.map +1 -1
- package/dist/e2e-tests/tests/help-message.test.js +8 -3
- package/dist/e2e-tests/tests/help-message.test.js.map +1 -1
- package/dist/e2e-tests/tests/nuxt-3.test.js +12 -6
- package/dist/e2e-tests/tests/nuxt-3.test.js.map +1 -1
- package/dist/e2e-tests/tests/nuxt-4.test.js +12 -6
- package/dist/e2e-tests/tests/nuxt-4.test.js.map +1 -1
- package/dist/e2e-tests/tests/pnpm-workspace.test.js +8 -4
- package/dist/e2e-tests/tests/pnpm-workspace.test.js.map +1 -1
- package/dist/e2e-tests/tests/react-router-instrumentation-api.test.js +96 -0
- package/dist/e2e-tests/tests/react-router-instrumentation-api.test.js.map +1 -0
- package/dist/e2e-tests/tests/react-router.test.js +6 -7
- package/dist/e2e-tests/tests/react-router.test.js.map +1 -1
- package/dist/e2e-tests/tests/remix.test.js +2 -4
- package/dist/e2e-tests/tests/remix.test.js.map +1 -1
- package/dist/e2e-tests/tests/sveltekit-hooks.test.js +24 -8
- package/dist/e2e-tests/tests/sveltekit-hooks.test.js.map +1 -1
- package/dist/e2e-tests/tests/sveltekit-tracing.test.js +8 -4
- package/dist/e2e-tests/tests/sveltekit-tracing.test.js.map +1 -1
- package/dist/lib/Constants.d.ts +1 -0
- package/dist/lib/Constants.js +5 -0
- package/dist/lib/Constants.js.map +1 -1
- package/dist/lib/Steps/Integrations/Electron.js +2 -2
- package/dist/lib/Steps/Integrations/Electron.js.map +1 -1
- package/dist/src/android/android-wizard.js +3 -0
- package/dist/src/android/android-wizard.js.map +1 -1
- package/dist/src/angular/codemods/main.d.ts +1 -1
- package/dist/src/angular/codemods/main.js +0 -1
- package/dist/src/angular/codemods/main.js.map +1 -1
- package/dist/src/apple/apple-wizard.js +2 -3
- package/dist/src/apple/apple-wizard.js.map +1 -1
- package/dist/src/apple/check-installed-cli.d.ts +1 -1
- package/dist/src/apple/check-installed-cli.js +13 -7
- package/dist/src/apple/check-installed-cli.js.map +1 -1
- package/dist/src/apple/code-tools.js +17 -3
- package/dist/src/apple/code-tools.js.map +1 -1
- package/dist/src/apple/configure-package-manager.js +18 -5
- package/dist/src/apple/configure-package-manager.js.map +1 -1
- package/dist/src/apple/configure-xcode-project.js +8 -1
- package/dist/src/apple/configure-xcode-project.js.map +1 -1
- package/dist/src/apple/lookup-xcode-project.d.ts +8 -5
- package/dist/src/apple/lookup-xcode-project.js +22 -17
- package/dist/src/apple/lookup-xcode-project.js.map +1 -1
- package/dist/src/apple/options.d.ts +5 -0
- package/dist/src/apple/options.js.map +1 -1
- package/dist/src/apple/sentry-swift-package.d.ts +4 -0
- package/dist/src/apple/sentry-swift-package.js +17 -0
- package/dist/src/apple/sentry-swift-package.js.map +1 -0
- package/dist/src/apple/snapshots/apple-snapshots-wizard.d.ts +2 -0
- package/dist/src/apple/snapshots/apple-snapshots-wizard.js +251 -0
- package/dist/src/apple/snapshots/apple-snapshots-wizard.js.map +1 -0
- package/dist/src/apple/snapshots/configure-snapshotpreviews-xcode-project.d.ts +13 -0
- package/dist/src/apple/snapshots/configure-snapshotpreviews-xcode-project.js +48 -0
- package/dist/src/apple/snapshots/configure-snapshotpreviews-xcode-project.js.map +1 -0
- package/dist/src/apple/snapshots/snapshot-test-file.d.ts +18 -0
- package/dist/src/apple/snapshots/snapshot-test-file.js +122 -0
- package/dist/src/apple/snapshots/snapshot-test-file.js.map +1 -0
- package/dist/src/apple/snapshots/snapshot-verification-scheme.d.ts +6 -0
- package/dist/src/apple/snapshots/snapshot-verification-scheme.js +147 -0
- package/dist/src/apple/snapshots/snapshot-verification-scheme.js.map +1 -0
- package/dist/src/apple/snapshots/snapshotpreviews-package.d.ts +4 -0
- package/dist/src/apple/snapshots/snapshotpreviews-package.js +8 -0
- package/dist/src/apple/snapshots/snapshotpreviews-package.js.map +1 -0
- package/dist/src/apple/snapshots/snapshots-cli-preflight.d.ts +23 -0
- package/dist/src/apple/snapshots/snapshots-cli-preflight.js +136 -0
- package/dist/src/apple/snapshots/snapshots-cli-preflight.js.map +1 -0
- package/dist/src/apple/xcode-manager.d.ts +59 -1
- package/dist/src/apple/xcode-manager.js +507 -106
- package/dist/src/apple/xcode-manager.js.map +1 -1
- package/dist/src/cloudflare/cloudflare-wizard.js +5 -0
- package/dist/src/cloudflare/cloudflare-wizard.js.map +1 -1
- package/dist/src/cloudflare/sdk-setup.d.ts +1 -0
- package/dist/src/cloudflare/sdk-setup.js.map +1 -1
- package/dist/src/cloudflare/templates.d.ts +1 -0
- package/dist/src/cloudflare/templates.js +7 -1
- package/dist/src/cloudflare/templates.js.map +1 -1
- package/dist/src/cloudflare/wrap-worker.d.ts +1 -0
- package/dist/src/cloudflare/wrap-worker.js +7 -0
- package/dist/src/cloudflare/wrap-worker.js.map +1 -1
- package/dist/src/flutter/flutter-wizard.js +3 -0
- package/dist/src/flutter/flutter-wizard.js.map +1 -1
- package/dist/src/nextjs/templates.js +12 -6
- package/dist/src/nextjs/templates.js.map +1 -1
- package/dist/src/nuxt/templates.js +12 -6
- package/dist/src/nuxt/templates.js.map +1 -1
- package/dist/src/react-native/expo.d.ts +6 -0
- package/dist/src/react-native/expo.js +27 -1
- package/dist/src/react-native/expo.js.map +1 -1
- package/dist/src/react-native/git.d.ts +5 -0
- package/dist/src/react-native/git.js +32 -1
- package/dist/src/react-native/git.js.map +1 -1
- package/dist/src/react-native/javascript.js +3 -1
- package/dist/src/react-native/javascript.js.map +1 -1
- package/dist/src/react-native/react-native-wizard.js +12 -6
- package/dist/src/react-native/react-native-wizard.js.map +1 -1
- package/dist/src/react-router/codemods/client.entry.d.ts +1 -1
- package/dist/src/react-router/codemods/client.entry.js +124 -26
- package/dist/src/react-router/codemods/client.entry.js.map +1 -1
- package/dist/src/react-router/codemods/react-router-config.js +1 -1
- package/dist/src/react-router/codemods/react-router-config.js.map +1 -1
- package/dist/src/react-router/codemods/server-entry.d.ts +1 -1
- package/dist/src/react-router/codemods/server-entry.js +40 -4
- package/dist/src/react-router/codemods/server-entry.js.map +1 -1
- package/dist/src/react-router/codemods/vite.js +46 -1
- package/dist/src/react-router/codemods/vite.js.map +1 -1
- package/dist/src/react-router/react-router-wizard.js +62 -21
- package/dist/src/react-router/react-router-wizard.js.map +1 -1
- package/dist/src/react-router/sdk-setup.d.ts +5 -3
- package/dist/src/react-router/sdk-setup.js +44 -16
- package/dist/src/react-router/sdk-setup.js.map +1 -1
- package/dist/src/react-router/templates.d.ts +2 -4
- package/dist/src/react-router/templates.js +89 -87
- package/dist/src/react-router/templates.js.map +1 -1
- package/dist/src/remix/sdk-setup.js +1 -2
- package/dist/src/remix/sdk-setup.js.map +1 -1
- package/dist/src/run.d.ts +4 -1
- package/dist/src/run.js +13 -0
- package/dist/src/run.js.map +1 -1
- package/dist/src/sourcemaps/tools/remix.js +4 -4
- package/dist/src/sourcemaps/tools/remix.js.map +1 -1
- package/dist/src/sourcemaps/tools/vite.js +1 -1
- package/dist/src/sourcemaps/tools/vite.js.map +1 -1
- package/dist/src/sveltekit/sdk-setup/setup.js +17 -4
- package/dist/src/sveltekit/sdk-setup/setup.js.map +1 -1
- package/dist/src/sveltekit/sdk-setup/vite.js +1 -1
- package/dist/src/sveltekit/sdk-setup/vite.js.map +1 -1
- package/dist/src/sveltekit/templates.js +12 -6
- package/dist/src/sveltekit/templates.js.map +1 -1
- package/dist/src/utils/ast-utils.d.ts +10 -0
- package/dist/src/utils/ast-utils.js +19 -1
- package/dist/src/utils/ast-utils.js.map +1 -1
- package/dist/src/utils/clack/index.d.ts +2 -1
- package/dist/src/utils/clack/index.js +17 -6
- package/dist/src/utils/clack/index.js.map +1 -1
- package/dist/src/utils/files.d.ts +2 -0
- package/dist/src/utils/files.js +58 -0
- package/dist/src/utils/files.js.map +1 -0
- package/dist/src/utils/git.d.ts +3 -1
- package/dist/src/utils/git.js +2 -1
- package/dist/src/utils/git.js.map +1 -1
- package/dist/src/utils/line-endings.d.ts +1 -0
- package/dist/src/utils/line-endings.js +76 -0
- package/dist/src/utils/line-endings.js.map +1 -0
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/test/angular/angular-wizard.test.js +0 -5
- package/dist/test/angular/angular-wizard.test.js.map +1 -1
- package/dist/test/apple/code-tools.test.js +78 -0
- package/dist/test/apple/code-tools.test.js.map +1 -1
- package/dist/test/apple/configure-package-manager.test.d.ts +1 -0
- package/dist/test/apple/configure-package-manager.test.js +161 -0
- package/dist/test/apple/configure-package-manager.test.js.map +1 -0
- package/dist/test/apple/lookup-xcode-project.test.d.ts +1 -0
- package/dist/test/apple/lookup-xcode-project.test.js +167 -0
- package/dist/test/apple/lookup-xcode-project.test.js.map +1 -0
- package/dist/test/apple/snapshots/apple-snapshots-wizard.test.d.ts +1 -0
- package/dist/test/apple/snapshots/apple-snapshots-wizard.test.js +487 -0
- package/dist/test/apple/snapshots/apple-snapshots-wizard.test.js.map +1 -0
- package/dist/test/apple/snapshots/hosted-test-target-fixture.d.ts +24 -0
- package/dist/test/apple/snapshots/hosted-test-target-fixture.js +191 -0
- package/dist/test/apple/snapshots/hosted-test-target-fixture.js.map +1 -0
- package/dist/test/apple/snapshots/snapshot-test-file.test.d.ts +1 -0
- package/dist/test/apple/snapshots/snapshot-test-file.test.js +110 -0
- package/dist/test/apple/snapshots/snapshot-test-file.test.js.map +1 -0
- package/dist/test/apple/snapshots/snapshot-verification-scheme.test.d.ts +1 -0
- package/dist/test/apple/snapshots/snapshot-verification-scheme.test.js +146 -0
- package/dist/test/apple/snapshots/snapshot-verification-scheme.test.js.map +1 -0
- package/dist/test/apple/snapshots/snapshotpreviews-xcode-smoke.test.d.ts +1 -0
- package/dist/test/apple/snapshots/snapshotpreviews-xcode-smoke.test.js +186 -0
- package/dist/test/apple/snapshots/snapshotpreviews-xcode-smoke.test.js.map +1 -0
- package/dist/test/apple/snapshots/snapshots-cli-preflight.test.d.ts +1 -0
- package/dist/test/apple/snapshots/snapshots-cli-preflight.test.js +192 -0
- package/dist/test/apple/snapshots/snapshots-cli-preflight.test.js.map +1 -0
- package/dist/test/apple/snapshots/source-file-insertion.test.d.ts +1 -0
- package/dist/test/apple/snapshots/source-file-insertion.test.js +77 -0
- package/dist/test/apple/snapshots/source-file-insertion.test.js.map +1 -0
- package/dist/test/apple/xcode-manager.test.js +452 -43
- package/dist/test/apple/xcode-manager.test.js.map +1 -1
- package/dist/test/cloudflare/sdk-setup.test.js +20 -2
- package/dist/test/cloudflare/sdk-setup.test.js.map +1 -1
- package/dist/test/cloudflare/templates.test.js +54 -0
- package/dist/test/cloudflare/templates.test.js.map +1 -1
- package/dist/test/cloudflare/wrap-worker.test.js +74 -11
- package/dist/test/cloudflare/wrap-worker.test.js.map +1 -1
- package/dist/test/constants.test.d.ts +1 -0
- package/dist/test/constants.test.js +12 -0
- package/dist/test/constants.test.js.map +1 -0
- package/dist/test/nextjs/templates.test.js +66 -33
- package/dist/test/nextjs/templates.test.js.map +1 -1
- package/dist/test/nuxt/templates.test.js +66 -36
- package/dist/test/nuxt/templates.test.js.map +1 -1
- package/dist/test/react-native/expo.test.js +140 -0
- package/dist/test/react-native/expo.test.js.map +1 -1
- package/dist/test/react-native/git.test.d.ts +1 -0
- package/dist/test/react-native/git.test.js +160 -0
- package/dist/test/react-native/git.test.js.map +1 -0
- package/dist/test/react-router/codemods/client-entry.test.js +38 -5
- package/dist/test/react-router/codemods/client-entry.test.js.map +1 -1
- package/dist/test/react-router/codemods/server-entry.test.js +83 -0
- package/dist/test/react-router/codemods/server-entry.test.js.map +1 -1
- package/dist/test/react-router/codemods/vite.test.js +89 -0
- package/dist/test/react-router/codemods/vite.test.js.map +1 -1
- package/dist/test/react-router/sdk-setup.test.js +98 -6
- package/dist/test/react-router/sdk-setup.test.js.map +1 -1
- package/dist/test/react-router/templates.test.js +50 -38
- package/dist/test/react-router/templates.test.js.map +1 -1
- package/dist/test/remix/build-script.test.d.ts +1 -0
- package/dist/test/remix/build-script.test.js +124 -0
- package/dist/test/remix/build-script.test.js.map +1 -0
- package/dist/test/remix/client-entry.test.js +4 -10
- package/dist/test/remix/client-entry.test.js.map +1 -1
- package/dist/test/run.test.d.ts +1 -0
- package/dist/test/run.test.js +137 -0
- package/dist/test/run.test.js.map +1 -0
- package/dist/test/sourcemaps/tools/vite.test.js +12 -8
- package/dist/test/sourcemaps/tools/vite.test.js.map +1 -1
- package/dist/test/sveltekit/templates.test.js +78 -27
- package/dist/test/sveltekit/templates.test.js.map +1 -1
- package/dist/test/utils/ast-utils.test.js +22 -0
- package/dist/test/utils/ast-utils.test.js.map +1 -1
- package/dist/test/utils/clack/index.test.js +101 -0
- package/dist/test/utils/clack/index.test.js.map +1 -1
- package/dist/test/utils/git.test.js +10 -0
- package/dist/test/utils/git.test.js.map +1 -1
- package/dist/test/utils/line-endings.test.d.ts +1 -0
- package/dist/test/utils/line-endings.test.js +103 -0
- package/dist/test/utils/line-endings.test.js.map +1 -0
- package/package.json +2 -2
- package/dist/src/react-router/codemods/root.d.ts +0 -1
- package/dist/src/react-router/codemods/root.js +0 -171
- package/dist/src/react-router/codemods/root.js.map +0 -1
- package/dist/test/react-router/codemods/root.test.js +0 -178
- package/dist/test/react-router/codemods/root.test.js.map +0 -1
- /package/dist/{test/react-router/codemods/root.test.d.ts → e2e-tests/tests/react-router-instrumentation-api.test.d.ts} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-router-config.js","sourceRoot":"","sources":["../../../../src/react-router/codemods/react-router-config.ts"],"names":[],"mappings":"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","sourcesContent":["import type { namedTypes as t } from 'ast-types';\nimport * as recast from 'recast';\nimport * as path from 'path';\nimport * as fs from 'fs';\n\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport { parseModule, generateCode } from 'magicast';\n\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\nimport chalk from 'chalk';\n\nimport { findProperty } from '../../utils/ast-utils';\n\n/**\n * Extracts the ObjectExpression from various export patterns.\n * Supports: direct object, `satisfies Config`, and `as Config` patterns.\n */\nfunction extractConfigObject(\n declaration: t.Declaration | t.Expression,\n): t.ObjectExpression | undefined {\n if (declaration.type === 'ObjectExpression') {\n return declaration as t.ObjectExpression;\n }\n\n if (\n declaration.type === 'TSSatisfiesExpression' ||\n declaration.type === 'TSAsExpression'\n ) {\n const expr = (declaration as t.TSSatisfiesExpression | t.TSAsExpression)\n .expression;\n return expr.type === 'ObjectExpression' ? expr : undefined;\n }\n\n return undefined;\n}\n\n/**\n * Creates an identifier property for object literals.\n */\nfunction createIdentifierProperty(name: string): t.Property {\n const b = recast.types.builders;\n return b.property('init', b.identifier(name), b.identifier(name));\n}\n\nexport function addSentryBuildEndToReactRouterConfig(program: t.Program): {\n success: boolean;\n ssrWasChanged: boolean;\n} {\n const b = recast.types.builders;\n let ssrWasChanged = false;\n\n const defaultExport = program.body.find(\n (node) => node.type === 'ExportDefaultDeclaration',\n ) as t.ExportDefaultDeclaration | undefined;\n\n if (!defaultExport) {\n return { success: false, ssrWasChanged: false };\n }\n\n const configObj = extractConfigObject(defaultExport.declaration);\n\n if (!configObj) {\n return { success: false, ssrWasChanged: false };\n }\n\n const buildEndProp = findProperty(configObj, 'buildEnd');\n\n if (buildEndProp) {\n throw new Error(\n 'A buildEnd hook already exists in your React Router config.',\n );\n }\n\n const ssrProp = findProperty(configObj, 'ssr');\n\n if (!ssrProp) {\n const ssrProperty = b.objectProperty(\n b.identifier('ssr'),\n b.booleanLiteral(true),\n );\n ssrProperty.comments = [\n {\n type: 'CommentLine',\n value:\n ' SSR is required for Sentry sourcemap uploads to work correctly',\n } as any, // eslint-disable-line @typescript-eslint/no-explicit-any\n ];\n configObj.properties.unshift(ssrProperty);\n ssrWasChanged = true;\n } else if (\n ssrProp.value.type === 'BooleanLiteral' ||\n ssrProp.value.type === 'Literal'\n ) {\n const wasExplicitlyFalse = ssrProp.value.value === false;\n\n if (wasExplicitlyFalse) {\n ssrWasChanged = true;\n }\n\n ssrProp.value = b.booleanLiteral(true);\n\n if (wasExplicitlyFalse) {\n ssrProp.comments = [\n {\n type: 'CommentLine',\n value:\n ' Changed to true - SSR is required for Sentry sourcemap uploads',\n } as any, // eslint-disable-line @typescript-eslint/no-explicit-any\n ];\n }\n }\n\n const paramNames = ['viteConfig', 'reactRouterConfig', 'buildManifest'];\n\n const buildEndFunction = b.arrowFunctionExpression(\n [b.objectPattern(paramNames.map(createIdentifierProperty))],\n b.blockStatement([\n b.expressionStatement(\n b.awaitExpression(\n b.callExpression(b.identifier('sentryOnBuildEnd'), [\n b.objectExpression(paramNames.map(createIdentifierProperty)),\n ]),\n ),\n ),\n ]),\n );\n buildEndFunction.async = true;\n\n configObj.properties.push(\n b.objectProperty(b.identifier('buildEnd'), buildEndFunction),\n );\n\n return { success: true, ssrWasChanged };\n}\n\nexport function hasReactRouterSentryContent(program: t.Program): boolean {\n let hasSentry = false;\n\n recast.visit(program, {\n visitIdentifier(path) {\n if (path.node.name === 'sentryOnBuildEnd') {\n hasSentry = true;\n return false; // stop traversal\n }\n this.traverse(path);\n },\n });\n\n return hasSentry;\n}\n\nexport async function instrumentReactRouterConfig(\n isTS: boolean,\n): Promise<{ ssrWasChanged: boolean }> {\n const configFilename = `react-router.config.${isTS ? 'ts' : 'js'}`;\n const configPath = path.join(process.cwd(), configFilename);\n\n if (!fs.existsSync(configPath)) {\n const defaultConfig = isTS\n ? `import type { Config } from \"@react-router/dev/config\";\nimport { sentryOnBuildEnd } from \"@sentry/react-router\";\n\nexport default {\n ssr: true,\n buildEnd: async ({ viteConfig, reactRouterConfig, buildManifest }) => {\n await sentryOnBuildEnd({ viteConfig, reactRouterConfig, buildManifest });\n },\n} satisfies Config;\n`\n : `import { sentryOnBuildEnd } from \"@sentry/react-router\";\n\nexport default {\n ssr: true,\n buildEnd: async ({ viteConfig, reactRouterConfig, buildManifest }) => {\n await sentryOnBuildEnd({ viteConfig, reactRouterConfig, buildManifest });\n },\n};\n`;\n await fs.promises.writeFile(configPath, defaultConfig);\n return { ssrWasChanged: false };\n }\n\n const configContent = await fs.promises.readFile(configPath, 'utf-8');\n const filename = chalk.cyan(configFilename);\n\n const mod = parseModule(configContent);\n\n if (hasReactRouterSentryContent(mod.$ast as t.Program)) {\n clack.log.info(`${filename} already contains sentryOnBuildEnd.`);\n return { ssrWasChanged: false };\n }\n\n mod.imports.$add({\n from: '@sentry/react-router',\n imported: 'sentryOnBuildEnd',\n local: 'sentryOnBuildEnd',\n });\n\n const { success, ssrWasChanged } = addSentryBuildEndToReactRouterConfig(\n mod.$ast as t.Program,\n );\n\n if (!success) {\n throw new Error('Failed to modify React Router config structure');\n }\n\n const code = generateCode(mod.$ast).code;\n await fs.promises.writeFile(configPath, code);\n\n return { ssrWasChanged };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"react-router-config.js","sourceRoot":"","sources":["../../../../src/react-router/codemods/react-router-config.ts"],"names":[],"mappings":"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","sourcesContent":["import type { namedTypes as t } from 'ast-types';\nimport * as recast from 'recast';\nimport * as path from 'path';\nimport * as fs from 'fs';\n\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport { parseModule, generateCode } from 'magicast';\n\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\nimport chalk from 'chalk';\n\nimport { findProperty, preserveTrailingNewline } from '../../utils/ast-utils';\n\n/**\n * Extracts the ObjectExpression from various export patterns.\n * Supports: direct object, `satisfies Config`, and `as Config` patterns.\n */\nfunction extractConfigObject(\n declaration: t.Declaration | t.Expression,\n): t.ObjectExpression | undefined {\n if (declaration.type === 'ObjectExpression') {\n return declaration as t.ObjectExpression;\n }\n\n if (\n declaration.type === 'TSSatisfiesExpression' ||\n declaration.type === 'TSAsExpression'\n ) {\n const expr = (declaration as t.TSSatisfiesExpression | t.TSAsExpression)\n .expression;\n return expr.type === 'ObjectExpression' ? expr : undefined;\n }\n\n return undefined;\n}\n\n/**\n * Creates an identifier property for object literals.\n */\nfunction createIdentifierProperty(name: string): t.Property {\n const b = recast.types.builders;\n return b.property('init', b.identifier(name), b.identifier(name));\n}\n\nexport function addSentryBuildEndToReactRouterConfig(program: t.Program): {\n success: boolean;\n ssrWasChanged: boolean;\n} {\n const b = recast.types.builders;\n let ssrWasChanged = false;\n\n const defaultExport = program.body.find(\n (node) => node.type === 'ExportDefaultDeclaration',\n ) as t.ExportDefaultDeclaration | undefined;\n\n if (!defaultExport) {\n return { success: false, ssrWasChanged: false };\n }\n\n const configObj = extractConfigObject(defaultExport.declaration);\n\n if (!configObj) {\n return { success: false, ssrWasChanged: false };\n }\n\n const buildEndProp = findProperty(configObj, 'buildEnd');\n\n if (buildEndProp) {\n throw new Error(\n 'A buildEnd hook already exists in your React Router config.',\n );\n }\n\n const ssrProp = findProperty(configObj, 'ssr');\n\n if (!ssrProp) {\n const ssrProperty = b.objectProperty(\n b.identifier('ssr'),\n b.booleanLiteral(true),\n );\n ssrProperty.comments = [\n {\n type: 'CommentLine',\n value:\n ' SSR is required for Sentry sourcemap uploads to work correctly',\n } as any, // eslint-disable-line @typescript-eslint/no-explicit-any\n ];\n configObj.properties.unshift(ssrProperty);\n ssrWasChanged = true;\n } else if (\n ssrProp.value.type === 'BooleanLiteral' ||\n ssrProp.value.type === 'Literal'\n ) {\n const wasExplicitlyFalse = ssrProp.value.value === false;\n\n if (wasExplicitlyFalse) {\n ssrWasChanged = true;\n }\n\n ssrProp.value = b.booleanLiteral(true);\n\n if (wasExplicitlyFalse) {\n ssrProp.comments = [\n {\n type: 'CommentLine',\n value:\n ' Changed to true - SSR is required for Sentry sourcemap uploads',\n } as any, // eslint-disable-line @typescript-eslint/no-explicit-any\n ];\n }\n }\n\n const paramNames = ['viteConfig', 'reactRouterConfig', 'buildManifest'];\n\n const buildEndFunction = b.arrowFunctionExpression(\n [b.objectPattern(paramNames.map(createIdentifierProperty))],\n b.blockStatement([\n b.expressionStatement(\n b.awaitExpression(\n b.callExpression(b.identifier('sentryOnBuildEnd'), [\n b.objectExpression(paramNames.map(createIdentifierProperty)),\n ]),\n ),\n ),\n ]),\n );\n buildEndFunction.async = true;\n\n configObj.properties.push(\n b.objectProperty(b.identifier('buildEnd'), buildEndFunction),\n );\n\n return { success: true, ssrWasChanged };\n}\n\nexport function hasReactRouterSentryContent(program: t.Program): boolean {\n let hasSentry = false;\n\n recast.visit(program, {\n visitIdentifier(path) {\n if (path.node.name === 'sentryOnBuildEnd') {\n hasSentry = true;\n return false; // stop traversal\n }\n this.traverse(path);\n },\n });\n\n return hasSentry;\n}\n\nexport async function instrumentReactRouterConfig(\n isTS: boolean,\n): Promise<{ ssrWasChanged: boolean }> {\n const configFilename = `react-router.config.${isTS ? 'ts' : 'js'}`;\n const configPath = path.join(process.cwd(), configFilename);\n\n if (!fs.existsSync(configPath)) {\n const defaultConfig = isTS\n ? `import type { Config } from \"@react-router/dev/config\";\nimport { sentryOnBuildEnd } from \"@sentry/react-router\";\n\nexport default {\n ssr: true,\n buildEnd: async ({ viteConfig, reactRouterConfig, buildManifest }) => {\n await sentryOnBuildEnd({ viteConfig, reactRouterConfig, buildManifest });\n },\n} satisfies Config;\n`\n : `import { sentryOnBuildEnd } from \"@sentry/react-router\";\n\nexport default {\n ssr: true,\n buildEnd: async ({ viteConfig, reactRouterConfig, buildManifest }) => {\n await sentryOnBuildEnd({ viteConfig, reactRouterConfig, buildManifest });\n },\n};\n`;\n await fs.promises.writeFile(configPath, defaultConfig);\n return { ssrWasChanged: false };\n }\n\n const configContent = await fs.promises.readFile(configPath, 'utf-8');\n const filename = chalk.cyan(configFilename);\n\n const mod = parseModule(configContent);\n\n if (hasReactRouterSentryContent(mod.$ast as t.Program)) {\n clack.log.info(`${filename} already contains sentryOnBuildEnd.`);\n return { ssrWasChanged: false };\n }\n\n mod.imports.$add({\n from: '@sentry/react-router',\n imported: 'sentryOnBuildEnd',\n local: 'sentryOnBuildEnd',\n });\n\n const { success, ssrWasChanged } = addSentryBuildEndToReactRouterConfig(\n mod.$ast as t.Program,\n );\n\n if (!success) {\n throw new Error('Failed to modify React Router config structure');\n }\n\n const code = preserveTrailingNewline(\n configContent,\n generateCode(mod.$ast).code,\n );\n await fs.promises.writeFile(configPath, code);\n\n return { ssrWasChanged };\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { ProxifiedModule } from 'magicast';
|
|
2
|
-
export declare function instrumentServerEntry(serverEntryPath: string): Promise<void>;
|
|
2
|
+
export declare function instrumentServerEntry(serverEntryPath: string, useInstrumentationAPI?: boolean): Promise<void>;
|
|
3
3
|
export declare function instrumentHandleRequest(originalEntryServerMod: ProxifiedModule<any>): void;
|
|
4
4
|
export declare function instrumentHandleError(originalEntryServerMod: ProxifiedModule<any>): void;
|
|
@@ -42,7 +42,7 @@ const magicast_1 = require("magicast");
|
|
|
42
42
|
const debug_1 = require("../../utils/debug");
|
|
43
43
|
const ast_utils_1 = require("../../utils/ast-utils");
|
|
44
44
|
const utils_1 = require("./utils");
|
|
45
|
-
async function instrumentServerEntry(serverEntryPath) {
|
|
45
|
+
async function instrumentServerEntry(serverEntryPath, useInstrumentationAPI = false) {
|
|
46
46
|
const serverEntryAst = await (0, magicast_1.loadFile)(serverEntryPath);
|
|
47
47
|
if (!(0, ast_utils_1.hasSentryContent)(serverEntryAst.$ast)) {
|
|
48
48
|
serverEntryAst.imports.$add({
|
|
@@ -53,9 +53,40 @@ async function instrumentServerEntry(serverEntryPath) {
|
|
|
53
53
|
}
|
|
54
54
|
instrumentHandleError(serverEntryAst);
|
|
55
55
|
instrumentHandleRequest(serverEntryAst);
|
|
56
|
+
if (useInstrumentationAPI) {
|
|
57
|
+
instrumentInstrumentations(serverEntryAst);
|
|
58
|
+
}
|
|
56
59
|
await (0, magicast_1.writeFile)(serverEntryAst.$ast, serverEntryPath);
|
|
57
60
|
}
|
|
58
61
|
exports.instrumentServerEntry = instrumentServerEntry;
|
|
62
|
+
function instrumentInstrumentations(originalEntryServerMod) {
|
|
63
|
+
const originalEntryServerModAST = originalEntryServerMod.$ast;
|
|
64
|
+
const hasInstrumentations = originalEntryServerModAST.body.some((node) => {
|
|
65
|
+
if (node.type !== 'ExportNamedDeclaration' ||
|
|
66
|
+
node.declaration?.type !== 'VariableDeclaration') {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
const declarations = node.declaration.declarations;
|
|
70
|
+
if (!declarations || declarations.length === 0) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
const firstDeclaration = declarations[0];
|
|
74
|
+
if (!firstDeclaration || firstDeclaration.type !== 'VariableDeclarator') {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
const id = firstDeclaration.id;
|
|
78
|
+
return (id &&
|
|
79
|
+
id.type === 'Identifier' &&
|
|
80
|
+
(id.name === 'instrumentations' ||
|
|
81
|
+
id.name === 'unstable_instrumentations'));
|
|
82
|
+
});
|
|
83
|
+
if (hasInstrumentations) {
|
|
84
|
+
(0, debug_1.debug)('instrumentations export already exists, skipping adding it again');
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const instrumentationsExport = recast.parse(`export const instrumentations = [Sentry.createSentryServerInstrumentation()];`).program.body[0];
|
|
88
|
+
originalEntryServerModAST.body.push(instrumentationsExport);
|
|
89
|
+
}
|
|
59
90
|
function instrumentHandleRequest(originalEntryServerMod) {
|
|
60
91
|
const originalEntryServerModAST = originalEntryServerMod.$ast;
|
|
61
92
|
const defaultServerEntryExport = originalEntryServerModAST.body.find((node) => {
|
|
@@ -148,10 +179,15 @@ function instrumentHandleRequest(originalEntryServerMod) {
|
|
|
148
179
|
this.traverse(path);
|
|
149
180
|
},
|
|
150
181
|
});
|
|
151
|
-
// Replace the existing default export with the
|
|
152
|
-
originalEntryServerModAST.body.splice(defaultExportIndex, 1,
|
|
182
|
+
// Replace the existing default export with the unwrapped function declaration
|
|
153
183
|
// @ts-expect-error - declaration works here because the AST is proxified by magicast
|
|
154
|
-
defaultExportNode.declaration
|
|
184
|
+
const funcDeclaration = defaultExportNode.declaration;
|
|
185
|
+
// Make non-async functions async so the return type matches wrapSentryHandleRequest
|
|
186
|
+
if (funcDeclaration.type === 'FunctionDeclaration' &&
|
|
187
|
+
!funcDeclaration.async) {
|
|
188
|
+
funcDeclaration.async = true;
|
|
189
|
+
}
|
|
190
|
+
originalEntryServerModAST.body.splice(defaultExportIndex, 1, funcDeclaration);
|
|
155
191
|
// Adding our wrapped export
|
|
156
192
|
originalEntryServerModAST.body.push(recast.types.builders.exportDefaultDeclaration(recast.types.builders.callExpression(recast.types.builders.memberExpression(recast.types.builders.identifier('Sentry'), recast.types.builders.identifier('wrapSentryHandleRequest')), [recast.types.builders.identifier('handleRequest')])));
|
|
157
193
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-entry.js","sourceRoot":"","sources":["../../../../src/react-router/codemods/server-entry.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-argument */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-return */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport type { ProxifiedModule } from 'magicast';\n\nimport * as recast from 'recast';\nimport type { namedTypes as t } from 'ast-types';\n\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\nimport chalk from 'chalk';\n\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport { generateCode, loadFile, writeFile } from 'magicast';\nimport { debug } from '../../utils/debug';\nimport {\n hasSentryContent,\n safeCalleeIdentifierMatch,\n safeGetIdentifierName,\n} from '../../utils/ast-utils';\nimport { getAfterImportsInsertionIndex } from './utils';\n\nexport async function instrumentServerEntry(\n serverEntryPath: string,\n): Promise<void> {\n const serverEntryAst = await loadFile(serverEntryPath);\n\n if (!hasSentryContent(serverEntryAst.$ast as t.Program)) {\n serverEntryAst.imports.$add({\n from: '@sentry/react-router',\n imported: '*',\n local: 'Sentry',\n });\n }\n\n instrumentHandleError(serverEntryAst);\n instrumentHandleRequest(serverEntryAst);\n\n await writeFile(serverEntryAst.$ast, serverEntryPath);\n}\n\nexport function instrumentHandleRequest(\n originalEntryServerMod: ProxifiedModule<any>,\n): void {\n const originalEntryServerModAST = originalEntryServerMod.$ast as t.Program;\n\n const defaultServerEntryExport = originalEntryServerModAST.body.find(\n (node) => {\n return node.type === 'ExportDefaultDeclaration';\n },\n );\n\n if (!defaultServerEntryExport) {\n clack.log.warn(\n `Could not find function ${chalk.cyan(\n 'handleRequest',\n )} in your server entry file. Creating one for you.`,\n );\n\n let foundServerRouterImport = false;\n let foundRenderToPipeableStreamImport = false;\n let foundCreateReadableStreamFromReadableImport = false;\n\n originalEntryServerMod.imports.$items.forEach((item) => {\n if (item.imported === 'ServerRouter' && item.from === 'react-router') {\n foundServerRouterImport = true;\n }\n if (\n item.imported === 'renderToPipeableStream' &&\n item.from === 'react-dom/server'\n ) {\n foundRenderToPipeableStreamImport = true;\n }\n if (\n item.imported === 'createReadableStreamFromReadable' &&\n item.from === '@react-router/node'\n ) {\n foundCreateReadableStreamFromReadableImport = true;\n }\n });\n\n if (!foundServerRouterImport) {\n originalEntryServerMod.imports.$add({\n from: 'react-router',\n imported: 'ServerRouter',\n local: 'ServerRouter',\n });\n }\n\n if (!foundRenderToPipeableStreamImport) {\n originalEntryServerMod.imports.$add({\n from: 'react-dom/server',\n imported: 'renderToPipeableStream',\n local: 'renderToPipeableStream',\n });\n }\n\n if (!foundCreateReadableStreamFromReadableImport) {\n originalEntryServerMod.imports.$add({\n from: '@react-router/node',\n imported: 'createReadableStreamFromReadable',\n local: 'createReadableStreamFromReadable',\n });\n }\n\n const implementation =\n recast.parse(`const handleRequest = Sentry.createSentryHandleRequest({\n ServerRouter,\n renderToPipeableStream,\n createReadableStreamFromReadable,\n})`).program.body[0];\n\n try {\n originalEntryServerModAST.body.splice(\n getAfterImportsInsertionIndex(originalEntryServerModAST),\n 0,\n implementation,\n );\n\n originalEntryServerModAST.body.push({\n type: 'ExportDefaultDeclaration',\n declaration: {\n type: 'Identifier',\n name: 'handleRequest',\n },\n });\n } catch (error) {\n debug('Failed to insert handleRequest implementation:', error);\n throw new Error(\n 'Could not automatically instrument handleRequest. Please add it manually.',\n );\n }\n } else if (\n defaultServerEntryExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(defaultServerEntryExport).code.includes(\n 'wrapSentryHandleRequest',\n )\n ) {\n debug('wrapSentryHandleRequest is already used, skipping wrapping again');\n clack.log.info(\n 'Sentry handleRequest wrapper already detected, skipping instrumentation.',\n );\n } else {\n let defaultExportNode: recast.types.namedTypes.ExportDefaultDeclaration | null =\n null;\n const defaultExportIndex = originalEntryServerModAST.body.findIndex(\n (node) => {\n const found = node.type === 'ExportDefaultDeclaration';\n\n if (found) {\n defaultExportNode = node;\n }\n\n return found;\n },\n );\n\n if (defaultExportIndex !== -1 && defaultExportNode !== null) {\n recast.visit(defaultExportNode, {\n visitCallExpression(path) {\n if (\n safeCalleeIdentifierMatch(path.value.callee, 'pipe') &&\n path.value.arguments.length &&\n path.value.arguments[0].type === 'Identifier' &&\n safeGetIdentifierName(path.value.arguments[0]) === 'body'\n ) {\n const wrapped = recast.types.builders.callExpression(\n recast.types.builders.memberExpression(\n recast.types.builders.identifier('Sentry'),\n recast.types.builders.identifier('getMetaTagTransformer'),\n ),\n [path.value.arguments[0]],\n );\n\n path.value.arguments[0] = wrapped;\n }\n\n this.traverse(path);\n },\n });\n\n // Replace the existing default export with the wrapped one\n originalEntryServerModAST.body.splice(\n defaultExportIndex,\n 1,\n // @ts-expect-error - declaration works here because the AST is proxified by magicast\n defaultExportNode.declaration,\n );\n\n // Adding our wrapped export\n originalEntryServerModAST.body.push(\n recast.types.builders.exportDefaultDeclaration(\n recast.types.builders.callExpression(\n recast.types.builders.memberExpression(\n recast.types.builders.identifier('Sentry'),\n recast.types.builders.identifier('wrapSentryHandleRequest'),\n ),\n [recast.types.builders.identifier('handleRequest')],\n ),\n ),\n );\n }\n }\n}\n\nexport function instrumentHandleError(\n originalEntryServerMod: ProxifiedModule<any>,\n): void {\n const originalEntryServerModAST = originalEntryServerMod.$ast as t.Program;\n\n const handleErrorFunctionExport = originalEntryServerModAST.body.find(\n (node) => {\n return (\n node.type === 'ExportNamedDeclaration' &&\n node.declaration?.type === 'FunctionDeclaration' &&\n node.declaration.id?.name === 'handleError'\n );\n },\n );\n\n const handleErrorFunctionVariableDeclarationExport =\n originalEntryServerModAST.body.find((node) => {\n if (\n node.type !== 'ExportNamedDeclaration' ||\n node.declaration?.type !== 'VariableDeclaration'\n ) {\n return false;\n }\n\n const declarations = node.declaration.declarations;\n if (!declarations || declarations.length === 0) {\n return false;\n }\n\n const firstDeclaration = declarations[0];\n if (!firstDeclaration || firstDeclaration.type !== 'VariableDeclarator') {\n return false;\n }\n\n const id = firstDeclaration.id;\n return id && id.type === 'Identifier' && id.name === 'handleError';\n });\n\n if (\n !handleErrorFunctionExport &&\n !handleErrorFunctionVariableDeclarationExport\n ) {\n clack.log.warn(\n `Could not find function ${chalk.cyan(\n 'handleError',\n )} in your server entry file. Creating one for you.`,\n );\n\n const implementation =\n recast.parse(`const handleError = Sentry.createSentryHandleError({\n logErrors: false\n})`).program.body[0];\n\n originalEntryServerModAST.body.splice(\n getAfterImportsInsertionIndex(originalEntryServerModAST),\n 0,\n recast.types.builders.exportNamedDeclaration(implementation),\n );\n } else if (\n (handleErrorFunctionExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(handleErrorFunctionExport).code.includes(\n 'captureException',\n )) ||\n (handleErrorFunctionVariableDeclarationExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(handleErrorFunctionVariableDeclarationExport).code.includes(\n 'captureException',\n ))\n ) {\n debug(\n 'Found captureException inside handleError, skipping adding it again',\n );\n } else if (\n (handleErrorFunctionExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(handleErrorFunctionExport).code.includes(\n 'createSentryHandleError',\n )) ||\n (handleErrorFunctionVariableDeclarationExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(handleErrorFunctionVariableDeclarationExport).code.includes(\n 'createSentryHandleError',\n ))\n ) {\n debug('createSentryHandleError is already used, skipping adding it again');\n } else if (handleErrorFunctionExport) {\n // Create the Sentry captureException call as an IfStatement\n const sentryCall = recast.parse(`if (!request.signal.aborted) {\n Sentry.captureException(error);\n}`).program.body[0];\n\n // Safely insert the Sentry call at the beginning of the handleError function body\n // @ts-expect-error - declaration works here because the AST is proxified by magicast\n const declaration = handleErrorFunctionExport.declaration;\n if (\n declaration &&\n declaration.body &&\n declaration.body.body &&\n Array.isArray(declaration.body.body)\n ) {\n declaration.body.body.unshift(sentryCall);\n } else {\n debug(\n 'Cannot safely access handleError function body, skipping instrumentation',\n );\n }\n } else if (handleErrorFunctionVariableDeclarationExport) {\n // Create the Sentry captureException call as an IfStatement\n const sentryCall = recast.parse(`if (!request.signal.aborted) {\n Sentry.captureException(error);\n}`).program.body[0];\n\n // Safe access to existing handle error implementation with proper null checks\n // We know this is ExportNamedDeclaration with VariableDeclaration from the earlier find\n const exportDeclaration =\n handleErrorFunctionVariableDeclarationExport as any;\n if (\n !exportDeclaration.declaration ||\n exportDeclaration.declaration.type !== 'VariableDeclaration' ||\n !exportDeclaration.declaration.declarations ||\n exportDeclaration.declaration.declarations.length === 0\n ) {\n debug(\n 'Cannot safely access handleError variable declaration, skipping instrumentation',\n );\n return;\n }\n\n const firstDeclaration = exportDeclaration.declaration.declarations[0];\n if (\n !firstDeclaration ||\n firstDeclaration.type !== 'VariableDeclarator' ||\n !firstDeclaration.init\n ) {\n debug(\n 'Cannot safely access handleError variable declarator init, skipping instrumentation',\n );\n return;\n }\n\n const existingHandleErrorImplementation = firstDeclaration.init;\n const existingParams = existingHandleErrorImplementation.params;\n const existingBody = existingHandleErrorImplementation.body;\n\n const requestParam = {\n ...recast.types.builders.property(\n 'init',\n recast.types.builders.identifier('request'), // key\n recast.types.builders.identifier('request'), // value\n ),\n shorthand: true,\n };\n // Add error and {request} parameters to handleError function if not present\n // When none of the parameters exist\n if (existingParams.length === 0) {\n existingParams.push(\n recast.types.builders.identifier('error'),\n recast.types.builders.objectPattern([requestParam]),\n );\n // When only error parameter exists\n } else if (existingParams.length === 1) {\n existingParams.push(recast.types.builders.objectPattern([requestParam]));\n // When both parameters exist, but request is not destructured\n } else if (\n existingParams[1].type === 'ObjectPattern' &&\n !existingParams[1].properties.some(\n (prop: t.ObjectProperty) =>\n safeGetIdentifierName(prop.key) === 'request',\n )\n ) {\n existingParams[1].properties.push(requestParam);\n }\n\n // Add the Sentry call to the function body\n existingBody.body.push(sentryCall);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"server-entry.js","sourceRoot":"","sources":["../../../../src/react-router/codemods/server-entry.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-argument */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-return */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport type { ProxifiedModule } from 'magicast';\n\nimport * as recast from 'recast';\nimport type { namedTypes as t } from 'ast-types';\n\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\nimport chalk from 'chalk';\n\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport { generateCode, loadFile, writeFile } from 'magicast';\nimport { debug } from '../../utils/debug';\nimport {\n hasSentryContent,\n safeCalleeIdentifierMatch,\n safeGetIdentifierName,\n} from '../../utils/ast-utils';\nimport { getAfterImportsInsertionIndex } from './utils';\n\nexport async function instrumentServerEntry(\n serverEntryPath: string,\n useInstrumentationAPI = false,\n): Promise<void> {\n const serverEntryAst = await loadFile(serverEntryPath);\n\n if (!hasSentryContent(serverEntryAst.$ast as t.Program)) {\n serverEntryAst.imports.$add({\n from: '@sentry/react-router',\n imported: '*',\n local: 'Sentry',\n });\n }\n\n instrumentHandleError(serverEntryAst);\n instrumentHandleRequest(serverEntryAst);\n\n if (useInstrumentationAPI) {\n instrumentInstrumentations(serverEntryAst);\n }\n\n await writeFile(serverEntryAst.$ast, serverEntryPath);\n}\n\nfunction instrumentInstrumentations(\n originalEntryServerMod: ProxifiedModule<any>,\n): void {\n const originalEntryServerModAST = originalEntryServerMod.$ast as t.Program;\n\n const hasInstrumentations = originalEntryServerModAST.body.some((node) => {\n if (\n node.type !== 'ExportNamedDeclaration' ||\n node.declaration?.type !== 'VariableDeclaration'\n ) {\n return false;\n }\n\n const declarations = node.declaration.declarations;\n if (!declarations || declarations.length === 0) {\n return false;\n }\n\n const firstDeclaration = declarations[0];\n if (!firstDeclaration || firstDeclaration.type !== 'VariableDeclarator') {\n return false;\n }\n\n const id = firstDeclaration.id;\n return (\n id &&\n id.type === 'Identifier' &&\n (id.name === 'instrumentations' ||\n id.name === 'unstable_instrumentations')\n );\n });\n\n if (hasInstrumentations) {\n debug('instrumentations export already exists, skipping adding it again');\n return;\n }\n\n const instrumentationsExport = recast.parse(\n `export const instrumentations = [Sentry.createSentryServerInstrumentation()];`,\n ).program.body[0];\n\n originalEntryServerModAST.body.push(instrumentationsExport);\n}\n\nexport function instrumentHandleRequest(\n originalEntryServerMod: ProxifiedModule<any>,\n): void {\n const originalEntryServerModAST = originalEntryServerMod.$ast as t.Program;\n\n const defaultServerEntryExport = originalEntryServerModAST.body.find(\n (node) => {\n return node.type === 'ExportDefaultDeclaration';\n },\n );\n\n if (!defaultServerEntryExport) {\n clack.log.warn(\n `Could not find function ${chalk.cyan(\n 'handleRequest',\n )} in your server entry file. Creating one for you.`,\n );\n\n let foundServerRouterImport = false;\n let foundRenderToPipeableStreamImport = false;\n let foundCreateReadableStreamFromReadableImport = false;\n\n originalEntryServerMod.imports.$items.forEach((item) => {\n if (item.imported === 'ServerRouter' && item.from === 'react-router') {\n foundServerRouterImport = true;\n }\n if (\n item.imported === 'renderToPipeableStream' &&\n item.from === 'react-dom/server'\n ) {\n foundRenderToPipeableStreamImport = true;\n }\n if (\n item.imported === 'createReadableStreamFromReadable' &&\n item.from === '@react-router/node'\n ) {\n foundCreateReadableStreamFromReadableImport = true;\n }\n });\n\n if (!foundServerRouterImport) {\n originalEntryServerMod.imports.$add({\n from: 'react-router',\n imported: 'ServerRouter',\n local: 'ServerRouter',\n });\n }\n\n if (!foundRenderToPipeableStreamImport) {\n originalEntryServerMod.imports.$add({\n from: 'react-dom/server',\n imported: 'renderToPipeableStream',\n local: 'renderToPipeableStream',\n });\n }\n\n if (!foundCreateReadableStreamFromReadableImport) {\n originalEntryServerMod.imports.$add({\n from: '@react-router/node',\n imported: 'createReadableStreamFromReadable',\n local: 'createReadableStreamFromReadable',\n });\n }\n\n const implementation =\n recast.parse(`const handleRequest = Sentry.createSentryHandleRequest({\n ServerRouter,\n renderToPipeableStream,\n createReadableStreamFromReadable,\n})`).program.body[0];\n\n try {\n originalEntryServerModAST.body.splice(\n getAfterImportsInsertionIndex(originalEntryServerModAST),\n 0,\n implementation,\n );\n\n originalEntryServerModAST.body.push({\n type: 'ExportDefaultDeclaration',\n declaration: {\n type: 'Identifier',\n name: 'handleRequest',\n },\n });\n } catch (error) {\n debug('Failed to insert handleRequest implementation:', error);\n throw new Error(\n 'Could not automatically instrument handleRequest. Please add it manually.',\n );\n }\n } else if (\n defaultServerEntryExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(defaultServerEntryExport).code.includes(\n 'wrapSentryHandleRequest',\n )\n ) {\n debug('wrapSentryHandleRequest is already used, skipping wrapping again');\n clack.log.info(\n 'Sentry handleRequest wrapper already detected, skipping instrumentation.',\n );\n } else {\n let defaultExportNode: recast.types.namedTypes.ExportDefaultDeclaration | null =\n null;\n const defaultExportIndex = originalEntryServerModAST.body.findIndex(\n (node) => {\n const found = node.type === 'ExportDefaultDeclaration';\n\n if (found) {\n defaultExportNode = node;\n }\n\n return found;\n },\n );\n\n if (defaultExportIndex !== -1 && defaultExportNode !== null) {\n recast.visit(defaultExportNode, {\n visitCallExpression(path) {\n if (\n safeCalleeIdentifierMatch(path.value.callee, 'pipe') &&\n path.value.arguments.length &&\n path.value.arguments[0].type === 'Identifier' &&\n safeGetIdentifierName(path.value.arguments[0]) === 'body'\n ) {\n const wrapped = recast.types.builders.callExpression(\n recast.types.builders.memberExpression(\n recast.types.builders.identifier('Sentry'),\n recast.types.builders.identifier('getMetaTagTransformer'),\n ),\n [path.value.arguments[0]],\n );\n\n path.value.arguments[0] = wrapped;\n }\n\n this.traverse(path);\n },\n });\n\n // Replace the existing default export with the unwrapped function declaration\n // @ts-expect-error - declaration works here because the AST is proxified by magicast\n const funcDeclaration = defaultExportNode.declaration;\n // Make non-async functions async so the return type matches wrapSentryHandleRequest\n if (\n funcDeclaration.type === 'FunctionDeclaration' &&\n !funcDeclaration.async\n ) {\n funcDeclaration.async = true;\n }\n originalEntryServerModAST.body.splice(\n defaultExportIndex,\n 1,\n funcDeclaration,\n );\n\n // Adding our wrapped export\n originalEntryServerModAST.body.push(\n recast.types.builders.exportDefaultDeclaration(\n recast.types.builders.callExpression(\n recast.types.builders.memberExpression(\n recast.types.builders.identifier('Sentry'),\n recast.types.builders.identifier('wrapSentryHandleRequest'),\n ),\n [recast.types.builders.identifier('handleRequest')],\n ),\n ),\n );\n }\n }\n}\n\nexport function instrumentHandleError(\n originalEntryServerMod: ProxifiedModule<any>,\n): void {\n const originalEntryServerModAST = originalEntryServerMod.$ast as t.Program;\n\n const handleErrorFunctionExport = originalEntryServerModAST.body.find(\n (node) => {\n return (\n node.type === 'ExportNamedDeclaration' &&\n node.declaration?.type === 'FunctionDeclaration' &&\n node.declaration.id?.name === 'handleError'\n );\n },\n );\n\n const handleErrorFunctionVariableDeclarationExport =\n originalEntryServerModAST.body.find((node) => {\n if (\n node.type !== 'ExportNamedDeclaration' ||\n node.declaration?.type !== 'VariableDeclaration'\n ) {\n return false;\n }\n\n const declarations = node.declaration.declarations;\n if (!declarations || declarations.length === 0) {\n return false;\n }\n\n const firstDeclaration = declarations[0];\n if (!firstDeclaration || firstDeclaration.type !== 'VariableDeclarator') {\n return false;\n }\n\n const id = firstDeclaration.id;\n return id && id.type === 'Identifier' && id.name === 'handleError';\n });\n\n if (\n !handleErrorFunctionExport &&\n !handleErrorFunctionVariableDeclarationExport\n ) {\n clack.log.warn(\n `Could not find function ${chalk.cyan(\n 'handleError',\n )} in your server entry file. Creating one for you.`,\n );\n\n const implementation =\n recast.parse(`const handleError = Sentry.createSentryHandleError({\n logErrors: false\n})`).program.body[0];\n\n originalEntryServerModAST.body.splice(\n getAfterImportsInsertionIndex(originalEntryServerModAST),\n 0,\n recast.types.builders.exportNamedDeclaration(implementation),\n );\n } else if (\n (handleErrorFunctionExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(handleErrorFunctionExport).code.includes(\n 'captureException',\n )) ||\n (handleErrorFunctionVariableDeclarationExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(handleErrorFunctionVariableDeclarationExport).code.includes(\n 'captureException',\n ))\n ) {\n debug(\n 'Found captureException inside handleError, skipping adding it again',\n );\n } else if (\n (handleErrorFunctionExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(handleErrorFunctionExport).code.includes(\n 'createSentryHandleError',\n )) ||\n (handleErrorFunctionVariableDeclarationExport &&\n // @ts-expect-error - StatementKind works here because the AST is proxified by magicast\n generateCode(handleErrorFunctionVariableDeclarationExport).code.includes(\n 'createSentryHandleError',\n ))\n ) {\n debug('createSentryHandleError is already used, skipping adding it again');\n } else if (handleErrorFunctionExport) {\n // Create the Sentry captureException call as an IfStatement\n const sentryCall = recast.parse(`if (!request.signal.aborted) {\n Sentry.captureException(error);\n}`).program.body[0];\n\n // Safely insert the Sentry call at the beginning of the handleError function body\n // @ts-expect-error - declaration works here because the AST is proxified by magicast\n const declaration = handleErrorFunctionExport.declaration;\n if (\n declaration &&\n declaration.body &&\n declaration.body.body &&\n Array.isArray(declaration.body.body)\n ) {\n declaration.body.body.unshift(sentryCall);\n } else {\n debug(\n 'Cannot safely access handleError function body, skipping instrumentation',\n );\n }\n } else if (handleErrorFunctionVariableDeclarationExport) {\n // Create the Sentry captureException call as an IfStatement\n const sentryCall = recast.parse(`if (!request.signal.aborted) {\n Sentry.captureException(error);\n}`).program.body[0];\n\n // Safe access to existing handle error implementation with proper null checks\n // We know this is ExportNamedDeclaration with VariableDeclaration from the earlier find\n const exportDeclaration =\n handleErrorFunctionVariableDeclarationExport as any;\n if (\n !exportDeclaration.declaration ||\n exportDeclaration.declaration.type !== 'VariableDeclaration' ||\n !exportDeclaration.declaration.declarations ||\n exportDeclaration.declaration.declarations.length === 0\n ) {\n debug(\n 'Cannot safely access handleError variable declaration, skipping instrumentation',\n );\n return;\n }\n\n const firstDeclaration = exportDeclaration.declaration.declarations[0];\n if (\n !firstDeclaration ||\n firstDeclaration.type !== 'VariableDeclarator' ||\n !firstDeclaration.init\n ) {\n debug(\n 'Cannot safely access handleError variable declarator init, skipping instrumentation',\n );\n return;\n }\n\n const existingHandleErrorImplementation = firstDeclaration.init;\n const existingParams = existingHandleErrorImplementation.params;\n const existingBody = existingHandleErrorImplementation.body;\n\n const requestParam = {\n ...recast.types.builders.property(\n 'init',\n recast.types.builders.identifier('request'), // key\n recast.types.builders.identifier('request'), // value\n ),\n shorthand: true,\n };\n // Add error and {request} parameters to handleError function if not present\n // When none of the parameters exist\n if (existingParams.length === 0) {\n existingParams.push(\n recast.types.builders.identifier('error'),\n recast.types.builders.objectPattern([requestParam]),\n );\n // When only error parameter exists\n } else if (existingParams.length === 1) {\n existingParams.push(recast.types.builders.objectPattern([requestParam]));\n // When both parameters exist, but request is not destructured\n } else if (\n existingParams[1].type === 'ObjectPattern' &&\n !existingParams[1].properties.some(\n (prop: t.ObjectProperty) =>\n safeGetIdentifierName(prop.key) === 'request',\n )\n ) {\n existingParams[1].properties.push(requestParam);\n }\n\n // Add the Sentry call to the function body\n existingBody.body.push(sentryCall);\n }\n}\n"]}
|
|
@@ -36,6 +36,7 @@ const magicast_1 = require("magicast");
|
|
|
36
36
|
const prompts_1 = __importDefault(require("@clack/prompts"));
|
|
37
37
|
const chalk_1 = __importDefault(require("chalk"));
|
|
38
38
|
const ast_utils_1 = require("../../utils/ast-utils");
|
|
39
|
+
const debug_1 = require("../../utils/debug");
|
|
39
40
|
/**
|
|
40
41
|
* Extracts ObjectExpression from function body.
|
|
41
42
|
* Handles both arrow functions with object returns and block statements with explicit returns.
|
|
@@ -85,6 +86,48 @@ function createSentryPluginCall(orgSlug, projectSlug) {
|
|
|
85
86
|
b.identifier('config'),
|
|
86
87
|
]);
|
|
87
88
|
}
|
|
89
|
+
/** Adds @sentry/react-router to optimizeDeps.exclude to prevent 504 errors during dev. */
|
|
90
|
+
function addOptimizeDepsExclude(configObj) {
|
|
91
|
+
const b = recast.types.builders;
|
|
92
|
+
const optimizeDeps = (0, ast_utils_1.findProperty)(configObj, 'optimizeDeps');
|
|
93
|
+
const optimizeDepsObj = optimizeDeps?.type === 'ObjectProperty' &&
|
|
94
|
+
optimizeDeps.value?.type === 'ObjectExpression'
|
|
95
|
+
? optimizeDeps.value
|
|
96
|
+
: null;
|
|
97
|
+
let targetDepsObj;
|
|
98
|
+
if (!optimizeDepsObj) {
|
|
99
|
+
if (optimizeDeps) {
|
|
100
|
+
(0, debug_1.debug)('optimizeDeps is not a static object, skipping exclude');
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
targetDepsObj = b.objectExpression([]);
|
|
104
|
+
configObj.properties.push(b.objectProperty(b.identifier('optimizeDeps'), targetDepsObj));
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
targetDepsObj = optimizeDepsObj;
|
|
108
|
+
}
|
|
109
|
+
const excludeProp = (0, ast_utils_1.findProperty)(targetDepsObj, 'exclude');
|
|
110
|
+
const excludeArr = excludeProp?.type === 'ObjectProperty' &&
|
|
111
|
+
excludeProp.value?.type === 'ArrayExpression'
|
|
112
|
+
? excludeProp.value
|
|
113
|
+
: null;
|
|
114
|
+
let targetArr;
|
|
115
|
+
if (!excludeArr) {
|
|
116
|
+
if (excludeProp) {
|
|
117
|
+
(0, debug_1.debug)('optimizeDeps.exclude is not a static array, skipping');
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
targetArr = b.arrayExpression([]);
|
|
121
|
+
targetDepsObj.properties.push(b.objectProperty(b.identifier('exclude'), targetArr));
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
targetArr = excludeArr;
|
|
125
|
+
}
|
|
126
|
+
const isAlreadyExcluded = targetArr.elements.some((el) => el?.type === 'StringLiteral' && el.value === '@sentry/react-router');
|
|
127
|
+
if (!isAlreadyExcluded) {
|
|
128
|
+
targetArr.elements.push(b.stringLiteral('@sentry/react-router'));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
88
131
|
function addReactRouterPluginToViteConfig(program, orgSlug, projectSlug) {
|
|
89
132
|
const b = recast.types.builders;
|
|
90
133
|
let wasConverted = false;
|
|
@@ -135,6 +178,8 @@ function addReactRouterPluginToViteConfig(program, orgSlug, projectSlug) {
|
|
|
135
178
|
else {
|
|
136
179
|
return { success: false, wasConverted };
|
|
137
180
|
}
|
|
181
|
+
// Prevent 504 "Outdated Optimize Dep" errors in dev (https://github.com/vitejs/vite/issues/13506)
|
|
182
|
+
addOptimizeDepsExclude(configObj);
|
|
138
183
|
return { success: true, wasConverted };
|
|
139
184
|
}
|
|
140
185
|
exports.addReactRouterPluginToViteConfig = addReactRouterPluginToViteConfig;
|
|
@@ -161,7 +206,7 @@ async function instrumentViteConfig(orgSlug, projectSlug) {
|
|
|
161
206
|
if (!success) {
|
|
162
207
|
throw new Error('Failed to modify Vite config structure');
|
|
163
208
|
}
|
|
164
|
-
const code = (0, magicast_1.generateCode)(mod.$ast).code;
|
|
209
|
+
const code = (0, ast_utils_1.preserveTrailingNewline)(configContent, (0, magicast_1.generateCode)(mod.$ast).code);
|
|
165
210
|
await fs.promises.writeFile(configPath, code);
|
|
166
211
|
return { wasConverted };
|
|
167
212
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.js","sourceRoot":"","sources":["../../../../src/react-router/codemods/vite.ts"],"names":[],"mappings":"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","sourcesContent":["import type { namedTypes as t } from 'ast-types';\nimport * as recast from 'recast';\nimport * as path from 'path';\nimport * as fs from 'fs';\n\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport { parseModule, generateCode } from 'magicast';\n\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\nimport chalk from 'chalk';\n\nimport { hasSentryContent, findProperty } from '../../utils/ast-utils';\n\n/**\n * Extracts ObjectExpression from function body.\n * Handles both arrow functions with object returns and block statements with explicit returns.\n *\n * - Arrow with object-return: (config) => ({ ... })\n * - Arrow with block: (config) => { return { ... }; }\n * - Function with block: function(config) { return { ... }; }\n *\n * @param body - The function body to extract from\n * @returns The ObjectExpression if found, undefined otherwise\n */\nfunction extractFromFunctionBody(\n body: t.Expression | t.BlockStatement,\n): t.ObjectExpression | undefined {\n if (body.type === 'ObjectExpression') {\n return body as t.ObjectExpression;\n }\n\n if (body.type === 'BlockStatement') {\n const blockBody = body as t.BlockStatement;\n const returnStatement = blockBody.body.find(\n (stmt: t.Statement): stmt is t.ReturnStatement =>\n stmt.type === 'ReturnStatement',\n );\n\n return returnStatement?.argument?.type === 'ObjectExpression'\n ? returnStatement.argument\n : undefined;\n }\n\n return undefined;\n}\n\n/**\n * Creates the sentryReactRouter Vite plugin call expression.\n *\n * Generates AST for:\n * sentryReactRouter({\n * org: \"...\",\n * project: \"...\",\n * authToken: process.env.SENTRY_AUTH_TOKEN\n * }, config)\n *\n * @param orgSlug - Sentry organization slug\n * @param projectSlug - Sentry project slug\n * @returns CallExpression node for the Sentry Vite plugin\n */\nfunction createSentryPluginCall(\n orgSlug: string,\n projectSlug: string,\n): t.CallExpression {\n const b = recast.types.builders;\n return b.callExpression(b.identifier('sentryReactRouter'), [\n b.objectExpression([\n b.objectProperty(b.identifier('org'), b.stringLiteral(orgSlug)),\n b.objectProperty(b.identifier('project'), b.stringLiteral(projectSlug)),\n b.objectProperty(\n b.identifier('authToken'),\n b.memberExpression(\n b.memberExpression(b.identifier('process'), b.identifier('env')),\n b.identifier('SENTRY_AUTH_TOKEN'),\n ),\n ),\n ]),\n b.identifier('config'),\n ]);\n}\n\nexport function addReactRouterPluginToViteConfig(\n program: t.Program,\n orgSlug: string,\n projectSlug: string,\n): { success: boolean; wasConverted: boolean } {\n const b = recast.types.builders;\n let wasConverted = false;\n\n const defaultExport = program.body.find(\n (node) => node.type === 'ExportDefaultDeclaration',\n ) as t.ExportDefaultDeclaration | undefined;\n\n if (!defaultExport) {\n return { success: false, wasConverted: false };\n }\n\n let configObj: t.ObjectExpression | undefined;\n let defineConfigCall: t.CallExpression | undefined;\n\n if (\n defaultExport.declaration.type === 'CallExpression' &&\n defaultExport.declaration.callee.type === 'Identifier' &&\n defaultExport.declaration.callee.name === 'defineConfig'\n ) {\n defineConfigCall = defaultExport.declaration;\n\n // Early exit if not single argument\n if (defineConfigCall.arguments.length !== 1) {\n return { success: false, wasConverted: false };\n }\n\n const arg = defineConfigCall.arguments[0];\n\n if (arg.type === 'ObjectExpression') {\n configObj = arg;\n // Convert to function form\n const arrowFunction = b.arrowFunctionExpression(\n [b.identifier('config')],\n configObj,\n );\n defineConfigCall.arguments[0] = arrowFunction;\n wasConverted = true;\n } else if (\n arg.type === 'ArrowFunctionExpression' ||\n arg.type === 'FunctionExpression'\n ) {\n configObj = extractFromFunctionBody(arg.body);\n }\n }\n\n if (!configObj) {\n return { success: false, wasConverted };\n }\n\n const pluginsProp = findProperty(configObj, 'plugins');\n const sentryPluginCall = createSentryPluginCall(orgSlug, projectSlug);\n\n if (!pluginsProp) {\n configObj.properties.push(\n b.objectProperty(\n b.identifier('plugins'),\n b.arrayExpression([sentryPluginCall]),\n ),\n );\n } else if (\n pluginsProp.value.type === 'ArrayExpression' &&\n pluginsProp.type === 'ObjectProperty'\n ) {\n const arrayExpr = pluginsProp.value;\n // Defensive: ensure elements array exists\n if (!arrayExpr.elements) {\n arrayExpr.elements = [];\n }\n arrayExpr.elements.push(sentryPluginCall);\n } else {\n return { success: false, wasConverted };\n }\n\n return { success: true, wasConverted };\n}\n\nexport async function instrumentViteConfig(\n orgSlug: string,\n projectSlug: string,\n): Promise<{ wasConverted: boolean }> {\n const configPath = fs.existsSync(path.join(process.cwd(), 'vite.config.ts'))\n ? path.join(process.cwd(), 'vite.config.ts')\n : path.join(process.cwd(), 'vite.config.js');\n\n if (!fs.existsSync(configPath)) {\n throw new Error('Could not find vite.config.ts or vite.config.js');\n }\n\n const configContent = await fs.promises.readFile(configPath, 'utf-8');\n const filename = chalk.cyan(path.basename(configPath));\n\n const mod = parseModule(configContent);\n\n if (hasSentryContent(mod.$ast as t.Program)) {\n clack.log.info(`${filename} already contains sentryReactRouter plugin.`);\n return { wasConverted: false };\n }\n\n mod.imports.$add({\n from: '@sentry/react-router',\n imported: 'sentryReactRouter',\n local: 'sentryReactRouter',\n });\n\n const { success, wasConverted } = addReactRouterPluginToViteConfig(\n mod.$ast as t.Program,\n orgSlug,\n projectSlug,\n );\n\n if (!success) {\n throw new Error('Failed to modify Vite config structure');\n }\n\n const code = generateCode(mod.$ast).code;\n await fs.promises.writeFile(configPath, code);\n\n return { wasConverted };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"vite.js","sourceRoot":"","sources":["../../../../src/react-router/codemods/vite.ts"],"names":[],"mappings":"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","sourcesContent":["import type { namedTypes as t } from 'ast-types';\nimport * as recast from 'recast';\nimport * as path from 'path';\nimport * as fs from 'fs';\n\n// @ts-expect-error - magicast is ESM and TS complains about that. It works though\nimport { parseModule, generateCode } from 'magicast';\n\n// @ts-expect-error - clack is ESM and TS complains about that. It works though\nimport clack from '@clack/prompts';\nimport chalk from 'chalk';\n\nimport {\n hasSentryContent,\n findProperty,\n preserveTrailingNewline,\n} from '../../utils/ast-utils';\nimport { debug } from '../../utils/debug';\n\n/**\n * Extracts ObjectExpression from function body.\n * Handles both arrow functions with object returns and block statements with explicit returns.\n *\n * - Arrow with object-return: (config) => ({ ... })\n * - Arrow with block: (config) => { return { ... }; }\n * - Function with block: function(config) { return { ... }; }\n *\n * @param body - The function body to extract from\n * @returns The ObjectExpression if found, undefined otherwise\n */\nfunction extractFromFunctionBody(\n body: t.Expression | t.BlockStatement,\n): t.ObjectExpression | undefined {\n if (body.type === 'ObjectExpression') {\n return body as t.ObjectExpression;\n }\n\n if (body.type === 'BlockStatement') {\n const blockBody = body as t.BlockStatement;\n const returnStatement = blockBody.body.find(\n (stmt: t.Statement): stmt is t.ReturnStatement =>\n stmt.type === 'ReturnStatement',\n );\n\n return returnStatement?.argument?.type === 'ObjectExpression'\n ? returnStatement.argument\n : undefined;\n }\n\n return undefined;\n}\n\n/**\n * Creates the sentryReactRouter Vite plugin call expression.\n *\n * Generates AST for:\n * sentryReactRouter({\n * org: \"...\",\n * project: \"...\",\n * authToken: process.env.SENTRY_AUTH_TOKEN\n * }, config)\n *\n * @param orgSlug - Sentry organization slug\n * @param projectSlug - Sentry project slug\n * @returns CallExpression node for the Sentry Vite plugin\n */\nfunction createSentryPluginCall(\n orgSlug: string,\n projectSlug: string,\n): t.CallExpression {\n const b = recast.types.builders;\n return b.callExpression(b.identifier('sentryReactRouter'), [\n b.objectExpression([\n b.objectProperty(b.identifier('org'), b.stringLiteral(orgSlug)),\n b.objectProperty(b.identifier('project'), b.stringLiteral(projectSlug)),\n b.objectProperty(\n b.identifier('authToken'),\n b.memberExpression(\n b.memberExpression(b.identifier('process'), b.identifier('env')),\n b.identifier('SENTRY_AUTH_TOKEN'),\n ),\n ),\n ]),\n b.identifier('config'),\n ]);\n}\n\n/** Adds @sentry/react-router to optimizeDeps.exclude to prevent 504 errors during dev. */\nfunction addOptimizeDepsExclude(configObj: t.ObjectExpression): void {\n const b = recast.types.builders;\n\n const optimizeDeps = findProperty(configObj, 'optimizeDeps');\n const optimizeDepsObj =\n optimizeDeps?.type === 'ObjectProperty' &&\n optimizeDeps.value?.type === 'ObjectExpression'\n ? optimizeDeps.value\n : null;\n\n let targetDepsObj: t.ObjectExpression;\n if (!optimizeDepsObj) {\n if (optimizeDeps) {\n debug('optimizeDeps is not a static object, skipping exclude');\n return;\n }\n targetDepsObj = b.objectExpression([]);\n configObj.properties.push(\n b.objectProperty(b.identifier('optimizeDeps'), targetDepsObj),\n );\n } else {\n targetDepsObj = optimizeDepsObj;\n }\n\n const excludeProp = findProperty(targetDepsObj, 'exclude');\n const excludeArr =\n excludeProp?.type === 'ObjectProperty' &&\n excludeProp.value?.type === 'ArrayExpression'\n ? excludeProp.value\n : null;\n\n let targetArr: t.ArrayExpression;\n if (!excludeArr) {\n if (excludeProp) {\n debug('optimizeDeps.exclude is not a static array, skipping');\n return;\n }\n targetArr = b.arrayExpression([]);\n targetDepsObj.properties.push(\n b.objectProperty(b.identifier('exclude'), targetArr),\n );\n } else {\n targetArr = excludeArr;\n }\n\n const isAlreadyExcluded = targetArr.elements.some(\n (el) => el?.type === 'StringLiteral' && el.value === '@sentry/react-router',\n );\n if (!isAlreadyExcluded) {\n targetArr.elements.push(b.stringLiteral('@sentry/react-router'));\n }\n}\n\nexport function addReactRouterPluginToViteConfig(\n program: t.Program,\n orgSlug: string,\n projectSlug: string,\n): { success: boolean; wasConverted: boolean } {\n const b = recast.types.builders;\n let wasConverted = false;\n\n const defaultExport = program.body.find(\n (node) => node.type === 'ExportDefaultDeclaration',\n ) as t.ExportDefaultDeclaration | undefined;\n\n if (!defaultExport) {\n return { success: false, wasConverted: false };\n }\n\n let configObj: t.ObjectExpression | undefined;\n let defineConfigCall: t.CallExpression | undefined;\n\n if (\n defaultExport.declaration.type === 'CallExpression' &&\n defaultExport.declaration.callee.type === 'Identifier' &&\n defaultExport.declaration.callee.name === 'defineConfig'\n ) {\n defineConfigCall = defaultExport.declaration;\n\n // Early exit if not single argument\n if (defineConfigCall.arguments.length !== 1) {\n return { success: false, wasConverted: false };\n }\n\n const arg = defineConfigCall.arguments[0];\n\n if (arg.type === 'ObjectExpression') {\n configObj = arg;\n // Convert to function form\n const arrowFunction = b.arrowFunctionExpression(\n [b.identifier('config')],\n configObj,\n );\n defineConfigCall.arguments[0] = arrowFunction;\n wasConverted = true;\n } else if (\n arg.type === 'ArrowFunctionExpression' ||\n arg.type === 'FunctionExpression'\n ) {\n configObj = extractFromFunctionBody(arg.body);\n }\n }\n\n if (!configObj) {\n return { success: false, wasConverted };\n }\n\n const pluginsProp = findProperty(configObj, 'plugins');\n const sentryPluginCall = createSentryPluginCall(orgSlug, projectSlug);\n\n if (!pluginsProp) {\n configObj.properties.push(\n b.objectProperty(\n b.identifier('plugins'),\n b.arrayExpression([sentryPluginCall]),\n ),\n );\n } else if (\n pluginsProp.value.type === 'ArrayExpression' &&\n pluginsProp.type === 'ObjectProperty'\n ) {\n const arrayExpr = pluginsProp.value;\n // Defensive: ensure elements array exists\n if (!arrayExpr.elements) {\n arrayExpr.elements = [];\n }\n arrayExpr.elements.push(sentryPluginCall);\n } else {\n return { success: false, wasConverted };\n }\n\n // Prevent 504 \"Outdated Optimize Dep\" errors in dev (https://github.com/vitejs/vite/issues/13506)\n addOptimizeDepsExclude(configObj);\n\n return { success: true, wasConverted };\n}\n\nexport async function instrumentViteConfig(\n orgSlug: string,\n projectSlug: string,\n): Promise<{ wasConverted: boolean }> {\n const configPath = fs.existsSync(path.join(process.cwd(), 'vite.config.ts'))\n ? path.join(process.cwd(), 'vite.config.ts')\n : path.join(process.cwd(), 'vite.config.js');\n\n if (!fs.existsSync(configPath)) {\n throw new Error('Could not find vite.config.ts or vite.config.js');\n }\n\n const configContent = await fs.promises.readFile(configPath, 'utf-8');\n const filename = chalk.cyan(path.basename(configPath));\n\n const mod = parseModule(configContent);\n\n if (hasSentryContent(mod.$ast as t.Program)) {\n clack.log.info(`${filename} already contains sentryReactRouter plugin.`);\n return { wasConverted: false };\n }\n\n mod.imports.$add({\n from: '@sentry/react-router',\n imported: 'sentryReactRouter',\n local: 'sentryReactRouter',\n });\n\n const { success, wasConverted } = addReactRouterPluginToViteConfig(\n mod.$ast as t.Program,\n orgSlug,\n projectSlug,\n );\n\n if (!success) {\n throw new Error('Failed to modify Vite config structure');\n }\n\n const code = preserveTrailingNewline(\n configContent,\n generateCode(mod.$ast).code,\n );\n await fs.promises.writeFile(configPath, code);\n\n return { wasConverted };\n}\n"]}
|
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
27
|
};
|
|
@@ -7,6 +30,7 @@ exports.runReactRouterWizard = void 0;
|
|
|
7
30
|
// @ts-expect-error - clack is ESM and TS complains about that. It works though
|
|
8
31
|
const prompts_1 = __importDefault(require("@clack/prompts"));
|
|
9
32
|
const chalk_1 = __importDefault(require("chalk"));
|
|
33
|
+
const Sentry = __importStar(require("@sentry/node"));
|
|
10
34
|
const telemetry_1 = require("../telemetry");
|
|
11
35
|
const clack_1 = require("../utils/clack");
|
|
12
36
|
const mcp_config_1 = require("../utils/clack/mcp-config");
|
|
@@ -75,6 +99,18 @@ async function runReactRouterWizardWithTelemetry(options) {
|
|
|
75
99
|
enabledHint: 'recommended for production debugging',
|
|
76
100
|
},
|
|
77
101
|
]);
|
|
102
|
+
// Only ask about Instrumentation API when Tracing is enabled, since it depends on it
|
|
103
|
+
let instrumentationAPISelected = false;
|
|
104
|
+
if (featureSelection.performance) {
|
|
105
|
+
const instrumentationAPISelection = await (0, clack_1.featureSelectionPrompt)([
|
|
106
|
+
{
|
|
107
|
+
id: 'instrumentationAPI',
|
|
108
|
+
prompt: `Do you want to use the ${chalk_1.default.bold('Instrumentation API')} for automatic tracing of loaders, actions, and middleware?`,
|
|
109
|
+
enabledHint: 'recommended',
|
|
110
|
+
},
|
|
111
|
+
]);
|
|
112
|
+
instrumentationAPISelected = instrumentationAPISelection.instrumentationAPI;
|
|
113
|
+
}
|
|
78
114
|
if (featureSelection.profiling) {
|
|
79
115
|
const profilingAlreadyInstalled = (0, package_json_1.hasPackageInstalled)('@sentry/profiling-node', packageJson);
|
|
80
116
|
await (0, clack_1.installPackage)({
|
|
@@ -94,14 +130,35 @@ Please create your entry files manually using React Router v7 commands.`);
|
|
|
94
130
|
(0, debug_1.debug)(e);
|
|
95
131
|
}
|
|
96
132
|
});
|
|
133
|
+
Sentry.setTag('instrumentation-api-selected', instrumentationAPISelected);
|
|
134
|
+
let useInstrumentationAPI = instrumentationAPISelected;
|
|
135
|
+
if (useInstrumentationAPI && !(0, sdk_setup_1.supportsInstrumentationAPI)(packageJson)) {
|
|
136
|
+
Sentry.setTag('instrumentation-api-version-guard', true);
|
|
137
|
+
const detectedVersion = (0, sdk_setup_1.getReactRouterVersion)(packageJson) ?? 'unknown';
|
|
138
|
+
prompts_1.default.log.warn(`The Instrumentation API requires React Router ${chalk_1.default.cyan('>=7.15.0')} (detected ${chalk_1.default.cyan(detectedVersion)}). Your version does not meet this requirement.\n` +
|
|
139
|
+
`Continuing without the Instrumentation API. Please upgrade React Router to use this feature:\n` +
|
|
140
|
+
chalk_1.default.dim('https://docs.sentry.io/platforms/javascript/guides/react-router/'));
|
|
141
|
+
useInstrumentationAPI = false;
|
|
142
|
+
}
|
|
143
|
+
Sentry.setTag('use-instrumentation-api', useInstrumentationAPI);
|
|
144
|
+
let useOnError = true;
|
|
145
|
+
if (!(0, sdk_setup_1.supportsOnError)(packageJson)) {
|
|
146
|
+
Sentry.setTag('on-error-version-guard', true);
|
|
147
|
+
const detectedVersion = (0, sdk_setup_1.getReactRouterVersion)(packageJson) ?? 'unknown';
|
|
148
|
+
prompts_1.default.log.warn(`The ${chalk_1.default.cyan('onError')} prop on HydratedRouter requires React Router ${chalk_1.default.cyan('>=7.11.0')} (detected ${chalk_1.default.cyan(detectedVersion)}).\n` +
|
|
149
|
+
`Skipping automatic error handler setup. Please upgrade React Router and follow the manual setup guide:\n` +
|
|
150
|
+
chalk_1.default.dim('https://docs.sentry.io/platforms/javascript/guides/react-router/'));
|
|
151
|
+
useOnError = false;
|
|
152
|
+
}
|
|
153
|
+
Sentry.setTag('use-on-error', useOnError);
|
|
97
154
|
await (0, telemetry_1.traceStep)('Initialize Sentry on client entry', async () => {
|
|
98
155
|
try {
|
|
99
|
-
await (0, sdk_setup_1.initializeSentryOnEntryClient)(selectedProject.keys[0].dsn.public, featureSelection.performance, featureSelection.replay, featureSelection.logs, typeScriptDetected);
|
|
156
|
+
await (0, sdk_setup_1.initializeSentryOnEntryClient)(selectedProject.keys[0].dsn.public, featureSelection.performance, featureSelection.replay, featureSelection.logs, typeScriptDetected, useInstrumentationAPI, useOnError);
|
|
100
157
|
}
|
|
101
158
|
catch (e) {
|
|
102
159
|
prompts_1.default.log.warn(`Could not initialize Sentry on client entry automatically.`);
|
|
103
160
|
const clientEntryFilename = `entry.client.${typeScriptDetected ? 'tsx' : 'jsx'}`;
|
|
104
|
-
const manualClientContent = (0, templates_1.getManualClientEntryContent)(selectedProject.keys[0].dsn.public, featureSelection.performance, featureSelection.replay, featureSelection.logs);
|
|
161
|
+
const manualClientContent = (0, templates_1.getManualClientEntryContent)(selectedProject.keys[0].dsn.public, featureSelection.performance, featureSelection.replay, featureSelection.logs, useInstrumentationAPI, useOnError);
|
|
105
162
|
await (0, clack_1.showCopyPasteInstructions)({
|
|
106
163
|
filename: clientEntryFilename,
|
|
107
164
|
codeSnippet: manualClientContent,
|
|
@@ -110,30 +167,14 @@ Please create your entry files manually using React Router v7 commands.`);
|
|
|
110
167
|
(0, debug_1.debug)(e);
|
|
111
168
|
}
|
|
112
169
|
});
|
|
113
|
-
await (0, telemetry_1.traceStep)('Instrument root route', async () => {
|
|
114
|
-
try {
|
|
115
|
-
await (0, sdk_setup_1.instrumentRootRoute)(typeScriptDetected);
|
|
116
|
-
}
|
|
117
|
-
catch (e) {
|
|
118
|
-
prompts_1.default.log.warn(`Could not instrument root route automatically.`);
|
|
119
|
-
const rootFilename = `app/root.${typeScriptDetected ? 'tsx' : 'jsx'}`;
|
|
120
|
-
const manualRootContent = (0, templates_1.getManualRootContent)(typeScriptDetected);
|
|
121
|
-
await (0, clack_1.showCopyPasteInstructions)({
|
|
122
|
-
filename: rootFilename,
|
|
123
|
-
codeSnippet: manualRootContent,
|
|
124
|
-
hint: 'This adds error boundary integration to capture exceptions in your React Router app',
|
|
125
|
-
});
|
|
126
|
-
(0, debug_1.debug)(e);
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
170
|
await (0, telemetry_1.traceStep)('Instrument server entry', async () => {
|
|
130
171
|
try {
|
|
131
|
-
await (0, sdk_setup_1.instrumentSentryOnEntryServer)(typeScriptDetected);
|
|
172
|
+
await (0, sdk_setup_1.instrumentSentryOnEntryServer)(typeScriptDetected, useInstrumentationAPI);
|
|
132
173
|
}
|
|
133
174
|
catch (e) {
|
|
134
175
|
prompts_1.default.log.warn(`Could not initialize Sentry on server entry automatically.`);
|
|
135
176
|
const serverEntryFilename = `entry.server.${typeScriptDetected ? 'tsx' : 'jsx'}`;
|
|
136
|
-
const manualServerContent = (0, templates_1.getManualServerEntryContent)();
|
|
177
|
+
const manualServerContent = (0, templates_1.getManualServerEntryContent)(useInstrumentationAPI);
|
|
137
178
|
await (0, clack_1.showCopyPasteInstructions)({
|
|
138
179
|
filename: serverEntryFilename,
|
|
139
180
|
codeSnippet: manualServerContent,
|
|
@@ -174,7 +215,7 @@ Please create your entry files manually using React Router v7 commands.`);
|
|
|
174
215
|
return unchanged(`{
|
|
175
216
|
scripts: {
|
|
176
217
|
${minus('"start": "react-router dev"')}
|
|
177
|
-
${plus('"start": "NODE_OPTIONS=\'--import ./instrument.server.mjs\' react-router-serve ./build/server/index.js"')}
|
|
218
|
+
${plus('"start": "NODE_ENV=production NODE_OPTIONS=\'--import ./instrument.server.mjs\' react-router-serve ./build/server/index.js"')}
|
|
178
219
|
${minus('"dev": "react-router dev"')}
|
|
179
220
|
${plus('"dev": "NODE_OPTIONS=\'--import ./instrument.server.mjs\' react-router dev"')}
|
|
180
221
|
},
|