From bdac93d7e183b9fef86967786ff5409103167497 Mon Sep 17 00:00:00 2001 From: m5r Date: Tue, 7 Sep 2021 04:49:13 +0800 Subject: [PATCH] * custom error component * upload sourcemaps to sentry * report caught errors to sentry --- app/core/components/error-component.tsx | 63 ++++ app/pages/404.tsx | 4 +- app/pages/_app.tsx | 23 +- app/pages/_error.tsx | 1 + blitz.config.ts | 60 +++- fly.dev.toml | 2 + fly.prod.toml | 2 + integrations/sentry.ts | 34 ++ package-lock.json | 430 +++++++++++++++++++++++- package.json | 4 + 10 files changed, 596 insertions(+), 27 deletions(-) create mode 100644 app/core/components/error-component.tsx create mode 100644 app/pages/_error.tsx create mode 100644 integrations/sentry.ts diff --git a/app/core/components/error-component.tsx b/app/core/components/error-component.tsx new file mode 100644 index 0000000..ab89ca1 --- /dev/null +++ b/app/core/components/error-component.tsx @@ -0,0 +1,63 @@ +import type { ErrorProps } from "next/error"; +import { ErrorComponent as DefaultErrorComponent } from "blitz"; + +import Sentry from "../../../integrations/sentry"; + +type ExtraProps = { + hasGetInitialPropsRun?: boolean; + err?: any; +}; + +class ErrorComponent extends DefaultErrorComponent { + render() { + const { statusCode, hasGetInitialPropsRun, err } = this.props; + if (!hasGetInitialPropsRun && err) { + // getInitialProps is not called in case of + // https://github.com/vercel/next.js/issues/8592. As a workaround, we pass + // err via _app.js so it can be captured + Sentry.captureException(err); + } + + return ; + } +} + +ErrorComponent.getInitialProps = async (ctx) => { + const errorInitialProps: ErrorProps & ExtraProps = await DefaultErrorComponent.getInitialProps(ctx); + + // Workaround for https://github.com/vercel/next.js/issues/8592, mark when + // getInitialProps has run + errorInitialProps.hasGetInitialPropsRun = true; + + // Running on the server, the response object (`res`) is available. + // Next.js will pass an err on the server if a page's data fetching methods + // threw or returned a Promise that rejected + // + // Running on the client (browser), Next.js will provide an err if: + // - a page's `getInitialProps` threw or returned a Promise that rejected + // - an exception was thrown somewhere in the React lifecycle (render, + // componentDidMount, etc) that was caught by Next.js's React Error + // Boundary. Read more about what types of exceptions are caught by Error + // Boundaries: https://reactjs.org/docs/error-boundaries.html + + if (ctx.res?.statusCode === 404) { + // Opinionated: do not record an exception in Sentry for 404 + return { statusCode: 404 }; + } + + if (ctx.err) { + Sentry.captureException(ctx.err); + await Sentry.flush(2000); + return errorInitialProps; + } + + // If this point is reached, getInitialProps was called without any + // information about what the error might be. This is unexpected and may + // indicate a bug introduced in Next.js, so record it in Sentry + Sentry.captureException(new Error(`_error.js getInitialProps missing data at path: ${ctx.asPath}`)); + await Sentry.flush(2000); + + return errorInitialProps; +}; + +export default ErrorComponent; diff --git a/app/pages/404.tsx b/app/pages/404.tsx index beb388d..e3c6a8c 100644 --- a/app/pages/404.tsx +++ b/app/pages/404.tsx @@ -1,4 +1,6 @@ -import { Head, ErrorComponent } from "blitz"; +import { Head } from "blitz"; + +import ErrorComponent from "../core/components/error-component"; // ------------------------------------------------------ // This page is rendered if a route match is not found diff --git a/app/pages/_app.tsx b/app/pages/_app.tsx index 8f9466d..7a8b117 100644 --- a/app/pages/_app.tsx +++ b/app/pages/_app.tsx @@ -1,15 +1,17 @@ -import { Suspense } from "react"; +import { Suspense, useEffect } from "react"; import { AppProps, ErrorBoundary, - ErrorComponent, AuthenticationError, AuthorizationError, ErrorFallbackProps, useQueryErrorResetBoundary, getConfig, + useSession, } from "blitz"; +import Sentry from "../../integrations/sentry"; +import ErrorComponent from "../core/components/error-component"; import LoginForm from "../auth/components/login-form"; import { usePanelbear } from "../core/hooks/use-panelbear"; @@ -18,12 +20,27 @@ import "app/core/styles/index.css"; const { publicRuntimeConfig } = getConfig(); export default function App({ Component, pageProps }: AppProps) { + const session = useSession(); usePanelbear(publicRuntimeConfig.panelBear.siteId); + useEffect(() => { + if (session.userId) { + Sentry.setUser({ + id: session.userId.toString(), + orgId: session.orgId, + }); + } + }, [session]); const getLayout = Component.getLayout || ((page) => page); return ( - + + Sentry.captureException(error, { contexts: { react: { componentStack } } }) + } + FallbackComponent={RootErrorFallback} + onReset={useQueryErrorResetBoundary().reset} + > {getLayout()} ); diff --git a/app/pages/_error.tsx b/app/pages/_error.tsx new file mode 100644 index 0000000..066da66 --- /dev/null +++ b/app/pages/_error.tsx @@ -0,0 +1 @@ +export { default } from "../core/components/error-component"; diff --git a/blitz.config.ts b/blitz.config.ts index a4d4a3a..fe83b8f 100644 --- a/blitz.config.ts +++ b/blitz.config.ts @@ -1,10 +1,13 @@ /// import type { BlitzConfig } from "blitz"; import { sessionMiddleware, simpleRolesIsAuthorized } from "blitz"; +import SentryWebpackPlugin from "@sentry/webpack-plugin"; // import withPWA from "next-pwa"; type Module = Omit & { exports: BlitzConfig }; +const { SENTRY_DSN, SENTRY_ORG, SENTRY_PROJECT, SENTRY_AUTH_TOKEN, NODE_ENV, GITHUB_SHA } = process.env; + (module as Module).exports = { async header() { return [ @@ -36,7 +39,13 @@ type Module = Omit & { exports: BlitzConfig }; images: { domains: ["www.datocms-assets.com"], }, + productionBrowserSourceMaps: true, + env: { + SENTRY_DSN: process.env.SENTRY_DSN, + }, serverRuntimeConfig: { + rootDir: __dirname, + masterEncryptionKey: process.env.MASTER_ENCRYPTION_KEY, paddle: { apiKey: process.env.PADDLE_API_KEY, publicKey: process.env.PADDLE_PUBLIC_KEY, @@ -51,7 +60,6 @@ type Module = Omit & { exports: BlitzConfig }; apiKey: process.env.MAILCHIMP_API_KEY, audienceId: process.env.MAILCHIMP_AUDIENCE_ID, }, - masterEncryptionKey: process.env.MASTER_ENCRYPTION_KEY, app: { baseUrl: process.env.APP_BASE_URL, }, @@ -71,14 +79,52 @@ type Module = Omit & { exports: BlitzConfig }; siteId: process.env.PANELBEAR_SITE_ID, }, }, - /* Uncomment this to customize the webpack config + // @ts-ignore webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => { - // Note: we provide webpack above so you should not `require` it - // Perform customizations to webpack config - // Important: return the modified config - return config + // In `pages/_app.js`, Sentry is imported from @sentry/browser. While + // @sentry/node will run in a Node.js environment. @sentry/node will use + // Node.js-only APIs to catch even more unhandled exceptions. + // + // This works well when Next.js is SSRing your page on a server with + // Node.js, but it is not what we want when your client-side bundle is being + // executed by a browser. + // + // Luckily, Next.js will call this webpack function twice, once for the + // server and once for the client. Read more: + // https://nextjs.org/docs/api-reference/next.config.js/custom-webpack-config + // + // So ask Webpack to replace @sentry/node imports with @sentry/browser when + // building the browser's bundle + if (!isServer) { + config.resolve.alias["@sentry/node"] = "@sentry/browser"; + } + + // When all the Sentry configuration env variables are available/configured + // The Sentry webpack plugin gets pushed to the webpack plugins to build + // and upload the source maps to sentry. + // This is an alternative to manually uploading the source maps + // Note: This is disabled in development mode. + if ( + SENTRY_DSN && + SENTRY_ORG && + SENTRY_PROJECT && + SENTRY_AUTH_TOKEN && + GITHUB_SHA && + NODE_ENV === "production" + ) { + config.plugins.push( + new SentryWebpackPlugin({ + include: ".next", + ignore: ["node_modules"], + stripPrefix: ["webpack://_N_E/"], + urlPrefix: `~/_next`, + release: GITHUB_SHA, + }), + ); + } + + return config; }, - */ /*pwa: { dest: "public", disable: process.env.NODE_ENV !== "production", diff --git a/fly.dev.toml b/fly.dev.toml index d8b4b23..c10651b 100644 --- a/fly.dev.toml +++ b/fly.dev.toml @@ -18,6 +18,8 @@ processes = [] QUIRREL_API_URL = "https://queue.mokhtar.dev" QUIRREL_BASE_URL = "dev.shellphone.app" APP_BASE_URL = "dev.shellphone.app" + SENTRY_ORG = "capsule-corp" + SENTRY_PROJECT = "shellphone" [deploy] release_command = "/app/node_modules/.bin/blitz prisma migrate deploy" diff --git a/fly.prod.toml b/fly.prod.toml index cd4a137..ba353f7 100644 --- a/fly.prod.toml +++ b/fly.prod.toml @@ -18,6 +18,8 @@ processes = [] QUIRREL_API_URL = "https://queue.mokhtar.dev" QUIRREL_BASE_URL = "www.shellphone.app" APP_BASE_URL = "www.shellphone.app" + SENTRY_ORG = "capsule-corp" + SENTRY_PROJECT = "shellphone" [deploy] release_command = "/app/node_modules/.bin/blitz prisma migrate deploy" diff --git a/integrations/sentry.ts b/integrations/sentry.ts new file mode 100644 index 0000000..1471d45 --- /dev/null +++ b/integrations/sentry.ts @@ -0,0 +1,34 @@ +import * as Sentry from "@sentry/node"; +import getConfig from "next/config"; +import { RewriteFrames } from "@sentry/integrations"; + +if (process.env.SENTRY_DSN) { + const config = getConfig(); + const distDir = `${config.serverRuntimeConfig.rootDir}/.next`; + Sentry.init({ + integrations: [ + new RewriteFrames({ + iteratee: (frame: any) => { + frame.filename = frame.filename.replace(distDir, "app:///_next"); + return frame; + }, + }), + ], + dsn: process.env.SENTRY_DSN, + beforeSend(event, hint) { + const error = hint?.originalException; + if (error && typeof error !== "string") { + switch (error.name) { + case "AuthenticationError": + case "AuthorizationError": + case "NotFoundError": + case "ChunkLoadError": + return null; + } + } + return event; + }, + }); +} + +export default Sentry; diff --git a/package-lock.json b/package-lock.json index 2d41de9..e21b56a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3790,18 +3790,107 @@ "selderee": "^0.6.0" } }, - "@sentry/core": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.11.0.tgz", - "integrity": "sha512-09TB+f3pqEq8LFahFWHO6I/4DxHo+NcS52OkbWMDqEi6oNZRD7PhPn3i14LfjsYVv3u3AESU8oxSEGbFrr2UjQ==", + "@sentry/browser": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.12.0.tgz", + "integrity": "sha512-wsJi1NLOmfwtPNYxEC50dpDcVY7sdYckzwfqz1/zHrede1mtxpqSw+7iP4bHADOJXuF+ObYYTHND0v38GSXznQ==", "requires": { - "@sentry/hub": "6.11.0", - "@sentry/minimal": "6.11.0", - "@sentry/types": "6.11.0", - "@sentry/utils": "6.11.0", + "@sentry/core": "6.12.0", + "@sentry/types": "6.12.0", + "@sentry/utils": "6.12.0", "tslib": "^1.9.3" }, "dependencies": { + "@sentry/types": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.12.0.tgz", + "integrity": "sha512-urtgLzE4EDMAYQHYdkgC0Ei9QvLajodK1ntg71bGn0Pm84QUpaqpPDfHRU+i6jLeteyC7kWwa5O5W1m/jrjGXA==" + }, + "@sentry/utils": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-oRHQ7TH5TSsJqoP9Gqq25Jvn9LKexXfAh/OoKwjMhYCGKGhqpDNUIZVgl9DWsGw5A5N5xnQyLOxDfyRV5RshdA==", + "requires": { + "@sentry/types": "6.12.0", + "tslib": "^1.9.3" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "@sentry/cli": { + "version": "1.68.0", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-1.68.0.tgz", + "integrity": "sha512-zc7+cxKDqpHLREGJKRH6KwE8fZW8bnczg3OLibJ0czleXoWPdAuOK1Xm1BTMcOnaXfg3VKAh0rI7S1PTdj+SrQ==", + "requires": { + "https-proxy-agent": "^5.0.0", + "mkdirp": "^0.5.5", + "node-fetch": "^2.6.0", + "npmlog": "^4.1.2", + "progress": "^2.0.3", + "proxy-from-env": "^1.1.0" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + } + } + }, + "@sentry/core": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.12.0.tgz", + "integrity": "sha512-mU/zdjlzFHzdXDZCPZm8OeCw7c9xsbL49Mq0TrY0KJjLt4CJBkiq5SDTGfRsenBLgTedYhe5Z/J8Z+xVVq+MfQ==", + "requires": { + "@sentry/hub": "6.12.0", + "@sentry/minimal": "6.12.0", + "@sentry/types": "6.12.0", + "@sentry/utils": "6.12.0", + "tslib": "^1.9.3" + }, + "dependencies": { + "@sentry/hub": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.12.0.tgz", + "integrity": "sha512-yR/UQVU+ukr42bSYpeqvb989SowIXlKBanU0cqLFDmv5LPCnaQB8PGeXwJAwWhQgx44PARhmB82S6Xor8gYNxg==", + "requires": { + "@sentry/types": "6.12.0", + "@sentry/utils": "6.12.0", + "tslib": "^1.9.3" + } + }, + "@sentry/minimal": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.12.0.tgz", + "integrity": "sha512-r3C54Q1KN+xIqUvcgX9DlcoWE7ezWvFk2pSu1Ojx9De81hVqR9u5T3sdSAP2Xma+um0zr6coOtDJG4WtYlOtsw==", + "requires": { + "@sentry/hub": "6.12.0", + "@sentry/types": "6.12.0", + "tslib": "^1.9.3" + } + }, + "@sentry/types": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.12.0.tgz", + "integrity": "sha512-urtgLzE4EDMAYQHYdkgC0Ei9QvLajodK1ntg71bGn0Pm84QUpaqpPDfHRU+i6jLeteyC7kWwa5O5W1m/jrjGXA==" + }, + "@sentry/utils": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-oRHQ7TH5TSsJqoP9Gqq25Jvn9LKexXfAh/OoKwjMhYCGKGhqpDNUIZVgl9DWsGw5A5N5xnQyLOxDfyRV5RshdA==", + "requires": { + "@sentry/types": "6.12.0", + "tslib": "^1.9.3" + } + }, "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -3826,6 +3915,38 @@ } } }, + "@sentry/integrations": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-6.12.0.tgz", + "integrity": "sha512-M9gsVdWZp5fAFFpTjK2IBuWzW4SBxGAI3tVbYZvVx16S/BY0GsPC1dYpjJx9OTBS/8CmCWdGxnUmjACo/8w1LA==", + "requires": { + "@sentry/types": "6.12.0", + "@sentry/utils": "6.12.0", + "localforage": "^1.8.1", + "tslib": "^1.9.3" + }, + "dependencies": { + "@sentry/types": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.12.0.tgz", + "integrity": "sha512-urtgLzE4EDMAYQHYdkgC0Ei9QvLajodK1ntg71bGn0Pm84QUpaqpPDfHRU+i6jLeteyC7kWwa5O5W1m/jrjGXA==" + }, + "@sentry/utils": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-oRHQ7TH5TSsJqoP9Gqq25Jvn9LKexXfAh/OoKwjMhYCGKGhqpDNUIZVgl9DWsGw5A5N5xnQyLOxDfyRV5RshdA==", + "requires": { + "@sentry/types": "6.12.0", + "tslib": "^1.9.3" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, "@sentry/minimal": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.11.0.tgz", @@ -3844,21 +3965,67 @@ } }, "@sentry/node": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.11.0.tgz", - "integrity": "sha512-vbk+V/n7ZIFD8rHPYy03t/gIG5V7LGdjU4qJxVDgNZzticfWPnd2sLgle/r+l60XF6SKW/epG4rnxnBcgPdWaw==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.12.0.tgz", + "integrity": "sha512-hfAU3cX5sNWgqyDQBCOIQOZj21l0w1z2dG4MjmrMMHKrQ18pfMaaOtEwRXMCdjTUlwsK+L3TOoUB23lbezmu1A==", "requires": { - "@sentry/core": "6.11.0", - "@sentry/hub": "6.11.0", - "@sentry/tracing": "6.11.0", - "@sentry/types": "6.11.0", - "@sentry/utils": "6.11.0", + "@sentry/core": "6.12.0", + "@sentry/hub": "6.12.0", + "@sentry/tracing": "6.12.0", + "@sentry/types": "6.12.0", + "@sentry/utils": "6.12.0", "cookie": "^0.4.1", "https-proxy-agent": "^5.0.0", "lru_map": "^0.3.3", "tslib": "^1.9.3" }, "dependencies": { + "@sentry/hub": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.12.0.tgz", + "integrity": "sha512-yR/UQVU+ukr42bSYpeqvb989SowIXlKBanU0cqLFDmv5LPCnaQB8PGeXwJAwWhQgx44PARhmB82S6Xor8gYNxg==", + "requires": { + "@sentry/types": "6.12.0", + "@sentry/utils": "6.12.0", + "tslib": "^1.9.3" + } + }, + "@sentry/minimal": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.12.0.tgz", + "integrity": "sha512-r3C54Q1KN+xIqUvcgX9DlcoWE7ezWvFk2pSu1Ojx9De81hVqR9u5T3sdSAP2Xma+um0zr6coOtDJG4WtYlOtsw==", + "requires": { + "@sentry/hub": "6.12.0", + "@sentry/types": "6.12.0", + "tslib": "^1.9.3" + } + }, + "@sentry/tracing": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.12.0.tgz", + "integrity": "sha512-u10QHNknPBzbWSUUNMkvuH53sQd5NaBo6YdNPj4p5b7sE7445Sh0PwBpRbY3ZiUUiwyxV59fx9UQ4yVnPGxZQA==", + "requires": { + "@sentry/hub": "6.12.0", + "@sentry/minimal": "6.12.0", + "@sentry/types": "6.12.0", + "@sentry/utils": "6.12.0", + "tslib": "^1.9.3" + } + }, + "@sentry/types": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.12.0.tgz", + "integrity": "sha512-urtgLzE4EDMAYQHYdkgC0Ei9QvLajodK1ntg71bGn0Pm84QUpaqpPDfHRU+i6jLeteyC7kWwa5O5W1m/jrjGXA==" + }, + "@sentry/utils": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-oRHQ7TH5TSsJqoP9Gqq25Jvn9LKexXfAh/OoKwjMhYCGKGhqpDNUIZVgl9DWsGw5A5N5xnQyLOxDfyRV5RshdA==", + "requires": { + "@sentry/types": "6.12.0", + "tslib": "^1.9.3" + } + }, "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -3906,6 +4073,14 @@ } } }, + "@sentry/webpack-plugin": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-1.17.1.tgz", + "integrity": "sha512-L47a0hxano4a+9jbvQSBzHCT1Ph8fYAvGGUvFg8qc69yXS9si5lXRNIH/pavN6mqJjhQjAcEsEp+vxgvT4xZDQ==", + "requires": { + "@sentry/cli": "^1.68.0" + } + }, "@sindresorhus/is": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.1.tgz", @@ -4939,6 +5114,11 @@ "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, "archiver": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/archiver/-/archiver-4.0.2.tgz", @@ -5011,6 +5191,44 @@ "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "arg": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", @@ -6695,6 +6913,11 @@ "convert-to-spaces": "^1.0.1" } }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, "collect-v8-coverage": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", @@ -7066,6 +7289,11 @@ "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, "console-table-printer": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/console-table-printer/-/console-table-printer-2.10.0.tgz", @@ -7734,6 +7962,11 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, "denque": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", @@ -9690,6 +9923,54 @@ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -9894,6 +10175,11 @@ "has-symbols": "^1.0.2" } }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -10237,6 +10523,11 @@ "queue": "6.0.2" } }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" + }, "import-cwd": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-3.0.0.tgz", @@ -12881,6 +13172,14 @@ "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", "dev": true }, + "lie": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", + "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", + "requires": { + "immediate": "~3.0.5" + } + }, "light-my-request": { "version": "4.4.4", "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-4.4.4.tgz", @@ -13060,6 +13359,14 @@ } } }, + "localforage": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", + "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==", + "requires": { + "lie": "3.1.1" + } + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -14626,6 +14933,17 @@ "which": "^1.2.10" } }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, "null-loader": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/null-loader/-/null-loader-4.0.1.tgz", @@ -14635,6 +14953,11 @@ "schema-utils": "^3.0.0" } }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, "nwsapi": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", @@ -15824,6 +16147,11 @@ } } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -16109,6 +16437,34 @@ "zod": "^3.0.0-alpha.29" }, "dependencies": { + "@sentry/core": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.11.0.tgz", + "integrity": "sha512-09TB+f3pqEq8LFahFWHO6I/4DxHo+NcS52OkbWMDqEi6oNZRD7PhPn3i14LfjsYVv3u3AESU8oxSEGbFrr2UjQ==", + "requires": { + "@sentry/hub": "6.11.0", + "@sentry/minimal": "6.11.0", + "@sentry/types": "6.11.0", + "@sentry/utils": "6.11.0", + "tslib": "^1.9.3" + } + }, + "@sentry/node": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.11.0.tgz", + "integrity": "sha512-vbk+V/n7ZIFD8rHPYy03t/gIG5V7LGdjU4qJxVDgNZzticfWPnd2sLgle/r+l60XF6SKW/epG4rnxnBcgPdWaw==", + "requires": { + "@sentry/core": "6.11.0", + "@sentry/hub": "6.11.0", + "@sentry/tracing": "6.11.0", + "@sentry/types": "6.11.0", + "@sentry/utils": "6.11.0", + "cookie": "^0.4.1", + "https-proxy-agent": "^5.0.0", + "lru_map": "^0.3.3", + "tslib": "^1.9.3" + } + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -16248,6 +16604,11 @@ "has-flag": "^4.0.0" } }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -19622,6 +19983,43 @@ "is-typed-array": "^1.1.7" } }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "^1.0.2 || 2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, "widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", diff --git a/package.json b/package.json index 307b02b..c74dca4 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,10 @@ "@panelbear/panelbear-js": "1.2.0", "@prisma/client": "2.30.0", "@react-aria/interactions": "3.5.1", + "@sentry/browser": "6.12.0", + "@sentry/integrations": "6.12.0", + "@sentry/node": "6.12.0", + "@sentry/webpack-plugin": "1.17.1", "@tailwindcss/forms": "0.3.3", "@tailwindcss/line-clamp": "0.2.1", "@tailwindcss/typography": "0.4.1",