@sentry/wizard 6.12.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 +15 -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/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 +6 -3
- package/dist/e2e-tests/tests/pnpm-workspace.test.js.map +1 -1
- package/dist/e2e-tests/tests/react-router-instrumentation-api.test.js +4 -4
- package/dist/e2e-tests/tests/react-router-instrumentation-api.test.js.map +1 -1
- package/dist/e2e-tests/tests/react-router.test.js +3 -6
- 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 +6 -3
- 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/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/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-router/codemods/client.entry.d.ts +1 -1
- package/dist/src/react-router/codemods/client.entry.js +93 -52
- package/dist/src/react-router/codemods/client.entry.js.map +1 -1
- package/dist/src/react-router/codemods/server-entry.js +8 -7
- package/dist/src/react-router/codemods/server-entry.js.map +1 -1
- package/dist/src/react-router/react-router-wizard.js +13 -19
- package/dist/src/react-router/react-router-wizard.js.map +1 -1
- package/dist/src/react-router/sdk-setup.d.ts +2 -2
- package/dist/src/react-router/sdk-setup.js +16 -15
- package/dist/src/react-router/sdk-setup.js.map +1 -1
- package/dist/src/react-router/templates.d.ts +1 -3
- package/dist/src/react-router/templates.js +24 -92
- 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/sveltekit/sdk-setup/setup.js +17 -4
- package/dist/src/sveltekit/sdk-setup/setup.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/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/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/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-router/codemods/client-entry.test.js +15 -11
- package/dist/test/react-router/codemods/client-entry.test.js.map +1 -1
- package/dist/test/react-router/codemods/server-entry.test.js +21 -8
- package/dist/test/react-router/codemods/server-entry.test.js.map +1 -1
- package/dist/test/react-router/sdk-setup.test.js +46 -10
- package/dist/test/react-router/sdk-setup.test.js.map +1 -1
- package/dist/test/react-router/templates.test.js +26 -64
- 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/sveltekit/templates.test.js +78 -27
- package/dist/test/sveltekit/templates.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 -170
- package/dist/src/react-router/codemods/root.js.map +0 -1
- package/dist/test/react-router/codemods/root.test.js +0 -182
- package/dist/test/react-router/codemods/root.test.js.map +0 -1
- /package/dist/test/{react-router/codemods/root.test.d.ts → apple/lookup-xcode-project.test.d.ts} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/nextjs/templates.ts"],"names":[],"mappings":"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","sourcesContent":["import chalk from 'chalk';\nimport { makeCodeSnippet } from '../utils/clack';\n\ntype WithSentryConfigOptions = {\n orgSlug: string;\n projectSlug: string;\n selfHosted: boolean;\n sentryUrl: string;\n tunnelRoute: boolean;\n};\n\nexport function getWithSentryConfigOptionsTemplate({\n orgSlug,\n projectSlug,\n selfHosted,\n tunnelRoute,\n sentryUrl,\n}: WithSentryConfigOptions): string {\n return `{\n // For all available options, see:\n // https://www.npmjs.com/package/@sentry/webpack-plugin#options\n\n org: \"${orgSlug}\",\n project: \"${projectSlug}\",${\n selfHosted ? `\\n sentryUrl: \"${sentryUrl}\",` : ''\n }\n\n // Only print logs for uploading source maps in CI\n silent: !process.env.CI,\n\n // For all available options, see:\n // https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/\n\n // Upload a larger set of source maps for prettier stack traces (increases build time)\n widenClientFileUpload: true,\n\n // ${\n tunnelRoute ? 'Route' : 'Uncomment to route'\n } browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.\n // This can increase your server load as well as your hosting bill.\n // Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-\n // side errors will fail.\n ${tunnelRoute ? '' : '// '}tunnelRoute: \"/monitoring\",\n\n webpack: {\n // Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.)\n // See the following for more information:\n // https://docs.sentry.io/product/crons/\n // https://vercel.com/docs/cron-jobs\n automaticVercelMonitors: true,\n\n // Tree-shaking options for reducing bundle size\n treeshake: {\n // Automatically tree-shake Sentry logger statements to reduce bundle size\n removeDebugLogging: true,\n },\n },\n}`;\n}\n\nexport function getNextjsConfigCjsTemplate(\n withSentryConfigOptionsTemplate: string,\n): string {\n return `const { withSentryConfig } = require(\"@sentry/nextjs\");\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {};\n\nmodule.exports = withSentryConfig(nextConfig, ${withSentryConfigOptionsTemplate});\n`;\n}\n\nexport function getNextjsConfigMjsTemplate(\n withSentryConfigOptionsTemplate: string,\n): string {\n return `import { withSentryConfig } from \"@sentry/nextjs\";\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {};\n\nexport default withSentryConfig(nextConfig, ${withSentryConfigOptionsTemplate});\n`;\n}\n\nexport function getNextjsConfigCjsAppendix(\n withSentryConfigOptionsTemplate: string,\n): string {\n return `\n\n// Injected content via Sentry wizard below\n\nconst { withSentryConfig } = require(\"@sentry/nextjs\");\n\nmodule.exports = withSentryConfig(module.exports, ${withSentryConfigOptionsTemplate});\n`;\n}\n\nexport function getNextjsConfigEsmCopyPasteSnippet(\n withSentryConfigOptionsTemplate: string,\n): string {\n return `\n\n// next.config.mjs\nimport { withSentryConfig } from \"@sentry/nextjs\";\n\nexport default withSentryConfig(yourNextConfig, ${withSentryConfigOptionsTemplate});\n`;\n}\n\nfunction getClientIntegrationsSnippet(features: { replay: boolean }) {\n if (features.replay) {\n return `\n\n // Add optional integrations for additional features\n integrations: [Sentry.replayIntegration()],`;\n }\n\n return '';\n}\n\nfunction getSpotlightOption(spotlight: boolean): string {\n if (!spotlight) {\n return '';\n }\n\n return `\n\n // Spotlight enabled for local development (https://spotlightjs.com)\n spotlight: true,`;\n}\n\nexport function getSentryServersideConfigContents(\n dsn: string,\n config: 'server' | 'edge',\n selectedFeaturesMap: {\n replay: boolean;\n performance: boolean;\n logs: boolean;\n },\n spotlight = false,\n): string {\n let primer = '';\n if (config === 'server') {\n primer = `// This file configures the initialization of Sentry on the server.\n// The config you add here will be used whenever the server handles a request.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;\n } else if (config === 'edge') {\n primer = `// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on).\n// The config you add here will be used whenever one of the edge features is loaded.\n// Note that this config is unrelated to the Vercel Edge Runtime and is also required when running locally.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;\n }\n\n let performanceOptions = '';\n if (selectedFeaturesMap.performance) {\n performanceOptions += `\n\n // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.\n tracesSampleRate: 1,`;\n }\n\n let logsOptions = '';\n if (selectedFeaturesMap.logs) {\n logsOptions += `\n\n // Enable logs to be sent to Sentry\n enableLogs: true,`;\n }\n\n const spotlightOptions = getSpotlightOption(spotlight);\n\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n return `${primer}\n\nimport * as Sentry from \"@sentry/nextjs\";\n\nSentry.init({\n dsn: \"${dsn}\",${performanceOptions}${logsOptions}\n\n // Enable sending user PII (Personally Identifiable Information)\n // https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/options/#sendDefaultPii\n sendDefaultPii: true,${spotlightOptions}\n});\n`;\n}\n\nexport function getInstrumentationClientFileContents(\n dsn: string,\n selectedFeaturesMap: {\n replay: boolean;\n performance: boolean;\n logs: boolean;\n },\n spotlight = false,\n): string {\n const integrationsOptions = getClientIntegrationsSnippet({\n replay: selectedFeaturesMap.replay,\n });\n\n let replayOptions = '';\n\n if (selectedFeaturesMap.replay) {\n replayOptions += `\n\n // Define how likely Replay events are sampled.\n // This sets the sample rate to be 10%. You may want this to be 100% while\n // in development and sample at a lower rate in production\n replaysSessionSampleRate: 0.1,\n\n // Define how likely Replay events are sampled when an error occurs.\n replaysOnErrorSampleRate: 1.0,`;\n }\n\n let performanceOptions = '';\n if (selectedFeaturesMap.performance) {\n performanceOptions += `\n\n // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.\n tracesSampleRate: 1,`;\n }\n\n let logsOptions = '';\n if (selectedFeaturesMap.logs) {\n logsOptions += `\n // Enable logs to be sent to Sentry\n enableLogs: true,`;\n }\n\n const spotlightOptions = getSpotlightOption(spotlight);\n\n return `// This file configures the initialization of Sentry on the client.\n// The added config here will be used whenever a users loads a page in their browser.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/\n\nimport * as Sentry from \"@sentry/nextjs\";\n\nSentry.init({\n dsn: \"${dsn}\",${integrationsOptions}${performanceOptions}${logsOptions}${replayOptions}\n\n // Enable sending user PII (Personally Identifiable Information)\n // https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/options/#sendDefaultPii\n sendDefaultPii: true,${spotlightOptions}\n});\n\nexport const onRouterTransitionStart = Sentry.captureRouterTransitionStart;\n`;\n}\n\nexport function getSentryExamplePageContents(options: {\n selfHosted: boolean;\n sentryUrl: string;\n orgSlug: string;\n projectId: string;\n useClient: boolean;\n isTypeScript?: boolean;\n logsEnabled?: boolean;\n}): string {\n const issuesPageLink = options.selfHosted\n ? `${options.sentryUrl}organizations/${options.orgSlug}/issues/?project=${options.projectId}`\n : `https://${options.orgSlug}.sentry.io/issues/?project=${options.projectId}`;\n\n const loggerPageLoad = options.logsEnabled\n ? `\n Sentry.logger.info(\"Sentry example page loaded\");`\n : '';\n\n const loggerUserAction = options.logsEnabled\n ? `\n Sentry.logger.info(\"User clicked the button, throwing a sample error\");`\n : '';\n\n return `${\n options.useClient ? '\"use client\";\\n\\n' : ''\n }import * as Sentry from \"@sentry/nextjs\";\nimport Head from \"next/head\";\nimport { useEffect, useState } from \"react\";\n\nclass SentryExampleFrontendError extends Error {\n constructor(message${options.isTypeScript ? ': string | undefined' : ''}) {\n super(message);\n this.name = \"SentryExampleFrontendError\";\n }\n}\n\nexport default function Page() {\n const [hasSentError, setHasSentError] = useState(false);\n const [isConnected, setIsConnected] = useState(true);\n\n useEffect(() => {${loggerPageLoad}\n async function checkConnectivity() {\n const result = await Sentry.diagnoseSdkConnectivity();\n setIsConnected(result !== \"sentry-unreachable\");\n }\n checkConnectivity();\n }, []);\n\n return (\n <div>\n <Head>\n <title>sentry-example-page</title>\n <meta name=\"description\" content=\"Test Sentry for your Next.js app!\" />\n </Head>\n\n <main>\n <div className=\"flex-spacer\" />\n <svg\n height=\"40\"\n width=\"40\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n role=\"img\"\n aria-label=\"Sentry logo\"\n >\n <path\n d=\"M21.85 2.995a3.698 3.698 0 0 1 1.353 1.354l16.303 28.278a3.703 3.703 0 0 1-1.354 5.053 3.694 3.694 0 0 1-1.848.496h-3.828a31.149 31.149 0 0 0 0-3.09h3.815a.61.61 0 0 0 .537-.917L20.523 5.893a.61.61 0 0 0-1.057 0l-3.739 6.494a28.948 28.948 0 0 1 9.63 10.453 28.988 28.988 0 0 1 3.499 13.78v1.542h-9.852v-1.544a19.106 19.106 0 0 0-2.182-8.85 19.08 19.08 0 0 0-6.032-6.829l-1.85 3.208a15.377 15.377 0 0 1 6.382 12.484v1.542H3.696A3.694 3.694 0 0 1 0 34.473c0-.648.17-1.286.494-1.849l2.33-4.074a8.562 8.562 0 0 1 2.689 1.536L3.158 34.17a.611.611 0 0 0 .538.917h8.448a12.481 12.481 0 0 0-6.037-9.09l-1.344-.772 4.908-8.545 1.344.77a22.16 22.16 0 0 1 7.705 7.444 22.193 22.193 0 0 1 3.316 10.193h3.699a25.892 25.892 0 0 0-3.811-12.033 25.856 25.856 0 0 0-9.046-8.796l-1.344-.772 5.269-9.136a3.698 3.698 0 0 1 3.2-1.849c.648 0 1.285.17 1.847.495Z\"\n fill=\"currentcolor\"\n />\n </svg>\n <h1>sentry-example-page</h1>\n\n <p className=\"description\">\n Click the button below, and view the sample error on the Sentry{\" \"}\n <a\n target=\"_blank\"\n rel=\"noopener\"\n href=\"${issuesPageLink}\"\n >\n Issues Page\n </a>\n . For more details about setting up Sentry,{\" \"}\n <a\n target=\"_blank\"\n rel=\"noopener\"\n href=\"https://docs.sentry.io/platforms/javascript/guides/nextjs/\"\n >\n read our docs\n </a>\n .\n </p>\n\n <button\n type=\"button\"\n onClick={async () => {${loggerUserAction}\n await Sentry.startSpan(\n {\n name: \"Example Frontend/Backend Span\",\n op: \"test\",\n },\n async () => {\n const res = await fetch(\"/api/sentry-example-api\");\n if (!res.ok) {\n setHasSentError(true);\n }\n },\n );\n throw new SentryExampleFrontendError(\n \"This error is raised on the frontend of the example page.\",\n );\n }}\n disabled={!isConnected}\n >\n <span>Throw Sample Error</span>\n </button>\n\n {hasSentError ? (\n <p className=\"success\">Error sent to Sentry.</p>\n ) : !isConnected ? (\n <div className=\"connectivity-error\">\n <p>\n It looks like network requests to Sentry are being blocked, which\n will prevent errors from being captured. Try disabling your\n ad-blocker to complete the test.\n </p>\n </div>\n ) : (\n <div className=\"success_placeholder\" />\n )}\n\n <div className=\"flex-spacer\" />\n </main>\n\n <style>{\\`\n main {\n display: flex;\n min-height: 100vh;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n gap: 16px;\n padding: 16px;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n\n h1 {\n padding: 0px 4px;\n border-radius: 4px;\n background-color: rgba(24, 20, 35, 0.03);\n font-family: monospace;\n font-size: 20px;\n line-height: 1.2;\n }\n\n p {\n margin: 0;\n font-size: 20px;\n }\n\n a {\n color: #6341F0;\n text-decoration: underline;\n cursor: pointer;\n\n @media (prefers-color-scheme: dark) {\n color: #B3A1FF;\n }\n }\n\n button {\n border-radius: 8px;\n color: white;\n cursor: pointer;\n background-color: #553DB8;\n border: none;\n padding: 0;\n margin-top: 4px;\n\n & > span {\n display: inline-block;\n padding: 12px 16px;\n border-radius: inherit;\n font-size: 20px;\n font-weight: bold;\n line-height: 1;\n background-color: #7553FF;\n border: 1px solid #553DB8;\n transform: translateY(-4px);\n }\n\n &:hover > span {\n transform: translateY(-8px);\n }\n\n &:active > span {\n transform: translateY(0);\n }\n\n &:disabled {\n\t cursor: not-allowed;\n\t opacity: 0.6;\n\n\t & > span {\n\t transform: translateY(0);\n\t border: none\n\t }\n\t }\n }\n\n .description {\n text-align: center;\n color: #6E6C75;\n max-width: 500px;\n line-height: 1.5;\n font-size: 20px;\n\n @media (prefers-color-scheme: dark) {\n color: #A49FB5;\n }\n }\n\n .flex-spacer {\n flex: 1;\n }\n\n .success {\n padding: 12px 16px;\n border-radius: 8px;\n font-size: 20px;\n line-height: 1;\n background-color: #00F261;\n border: 1px solid #00BF4D;\n color: #181423;\n }\n\n .success_placeholder {\n height: 46px;\n }\n\n .connectivity-error {\n padding: 12px 16px;\n background-color: #E50045;\n border-radius: 8px;\n width: 500px;\n color: #FFFFFF;\n border: 1px solid #A80033;\n text-align: center;\n margin: 0;\n }\n\n .connectivity-error a {\n color: #FFFFFF;\n text-decoration: underline;\n }\n \\`}</style>\n </div>\n );\n}\n`;\n}\n\nexport function getSentryExamplePagesDirApiRoute({\n isTypeScript,\n logsEnabled,\n}: {\n isTypeScript: boolean;\n logsEnabled?: boolean;\n}) {\n const sentryImport = logsEnabled\n ? `import * as Sentry from \"@sentry/nextjs\";\n\n`\n : '';\n\n const loggerCall = logsEnabled\n ? ` Sentry.logger.info(\"Sentry example API called\");\n`\n : '';\n\n return `${sentryImport}// Custom error class for Sentry testing\nclass SentryExampleAPIError extends Error {\n constructor(message${isTypeScript ? ': string | undefined' : ''}) {\n super(message);\n this.name = \"SentryExampleAPIError\";\n }\n}\n// A faulty API route to test Sentry's error monitoring\nexport default function handler(_req, res) {\n${loggerCall}throw new SentryExampleAPIError(\"This error is raised on the backend called by the example page.\");\nres.status(200).json({ name: \"John Doe\" });\n}\n`;\n}\n\nexport function getSentryExampleAppDirApiRoute({\n isTypeScript,\n logsEnabled,\n}: {\n isTypeScript: boolean;\n logsEnabled?: boolean;\n}) {\n const sentryImport = logsEnabled\n ? `import * as Sentry from \"@sentry/nextjs\";\n`\n : '';\n\n const loggerCall = logsEnabled\n ? `\n Sentry.logger.info(\"Sentry example API called\");`\n : '';\n\n // Note: We intentionally don't have a return statement after throw - it would be unreachable code\n // We also don't import NextResponse since we don't use it (Biome noUnusedImports rule)\n return `${sentryImport}export const dynamic = \"force-dynamic\";\n\nclass SentryExampleAPIError extends Error {\n constructor(message${isTypeScript ? ': string | undefined' : ''}) {\n super(message);\n this.name = \"SentryExampleAPIError\";\n }\n}\n\n// A faulty API route to test Sentry's error monitoring\nexport function GET() {${loggerCall}\n throw new SentryExampleAPIError(\n \"This error is raised on the backend called by the example page.\",\n );\n}\n`;\n}\n\nexport function getSentryDefaultUnderscoreErrorPage() {\n return `import * as Sentry from \"@sentry/nextjs\";\nimport Error from \"next/error\";\n\nconst CustomErrorComponent = (props) => {\n return <Error statusCode={props.statusCode} />;\n};\n\nCustomErrorComponent.getInitialProps = async (contextData) => {\n // In case this is running in a serverless function, await this in order to give Sentry\n // time to send the error before the lambda exits\n await Sentry.captureUnderscoreErrorException(contextData);\n\n // This will contain the status code of the response\n return Error.getInitialProps(contextData);\n};\n\nexport default CustomErrorComponent;\n`;\n}\n\nexport function getSimpleUnderscoreErrorCopyPasteSnippet() {\n return `\n${chalk.green(`import * as Sentry from '@sentry/nextjs';`)}\n${chalk.green(`import Error from \"next/error\";`)}\n\n${chalk.dim(\n '// Replace \"YourCustomErrorComponent\" with your custom error component!',\n)}\nYourCustomErrorComponent.getInitialProps = async (${chalk.green(\n 'contextData',\n )}) => {\n ${chalk.green('await Sentry.captureUnderscoreErrorException(contextData);')}\n\n ${chalk.dim('// ...other getInitialProps code')}\n\n return Error.getInitialProps(contextData);\n};\n`;\n}\n\nexport function getGenerateMetadataSnippet(isTs: boolean) {\n return makeCodeSnippet(true, (unchanged, plus) => {\n return plus(`\n import * as Sentry from '@sentry/nextjs';\n ${isTs ? `import type { Metadata } from 'next';` : ''}\n\n ${unchanged(\n '// Add or edit your \"generateMetadata\" to include the Sentry trace data:',\n )}\n export function generateMetadata()${isTs ? ': Metadata' : ''} {\n return {\n // ... your existing metadata\n other: {\n ...Sentry.getTraceData()\n }\n };\n }\n`);\n });\n}\n\nexport function getFullUnderscoreErrorCopyPasteSnippet(isTs: boolean) {\n return `\nimport * as Sentry from '@sentry/nextjs';${\n isTs ? '\\nimport type { NextPageContext } from \"next\";' : ''\n }\nimport Error from \"next/error\";\n\n${chalk.dim(\n '// Replace \"YourCustomErrorComponent\" with your custom error component!',\n)}\nYourCustomErrorComponent.getInitialProps = async (contextData${\n isTs ? ': NextPageContext' : ''\n }) => {\n await Sentry.captureUnderscoreErrorException(contextData);\n\n return Error.getInitialProps(contextData);\n};\n`;\n}\n\nexport function getInstrumentationHookContent(\n instrumentationHookLocation: 'src' | 'root',\n) {\n return `import * as Sentry from \"@sentry/nextjs\";\n\nexport async function register() {\n if (process.env.NEXT_RUNTIME === \"nodejs\") {\n await import(\"${\n instrumentationHookLocation === 'root' ? '.' : '..'\n }/sentry.server.config\");\n }\n\n if (process.env.NEXT_RUNTIME === \"edge\") {\n await import(\"${\n instrumentationHookLocation === 'root' ? '.' : '..'\n }/sentry.edge.config\");\n }\n}\n\nexport const onRequestError = Sentry.captureRequestError;\n`;\n}\n\nexport function getInstrumentationHookCopyPasteSnippet(\n instrumentationHookLocation: 'src' | 'root',\n) {\n return makeCodeSnippet(true, (unchanged, plus) => {\n return unchanged(`${plus(\"import * as Sentry from '@sentry/nextjs';\")}\n\nexport ${plus('async')} function register() {\n ${plus(`if (process.env.NEXT_RUNTIME === 'nodejs') {\n await import('${\n instrumentationHookLocation === 'root' ? '.' : '..'\n }/sentry.server.config');\n }\n\n if (process.env.NEXT_RUNTIME === 'edge') {\n await import('${\n instrumentationHookLocation === 'root' ? '.' : '..'\n }/sentry.edge.config');\n }`)}\n}\n\n${plus('export const onRequestError = Sentry.captureRequestError;')}\n`);\n });\n}\n\nexport function getInstrumentationClientHookCopyPasteSnippet(\n dsn: string,\n selectedFeaturesMap: {\n replay: boolean;\n performance: boolean;\n logs: boolean;\n },\n spotlight = false,\n) {\n return makeCodeSnippet(true, (_unchanged, plus) => {\n return plus(\n getInstrumentationClientFileContents(dsn, selectedFeaturesMap, spotlight),\n );\n });\n}\n\nexport function getSentryDefaultGlobalErrorPage(isTs: boolean) {\n return isTs\n ? `\"use client\";\n\nimport * as Sentry from \"@sentry/nextjs\";\nimport NextError from \"next/error\";\nimport { useEffect } from \"react\";\n\nexport default function GlobalError({\n error,\n}: {\n error: Error & { digest?: string };\n}) {\n useEffect(() => {\n Sentry.captureException(error);\n }, [error]);\n\n return (\n <html lang=\"en\">\n <body>\n {/* \\`NextError\\` is the default Next.js error page component. Its type\n definition requires a \\`statusCode\\` prop. However, since the App Router\n does not expose status codes for errors, we simply pass 0 to render a\n generic error message. */}\n <NextError statusCode={0} />\n </body>\n </html>\n );\n}\n`\n : `\"use client\";\n\nimport * as Sentry from \"@sentry/nextjs\";\nimport NextError from \"next/error\";\nimport { useEffect } from \"react\";\n\nexport default function GlobalError({ error }) {\n useEffect(() => {\n Sentry.captureException(error);\n }, [error]);\n\n return (\n <html lang=\"en\">\n <body>\n {/* \\`NextError\\` is the default Next.js error page component. Its type\n definition requires a \\`statusCode\\` prop. However, since the App Router\n does not expose status codes for errors, we simply pass 0 to render a\n generic error message. */}\n <NextError statusCode={0} />\n </body>\n </html>\n );\n}\n`;\n}\n\nexport function getGlobalErrorCopyPasteSnippet(isTs: boolean) {\n if (isTs) {\n return `\"use client\";\n\n${chalk.green('import * as Sentry from \"@sentry/nextjs\";')}\n${chalk.green('import Error from \"next/error\";')}\n${chalk.green('import { useEffect } from \"react\";')}\n\nexport default function GlobalError(${chalk.green(\n '{ error }: { error: Error }',\n )}) {\n ${chalk.green(`useEffect(() => {\n Sentry.captureException(error);\n }, [error]);`)}\n\n return (\n <html>\n <body>\n {/* Your Error component here... */}\n </body>\n </html>\n );\n}\n`;\n }\n return `\"use client\";\n\n${chalk.green('import * as Sentry from \"@sentry/nextjs\";')}\n${chalk.green('import Error from \"next/error\";')}\n${chalk.green('import { useEffect } from \"react\";')}\n\nexport default function GlobalError(${chalk.green('{ error }')}) {\n ${chalk.green(`useEffect(() => {\n Sentry.captureException(error);\n }, [error]);`)}\n\n return (\n <html>\n <body>\n {/* Your Error component here... */}\n </body>\n </html>\n );\n}\n`;\n}\n\nexport const getRootLayout = (\n isTs: boolean,\n) => `// This file was generated by the Sentry wizard because we couldn't find a root layout file.\n// You can delete this file at any time.\n\nexport const metadata = {\n title: 'Sentry NextJS Example',\n description: 'Generated by Sentry',\n}\n\nexport default function RootLayout({\n children,\n}${\n isTs\n ? `: {\n children: React.ReactNode\n}`\n : ''\n}) {\n return (\n <html lang=\"en\">\n <body>{children}</body>\n </html>\n )\n}\n`;\n\nexport const getRootLayoutWithGenerateMetadata = (\n isTs: boolean,\n) => `// This file was generated by the Sentry wizard because we couldn't find a root layout file.\nimport * as Sentry from '@sentry/nextjs';\n${isTs ? `import type { Metadata } from 'next';` : ''}\n\nexport function generateMetadata()${isTs ? ': Metadata' : ''} {\n return {\n other: {\n ...Sentry.getTraceData(),\n }\n }\n};\n\nexport default function RootLayout({\n children,\n}${\n isTs\n ? `: {\n children: React.ReactNode\n}`\n : ''\n}) {\n return (\n <html lang=\"en\">\n <body>{children}</body>\n </html>\n )\n}\n`;\n"]}
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/nextjs/templates.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAC1B,0CAAiD;AAUjD,SAAgB,kCAAkC,CAAC,EACjD,OAAO,EACP,WAAW,EACX,UAAU,EACV,WAAW,EACX,SAAS,GACe;IACxB,OAAO;;;;UAIC,OAAO;cACH,WAAW,KACrB,UAAU,CAAC,CAAC,CAAC,mBAAmB,SAAS,IAAI,CAAC,CAAC,CAAC,EAClD;;;;;;;;;;;OAYE,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,oBAC1B;;;;IAIE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK;;;;;;;;;;;;;;;EAe1B,CAAC;AACH,CAAC;AA/CD,gFA+CC;AAED,SAAgB,0BAA0B,CACxC,+BAAuC;IAEvC,OAAO;;;;;gDAKuC,+BAA+B;CAC9E,CAAC;AACF,CAAC;AAVD,gEAUC;AAED,SAAgB,0BAA0B,CACxC,+BAAuC;IAEvC,OAAO;;;;;8CAKqC,+BAA+B;CAC5E,CAAC;AACF,CAAC;AAVD,gEAUC;AAED,SAAgB,0BAA0B,CACxC,+BAAuC;IAEvC,OAAO;;;;;;oDAM2C,+BAA+B;CAClF,CAAC;AACF,CAAC;AAXD,gEAWC;AAED,SAAgB,kCAAkC,CAChD,+BAAuC;IAEvC,OAAO;;;;;kDAKyC,+BAA+B;CAChF,CAAC;AACF,CAAC;AAVD,gFAUC;AAED,SAAS,4BAA4B,CAAC,QAA6B;IACjE,IAAI,QAAQ,CAAC,MAAM,EAAE;QACnB,OAAO;;;8CAGmC,CAAC;KAC5C;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,kBAAkB,CAAC,SAAkB;IAC5C,IAAI,CAAC,SAAS,EAAE;QACd,OAAO,EAAE,CAAC;KACX;IAED,OAAO;;;mBAGU,CAAC;AACpB,CAAC;AAED,SAAgB,iCAAiC,CAC/C,GAAW,EACX,MAAyB,EACzB,mBAIC,EACD,SAAS,GAAG,KAAK;IAEjB,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,MAAM,KAAK,QAAQ,EAAE;QACvB,MAAM,GAAG;;8DAEiD,CAAC;KAC5D;SAAM,IAAI,MAAM,KAAK,MAAM,EAAE;QAC5B,MAAM,GAAG;;;8DAGiD,CAAC;KAC5D;IAED,IAAI,kBAAkB,GAAG,EAAE,CAAC;IAC5B,IAAI,mBAAmB,CAAC,WAAW,EAAE;QACnC,kBAAkB,IAAI;;;uBAGH,CAAC;KACrB;IAED,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI,mBAAmB,CAAC,IAAI,EAAE;QAC5B,WAAW,IAAI;;;oBAGC,CAAC;KAClB;IAED,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAEvD,4EAA4E;IAC5E,OAAO,GAAG,MAAM;;;;;UAKR,GAAG,KAAK,kBAAkB,GAAG,WAAW;;;;;;;MAO5C,gBAAgB;;CAErB,CAAC;AACF,CAAC;AAxDD,8EAwDC;AAED,SAAgB,oCAAoC,CAClD,GAAW,EACX,mBAIC,EACD,SAAS,GAAG,KAAK;IAEjB,MAAM,mBAAmB,GAAG,4BAA4B,CAAC;QACvD,MAAM,EAAE,mBAAmB,CAAC,MAAM;KACnC,CAAC,CAAC;IAEH,IAAI,aAAa,GAAG,EAAE,CAAC;IAEvB,IAAI,mBAAmB,CAAC,MAAM,EAAE;QAC9B,aAAa,IAAI;;;;;;;;iCAQY,CAAC;KAC/B;IAED,IAAI,kBAAkB,GAAG,EAAE,CAAC;IAC5B,IAAI,mBAAmB,CAAC,WAAW,EAAE;QACnC,kBAAkB,IAAI;;;uBAGH,CAAC;KACrB;IAED,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI,mBAAmB,CAAC,IAAI,EAAE;QAC5B,WAAW,IAAI;;oBAEC,CAAC;KAClB;IAED,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAEvD,OAAO;;;;;;;UAOC,GAAG,KAAK,mBAAmB,GAAG,kBAAkB,GAAG,WAAW,GAAG,aAAa;;;;;;;MAOlF,gBAAgB;;;;CAIrB,CAAC;AACF,CAAC;AA/DD,oFA+DC;AAED,SAAgB,4BAA4B,CAAC,OAQ5C;IACC,MAAM,cAAc,GAAG,OAAO,CAAC,UAAU;QACvC,CAAC,CAAC,GAAG,OAAO,CAAC,SAAS,iBAAiB,OAAO,CAAC,OAAO,oBAAoB,OAAO,CAAC,SAAS,EAAE;QAC7F,CAAC,CAAC,WAAW,OAAO,CAAC,OAAO,8BAA8B,OAAO,CAAC,SAAS,EAAE,CAAC;IAEhF,MAAM,cAAc,GAAG,OAAO,CAAC,WAAW;QACxC,CAAC,CAAC;sDACgD;QAClD,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,gBAAgB,GAAG,OAAO,CAAC,WAAW;QAC1C,CAAC,CAAC;oFAC8E;QAChF,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO,GACL,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAC5C;;;;;uBAKqB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;qBAUpD,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAqCf,cAAc;;;;;;;;;;;;;;;;;kCAiBA,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoKjD,CAAC;AACF,CAAC;AAnQD,oEAmQC;AAED,SAAgB,gCAAgC,CAAC,EAC/C,YAAY,EACZ,WAAW,GAIZ;IACC,MAAM,YAAY,GAAG,WAAW;QAC9B,CAAC,CAAC;;CAEL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,UAAU,GAAG,WAAW;QAC5B,CAAC,CAAC;CACL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO,GAAG,YAAY;;uBAED,YAAY,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE;;;;;;;EAO/D,UAAU;;;CAGX,CAAC;AACF,CAAC;AA/BD,4EA+BC;AAED,SAAgB,8BAA8B,CAAC,EAC7C,YAAY,EACZ,WAAW,GAIZ;IACC,MAAM,YAAY,GAAG,WAAW;QAC9B,CAAC,CAAC;CACL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,UAAU,GAAG,WAAW;QAC5B,CAAC,CAAC;mDAC6C;QAC/C,CAAC,CAAC,EAAE,CAAC;IAEP,kGAAkG;IAClG,uFAAuF;IACvF,OAAO,GAAG,YAAY;;;uBAGD,YAAY,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE;;;;;;;yBAOxC,UAAU;;;;;CAKlC,CAAC;AACF,CAAC;AAnCD,wEAmCC;AAED,SAAgB,mCAAmC;IACjD,OAAO;;;;;;;;;;;;;;;;;CAiBR,CAAC;AACF,CAAC;AAnBD,kFAmBC;AAED,SAAgB,wCAAwC;IACtD,OAAO;EACP,eAAK,CAAC,KAAK,CAAC,2CAA2C,CAAC;EACxD,eAAK,CAAC,KAAK,CAAC,iCAAiC,CAAC;;EAE9C,eAAK,CAAC,GAAG,CACT,yEAAyE,CAC1E;oDACmD,eAAK,CAAC,KAAK,CAC3D,aAAa,CACd;IACC,eAAK,CAAC,KAAK,CAAC,4DAA4D,CAAC;;IAEzE,eAAK,CAAC,GAAG,CAAC,kCAAkC,CAAC;;;;CAIhD,CAAC;AACF,CAAC;AAlBD,4FAkBC;AAED,SAAgB,0BAA0B,CAAC,IAAa;IACtD,OAAO,IAAA,uBAAe,EAAC,IAAI,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE;QAC/C,OAAO,IAAI,CAAC;;QAER,IAAI,CAAC,CAAC,CAAC,uCAAuC,CAAC,CAAC,CAAC,EAAE;;QAEnD,SAAS,CACT,0EAA0E,CAC3E;0CACmC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE;;;;;;;;CAQjE,CAAC,CAAC;IACD,CAAC,CAAC,CAAC;AACL,CAAC;AAnBD,gEAmBC;AAED,SAAgB,sCAAsC,CAAC,IAAa;IAClE,OAAO;2CAEL,IAAI,CAAC,CAAC,CAAC,gDAAgD,CAAC,CAAC,CAAC,EAC5D;;;EAGA,eAAK,CAAC,GAAG,CACT,yEAAyE,CAC1E;+DAEG,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAC/B;;;;;CAKD,CAAC;AACF,CAAC;AAlBD,wFAkBC;AAED,SAAgB,6BAA6B,CAC3C,2BAA2C;IAE3C,OAAO;;;;oBAKH,2BAA2B,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IACjD;;;;oBAKE,2BAA2B,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IACjD;;;;;CAKH,CAAC;AACF,CAAC;AArBD,sEAqBC;AAED,SAAgB,sCAAsC,CACpD,2BAA2C;IAE3C,OAAO,IAAA,uBAAe,EAAC,IAAI,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE;QAC/C,OAAO,SAAS,CAAC,GAAG,IAAI,CAAC,2CAA2C,CAAC;;SAEhE,IAAI,CAAC,OAAO,CAAC;IAClB,IAAI,CAAC;oBAEH,2BAA2B,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IACjD;;;;oBAKE,2BAA2B,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IACjD;IACA,CAAC;;;EAGH,IAAI,CAAC,2DAA2D,CAAC;CAClE,CAAC,CAAC;IACD,CAAC,CAAC,CAAC;AACL,CAAC;AAvBD,wFAuBC;AAED,SAAgB,4CAA4C,CAC1D,GAAW,EACX,mBAIC,EACD,SAAS,GAAG,KAAK;IAEjB,OAAO,IAAA,uBAAe,EAAC,IAAI,EAAE,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE;QAChD,OAAO,IAAI,CACT,oCAAoC,CAAC,GAAG,EAAE,mBAAmB,EAAE,SAAS,CAAC,CAC1E,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAdD,oGAcC;AAED,SAAgB,+BAA+B,CAAC,IAAa;IAC3D,OAAO,IAAI;QACT,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BL;QACG,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;CAuBL,CAAC;AACF,CAAC;AAtDD,0EAsDC;AAED,SAAgB,8BAA8B,CAAC,IAAa;IAC1D,IAAI,IAAI,EAAE;QACR,OAAO;;EAET,eAAK,CAAC,KAAK,CAAC,2CAA2C,CAAC;EACxD,eAAK,CAAC,KAAK,CAAC,iCAAiC,CAAC;EAC9C,eAAK,CAAC,KAAK,CAAC,oCAAoC,CAAC;;sCAEb,eAAK,CAAC,KAAK,CAC3C,6BAA6B,CAC9B;IACD,eAAK,CAAC,KAAK,CAAC;;eAED,CAAC;;;;;;;;;;CAUf,CAAC;KACC;IACD,OAAO;;EAEP,eAAK,CAAC,KAAK,CAAC,2CAA2C,CAAC;EACxD,eAAK,CAAC,KAAK,CAAC,iCAAiC,CAAC;EAC9C,eAAK,CAAC,KAAK,CAAC,oCAAoC,CAAC;;sCAEb,eAAK,CAAC,KAAK,CAAC,WAAW,CAAC;IAC1D,eAAK,CAAC,KAAK,CAAC;;eAED,CAAC;;;;;;;;;;CAUf,CAAC;AACF,CAAC;AA7CD,wEA6CC;AAEM,MAAM,aAAa,GAAG,CAC3B,IAAa,EACb,EAAE,CAAC;;;;;;;;;;GAWH,IAAI;IACF,CAAC,CAAC;;EAEJ;IACE,CAAC,CAAC,EACN;;;;;;;CAOC,CAAC;AAzBW,QAAA,aAAa,iBAyBxB;AAEK,MAAM,iCAAiC,GAAG,CAC/C,IAAa,EACb,EAAE,CAAC;;EAEH,IAAI,CAAC,CAAC,CAAC,uCAAuC,CAAC,CAAC,CAAC,EAAE;;oCAEjB,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;GAW1D,IAAI;IACF,CAAC,CAAC;;EAEJ;IACE,CAAC,CAAC,EACN;;;;;;;CAOC,CAAC;AA7BW,QAAA,iCAAiC,qCA6B5C","sourcesContent":["import chalk from 'chalk';\nimport { makeCodeSnippet } from '../utils/clack';\n\ntype WithSentryConfigOptions = {\n orgSlug: string;\n projectSlug: string;\n selfHosted: boolean;\n sentryUrl: string;\n tunnelRoute: boolean;\n};\n\nexport function getWithSentryConfigOptionsTemplate({\n orgSlug,\n projectSlug,\n selfHosted,\n tunnelRoute,\n sentryUrl,\n}: WithSentryConfigOptions): string {\n return `{\n // For all available options, see:\n // https://www.npmjs.com/package/@sentry/webpack-plugin#options\n\n org: \"${orgSlug}\",\n project: \"${projectSlug}\",${\n selfHosted ? `\\n sentryUrl: \"${sentryUrl}\",` : ''\n }\n\n // Only print logs for uploading source maps in CI\n silent: !process.env.CI,\n\n // For all available options, see:\n // https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/\n\n // Upload a larger set of source maps for prettier stack traces (increases build time)\n widenClientFileUpload: true,\n\n // ${\n tunnelRoute ? 'Route' : 'Uncomment to route'\n } browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.\n // This can increase your server load as well as your hosting bill.\n // Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-\n // side errors will fail.\n ${tunnelRoute ? '' : '// '}tunnelRoute: \"/monitoring\",\n\n webpack: {\n // Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.)\n // See the following for more information:\n // https://docs.sentry.io/product/crons/\n // https://vercel.com/docs/cron-jobs\n automaticVercelMonitors: true,\n\n // Tree-shaking options for reducing bundle size\n treeshake: {\n // Automatically tree-shake Sentry logger statements to reduce bundle size\n removeDebugLogging: true,\n },\n },\n}`;\n}\n\nexport function getNextjsConfigCjsTemplate(\n withSentryConfigOptionsTemplate: string,\n): string {\n return `const { withSentryConfig } = require(\"@sentry/nextjs\");\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {};\n\nmodule.exports = withSentryConfig(nextConfig, ${withSentryConfigOptionsTemplate});\n`;\n}\n\nexport function getNextjsConfigMjsTemplate(\n withSentryConfigOptionsTemplate: string,\n): string {\n return `import { withSentryConfig } from \"@sentry/nextjs\";\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {};\n\nexport default withSentryConfig(nextConfig, ${withSentryConfigOptionsTemplate});\n`;\n}\n\nexport function getNextjsConfigCjsAppendix(\n withSentryConfigOptionsTemplate: string,\n): string {\n return `\n\n// Injected content via Sentry wizard below\n\nconst { withSentryConfig } = require(\"@sentry/nextjs\");\n\nmodule.exports = withSentryConfig(module.exports, ${withSentryConfigOptionsTemplate});\n`;\n}\n\nexport function getNextjsConfigEsmCopyPasteSnippet(\n withSentryConfigOptionsTemplate: string,\n): string {\n return `\n\n// next.config.mjs\nimport { withSentryConfig } from \"@sentry/nextjs\";\n\nexport default withSentryConfig(yourNextConfig, ${withSentryConfigOptionsTemplate});\n`;\n}\n\nfunction getClientIntegrationsSnippet(features: { replay: boolean }) {\n if (features.replay) {\n return `\n\n // Add optional integrations for additional features\n integrations: [Sentry.replayIntegration()],`;\n }\n\n return '';\n}\n\nfunction getSpotlightOption(spotlight: boolean): string {\n if (!spotlight) {\n return '';\n }\n\n return `\n\n // Spotlight enabled for local development (https://spotlightjs.com)\n spotlight: true,`;\n}\n\nexport function getSentryServersideConfigContents(\n dsn: string,\n config: 'server' | 'edge',\n selectedFeaturesMap: {\n replay: boolean;\n performance: boolean;\n logs: boolean;\n },\n spotlight = false,\n): string {\n let primer = '';\n if (config === 'server') {\n primer = `// This file configures the initialization of Sentry on the server.\n// The config you add here will be used whenever the server handles a request.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;\n } else if (config === 'edge') {\n primer = `// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on).\n// The config you add here will be used whenever one of the edge features is loaded.\n// Note that this config is unrelated to the Vercel Edge Runtime and is also required when running locally.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/`;\n }\n\n let performanceOptions = '';\n if (selectedFeaturesMap.performance) {\n performanceOptions += `\n\n // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.\n tracesSampleRate: 1,`;\n }\n\n let logsOptions = '';\n if (selectedFeaturesMap.logs) {\n logsOptions += `\n\n // Enable logs to be sent to Sentry\n enableLogs: true,`;\n }\n\n const spotlightOptions = getSpotlightOption(spotlight);\n\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n return `${primer}\n\nimport * as Sentry from \"@sentry/nextjs\";\n\nSentry.init({\n dsn: \"${dsn}\",${performanceOptions}${logsOptions}\n\n dataCollection: {\n // To disable sending user data and HTTP bodies, uncomment the lines below. For more info visit:\n // https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/options/#dataCollection\n // userInfo: false,\n // httpBodies: [],\n },${spotlightOptions}\n});\n`;\n}\n\nexport function getInstrumentationClientFileContents(\n dsn: string,\n selectedFeaturesMap: {\n replay: boolean;\n performance: boolean;\n logs: boolean;\n },\n spotlight = false,\n): string {\n const integrationsOptions = getClientIntegrationsSnippet({\n replay: selectedFeaturesMap.replay,\n });\n\n let replayOptions = '';\n\n if (selectedFeaturesMap.replay) {\n replayOptions += `\n\n // Define how likely Replay events are sampled.\n // This sets the sample rate to be 10%. You may want this to be 100% while\n // in development and sample at a lower rate in production\n replaysSessionSampleRate: 0.1,\n\n // Define how likely Replay events are sampled when an error occurs.\n replaysOnErrorSampleRate: 1.0,`;\n }\n\n let performanceOptions = '';\n if (selectedFeaturesMap.performance) {\n performanceOptions += `\n\n // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.\n tracesSampleRate: 1,`;\n }\n\n let logsOptions = '';\n if (selectedFeaturesMap.logs) {\n logsOptions += `\n // Enable logs to be sent to Sentry\n enableLogs: true,`;\n }\n\n const spotlightOptions = getSpotlightOption(spotlight);\n\n return `// This file configures the initialization of Sentry on the client.\n// The added config here will be used whenever a users loads a page in their browser.\n// https://docs.sentry.io/platforms/javascript/guides/nextjs/\n\nimport * as Sentry from \"@sentry/nextjs\";\n\nSentry.init({\n dsn: \"${dsn}\",${integrationsOptions}${performanceOptions}${logsOptions}${replayOptions}\n\n dataCollection: {\n // To disable sending user data and HTTP bodies, uncomment the lines below. For more info visit:\n // https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/options/#dataCollection\n // userInfo: false,\n // httpBodies: [],\n },${spotlightOptions}\n});\n\nexport const onRouterTransitionStart = Sentry.captureRouterTransitionStart;\n`;\n}\n\nexport function getSentryExamplePageContents(options: {\n selfHosted: boolean;\n sentryUrl: string;\n orgSlug: string;\n projectId: string;\n useClient: boolean;\n isTypeScript?: boolean;\n logsEnabled?: boolean;\n}): string {\n const issuesPageLink = options.selfHosted\n ? `${options.sentryUrl}organizations/${options.orgSlug}/issues/?project=${options.projectId}`\n : `https://${options.orgSlug}.sentry.io/issues/?project=${options.projectId}`;\n\n const loggerPageLoad = options.logsEnabled\n ? `\n Sentry.logger.info(\"Sentry example page loaded\");`\n : '';\n\n const loggerUserAction = options.logsEnabled\n ? `\n Sentry.logger.info(\"User clicked the button, throwing a sample error\");`\n : '';\n\n return `${\n options.useClient ? '\"use client\";\\n\\n' : ''\n }import * as Sentry from \"@sentry/nextjs\";\nimport Head from \"next/head\";\nimport { useEffect, useState } from \"react\";\n\nclass SentryExampleFrontendError extends Error {\n constructor(message${options.isTypeScript ? ': string | undefined' : ''}) {\n super(message);\n this.name = \"SentryExampleFrontendError\";\n }\n}\n\nexport default function Page() {\n const [hasSentError, setHasSentError] = useState(false);\n const [isConnected, setIsConnected] = useState(true);\n\n useEffect(() => {${loggerPageLoad}\n async function checkConnectivity() {\n const result = await Sentry.diagnoseSdkConnectivity();\n setIsConnected(result !== \"sentry-unreachable\");\n }\n checkConnectivity();\n }, []);\n\n return (\n <div>\n <Head>\n <title>sentry-example-page</title>\n <meta name=\"description\" content=\"Test Sentry for your Next.js app!\" />\n </Head>\n\n <main>\n <div className=\"flex-spacer\" />\n <svg\n height=\"40\"\n width=\"40\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n role=\"img\"\n aria-label=\"Sentry logo\"\n >\n <path\n d=\"M21.85 2.995a3.698 3.698 0 0 1 1.353 1.354l16.303 28.278a3.703 3.703 0 0 1-1.354 5.053 3.694 3.694 0 0 1-1.848.496h-3.828a31.149 31.149 0 0 0 0-3.09h3.815a.61.61 0 0 0 .537-.917L20.523 5.893a.61.61 0 0 0-1.057 0l-3.739 6.494a28.948 28.948 0 0 1 9.63 10.453 28.988 28.988 0 0 1 3.499 13.78v1.542h-9.852v-1.544a19.106 19.106 0 0 0-2.182-8.85 19.08 19.08 0 0 0-6.032-6.829l-1.85 3.208a15.377 15.377 0 0 1 6.382 12.484v1.542H3.696A3.694 3.694 0 0 1 0 34.473c0-.648.17-1.286.494-1.849l2.33-4.074a8.562 8.562 0 0 1 2.689 1.536L3.158 34.17a.611.611 0 0 0 .538.917h8.448a12.481 12.481 0 0 0-6.037-9.09l-1.344-.772 4.908-8.545 1.344.77a22.16 22.16 0 0 1 7.705 7.444 22.193 22.193 0 0 1 3.316 10.193h3.699a25.892 25.892 0 0 0-3.811-12.033 25.856 25.856 0 0 0-9.046-8.796l-1.344-.772 5.269-9.136a3.698 3.698 0 0 1 3.2-1.849c.648 0 1.285.17 1.847.495Z\"\n fill=\"currentcolor\"\n />\n </svg>\n <h1>sentry-example-page</h1>\n\n <p className=\"description\">\n Click the button below, and view the sample error on the Sentry{\" \"}\n <a\n target=\"_blank\"\n rel=\"noopener\"\n href=\"${issuesPageLink}\"\n >\n Issues Page\n </a>\n . For more details about setting up Sentry,{\" \"}\n <a\n target=\"_blank\"\n rel=\"noopener\"\n href=\"https://docs.sentry.io/platforms/javascript/guides/nextjs/\"\n >\n read our docs\n </a>\n .\n </p>\n\n <button\n type=\"button\"\n onClick={async () => {${loggerUserAction}\n await Sentry.startSpan(\n {\n name: \"Example Frontend/Backend Span\",\n op: \"test\",\n },\n async () => {\n const res = await fetch(\"/api/sentry-example-api\");\n if (!res.ok) {\n setHasSentError(true);\n }\n },\n );\n throw new SentryExampleFrontendError(\n \"This error is raised on the frontend of the example page.\",\n );\n }}\n disabled={!isConnected}\n >\n <span>Throw Sample Error</span>\n </button>\n\n {hasSentError ? (\n <p className=\"success\">Error sent to Sentry.</p>\n ) : !isConnected ? (\n <div className=\"connectivity-error\">\n <p>\n It looks like network requests to Sentry are being blocked, which\n will prevent errors from being captured. Try disabling your\n ad-blocker to complete the test.\n </p>\n </div>\n ) : (\n <div className=\"success_placeholder\" />\n )}\n\n <div className=\"flex-spacer\" />\n </main>\n\n <style>{\\`\n main {\n display: flex;\n min-height: 100vh;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n gap: 16px;\n padding: 16px;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n\n h1 {\n padding: 0px 4px;\n border-radius: 4px;\n background-color: rgba(24, 20, 35, 0.03);\n font-family: monospace;\n font-size: 20px;\n line-height: 1.2;\n }\n\n p {\n margin: 0;\n font-size: 20px;\n }\n\n a {\n color: #6341F0;\n text-decoration: underline;\n cursor: pointer;\n\n @media (prefers-color-scheme: dark) {\n color: #B3A1FF;\n }\n }\n\n button {\n border-radius: 8px;\n color: white;\n cursor: pointer;\n background-color: #553DB8;\n border: none;\n padding: 0;\n margin-top: 4px;\n\n & > span {\n display: inline-block;\n padding: 12px 16px;\n border-radius: inherit;\n font-size: 20px;\n font-weight: bold;\n line-height: 1;\n background-color: #7553FF;\n border: 1px solid #553DB8;\n transform: translateY(-4px);\n }\n\n &:hover > span {\n transform: translateY(-8px);\n }\n\n &:active > span {\n transform: translateY(0);\n }\n\n &:disabled {\n\t cursor: not-allowed;\n\t opacity: 0.6;\n\n\t & > span {\n\t transform: translateY(0);\n\t border: none\n\t }\n\t }\n }\n\n .description {\n text-align: center;\n color: #6E6C75;\n max-width: 500px;\n line-height: 1.5;\n font-size: 20px;\n\n @media (prefers-color-scheme: dark) {\n color: #A49FB5;\n }\n }\n\n .flex-spacer {\n flex: 1;\n }\n\n .success {\n padding: 12px 16px;\n border-radius: 8px;\n font-size: 20px;\n line-height: 1;\n background-color: #00F261;\n border: 1px solid #00BF4D;\n color: #181423;\n }\n\n .success_placeholder {\n height: 46px;\n }\n\n .connectivity-error {\n padding: 12px 16px;\n background-color: #E50045;\n border-radius: 8px;\n width: 500px;\n color: #FFFFFF;\n border: 1px solid #A80033;\n text-align: center;\n margin: 0;\n }\n\n .connectivity-error a {\n color: #FFFFFF;\n text-decoration: underline;\n }\n \\`}</style>\n </div>\n );\n}\n`;\n}\n\nexport function getSentryExamplePagesDirApiRoute({\n isTypeScript,\n logsEnabled,\n}: {\n isTypeScript: boolean;\n logsEnabled?: boolean;\n}) {\n const sentryImport = logsEnabled\n ? `import * as Sentry from \"@sentry/nextjs\";\n\n`\n : '';\n\n const loggerCall = logsEnabled\n ? ` Sentry.logger.info(\"Sentry example API called\");\n`\n : '';\n\n return `${sentryImport}// Custom error class for Sentry testing\nclass SentryExampleAPIError extends Error {\n constructor(message${isTypeScript ? ': string | undefined' : ''}) {\n super(message);\n this.name = \"SentryExampleAPIError\";\n }\n}\n// A faulty API route to test Sentry's error monitoring\nexport default function handler(_req, res) {\n${loggerCall}throw new SentryExampleAPIError(\"This error is raised on the backend called by the example page.\");\nres.status(200).json({ name: \"John Doe\" });\n}\n`;\n}\n\nexport function getSentryExampleAppDirApiRoute({\n isTypeScript,\n logsEnabled,\n}: {\n isTypeScript: boolean;\n logsEnabled?: boolean;\n}) {\n const sentryImport = logsEnabled\n ? `import * as Sentry from \"@sentry/nextjs\";\n`\n : '';\n\n const loggerCall = logsEnabled\n ? `\n Sentry.logger.info(\"Sentry example API called\");`\n : '';\n\n // Note: We intentionally don't have a return statement after throw - it would be unreachable code\n // We also don't import NextResponse since we don't use it (Biome noUnusedImports rule)\n return `${sentryImport}export const dynamic = \"force-dynamic\";\n\nclass SentryExampleAPIError extends Error {\n constructor(message${isTypeScript ? ': string | undefined' : ''}) {\n super(message);\n this.name = \"SentryExampleAPIError\";\n }\n}\n\n// A faulty API route to test Sentry's error monitoring\nexport function GET() {${loggerCall}\n throw new SentryExampleAPIError(\n \"This error is raised on the backend called by the example page.\",\n );\n}\n`;\n}\n\nexport function getSentryDefaultUnderscoreErrorPage() {\n return `import * as Sentry from \"@sentry/nextjs\";\nimport Error from \"next/error\";\n\nconst CustomErrorComponent = (props) => {\n return <Error statusCode={props.statusCode} />;\n};\n\nCustomErrorComponent.getInitialProps = async (contextData) => {\n // In case this is running in a serverless function, await this in order to give Sentry\n // time to send the error before the lambda exits\n await Sentry.captureUnderscoreErrorException(contextData);\n\n // This will contain the status code of the response\n return Error.getInitialProps(contextData);\n};\n\nexport default CustomErrorComponent;\n`;\n}\n\nexport function getSimpleUnderscoreErrorCopyPasteSnippet() {\n return `\n${chalk.green(`import * as Sentry from '@sentry/nextjs';`)}\n${chalk.green(`import Error from \"next/error\";`)}\n\n${chalk.dim(\n '// Replace \"YourCustomErrorComponent\" with your custom error component!',\n)}\nYourCustomErrorComponent.getInitialProps = async (${chalk.green(\n 'contextData',\n )}) => {\n ${chalk.green('await Sentry.captureUnderscoreErrorException(contextData);')}\n\n ${chalk.dim('// ...other getInitialProps code')}\n\n return Error.getInitialProps(contextData);\n};\n`;\n}\n\nexport function getGenerateMetadataSnippet(isTs: boolean) {\n return makeCodeSnippet(true, (unchanged, plus) => {\n return plus(`\n import * as Sentry from '@sentry/nextjs';\n ${isTs ? `import type { Metadata } from 'next';` : ''}\n\n ${unchanged(\n '// Add or edit your \"generateMetadata\" to include the Sentry trace data:',\n )}\n export function generateMetadata()${isTs ? ': Metadata' : ''} {\n return {\n // ... your existing metadata\n other: {\n ...Sentry.getTraceData()\n }\n };\n }\n`);\n });\n}\n\nexport function getFullUnderscoreErrorCopyPasteSnippet(isTs: boolean) {\n return `\nimport * as Sentry from '@sentry/nextjs';${\n isTs ? '\\nimport type { NextPageContext } from \"next\";' : ''\n }\nimport Error from \"next/error\";\n\n${chalk.dim(\n '// Replace \"YourCustomErrorComponent\" with your custom error component!',\n)}\nYourCustomErrorComponent.getInitialProps = async (contextData${\n isTs ? ': NextPageContext' : ''\n }) => {\n await Sentry.captureUnderscoreErrorException(contextData);\n\n return Error.getInitialProps(contextData);\n};\n`;\n}\n\nexport function getInstrumentationHookContent(\n instrumentationHookLocation: 'src' | 'root',\n) {\n return `import * as Sentry from \"@sentry/nextjs\";\n\nexport async function register() {\n if (process.env.NEXT_RUNTIME === \"nodejs\") {\n await import(\"${\n instrumentationHookLocation === 'root' ? '.' : '..'\n }/sentry.server.config\");\n }\n\n if (process.env.NEXT_RUNTIME === \"edge\") {\n await import(\"${\n instrumentationHookLocation === 'root' ? '.' : '..'\n }/sentry.edge.config\");\n }\n}\n\nexport const onRequestError = Sentry.captureRequestError;\n`;\n}\n\nexport function getInstrumentationHookCopyPasteSnippet(\n instrumentationHookLocation: 'src' | 'root',\n) {\n return makeCodeSnippet(true, (unchanged, plus) => {\n return unchanged(`${plus(\"import * as Sentry from '@sentry/nextjs';\")}\n\nexport ${plus('async')} function register() {\n ${plus(`if (process.env.NEXT_RUNTIME === 'nodejs') {\n await import('${\n instrumentationHookLocation === 'root' ? '.' : '..'\n }/sentry.server.config');\n }\n\n if (process.env.NEXT_RUNTIME === 'edge') {\n await import('${\n instrumentationHookLocation === 'root' ? '.' : '..'\n }/sentry.edge.config');\n }`)}\n}\n\n${plus('export const onRequestError = Sentry.captureRequestError;')}\n`);\n });\n}\n\nexport function getInstrumentationClientHookCopyPasteSnippet(\n dsn: string,\n selectedFeaturesMap: {\n replay: boolean;\n performance: boolean;\n logs: boolean;\n },\n spotlight = false,\n) {\n return makeCodeSnippet(true, (_unchanged, plus) => {\n return plus(\n getInstrumentationClientFileContents(dsn, selectedFeaturesMap, spotlight),\n );\n });\n}\n\nexport function getSentryDefaultGlobalErrorPage(isTs: boolean) {\n return isTs\n ? `\"use client\";\n\nimport * as Sentry from \"@sentry/nextjs\";\nimport NextError from \"next/error\";\nimport { useEffect } from \"react\";\n\nexport default function GlobalError({\n error,\n}: {\n error: Error & { digest?: string };\n}) {\n useEffect(() => {\n Sentry.captureException(error);\n }, [error]);\n\n return (\n <html lang=\"en\">\n <body>\n {/* \\`NextError\\` is the default Next.js error page component. Its type\n definition requires a \\`statusCode\\` prop. However, since the App Router\n does not expose status codes for errors, we simply pass 0 to render a\n generic error message. */}\n <NextError statusCode={0} />\n </body>\n </html>\n );\n}\n`\n : `\"use client\";\n\nimport * as Sentry from \"@sentry/nextjs\";\nimport NextError from \"next/error\";\nimport { useEffect } from \"react\";\n\nexport default function GlobalError({ error }) {\n useEffect(() => {\n Sentry.captureException(error);\n }, [error]);\n\n return (\n <html lang=\"en\">\n <body>\n {/* \\`NextError\\` is the default Next.js error page component. Its type\n definition requires a \\`statusCode\\` prop. However, since the App Router\n does not expose status codes for errors, we simply pass 0 to render a\n generic error message. */}\n <NextError statusCode={0} />\n </body>\n </html>\n );\n}\n`;\n}\n\nexport function getGlobalErrorCopyPasteSnippet(isTs: boolean) {\n if (isTs) {\n return `\"use client\";\n\n${chalk.green('import * as Sentry from \"@sentry/nextjs\";')}\n${chalk.green('import Error from \"next/error\";')}\n${chalk.green('import { useEffect } from \"react\";')}\n\nexport default function GlobalError(${chalk.green(\n '{ error }: { error: Error }',\n )}) {\n ${chalk.green(`useEffect(() => {\n Sentry.captureException(error);\n }, [error]);`)}\n\n return (\n <html>\n <body>\n {/* Your Error component here... */}\n </body>\n </html>\n );\n}\n`;\n }\n return `\"use client\";\n\n${chalk.green('import * as Sentry from \"@sentry/nextjs\";')}\n${chalk.green('import Error from \"next/error\";')}\n${chalk.green('import { useEffect } from \"react\";')}\n\nexport default function GlobalError(${chalk.green('{ error }')}) {\n ${chalk.green(`useEffect(() => {\n Sentry.captureException(error);\n }, [error]);`)}\n\n return (\n <html>\n <body>\n {/* Your Error component here... */}\n </body>\n </html>\n );\n}\n`;\n}\n\nexport const getRootLayout = (\n isTs: boolean,\n) => `// This file was generated by the Sentry wizard because we couldn't find a root layout file.\n// You can delete this file at any time.\n\nexport const metadata = {\n title: 'Sentry NextJS Example',\n description: 'Generated by Sentry',\n}\n\nexport default function RootLayout({\n children,\n}${\n isTs\n ? `: {\n children: React.ReactNode\n}`\n : ''\n}) {\n return (\n <html lang=\"en\">\n <body>{children}</body>\n </html>\n )\n}\n`;\n\nexport const getRootLayoutWithGenerateMetadata = (\n isTs: boolean,\n) => `// This file was generated by the Sentry wizard because we couldn't find a root layout file.\nimport * as Sentry from '@sentry/nextjs';\n${isTs ? `import type { Metadata } from 'next';` : ''}\n\nexport function generateMetadata()${isTs ? ': Metadata' : ''} {\n return {\n other: {\n ...Sentry.getTraceData(),\n }\n }\n};\n\nexport default function RootLayout({\n children,\n}${\n isTs\n ? `: {\n children: React.ReactNode\n}`\n : ''\n}) {\n return (\n <html lang=\"en\">\n <body>{children}</body>\n </html>\n )\n}\n`;\n"]}
|
|
@@ -82,9 +82,12 @@ Sentry.init({
|
|
|
82
82
|
// dsn: useRuntimeConfig().public.sentry.dsn,
|
|
83
83
|
${getConfigBody(dsn, 'client', selectedFeatures)}
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
dataCollection: {
|
|
86
|
+
// To disable sending user data and HTTP bodies, uncomment the lines below. For more info visit:
|
|
87
|
+
// https://docs.sentry.io/platforms/javascript/guides/nuxt/configuration/options/#dataCollection
|
|
88
|
+
// userInfo: false,
|
|
89
|
+
// httpBodies: [],
|
|
90
|
+
},
|
|
88
91
|
|
|
89
92
|
// Setting this option to true will print useful information to the console while you're setting up Sentry.
|
|
90
93
|
debug: false,
|
|
@@ -97,9 +100,12 @@ function getSentryServerConfigContents(dsn, selectedFeatures) {
|
|
|
97
100
|
Sentry.init({
|
|
98
101
|
${getConfigBody(dsn, 'server', selectedFeatures)}
|
|
99
102
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
dataCollection: {
|
|
104
|
+
// To disable sending user data and HTTP bodies, uncomment the lines below. For more info visit:
|
|
105
|
+
// https://docs.sentry.io/platforms/javascript/guides/nuxt/configuration/options/#dataCollection
|
|
106
|
+
// userInfo: false,
|
|
107
|
+
// httpBodies: [],
|
|
108
|
+
},
|
|
103
109
|
|
|
104
110
|
// Setting this option to true will print useful information to the console while you're setting up Sentry.
|
|
105
111
|
debug: false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/nuxt/templates.ts"],"names":[],"mappings":"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","sourcesContent":["import { getIssueStreamUrl } from '../utils/url';\n\ntype SelectedSentryFeatures = {\n performance: boolean;\n replay: boolean;\n logs: boolean;\n};\n\nexport function getDefaultNuxtConfig(): string {\n return `// https://nuxt.com/docs/api/configuration/nuxt-config\nexport default defineNuxtConfig({\n compatibilityDate: '2024-04-03',\n devtools: { enabled: true }\n})\n`;\n}\n\nexport function getNuxtModuleFallbackTemplate(\n options: {\n org: string;\n project: string;\n url: string;\n selfHosted: boolean;\n },\n shouldTopLevelImport: boolean,\n): string {\n return ` modules: [\"@sentry/nuxt/module\"],\n sentry: {\n org: \"${options.org}\",\n project: \"${options.project}\",${\n options.selfHosted ? `\\n url: \"${options.url}\",` : ''\n }\n sourcemaps: { \n // This will delete all .map files in the build output after uploading them to Sentry. Modify as needed.\n // For more information, see: https://docs.sentry.io/platforms/javascript/guides/nuxt/sourcemaps/\n filesToDeleteAfterUpload: ['.*/**/*.map'] \n },${\n shouldTopLevelImport\n ? `\\n autoInjectServerSentry: \"top-level-import\",`\n : ''\n }\n },\n sourcemap: { client: \"hidden\" },`;\n}\n\nexport function getSentryConfigContents(\n dsn: string,\n config: 'client' | 'server',\n selectedFeatures: SelectedSentryFeatures,\n): string {\n if (config === 'client') {\n return getSentryClientConfigContents(dsn, selectedFeatures);\n }\n\n return getSentryServerConfigContents(dsn, selectedFeatures);\n}\n\nconst featuresConfigMap: Record<keyof SelectedSentryFeatures, string> = {\n performance: [\n ' // We recommend adjusting this value in production, or using tracesSampler',\n ' // for finer control',\n ' tracesSampleRate: 1.0,',\n ].join('\\n'),\n replay: [\n ' // This sets the sample rate to be 10%. You may want this to be 100% while',\n ' // in development and sample at a lower rate in production',\n ' replaysSessionSampleRate: 0.1,',\n ' ',\n ' // If the entire session is not sampled, use the below sample rate to sample',\n ' // sessions when an error occurs.',\n ' replaysOnErrorSampleRate: 1.0,',\n ' ',\n \" // If you don't want to use Session Replay, just remove the line below:\",\n ' integrations: [Sentry.replayIntegration()],',\n ].join('\\n'),\n logs: [' // Enable logs to be sent to Sentry', ' enableLogs: true,'].join(\n '\\n',\n ),\n};\n\nconst featuresMap: Record<\n 'client' | 'server',\n Array<keyof SelectedSentryFeatures>\n> = {\n client: ['performance', 'replay', 'logs'],\n server: ['performance', 'logs'],\n};\n\nexport function getConfigBody(\n dsn: string,\n variant: 'client' | 'server',\n selectedFeatures: SelectedSentryFeatures,\n) {\n return [\n `dsn: \"${dsn}\",`,\n Object.entries(selectedFeatures)\n .map(([feature, activated]: [keyof SelectedSentryFeatures, boolean]) => {\n return featuresMap[variant].includes(feature) && activated\n ? featuresConfigMap[feature]\n : null;\n })\n .filter(Boolean)\n .join('\\n\\n'),\n ]\n .filter(Boolean)\n .join('\\n\\n');\n}\n\nfunction getSentryClientConfigContents(\n dsn: string,\n selectedFeatures: SelectedSentryFeatures,\n): string {\n return `import * as Sentry from \"@sentry/nuxt\";\n\nSentry.init({\n // If set up, you can use your runtime config here\n // dsn: useRuntimeConfig().public.sentry.dsn,\n ${getConfigBody(dsn, 'client', selectedFeatures)}\n\n // Enable sending of user PII (Personally Identifiable Information)\n // https://docs.sentry.io/platforms/javascript/guides/nuxt/configuration/options/#sendDefaultPii\n sendDefaultPii: true,\n\n // Setting this option to true will print useful information to the console while you're setting up Sentry.\n debug: false,\n});\n`;\n}\n\nfunction getSentryServerConfigContents(\n dsn: string,\n selectedFeatures: SelectedSentryFeatures,\n): string {\n return `import * as Sentry from \"@sentry/nuxt\";\n \nSentry.init({\n ${getConfigBody(dsn, 'server', selectedFeatures)}\n\n // Enable sending of user PII (Personally Identifiable Information)\n // https://docs.sentry.io/platforms/javascript/guides/nuxt/configuration/options/#sendDefaultPii\n sendDefaultPii: true,\n\n // Setting this option to true will print useful information to the console while you're setting up Sentry.\n debug: false,\n});\n`;\n}\n\nexport function getIndexRouteTemplate(): string {\n return `<!--\nThis is just to verify the sentry-example-page.\nFeel free to delete this file.\n-->\n\n<template></template>`;\n}\n\nexport function getSentryExamplePageTemplate(options: {\n url: string;\n org: string;\n projectId: string;\n}): string {\n const { url, org, projectId } = options;\n const issuesPageLink = getIssueStreamUrl({ url, orgSlug: org, projectId });\n\n return `<!--\nThis is just a very simple page with a button to throw an example error.\nFeel free to delete this file.\n-->\n\n<script setup>\n import * as Sentry from '@sentry/nuxt';\n\n class SentryExampleFrontendError extends Error {\n constructor(message) {\n super(message);\n this.name = \"SentryExampleFrontendError\";\n }\n }\n\n const hasSentError = ref(false);\n const isConnected = ref(true);\n \n onMounted(async () => {\n try {\n const result = await Sentry.diagnoseSdkConnectivity();\n isConnected.value = result !== 'sentry-unreachable';\n } catch (error) {\n isConnected.value = false;\n }\n });\n \n async function getSentryData() {\n await Sentry.startSpan(\n {\n name: 'Example Frontend Span',\n op: 'test'\n },\n async () => {\n const res = await $fetch('/api/sentry-example-api', { \n method: 'GET',\n ignoreResponseError: true \n }).catch(() => null);\n if (!res) {\n hasSentError.value = true;\n }\n }\n );\n throw new SentryExampleFrontendError(\"This error is raised on the frontend of the example page.\");\n }\n</script>\n\n<template>\n <title>Sentry Onboarding</title>\n <div>\n <main>\n <div class=\"flex-spacer\" />\n <svg height=\"40\" width=\"40\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M21.85 2.995a3.698 3.698 0 0 1 1.353 1.354l16.303 28.278a3.703 3.703 0 0 1-1.354 5.053 3.694 3.694 0 0 1-1.848.496h-3.828a31.149 31.149 0 0 0 0-3.09h3.815a.61.61 0 0 0 .537-.917L20.523 5.893a.61.61 0 0 0-1.057 0l-3.739 6.494a28.948 28.948 0 0 1 9.63 10.453 28.988 28.988 0 0 1 3.499 13.78v1.542h-9.852v-1.544a19.106 19.106 0 0 0-2.182-8.85 19.08 19.08 0 0 0-6.032-6.829l-1.85 3.208a15.377 15.377 0 0 1 6.382 12.484v1.542H3.696A3.694 3.694 0 0 1 0 34.473c0-.648.17-1.286.494-1.849l2.33-4.074a8.562 8.562 0 0 1 2.689 1.536L3.158 34.17a.611.611 0 0 0 .538.917h8.448a12.481 12.481 0 0 0-6.037-9.09l-1.344-.772 4.908-8.545 1.344.77a22.16 22.16 0 0 1 7.705 7.444 22.193 22.193 0 0 1 3.316 10.193h3.699a25.892 25.892 0 0 0-3.811-12.033 25.856 25.856 0 0 0-9.046-8.796l-1.344-.772 5.269-9.136a3.698 3.698 0 0 1 3.2-1.849c.648 0 1.285.17 1.847.495Z\" fill=\"currentcolor\"/>\n </svg>\n <h1>\n sentry-example-page\n </h1>\n\n <p class=\"description\">\n Click the button below, and view the sample error on the Sentry <a target=\"_blank\" href=\"${issuesPageLink}\">Issues Page</a>.\n For more details about setting up Sentry, <a target=\"_blank\" href=\"https://docs.sentry.io/platforms/javascript/guides/nuxt/\">read our docs</a>.\n </p>\n\n <button\n type=\"button\"\n @click=\"getSentryData\"\n :disabled=\"!isConnected\"\n >\n <span>\n Throw Sample Error\n </span>\n </button>\n\n <p v-if=\"hasSentError\" class=\"success\">\n Sample error was sent to Sentry.\n </p>\n <div v-else-if=\"!isConnected\" class=\"connectivity-error\">\n <p>It looks like network requests to Sentry are being blocked, which will prevent errors from being captured. Try disabling your ad-blocker to complete the test.</p>\n </div>\n <div v-else class=\"success_placeholder\" />\n\n <div class=\"flex-spacer\" />\n </main>\n </div>\n</template>\n\n<style scoped>\n :global(body) {\n margin: 0;\n\n @media (prefers-color-scheme: dark) {\n color: #ededed;\n background-color: #0a0a0a;\n }\n }\n\n main {\n display: flex;\n min-height: 100vh;\n box-sizing: border-box;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n gap: 16px;\n padding: 16px;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n\n h1 {\n padding: 0px 4px;\n margin: 0;\n border-radius: 4px;\n background-color: rgba(24, 20, 35, 0.03);\n font-family: monospace;\n font-size: 20px;\n line-height: 1.2;\n }\n\n p {\n margin: 0;\n font-size: 20px;\n }\n\n a {\n color: #6341F0;\n text-decoration: underline;\n cursor: pointer;\n\n @media (prefers-color-scheme: dark) {\n color: #B3A1FF;\n }\n }\n\n button {\n border-radius: 8px;\n color: white;\n cursor: pointer;\n background-color: #553DB8;\n border: none;\n padding: 0;\n margin-top: 4px;\n\n & > span {\n display: inline-block;\n padding: 12px 16px;\n border-radius: inherit;\n font-size: 20px;\n font-weight: bold;\n line-height: 1;\n background-color: #7553FF;\n border: 1px solid #553DB8;\n transform: translateY(-4px);\n }\n\n &:hover > span {\n transform: translateY(-8px);\n }\n\n &:active > span {\n transform: translateY(0); \n }\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.6;\n\n & > span {\n transform: translateY(0);\n border: none;\n }\n }\n }\n\n .description {\n text-align: center;\n color: #6E6C75;\n max-width: 500px;\n line-height: 1.5;\n font-size: 20px;\n\n @media (prefers-color-scheme: dark) {\n color: #A49FB5;\n }\n }\n\n .flex-spacer {\n flex: 1;\n }\n\n .success {\n padding: 12px 16px;\n border-radius: 8px;\n font-size: 20px;\n line-height: 1;\n background-color: #00F261;\n border: 1px solid #00BF4D;\n color: #181423;\n }\n\n .success_placeholder {\n height: 46px;\n }\n \n .connectivity-error {\n padding: 12px 16px;\n background-color: #E50045;\n border-radius: 8px;\n width: 500px;\n color: #FFFFFF;\n border: 1px solid #A80033;\n text-align: center;\n margin: 0;\n }\n \n .connectivity-error a {\n color: #FFFFFF;\n text-decoration: underline;\n }\n</style>\n\n`;\n}\n\nexport function getSentryExampleApiTemplate() {\n return `// This is just a very simple API route that throws an example error.\n// Feel free to delete this file.\nimport { defineEventHandler } from '#imports';\n\nexport default defineEventHandler(() => {\n throw new Error(\"Sentry Example API Route Error\");\n});\n`;\n}\n\nexport function getSentryErrorButtonTemplate() {\n return `<!--\nThis is just a very simple component that throws an example error.\nFeel free to delete this file.\n-->\n\n<script setup>\n import * as Sentry from '@sentry/nuxt';\n\n const hasSentError = ref(false);\n \n const throwError = () => {\n Sentry.startSpan(\n {\n name: 'Example Frontend Span',\n op: 'test'\n },\n () => {\n hasSentError.value = true;\n throw new Error('Sentry Example Error');\n }\n )\n };\n</script>\n\n<template>\n <div v-if=\"hasSentError\" class=\"success\">\n Sample error was sent to Sentry.\n </div>\n <button v-else @click=\"throwError\">\n <span>Throw Sample Error</span>\n </button>\n</template>\n\n<style scoped>\n button {\n border-radius: 8px;\n color: white;\n cursor: pointer;\n background-color: #553DB8;\n border: none;\n padding: 0;\n margin-top: 4px;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n\n & > span {\n display: inline-block;\n padding: 12px 16px;\n border-radius: inherit;\n font-size: 20px;\n font-weight: bold;\n line-height: 1;\n background-color: #7553FF;\n border: 1px solid #553DB8;\n transform: translateY(-4px);\n }\n\n &:hover > span {\n transform: translateY(-8px);\n }\n\n &:active > span {\n transform: translateY(0);\n }\n }\n\n .success {\n width: max-content;\n padding: 12px 16px;\n border-radius: 8px;\n font-size: 20px;\n line-height: 1;\n background-color: #00F261;\n border: 1px solid #00BF4D;\n color: #181423;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n</style>\n`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/nuxt/templates.ts"],"names":[],"mappings":"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","sourcesContent":["import { getIssueStreamUrl } from '../utils/url';\n\ntype SelectedSentryFeatures = {\n performance: boolean;\n replay: boolean;\n logs: boolean;\n};\n\nexport function getDefaultNuxtConfig(): string {\n return `// https://nuxt.com/docs/api/configuration/nuxt-config\nexport default defineNuxtConfig({\n compatibilityDate: '2024-04-03',\n devtools: { enabled: true }\n})\n`;\n}\n\nexport function getNuxtModuleFallbackTemplate(\n options: {\n org: string;\n project: string;\n url: string;\n selfHosted: boolean;\n },\n shouldTopLevelImport: boolean,\n): string {\n return ` modules: [\"@sentry/nuxt/module\"],\n sentry: {\n org: \"${options.org}\",\n project: \"${options.project}\",${\n options.selfHosted ? `\\n url: \"${options.url}\",` : ''\n }\n sourcemaps: { \n // This will delete all .map files in the build output after uploading them to Sentry. Modify as needed.\n // For more information, see: https://docs.sentry.io/platforms/javascript/guides/nuxt/sourcemaps/\n filesToDeleteAfterUpload: ['.*/**/*.map'] \n },${\n shouldTopLevelImport\n ? `\\n autoInjectServerSentry: \"top-level-import\",`\n : ''\n }\n },\n sourcemap: { client: \"hidden\" },`;\n}\n\nexport function getSentryConfigContents(\n dsn: string,\n config: 'client' | 'server',\n selectedFeatures: SelectedSentryFeatures,\n): string {\n if (config === 'client') {\n return getSentryClientConfigContents(dsn, selectedFeatures);\n }\n\n return getSentryServerConfigContents(dsn, selectedFeatures);\n}\n\nconst featuresConfigMap: Record<keyof SelectedSentryFeatures, string> = {\n performance: [\n ' // We recommend adjusting this value in production, or using tracesSampler',\n ' // for finer control',\n ' tracesSampleRate: 1.0,',\n ].join('\\n'),\n replay: [\n ' // This sets the sample rate to be 10%. You may want this to be 100% while',\n ' // in development and sample at a lower rate in production',\n ' replaysSessionSampleRate: 0.1,',\n ' ',\n ' // If the entire session is not sampled, use the below sample rate to sample',\n ' // sessions when an error occurs.',\n ' replaysOnErrorSampleRate: 1.0,',\n ' ',\n \" // If you don't want to use Session Replay, just remove the line below:\",\n ' integrations: [Sentry.replayIntegration()],',\n ].join('\\n'),\n logs: [' // Enable logs to be sent to Sentry', ' enableLogs: true,'].join(\n '\\n',\n ),\n};\n\nconst featuresMap: Record<\n 'client' | 'server',\n Array<keyof SelectedSentryFeatures>\n> = {\n client: ['performance', 'replay', 'logs'],\n server: ['performance', 'logs'],\n};\n\nexport function getConfigBody(\n dsn: string,\n variant: 'client' | 'server',\n selectedFeatures: SelectedSentryFeatures,\n) {\n return [\n `dsn: \"${dsn}\",`,\n Object.entries(selectedFeatures)\n .map(([feature, activated]: [keyof SelectedSentryFeatures, boolean]) => {\n return featuresMap[variant].includes(feature) && activated\n ? featuresConfigMap[feature]\n : null;\n })\n .filter(Boolean)\n .join('\\n\\n'),\n ]\n .filter(Boolean)\n .join('\\n\\n');\n}\n\nfunction getSentryClientConfigContents(\n dsn: string,\n selectedFeatures: SelectedSentryFeatures,\n): string {\n return `import * as Sentry from \"@sentry/nuxt\";\n\nSentry.init({\n // If set up, you can use your runtime config here\n // dsn: useRuntimeConfig().public.sentry.dsn,\n ${getConfigBody(dsn, 'client', selectedFeatures)}\n\n dataCollection: {\n // To disable sending user data and HTTP bodies, uncomment the lines below. For more info visit:\n // https://docs.sentry.io/platforms/javascript/guides/nuxt/configuration/options/#dataCollection\n // userInfo: false,\n // httpBodies: [],\n },\n\n // Setting this option to true will print useful information to the console while you're setting up Sentry.\n debug: false,\n});\n`;\n}\n\nfunction getSentryServerConfigContents(\n dsn: string,\n selectedFeatures: SelectedSentryFeatures,\n): string {\n return `import * as Sentry from \"@sentry/nuxt\";\n \nSentry.init({\n ${getConfigBody(dsn, 'server', selectedFeatures)}\n\n dataCollection: {\n // To disable sending user data and HTTP bodies, uncomment the lines below. For more info visit:\n // https://docs.sentry.io/platforms/javascript/guides/nuxt/configuration/options/#dataCollection\n // userInfo: false,\n // httpBodies: [],\n },\n\n // Setting this option to true will print useful information to the console while you're setting up Sentry.\n debug: false,\n});\n`;\n}\n\nexport function getIndexRouteTemplate(): string {\n return `<!--\nThis is just to verify the sentry-example-page.\nFeel free to delete this file.\n-->\n\n<template></template>`;\n}\n\nexport function getSentryExamplePageTemplate(options: {\n url: string;\n org: string;\n projectId: string;\n}): string {\n const { url, org, projectId } = options;\n const issuesPageLink = getIssueStreamUrl({ url, orgSlug: org, projectId });\n\n return `<!--\nThis is just a very simple page with a button to throw an example error.\nFeel free to delete this file.\n-->\n\n<script setup>\n import * as Sentry from '@sentry/nuxt';\n\n class SentryExampleFrontendError extends Error {\n constructor(message) {\n super(message);\n this.name = \"SentryExampleFrontendError\";\n }\n }\n\n const hasSentError = ref(false);\n const isConnected = ref(true);\n \n onMounted(async () => {\n try {\n const result = await Sentry.diagnoseSdkConnectivity();\n isConnected.value = result !== 'sentry-unreachable';\n } catch (error) {\n isConnected.value = false;\n }\n });\n \n async function getSentryData() {\n await Sentry.startSpan(\n {\n name: 'Example Frontend Span',\n op: 'test'\n },\n async () => {\n const res = await $fetch('/api/sentry-example-api', { \n method: 'GET',\n ignoreResponseError: true \n }).catch(() => null);\n if (!res) {\n hasSentError.value = true;\n }\n }\n );\n throw new SentryExampleFrontendError(\"This error is raised on the frontend of the example page.\");\n }\n</script>\n\n<template>\n <title>Sentry Onboarding</title>\n <div>\n <main>\n <div class=\"flex-spacer\" />\n <svg height=\"40\" width=\"40\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M21.85 2.995a3.698 3.698 0 0 1 1.353 1.354l16.303 28.278a3.703 3.703 0 0 1-1.354 5.053 3.694 3.694 0 0 1-1.848.496h-3.828a31.149 31.149 0 0 0 0-3.09h3.815a.61.61 0 0 0 .537-.917L20.523 5.893a.61.61 0 0 0-1.057 0l-3.739 6.494a28.948 28.948 0 0 1 9.63 10.453 28.988 28.988 0 0 1 3.499 13.78v1.542h-9.852v-1.544a19.106 19.106 0 0 0-2.182-8.85 19.08 19.08 0 0 0-6.032-6.829l-1.85 3.208a15.377 15.377 0 0 1 6.382 12.484v1.542H3.696A3.694 3.694 0 0 1 0 34.473c0-.648.17-1.286.494-1.849l2.33-4.074a8.562 8.562 0 0 1 2.689 1.536L3.158 34.17a.611.611 0 0 0 .538.917h8.448a12.481 12.481 0 0 0-6.037-9.09l-1.344-.772 4.908-8.545 1.344.77a22.16 22.16 0 0 1 7.705 7.444 22.193 22.193 0 0 1 3.316 10.193h3.699a25.892 25.892 0 0 0-3.811-12.033 25.856 25.856 0 0 0-9.046-8.796l-1.344-.772 5.269-9.136a3.698 3.698 0 0 1 3.2-1.849c.648 0 1.285.17 1.847.495Z\" fill=\"currentcolor\"/>\n </svg>\n <h1>\n sentry-example-page\n </h1>\n\n <p class=\"description\">\n Click the button below, and view the sample error on the Sentry <a target=\"_blank\" href=\"${issuesPageLink}\">Issues Page</a>.\n For more details about setting up Sentry, <a target=\"_blank\" href=\"https://docs.sentry.io/platforms/javascript/guides/nuxt/\">read our docs</a>.\n </p>\n\n <button\n type=\"button\"\n @click=\"getSentryData\"\n :disabled=\"!isConnected\"\n >\n <span>\n Throw Sample Error\n </span>\n </button>\n\n <p v-if=\"hasSentError\" class=\"success\">\n Sample error was sent to Sentry.\n </p>\n <div v-else-if=\"!isConnected\" class=\"connectivity-error\">\n <p>It looks like network requests to Sentry are being blocked, which will prevent errors from being captured. Try disabling your ad-blocker to complete the test.</p>\n </div>\n <div v-else class=\"success_placeholder\" />\n\n <div class=\"flex-spacer\" />\n </main>\n </div>\n</template>\n\n<style scoped>\n :global(body) {\n margin: 0;\n\n @media (prefers-color-scheme: dark) {\n color: #ededed;\n background-color: #0a0a0a;\n }\n }\n\n main {\n display: flex;\n min-height: 100vh;\n box-sizing: border-box;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n gap: 16px;\n padding: 16px;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n\n h1 {\n padding: 0px 4px;\n margin: 0;\n border-radius: 4px;\n background-color: rgba(24, 20, 35, 0.03);\n font-family: monospace;\n font-size: 20px;\n line-height: 1.2;\n }\n\n p {\n margin: 0;\n font-size: 20px;\n }\n\n a {\n color: #6341F0;\n text-decoration: underline;\n cursor: pointer;\n\n @media (prefers-color-scheme: dark) {\n color: #B3A1FF;\n }\n }\n\n button {\n border-radius: 8px;\n color: white;\n cursor: pointer;\n background-color: #553DB8;\n border: none;\n padding: 0;\n margin-top: 4px;\n\n & > span {\n display: inline-block;\n padding: 12px 16px;\n border-radius: inherit;\n font-size: 20px;\n font-weight: bold;\n line-height: 1;\n background-color: #7553FF;\n border: 1px solid #553DB8;\n transform: translateY(-4px);\n }\n\n &:hover > span {\n transform: translateY(-8px);\n }\n\n &:active > span {\n transform: translateY(0); \n }\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.6;\n\n & > span {\n transform: translateY(0);\n border: none;\n }\n }\n }\n\n .description {\n text-align: center;\n color: #6E6C75;\n max-width: 500px;\n line-height: 1.5;\n font-size: 20px;\n\n @media (prefers-color-scheme: dark) {\n color: #A49FB5;\n }\n }\n\n .flex-spacer {\n flex: 1;\n }\n\n .success {\n padding: 12px 16px;\n border-radius: 8px;\n font-size: 20px;\n line-height: 1;\n background-color: #00F261;\n border: 1px solid #00BF4D;\n color: #181423;\n }\n\n .success_placeholder {\n height: 46px;\n }\n \n .connectivity-error {\n padding: 12px 16px;\n background-color: #E50045;\n border-radius: 8px;\n width: 500px;\n color: #FFFFFF;\n border: 1px solid #A80033;\n text-align: center;\n margin: 0;\n }\n \n .connectivity-error a {\n color: #FFFFFF;\n text-decoration: underline;\n }\n</style>\n\n`;\n}\n\nexport function getSentryExampleApiTemplate() {\n return `// This is just a very simple API route that throws an example error.\n// Feel free to delete this file.\nimport { defineEventHandler } from '#imports';\n\nexport default defineEventHandler(() => {\n throw new Error(\"Sentry Example API Route Error\");\n});\n`;\n}\n\nexport function getSentryErrorButtonTemplate() {\n return `<!--\nThis is just a very simple component that throws an example error.\nFeel free to delete this file.\n-->\n\n<script setup>\n import * as Sentry from '@sentry/nuxt';\n\n const hasSentError = ref(false);\n \n const throwError = () => {\n Sentry.startSpan(\n {\n name: 'Example Frontend Span',\n op: 'test'\n },\n () => {\n hasSentError.value = true;\n throw new Error('Sentry Example Error');\n }\n )\n };\n</script>\n\n<template>\n <div v-if=\"hasSentError\" class=\"success\">\n Sample error was sent to Sentry.\n </div>\n <button v-else @click=\"throwError\">\n <span>Throw Sample Error</span>\n </button>\n</template>\n\n<style scoped>\n button {\n border-radius: 8px;\n color: white;\n cursor: pointer;\n background-color: #553DB8;\n border: none;\n padding: 0;\n margin-top: 4px;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n\n & > span {\n display: inline-block;\n padding: 12px 16px;\n border-radius: inherit;\n font-size: 20px;\n font-weight: bold;\n line-height: 1;\n background-color: #7553FF;\n border: 1px solid #553DB8;\n transform: translateY(-4px);\n }\n\n &:hover > span {\n transform: translateY(-8px);\n }\n\n &:active > span {\n transform: translateY(0);\n }\n }\n\n .success {\n width: max-content;\n padding: 12px 16px;\n border-radius: 8px;\n font-size: 20px;\n line-height: 1;\n background-color: #00F261;\n border: 1px solid #00BF4D;\n color: #181423;\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", sans-serif;\n }\n</style>\n`;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function instrumentClientEntry(clientEntryPath: string, dsn: string, enableTracing: boolean, enableReplay: boolean, enableLogs: boolean, useInstrumentationAPI?: boolean): Promise<void>;
|
|
1
|
+
export declare function instrumentClientEntry(clientEntryPath: string, dsn: string, enableTracing: boolean, enableReplay: boolean, enableLogs: boolean, useInstrumentationAPI?: boolean, useOnError?: boolean): Promise<void>;
|
|
@@ -30,7 +30,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
30
30
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
31
|
exports.instrumentClientEntry = void 0;
|
|
32
32
|
const recast = __importStar(require("recast"));
|
|
33
|
-
const path = __importStar(require("path"));
|
|
34
33
|
// @ts-expect-error - clack is ESM and TS complains about that. It works though
|
|
35
34
|
const prompts_1 = __importDefault(require("@clack/prompts"));
|
|
36
35
|
const chalk_1 = __importDefault(require("chalk"));
|
|
@@ -38,72 +37,108 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
38
37
|
const magicast_1 = require("magicast");
|
|
39
38
|
const ast_utils_1 = require("../../utils/ast-utils");
|
|
40
39
|
const utils_1 = require("./utils");
|
|
41
|
-
async function instrumentClientEntry(clientEntryPath, dsn, enableTracing, enableReplay, enableLogs, useInstrumentationAPI = false) {
|
|
40
|
+
async function instrumentClientEntry(clientEntryPath, dsn, enableTracing, enableReplay, enableLogs, useInstrumentationAPI = false, useOnError = false) {
|
|
42
41
|
const clientEntryAst = await (0, magicast_1.loadFile)(clientEntryPath);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
initContent = `
|
|
60
|
-
const tracing = Sentry.reactRouterTracingIntegration({ useInstrumentationAPI: true });
|
|
42
|
+
const alreadyHasSentry = (0, ast_utils_1.hasSentryContent)(clientEntryAst.$ast);
|
|
43
|
+
if (!alreadyHasSentry) {
|
|
44
|
+
clientEntryAst.imports.$add({
|
|
45
|
+
from: '@sentry/react-router',
|
|
46
|
+
imported: '*',
|
|
47
|
+
local: 'Sentry',
|
|
48
|
+
});
|
|
49
|
+
let initContent;
|
|
50
|
+
if (useInstrumentationAPI && enableTracing) {
|
|
51
|
+
const integrations = ['tracing'];
|
|
52
|
+
if (enableReplay) {
|
|
53
|
+
integrations.push('Sentry.replayIntegration()');
|
|
54
|
+
}
|
|
55
|
+
initContent = `
|
|
56
|
+
const tracing = Sentry.reactRouterTracingIntegration();
|
|
61
57
|
|
|
62
58
|
Sentry.init({
|
|
63
59
|
dsn: "${dsn}",
|
|
64
|
-
|
|
60
|
+
dataCollection: {
|
|
61
|
+
// To disable sending user data and HTTP bodies, uncomment the lines below. For more info visit:
|
|
62
|
+
// https://docs.sentry.io/platforms/javascript/guides/react-router/configuration/options/#dataCollection
|
|
63
|
+
// userInfo: false,
|
|
64
|
+
// httpBodies: [],
|
|
65
|
+
},
|
|
65
66
|
integrations: [${integrations.join(', ')}],
|
|
66
67
|
${enableLogs ? 'enableLogs: true,' : ''}
|
|
67
68
|
tracesSampleRate: 1.0,
|
|
68
69
|
tracePropagationTargets: [/^\\//, /^https:\\/\\/yourserver\\.io\\/api/],${enableReplay
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
? '\n replaysSessionSampleRate: 0.1,\n replaysOnErrorSampleRate: 1.0,'
|
|
71
|
+
: ''}
|
|
71
72
|
});`;
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
const integrations = [];
|
|
75
|
-
if (enableTracing) {
|
|
76
|
-
integrations.push('Sentry.reactRouterTracingIntegration()');
|
|
77
|
-
}
|
|
78
|
-
if (enableReplay) {
|
|
79
|
-
integrations.push('Sentry.replayIntegration()');
|
|
80
73
|
}
|
|
81
|
-
|
|
74
|
+
else {
|
|
75
|
+
const integrations = [];
|
|
76
|
+
if (enableTracing) {
|
|
77
|
+
integrations.push('Sentry.reactRouterTracingIntegration()');
|
|
78
|
+
}
|
|
79
|
+
if (enableReplay) {
|
|
80
|
+
integrations.push('Sentry.replayIntegration()');
|
|
81
|
+
}
|
|
82
|
+
initContent = `
|
|
82
83
|
Sentry.init({
|
|
83
84
|
dsn: "${dsn}",
|
|
84
|
-
|
|
85
|
+
dataCollection: {
|
|
86
|
+
// To disable sending user data and HTTP bodies, uncomment the lines below. For more info visit:
|
|
87
|
+
// https://docs.sentry.io/platforms/javascript/guides/react-router/configuration/options/#dataCollection
|
|
88
|
+
// userInfo: false,
|
|
89
|
+
// httpBodies: [],
|
|
90
|
+
},
|
|
85
91
|
integrations: [${integrations.join(', ')}],
|
|
86
92
|
${enableLogs ? 'enableLogs: true,' : ''}
|
|
87
93
|
tracesSampleRate: ${enableTracing ? '1.0' : '0'},${enableTracing
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
94
|
+
? '\n tracePropagationTargets: [/^\\//, /^https:\\/\\/yourserver\\.io\\/api/],'
|
|
95
|
+
: ''}${enableReplay
|
|
96
|
+
? '\n replaysSessionSampleRate: 0.1,\n replaysOnErrorSampleRate: 1.0,'
|
|
97
|
+
: ''}
|
|
92
98
|
});`;
|
|
99
|
+
}
|
|
100
|
+
clientEntryAst.$ast.body.splice((0, utils_1.getAfterImportsInsertionIndex)(clientEntryAst.$ast), 0, ...recast.parse(initContent).program.body);
|
|
101
|
+
}
|
|
102
|
+
const useInstrAPI = useInstrumentationAPI && enableTracing;
|
|
103
|
+
const addInstrProp = useInstrAPI && !alreadyHasSentry;
|
|
104
|
+
if (addInstrProp) {
|
|
105
|
+
addInstrumentationPropsToHydratedRouter(clientEntryAst.$ast);
|
|
106
|
+
}
|
|
107
|
+
if (useOnError) {
|
|
108
|
+
addOnErrorToHydratedRouter(clientEntryAst.$ast);
|
|
93
109
|
}
|
|
94
|
-
|
|
95
|
-
if (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
` ${chalk_1.default.green('<HydratedRouter unstable_instrumentations={[tracing.clientInstrumentation]} />')}`);
|
|
110
|
+
// Emit a single warning if HydratedRouter wasn't found for any prop we tried to add
|
|
111
|
+
if ((addInstrProp || useOnError) &&
|
|
112
|
+
!hasHydratedRouter(clientEntryAst.$ast)) {
|
|
113
|
+
const props = [];
|
|
114
|
+
if (useOnError) {
|
|
115
|
+
props.push('onError={Sentry.sentryOnError}');
|
|
101
116
|
}
|
|
117
|
+
if (addInstrProp) {
|
|
118
|
+
props.push('instrumentations={[tracing.clientInstrumentation]}');
|
|
119
|
+
}
|
|
120
|
+
prompts_1.default.log.warn(`Could not find ${chalk_1.default.cyan('HydratedRouter')} component in your client entry file.\n` +
|
|
121
|
+
`Manually add the following props:\n` +
|
|
122
|
+
` ${chalk_1.default.green(`<HydratedRouter ${props.join(' ')} />`)}`);
|
|
102
123
|
}
|
|
103
124
|
await (0, magicast_1.writeFile)(clientEntryAst.$ast, clientEntryPath);
|
|
104
125
|
}
|
|
105
126
|
exports.instrumentClientEntry = instrumentClientEntry;
|
|
106
|
-
function
|
|
127
|
+
function hasHydratedRouter(ast) {
|
|
128
|
+
let found = false;
|
|
129
|
+
recast.visit(ast, {
|
|
130
|
+
visitJSXElement(path) {
|
|
131
|
+
const name = path.node.openingElement.name;
|
|
132
|
+
if (name.type === 'JSXIdentifier' && name.name === 'HydratedRouter') {
|
|
133
|
+
found = true;
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
this.traverse(path);
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
return found;
|
|
140
|
+
}
|
|
141
|
+
function addPropToHydratedRouter(ast, propName, propValue) {
|
|
107
142
|
let found = false;
|
|
108
143
|
recast.visit(ast, {
|
|
109
144
|
visitJSXElement(path) {
|
|
@@ -111,17 +146,15 @@ function addInstrumentationPropsToHydratedRouter(ast) {
|
|
|
111
146
|
if (openingElement.name.type === 'JSXIdentifier' &&
|
|
112
147
|
openingElement.name.name === 'HydratedRouter') {
|
|
113
148
|
found = true;
|
|
114
|
-
const
|
|
149
|
+
const hasProp = openingElement.attributes?.some((attr) => attr.type === 'JSXAttribute' &&
|
|
115
150
|
attr.name.type === 'JSXIdentifier' &&
|
|
116
|
-
attr.name.name ===
|
|
117
|
-
if (!
|
|
118
|
-
const
|
|
119
|
-
recast.types.builders.memberExpression(recast.types.builders.identifier('tracing'), recast.types.builders.identifier('clientInstrumentation')),
|
|
120
|
-
])));
|
|
151
|
+
attr.name.name === propName);
|
|
152
|
+
if (!hasProp) {
|
|
153
|
+
const prop = recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier(propName), recast.types.builders.jsxExpressionContainer(propValue));
|
|
121
154
|
if (!openingElement.attributes) {
|
|
122
155
|
openingElement.attributes = [];
|
|
123
156
|
}
|
|
124
|
-
openingElement.attributes.push(
|
|
157
|
+
openingElement.attributes.push(prop);
|
|
125
158
|
}
|
|
126
159
|
return false;
|
|
127
160
|
}
|
|
@@ -130,4 +163,12 @@ function addInstrumentationPropsToHydratedRouter(ast) {
|
|
|
130
163
|
});
|
|
131
164
|
return found;
|
|
132
165
|
}
|
|
166
|
+
function addOnErrorToHydratedRouter(ast) {
|
|
167
|
+
return addPropToHydratedRouter(ast, 'onError', recast.types.builders.memberExpression(recast.types.builders.identifier('Sentry'), recast.types.builders.identifier('sentryOnError')));
|
|
168
|
+
}
|
|
169
|
+
function addInstrumentationPropsToHydratedRouter(ast) {
|
|
170
|
+
return addPropToHydratedRouter(ast, 'instrumentations', recast.types.builders.arrayExpression([
|
|
171
|
+
recast.types.builders.memberExpression(recast.types.builders.identifier('tracing'), recast.types.builders.identifier('clientInstrumentation')),
|
|
172
|
+
]));
|
|
173
|
+
}
|
|
133
174
|
//# sourceMappingURL=client.entry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.entry.js","sourceRoot":"","sources":["../../../../src/react-router/codemods/client.entry.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-argument */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n\nimport * as recast from 'recast';\nimport * as path from 'path';\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 { loadFile, writeFile } from 'magicast';\nimport { hasSentryContent } from '../../utils/ast-utils';\nimport { getAfterImportsInsertionIndex } from './utils';\n\nexport async function instrumentClientEntry(\n clientEntryPath: string,\n dsn: string,\n enableTracing: boolean,\n enableReplay: boolean,\n enableLogs: boolean,\n useInstrumentationAPI = false,\n): Promise<void> {\n const clientEntryAst = await loadFile(clientEntryPath);\n\n if (hasSentryContent(clientEntryAst.$ast as t.Program)) {\n const filename = path.basename(clientEntryPath);\n clack.log.info(`Sentry initialization found in ${chalk.cyan(filename)}`);\n return;\n }\n\n clientEntryAst.imports.$add({\n from: '@sentry/react-router',\n imported: '*',\n local: 'Sentry',\n });\n\n let initContent: string;\n\n if (useInstrumentationAPI && enableTracing) {\n const integrations = ['tracing'];\n if (enableReplay) {\n integrations.push('Sentry.replayIntegration()');\n }\n\n initContent = `\nconst tracing = Sentry.reactRouterTracingIntegration({ useInstrumentationAPI: true });\n\nSentry.init({\n dsn: \"${dsn}\",\n sendDefaultPii: true,\n integrations: [${integrations.join(', ')}],\n ${enableLogs ? 'enableLogs: true,' : ''}\n tracesSampleRate: 1.0,\n tracePropagationTargets: [/^\\\\//, /^https:\\\\/\\\\/yourserver\\\\.io\\\\/api/],${\n enableReplay\n ? '\\n replaysSessionSampleRate: 0.1,\\n replaysOnErrorSampleRate: 1.0,'\n : ''\n }\n});`;\n } else {\n const integrations = [];\n if (enableTracing) {\n integrations.push('Sentry.reactRouterTracingIntegration()');\n }\n if (enableReplay) {\n integrations.push('Sentry.replayIntegration()');\n }\n\n initContent = `\nSentry.init({\n dsn: \"${dsn}\",\n sendDefaultPii: true,\n integrations: [${integrations.join(', ')}],\n ${enableLogs ? 'enableLogs: true,' : ''}\n tracesSampleRate: ${enableTracing ? '1.0' : '0'},${\n enableTracing\n ? '\\n tracePropagationTargets: [/^\\\\//, /^https:\\\\/\\\\/yourserver\\\\.io\\\\/api/],'\n : ''\n }${\n enableReplay\n ? '\\n replaysSessionSampleRate: 0.1,\\n replaysOnErrorSampleRate: 1.0,'\n : ''\n }\n});`;\n }\n\n (clientEntryAst.$ast as t.Program).body.splice(\n getAfterImportsInsertionIndex(clientEntryAst.$ast as t.Program),\n 0,\n ...recast.parse(initContent).program.body,\n );\n\n if (useInstrumentationAPI && enableTracing) {\n const hydratedRouterFound = addInstrumentationPropsToHydratedRouter(\n clientEntryAst.$ast as t.Program,\n );\n\n if (!hydratedRouterFound) {\n clack.log.warn(\n `Could not find ${chalk.cyan(\n 'HydratedRouter',\n )} component in your client entry file.\\n` +\n `To use the Instrumentation API, manually add the ${chalk.cyan(\n 'unstable_instrumentations',\n )} prop:\\n` +\n ` ${chalk.green(\n '<HydratedRouter unstable_instrumentations={[tracing.clientInstrumentation]} />',\n )}`,\n );\n }\n }\n\n await writeFile(clientEntryAst.$ast, clientEntryPath);\n}\n\nfunction addInstrumentationPropsToHydratedRouter(ast: t.Program): boolean {\n let found = false;\n\n recast.visit(ast, {\n visitJSXElement(path) {\n const openingElement = path.node.openingElement;\n\n if (\n openingElement.name.type === 'JSXIdentifier' &&\n openingElement.name.name === 'HydratedRouter'\n ) {\n found = true;\n\n const hasInstrumentationsProp = openingElement.attributes?.some(\n (attr) =>\n attr.type === 'JSXAttribute' &&\n attr.name.type === 'JSXIdentifier' &&\n attr.name.name === 'unstable_instrumentations',\n );\n\n if (!hasInstrumentationsProp) {\n const instrumentationsProp = recast.types.builders.jsxAttribute(\n recast.types.builders.jsxIdentifier('unstable_instrumentations'),\n recast.types.builders.jsxExpressionContainer(\n recast.types.builders.arrayExpression([\n recast.types.builders.memberExpression(\n recast.types.builders.identifier('tracing'),\n recast.types.builders.identifier('clientInstrumentation'),\n ),\n ]),\n ),\n );\n\n if (!openingElement.attributes) {\n openingElement.attributes = [];\n }\n openingElement.attributes.push(instrumentationsProp);\n }\n\n return false;\n }\n\n this.traverse(path);\n },\n });\n\n return found;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"client.entry.js","sourceRoot":"","sources":["../../../../src/react-router/codemods/client.entry.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-argument */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n\nimport * as recast from 'recast';\nimport type { namedTypes as t } from 'ast-types';\nimport type { ExpressionKind } from 'ast-types/lib/gen/kinds';\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 { loadFile, writeFile } from 'magicast';\nimport { hasSentryContent } from '../../utils/ast-utils';\nimport { getAfterImportsInsertionIndex } from './utils';\n\nexport async function instrumentClientEntry(\n clientEntryPath: string,\n dsn: string,\n enableTracing: boolean,\n enableReplay: boolean,\n enableLogs: boolean,\n useInstrumentationAPI = false,\n useOnError = false,\n): Promise<void> {\n const clientEntryAst = await loadFile(clientEntryPath);\n\n const alreadyHasSentry = hasSentryContent(clientEntryAst.$ast as t.Program);\n\n if (!alreadyHasSentry) {\n clientEntryAst.imports.$add({\n from: '@sentry/react-router',\n imported: '*',\n local: 'Sentry',\n });\n\n let initContent: string;\n\n if (useInstrumentationAPI && enableTracing) {\n const integrations = ['tracing'];\n if (enableReplay) {\n integrations.push('Sentry.replayIntegration()');\n }\n\n initContent = `\nconst tracing = Sentry.reactRouterTracingIntegration();\n\nSentry.init({\n dsn: \"${dsn}\",\n dataCollection: {\n // To disable sending user data and HTTP bodies, uncomment the lines below. For more info visit:\n // https://docs.sentry.io/platforms/javascript/guides/react-router/configuration/options/#dataCollection\n // userInfo: false,\n // httpBodies: [],\n },\n integrations: [${integrations.join(', ')}],\n ${enableLogs ? 'enableLogs: true,' : ''}\n tracesSampleRate: 1.0,\n tracePropagationTargets: [/^\\\\//, /^https:\\\\/\\\\/yourserver\\\\.io\\\\/api/],${\n enableReplay\n ? '\\n replaysSessionSampleRate: 0.1,\\n replaysOnErrorSampleRate: 1.0,'\n : ''\n }\n});`;\n } else {\n const integrations = [];\n if (enableTracing) {\n integrations.push('Sentry.reactRouterTracingIntegration()');\n }\n if (enableReplay) {\n integrations.push('Sentry.replayIntegration()');\n }\n\n initContent = `\nSentry.init({\n dsn: \"${dsn}\",\n dataCollection: {\n // To disable sending user data and HTTP bodies, uncomment the lines below. For more info visit:\n // https://docs.sentry.io/platforms/javascript/guides/react-router/configuration/options/#dataCollection\n // userInfo: false,\n // httpBodies: [],\n },\n integrations: [${integrations.join(', ')}],\n ${enableLogs ? 'enableLogs: true,' : ''}\n tracesSampleRate: ${enableTracing ? '1.0' : '0'},${\n enableTracing\n ? '\\n tracePropagationTargets: [/^\\\\//, /^https:\\\\/\\\\/yourserver\\\\.io\\\\/api/],'\n : ''\n }${\n enableReplay\n ? '\\n replaysSessionSampleRate: 0.1,\\n replaysOnErrorSampleRate: 1.0,'\n : ''\n }\n});`;\n }\n\n (clientEntryAst.$ast as t.Program).body.splice(\n getAfterImportsInsertionIndex(clientEntryAst.$ast as t.Program),\n 0,\n ...recast.parse(initContent).program.body,\n );\n }\n\n const useInstrAPI = useInstrumentationAPI && enableTracing;\n const addInstrProp = useInstrAPI && !alreadyHasSentry;\n\n if (addInstrProp) {\n addInstrumentationPropsToHydratedRouter(clientEntryAst.$ast as t.Program);\n }\n\n if (useOnError) {\n addOnErrorToHydratedRouter(clientEntryAst.$ast as t.Program);\n }\n\n // Emit a single warning if HydratedRouter wasn't found for any prop we tried to add\n if (\n (addInstrProp || useOnError) &&\n !hasHydratedRouter(clientEntryAst.$ast as t.Program)\n ) {\n const props: string[] = [];\n if (useOnError) {\n props.push('onError={Sentry.sentryOnError}');\n }\n if (addInstrProp) {\n props.push('instrumentations={[tracing.clientInstrumentation]}');\n }\n clack.log.warn(\n `Could not find ${chalk.cyan(\n 'HydratedRouter',\n )} component in your client entry file.\\n` +\n `Manually add the following props:\\n` +\n ` ${chalk.green(`<HydratedRouter ${props.join(' ')} />`)}`,\n );\n }\n\n await writeFile(clientEntryAst.$ast, clientEntryPath);\n}\n\nfunction hasHydratedRouter(ast: t.Program): boolean {\n let found = false;\n recast.visit(ast, {\n visitJSXElement(path) {\n const name = path.node.openingElement.name;\n if (name.type === 'JSXIdentifier' && name.name === 'HydratedRouter') {\n found = true;\n return false;\n }\n this.traverse(path);\n },\n });\n return found;\n}\n\nfunction addPropToHydratedRouter(\n ast: t.Program,\n propName: string,\n propValue: ExpressionKind,\n): boolean {\n let found = false;\n\n recast.visit(ast, {\n visitJSXElement(path) {\n const openingElement = path.node.openingElement;\n\n if (\n openingElement.name.type === 'JSXIdentifier' &&\n openingElement.name.name === 'HydratedRouter'\n ) {\n found = true;\n\n const hasProp = openingElement.attributes?.some(\n (attr) =>\n attr.type === 'JSXAttribute' &&\n attr.name.type === 'JSXIdentifier' &&\n attr.name.name === propName,\n );\n\n if (!hasProp) {\n const prop = recast.types.builders.jsxAttribute(\n recast.types.builders.jsxIdentifier(propName),\n recast.types.builders.jsxExpressionContainer(propValue),\n );\n\n if (!openingElement.attributes) {\n openingElement.attributes = [];\n }\n openingElement.attributes.push(prop);\n }\n\n return false;\n }\n\n this.traverse(path);\n },\n });\n\n return found;\n}\n\nfunction addOnErrorToHydratedRouter(ast: t.Program): boolean {\n return addPropToHydratedRouter(\n ast,\n 'onError',\n recast.types.builders.memberExpression(\n recast.types.builders.identifier('Sentry'),\n recast.types.builders.identifier('sentryOnError'),\n ),\n );\n}\n\nfunction addInstrumentationPropsToHydratedRouter(ast: t.Program): boolean {\n return addPropToHydratedRouter(\n ast,\n 'instrumentations',\n recast.types.builders.arrayExpression([\n recast.types.builders.memberExpression(\n recast.types.builders.identifier('tracing'),\n recast.types.builders.identifier('clientInstrumentation'),\n ),\n ]),\n );\n}\n"]}
|
|
@@ -54,14 +54,14 @@ async function instrumentServerEntry(serverEntryPath, useInstrumentationAPI = fa
|
|
|
54
54
|
instrumentHandleError(serverEntryAst);
|
|
55
55
|
instrumentHandleRequest(serverEntryAst);
|
|
56
56
|
if (useInstrumentationAPI) {
|
|
57
|
-
|
|
57
|
+
instrumentInstrumentations(serverEntryAst);
|
|
58
58
|
}
|
|
59
59
|
await (0, magicast_1.writeFile)(serverEntryAst.$ast, serverEntryPath);
|
|
60
60
|
}
|
|
61
61
|
exports.instrumentServerEntry = instrumentServerEntry;
|
|
62
|
-
function
|
|
62
|
+
function instrumentInstrumentations(originalEntryServerMod) {
|
|
63
63
|
const originalEntryServerModAST = originalEntryServerMod.$ast;
|
|
64
|
-
const
|
|
64
|
+
const hasInstrumentations = originalEntryServerModAST.body.some((node) => {
|
|
65
65
|
if (node.type !== 'ExportNamedDeclaration' ||
|
|
66
66
|
node.declaration?.type !== 'VariableDeclaration') {
|
|
67
67
|
return false;
|
|
@@ -77,13 +77,14 @@ function instrumentUnstableInstrumentations(originalEntryServerMod) {
|
|
|
77
77
|
const id = firstDeclaration.id;
|
|
78
78
|
return (id &&
|
|
79
79
|
id.type === 'Identifier' &&
|
|
80
|
-
id.name === '
|
|
80
|
+
(id.name === 'instrumentations' ||
|
|
81
|
+
id.name === 'unstable_instrumentations'));
|
|
81
82
|
});
|
|
82
|
-
if (
|
|
83
|
-
(0, debug_1.debug)('
|
|
83
|
+
if (hasInstrumentations) {
|
|
84
|
+
(0, debug_1.debug)('instrumentations export already exists, skipping adding it again');
|
|
84
85
|
return;
|
|
85
86
|
}
|
|
86
|
-
const instrumentationsExport = recast.parse(`export const
|
|
87
|
+
const instrumentationsExport = recast.parse(`export const instrumentations = [Sentry.createSentryServerInstrumentation()];`).program.body[0];
|
|
87
88
|
originalEntryServerModAST.body.push(instrumentationsExport);
|
|
88
89
|
}
|
|
89
90
|
function instrumentHandleRequest(originalEntryServerMod) {
|