diff --git a/.changeset/gold-pigs-knock.md b/.changeset/gold-pigs-knock.md new file mode 100644 index 0000000..538d81e --- /dev/null +++ b/.changeset/gold-pigs-knock.md @@ -0,0 +1,5 @@ +--- +"saleor-app-taxes": patch +--- + +Added Sentry configuration that can be enabled via env variables diff --git a/apps/taxes/.gitignore b/apps/taxes/.gitignore new file mode 100644 index 0000000..12a64be --- /dev/null +++ b/apps/taxes/.gitignore @@ -0,0 +1,6 @@ + +# Sentry +.sentryclirc + +# Sentry +next.config.original.js diff --git a/apps/taxes/next.config.js b/apps/taxes/next.config.js index 26fb3f0..e19ff7d 100644 --- a/apps/taxes/next.config.js +++ b/apps/taxes/next.config.js @@ -1,10 +1,29 @@ +// This file sets a custom webpack configuration to use your Next.js app +// with Sentry. +// https://nextjs.org/docs/api-reference/next.config.js/introduction +// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/ +const { withSentryConfig } = require("@sentry/nextjs"); + +const isSentryPropertiesInEnvironment = + process.env.SENTRY_AUTH_TOKEN && process.env.SENTRY_PROJECT && process.env.SENTRY_ORG; + /** * @type {import('next').NextConfig} */ -module.exports = { +const config = { reactStrictMode: true, experimental: { esmExternals: true, }, transpilePackages: ["@saleor/apps-shared"], }; + +module.exports = withSentryConfig( + config, + { silent: true }, + { + hideSourcemaps: true, + disableServerWebpackPlugin: !isSentryPropertiesInEnvironment, + disableClientWebpackPlugin: !isSentryPropertiesInEnvironment, + } +); diff --git a/apps/taxes/package.json b/apps/taxes/package.json index 0b4b310..908f83b 100644 --- a/apps/taxes/package.json +++ b/apps/taxes/package.json @@ -45,7 +45,8 @@ "usehooks-ts": "^2.9.1", "vite": "^4.0.1", "vitest": "^0.25.8", - "zod": "^3.20.2" + "zod": "^3.20.2", + "@sentry/nextjs": "^7.45.0" }, "devDependencies": { "@graphql-codegen/cli": "3.2.2", diff --git a/apps/taxes/sentry.client.config.js b/apps/taxes/sentry.client.config.js new file mode 100644 index 0000000..09f7c52 --- /dev/null +++ b/apps/taxes/sentry.client.config.js @@ -0,0 +1,17 @@ +// This file configures the initialization of Sentry on the browser. +// The config you add here will be used whenever a page is visited. +// https://docs.sentry.io/platforms/javascript/guides/nextjs/ + +import * as Sentry from '@sentry/nextjs'; + +const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN; + +Sentry.init({ + dsn: SENTRY_DSN, + // Adjust this value in production, or use tracesSampler for greater control + tracesSampleRate: 1.0, + // ... + // Note: if you want to override the automatic release value, do not set a + // `release` value here - use the environment variable `SENTRY_RELEASE`, so + // that it will also get attached to your source maps +}); diff --git a/apps/taxes/sentry.edge.config.js b/apps/taxes/sentry.edge.config.js new file mode 100644 index 0000000..fcf9cb8 --- /dev/null +++ b/apps/taxes/sentry.edge.config.js @@ -0,0 +1,17 @@ +// This file configures the initialization of Sentry on the server. +// The config you add here will be used whenever middleware or an Edge route handles a request. +// https://docs.sentry.io/platforms/javascript/guides/nextjs/ + +import * as Sentry from '@sentry/nextjs'; + +const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN; + +Sentry.init({ + dsn: SENTRY_DSN, + // Adjust this value in production, or use tracesSampler for greater control + tracesSampleRate: 1.0, + // ... + // Note: if you want to override the automatic release value, do not set a + // `release` value here - use the environment variable `SENTRY_RELEASE`, so + // that it will also get attached to your source maps +}); diff --git a/apps/taxes/sentry.server.config.js b/apps/taxes/sentry.server.config.js new file mode 100644 index 0000000..990cf22 --- /dev/null +++ b/apps/taxes/sentry.server.config.js @@ -0,0 +1,17 @@ +// This file configures the initialization of Sentry on the server. +// The config you add here will be used whenever the server handles a request. +// https://docs.sentry.io/platforms/javascript/guides/nextjs/ + +import * as Sentry from '@sentry/nextjs'; + +const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN; + +Sentry.init({ + dsn: SENTRY_DSN, + // Adjust this value in production, or use tracesSampler for greater control + tracesSampleRate: 1.0, + // ... + // Note: if you want to override the automatic release value, do not set a + // `release` value here - use the environment variable `SENTRY_RELEASE`, so + // that it will also get attached to your source maps +}); diff --git a/apps/taxes/src/pages/_error.js b/apps/taxes/src/pages/_error.js new file mode 100644 index 0000000..49f0ea6 --- /dev/null +++ b/apps/taxes/src/pages/_error.js @@ -0,0 +1,39 @@ +/** + * NOTE: This requires `@sentry/nextjs` version 7.3.0 or higher. + * + * NOTE: If using this with `next` version 12.2.0 or lower, uncomment the + * penultimate line in `CustomErrorComponent`. + * + * This page is loaded by Nextjs: + * - on the server, when data-fetching methods throw or reject + * - on the client, when `getInitialProps` throws or rejects + * - on the client, when a React lifecycle method throws or rejects, and it's + * caught by the built-in Nextjs error boundary + * + * See: + * - https://nextjs.org/docs/basic-features/data-fetching/overview + * - https://nextjs.org/docs/api-reference/data-fetching/get-initial-props + * - https://reactjs.org/docs/error-boundaries.html + */ + +import * as Sentry from '@sentry/nextjs'; +import NextErrorComponent from 'next/error'; + +const CustomErrorComponent = props => { + // If you're using a Nextjs version prior to 12.2.1, uncomment this to + // compensate for https://github.com/vercel/next.js/issues/8592 + // Sentry.captureUnderscoreErrorException(props); + + return ; +}; + +CustomErrorComponent.getInitialProps = async contextData => { + // In case this is running in a serverless function, await this in order to give Sentry + // time to send the error before the lambda exits + await Sentry.captureUnderscoreErrorException(contextData); + + // This will contain the status code of the response + return NextErrorComponent.getInitialProps(contextData); +}; + +export default CustomErrorComponent; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9b8596e..bd89d7b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -905,6 +905,7 @@ importers: '@saleor/app-sdk': 0.37.1 '@saleor/apps-shared': workspace:* '@saleor/macaw-ui': ^0.7.2 + '@sentry/nextjs': ^7.45.0 '@tanstack/react-query': ^4.19.1 '@testing-library/react': ^13.4.0 '@testing-library/react-hooks': ^8.0.1 @@ -950,6 +951,7 @@ importers: '@saleor/app-sdk': 0.37.1_nvzgbose6yf6w7ijjprgspqefi '@saleor/apps-shared': link:../../packages/shared '@saleor/macaw-ui': 0.7.2_pmlnlm755hlzzzocw2qhf3a34e + '@sentry/nextjs': 7.45.0_next@13.2.3+react@18.2.0 '@tanstack/react-query': 4.24.4_biqbaboplfbrettd7655fr4n2y '@trpc/client': 10.10.0_@trpc+server@10.10.0 '@trpc/next': 10.10.0_lcxe5qnfqqdfrxa5owczufvuce @@ -4889,6 +4891,16 @@ packages: - debug dev: false + /@sentry-internal/tracing/7.45.0: + resolution: {integrity: sha512-0aIDY2OvUX7k2XHaimOlWkboXoQvJ9dEKvfpu0Wh0YxfUTGPa+wplUdg3WVdkk018sq1L11MKmj4MPZyYUvXhw==} + engines: {node: '>=8'} + dependencies: + '@sentry/core': 7.45.0 + '@sentry/types': 7.45.0 + '@sentry/utils': 7.45.0 + tslib: 1.14.1 + dev: false + /@sentry/browser/7.36.0: resolution: {integrity: sha512-Mu0OpisCZFICBGxVXdHWjUDgSvuQKjnO9acNcXR1+68IU08iX+cU6f2kq6VzI4mW/pNieI20FDFbx9KA0YZ4+A==} engines: {node: '>=8'} @@ -4922,6 +4934,18 @@ packages: tslib: 1.14.1 dev: false + /@sentry/browser/7.45.0: + resolution: {integrity: sha512-/dUrUwnI34voMj+jSJT7b5Jun+xy1utVyzzwTq3Oc22N+SB17ZOX9svZ4jl1Lu6tVJPVjPyvL6zlcbrbMwqFjg==} + engines: {node: '>=8'} + dependencies: + '@sentry-internal/tracing': 7.45.0 + '@sentry/core': 7.45.0 + '@sentry/replay': 7.45.0 + '@sentry/types': 7.45.0 + '@sentry/utils': 7.45.0 + tslib: 1.14.1 + dev: false + /@sentry/cli/1.74.6: resolution: {integrity: sha512-pJ7JJgozyjKZSTjOGi86chIngZMLUlYt2HOog+OJn+WGvqEkVymu8m462j1DiXAnex9NspB4zLLNuZ/R6rTQHg==} engines: {node: '>= 8'} @@ -4967,6 +4991,15 @@ packages: tslib: 1.14.1 dev: false + /@sentry/core/7.45.0: + resolution: {integrity: sha512-xJfdTS4lRmHvZI/A5MazdnKhBJFkisKu6G9EGNLlZLre+6W4PH5sb7QX4+xoBdqG7v10Jvdia112vi762ojO2w==} + engines: {node: '>=8'} + dependencies: + '@sentry/types': 7.45.0 + '@sentry/utils': 7.45.0 + tslib: 1.14.1 + dev: false + /@sentry/integrations/7.36.0: resolution: {integrity: sha512-wrRoUqdeGi64NNimGVk8U8DBiXamxTYPBux0/faFDyau8EJyQFcv8zOyB78Za4W2Ss3ZXNaE/WtFF8UxalHzBQ==} engines: {node: '>=8'} @@ -4997,6 +5030,16 @@ packages: tslib: 1.14.1 dev: false + /@sentry/integrations/7.45.0: + resolution: {integrity: sha512-2lwBACr7w9YmnilndRH+39Ow97DJIZUPsDMlppu2NNFEZl2fBDpl+YWh7rxuMIpsOKqZkgxVhxWuoZL9gcWvEA==} + engines: {node: '>=8'} + dependencies: + '@sentry/types': 7.45.0 + '@sentry/utils': 7.45.0 + localforage: 1.10.0 + tslib: 1.14.1 + dev: false + /@sentry/nextjs/7.36.0_next@13.1.0+react@18.2.0: resolution: {integrity: sha512-7IUwBjCjo3rWuvEG16D1wKb0D+aMyCU920VGCAQVZaqTZAgrgAKfpTa1Sk0fmDxYglW1EBI9QM+WEnOa9RleLw==} engines: {node: '>=8'} @@ -5118,6 +5161,36 @@ packages: - supports-color dev: false + /@sentry/nextjs/7.45.0_next@13.2.3+react@18.2.0: + resolution: {integrity: sha512-JEWM3g0X1a57qY6PpCFUYr/Zigyl/AlmVwl8RbAS9J4LF5M6wD9CXSFIGOtS+Pt3KoxJCgiUsRJg+KCsszIcCg==} + engines: {node: '>=8'} + peerDependencies: + next: ^10.0.8 || ^11.0 || ^12.0 || ^13.0 + react: 16.x || 17.x || 18.x + webpack: '>= 4.0.0' + peerDependenciesMeta: + webpack: + optional: true + dependencies: + '@rollup/plugin-commonjs': 24.0.0_rollup@2.78.0 + '@sentry/core': 7.45.0 + '@sentry/integrations': 7.45.0 + '@sentry/node': 7.45.0 + '@sentry/react': 7.45.0_react@18.2.0 + '@sentry/types': 7.45.0 + '@sentry/utils': 7.45.0 + '@sentry/webpack-plugin': 1.20.0 + chalk: 3.0.0 + next: 13.2.3_biqbaboplfbrettd7655fr4n2y + react: 18.2.0 + rollup: 2.78.0 + stacktrace-parser: 0.1.10 + tslib: 1.14.1 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + /@sentry/node/7.36.0: resolution: {integrity: sha512-nAHAY+Rbn5OlTpNX/i6wYrmw3hT/BtwPZ/vNU52cKgw7CpeE1UrCeFjnPn18rQPB7lIh7x0vNvoaPrfemRzpSQ==} engines: {node: '>=8'} @@ -5163,6 +5236,22 @@ packages: - supports-color dev: false + /@sentry/node/7.45.0: + resolution: {integrity: sha512-x8mq+DrJWpSi716Rap/2w70DKWD8vjl87Y70OYFu+Dn6CxWDHClObSxLzuJcE5lww0Sq9RnU6UHQWzjXSb/pVQ==} + engines: {node: '>=8'} + dependencies: + '@sentry-internal/tracing': 7.45.0 + '@sentry/core': 7.45.0 + '@sentry/types': 7.45.0 + '@sentry/utils': 7.45.0 + cookie: 0.4.2 + https-proxy-agent: 5.0.1 + lru_map: 0.3.3 + tslib: 1.14.1 + transitivePeerDependencies: + - supports-color + dev: false + /@sentry/react/7.36.0_react@18.2.0: resolution: {integrity: sha512-ttrRqbgeqvkV3DwkDRZC/V8OEnBKGpQf4dKpG8oMlfdVbMTINzrxYUgkhi9xAkxkH9O+vj3Md8L3Rdqw/SDwKQ==} engines: {node: '>=8'} @@ -5205,6 +5294,20 @@ packages: tslib: 1.14.1 dev: false + /@sentry/react/7.45.0_react@18.2.0: + resolution: {integrity: sha512-Dbz85nfvMUikbLHUuIt6fBNPmTvThFn+rWB5KS1NIOJifyWAdpIU3X7yCUJE5xhsUObNLiHlNJlqhaQI4nR1bQ==} + engines: {node: '>=8'} + peerDependencies: + react: 15.x || 16.x || 17.x || 18.x + dependencies: + '@sentry/browser': 7.45.0 + '@sentry/types': 7.45.0 + '@sentry/utils': 7.45.0 + hoist-non-react-statics: 3.3.2 + react: 18.2.0 + tslib: 1.14.1 + dev: false + /@sentry/replay/7.36.0: resolution: {integrity: sha512-wNbME74/2GtkqdDXz7NaStyfPWVLjYmN9TFWvu6E9sNl9pkDDvii/Qc8F6ps1wa7bozkKcWRHgNvYiGCxUBHcg==} engines: {node: '>=12'} @@ -5232,6 +5335,15 @@ packages: '@sentry/utils': 7.43.0 dev: false + /@sentry/replay/7.45.0: + resolution: {integrity: sha512-smM7FIcFIyKu30BqCl8BzLo1gH/z9WwXdGX6V0fNvHab9fJZ09+xjFn+LmIyo6N8H8jjwsup0+yQ12kiF/ZsEw==} + engines: {node: '>=12'} + dependencies: + '@sentry/core': 7.45.0 + '@sentry/types': 7.45.0 + '@sentry/utils': 7.45.0 + dev: false + /@sentry/tracing/7.36.0: resolution: {integrity: sha512-5R5mfWMDncOcTMmmyYMjgus1vZJzIFw4LHaSbrX7e1IRNT/6vFyNeVxATa2ePXb9mI3XHo5f2p7YrnreAtaSXw==} engines: {node: '>=8'} @@ -5277,6 +5389,11 @@ packages: engines: {node: '>=8'} dev: false + /@sentry/types/7.45.0: + resolution: {integrity: sha512-iFt7msfUK8LCodFF3RKUyaxy9tJv/gpWhzxUFyNxtuVwlpmd+q6mtsFGn8Af3pbpm8A+MKyz1ebMwXj0PQqknw==} + engines: {node: '>=8'} + dev: false + /@sentry/utils/7.36.0: resolution: {integrity: sha512-mgDi5X5Bm0sydCzXpnyKD/sD98yc2qnKXyRdNX4HRRwruhC/P53LT0hGhZXsyqsB/l8OAMl0zWXJLg0xONQsEw==} engines: {node: '>=8'} @@ -5301,6 +5418,14 @@ packages: tslib: 1.14.1 dev: false + /@sentry/utils/7.45.0: + resolution: {integrity: sha512-aTY7qqtNUudd09SH5DVSKMm3iQ6ZeWufduc0I9bPZe6UMM09BDc4KmjmrzRkdQ+VaOmHo7+v+HZKQk5f+AbuTQ==} + engines: {node: '>=8'} + dependencies: + '@sentry/types': 7.45.0 + tslib: 1.14.1 + dev: false + /@sentry/webpack-plugin/1.20.0: resolution: {integrity: sha512-Ssj1mJVFsfU6vMCOM2d+h+KQR7QHSfeIP16t4l20Uq/neqWXZUQ2yvQfe4S3BjdbJXz/X4Rw8Hfy1Sd0ocunYw==} engines: {node: '>= 8'}