diff --git a/packages/twenty-front/package.json b/packages/twenty-front/package.json index d2170c6315..440ae551c0 100644 --- a/packages/twenty-front/package.json +++ b/packages/twenty-front/package.json @@ -47,6 +47,7 @@ "@floating-ui/react": "^0.24.3", "@hello-pangea/dnd": "^16.2.0", "@hookform/resolvers": "^3.1.1", + "@sentry/react": "^7.88.0", "@sniptt/guards": "^0.2.0", "@swc/core": "^1.3.100", "@swc/jest": "^0.2.29", diff --git a/packages/twenty-front/src/generated/graphql.tsx b/packages/twenty-front/src/generated/graphql.tsx index 2c35466a7c..66a687f786 100644 --- a/packages/twenty-front/src/generated/graphql.tsx +++ b/packages/twenty-front/src/generated/graphql.tsx @@ -70,6 +70,7 @@ export type ClientConfig = { authProviders: AuthProviders; billing: Billing; debugMode: Scalars['Boolean']; + sentry: Sentry; signInPrefilled: Scalars['Boolean']; support: Support; telemetry: Telemetry; @@ -174,6 +175,12 @@ export enum FileFolder { WorkspaceLogo = 'WorkspaceLogo' } +export type FullName = { + __typename?: 'FullName'; + firstName: Scalars['String']; + lastName: Scalars['String']; +}; + export type IdFilterComparison = { eq?: InputMaybe; gt?: InputMaybe; @@ -426,6 +433,11 @@ export enum RelationMetadataType { OneToOne = 'ONE_TO_ONE' } +export type Sentry = { + __typename?: 'Sentry'; + dsn: Scalars['String']; +}; + /** Sort Directions */ export enum SortDirection { Asc = 'ASC', @@ -489,7 +501,7 @@ export type User = { passwordHash?: Maybe; supportUserHash?: Maybe; updatedAt: Scalars['DateTime']; - workspaceMember: UserWorkspaceMember; + workspaceMember: WorkspaceMember; }; export type UserEdge = { @@ -505,21 +517,6 @@ export type UserExists = { exists: Scalars['Boolean']; }; -export type UserWorkspaceMember = { - __typename?: 'UserWorkspaceMember'; - avatarUrl?: Maybe; - colorScheme: Scalars['String']; - id: Scalars['ID']; - locale: Scalars['String']; - name: UserWorkspaceMemberName; -}; - -export type UserWorkspaceMemberName = { - __typename?: 'UserWorkspaceMemberName'; - firstName: Scalars['String']; - lastName: Scalars['String']; -}; - export type Verify = { __typename?: 'Verify'; tokens: AuthTokenPair; @@ -560,6 +557,15 @@ export type WorkspaceInviteHashValid = { isValid: Scalars['Boolean']; }; +export type WorkspaceMember = { + __typename?: 'WorkspaceMember'; + avatarUrl?: Maybe; + colorScheme: Scalars['String']; + id: Scalars['ID']; + locale: Scalars['String']; + name: FullName; +}; + export type Field = { __typename?: 'field'; createdAt: Scalars['DateTime']; @@ -705,7 +711,7 @@ export type ImpersonateMutationVariables = Exact<{ }>; -export type ImpersonateMutation = { __typename?: 'Mutation', impersonate: { __typename?: 'Verify', user: { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, workspaceMember: { __typename?: 'UserWorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'UserWorkspaceMemberName', firstName: string, lastName: string } }, defaultWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: string, key: string, value: boolean, workspaceId: string }> | null } }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; +export type ImpersonateMutation = { __typename?: 'Mutation', impersonate: { __typename?: 'Verify', user: { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, workspaceMember: { __typename?: 'WorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'FullName', firstName: string, lastName: string } }, defaultWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: string, key: string, value: boolean, workspaceId: string }> | null } }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; export type RenewTokenMutationVariables = Exact<{ refreshToken: Scalars['String']; @@ -728,7 +734,7 @@ export type VerifyMutationVariables = Exact<{ }>; -export type VerifyMutation = { __typename?: 'Mutation', verify: { __typename?: 'Verify', user: { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, workspaceMember: { __typename?: 'UserWorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'UserWorkspaceMemberName', firstName: string, lastName: string } }, defaultWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: string, key: string, value: boolean, workspaceId: string }> | null } }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; +export type VerifyMutation = { __typename?: 'Mutation', verify: { __typename?: 'Verify', user: { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, workspaceMember: { __typename?: 'WorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'FullName', firstName: string, lastName: string } }, defaultWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: string, key: string, value: boolean, workspaceId: string }> | null } }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; export type CheckUserExistsQueryVariables = Exact<{ email: Scalars['String']; @@ -740,7 +746,7 @@ export type CheckUserExistsQuery = { __typename?: 'Query', checkUserExists: { __ export type GetClientConfigQueryVariables = Exact<{ [key: string]: never; }>; -export type GetClientConfigQuery = { __typename?: 'Query', clientConfig: { __typename?: 'ClientConfig', signInPrefilled: boolean, debugMode: boolean, authProviders: { __typename?: 'AuthProviders', google: boolean, password: boolean }, billing: { __typename?: 'Billing', isBillingEnabled: boolean, billingUrl: string }, telemetry: { __typename?: 'Telemetry', enabled: boolean, anonymizationEnabled: boolean }, support: { __typename?: 'Support', supportDriver: string, supportFrontChatId?: string | null } } }; +export type GetClientConfigQuery = { __typename?: 'Query', clientConfig: { __typename?: 'ClientConfig', signInPrefilled: boolean, debugMode: boolean, authProviders: { __typename?: 'AuthProviders', google: boolean, password: boolean }, billing: { __typename?: 'Billing', isBillingEnabled: boolean, billingUrl: string }, telemetry: { __typename?: 'Telemetry', enabled: boolean, anonymizationEnabled: boolean }, support: { __typename?: 'Support', supportDriver: string, supportFrontChatId?: string | null }, sentry: { __typename?: 'Sentry', dsn: string } } }; export type UploadFileMutationVariables = Exact<{ file: Scalars['Upload']; @@ -758,7 +764,7 @@ export type UploadImageMutationVariables = Exact<{ export type UploadImageMutation = { __typename?: 'Mutation', uploadImage: string }; -export type UserQueryFragmentFragment = { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, workspaceMember: { __typename?: 'UserWorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'UserWorkspaceMemberName', firstName: string, lastName: string } }, defaultWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: string, key: string, value: boolean, workspaceId: string }> | null } }; +export type UserQueryFragmentFragment = { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, workspaceMember: { __typename?: 'WorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'FullName', firstName: string, lastName: string } }, defaultWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: string, key: string, value: boolean, workspaceId: string }> | null } }; export type DeleteUserAccountMutationVariables = Exact<{ [key: string]: never; }>; @@ -775,7 +781,7 @@ export type UploadProfilePictureMutation = { __typename?: 'Mutation', uploadProf export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>; -export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, workspaceMember: { __typename?: 'UserWorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'UserWorkspaceMemberName', firstName: string, lastName: string } }, defaultWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: string, key: string, value: boolean, workspaceId: string }> | null } } }; +export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, workspaceMember: { __typename?: 'WorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'FullName', firstName: string, lastName: string } }, defaultWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: string, key: string, value: boolean, workspaceId: string }> | null } } }; export type DeleteCurrentWorkspaceMutationVariables = Exact<{ [key: string]: never; }>; @@ -1284,6 +1290,9 @@ export const GetClientConfigDocument = gql` supportDriver supportFrontChatId } + sentry { + dsn + } } } `; diff --git a/packages/twenty-front/src/index.tsx b/packages/twenty-front/src/index.tsx index 89dc163760..9dfb43090d 100644 --- a/packages/twenty-front/src/index.tsx +++ b/packages/twenty-front/src/index.tsx @@ -8,6 +8,7 @@ import { ApolloProvider } from '@/apollo/components/ApolloProvider'; import { ClientConfigProvider } from '@/client-config/components/ClientConfigProvider'; import { RecoilDebugObserverEffect } from '@/debug/components/RecoilDebugObserver'; import { AppErrorBoundary } from '@/error-handler/components/AppErrorBoundary'; +import { ExceptionHandlerProvider } from '@/error-handler/components/ExceptionHandlerProvider'; import { PromiseRejectionEffect } from '@/error-handler/components/PromiseRejectionEffect'; import { ApolloMetadataClientProvider } from '@/object-metadata/components/ApolloMetadataClientProvider'; import { ObjectMetadataItemsProvider } from '@/object-metadata/components/ObjectMetadataItemsProvider'; @@ -36,31 +37,33 @@ root.render( - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/twenty-front/src/modules/client-config/components/ClientConfigProvider.tsx b/packages/twenty-front/src/modules/client-config/components/ClientConfigProvider.tsx index aa114b34f3..2498637b2b 100644 --- a/packages/twenty-front/src/modules/client-config/components/ClientConfigProvider.tsx +++ b/packages/twenty-front/src/modules/client-config/components/ClientConfigProvider.tsx @@ -5,6 +5,7 @@ import { authProvidersState } from '@/client-config/states/authProvidersState'; import { billingState } from '@/client-config/states/billingState'; import { isDebugModeState } from '@/client-config/states/isDebugModeState'; import { isSignInPrefilledState } from '@/client-config/states/isSignInPrefilledState'; +import { sentryConfigState } from '@/client-config/states/sentryConfigState'; import { supportChatState } from '@/client-config/states/supportChatState'; import { telemetryState } from '@/client-config/states/telemetryState'; import { useGetClientConfigQuery } from '~/generated/graphql'; @@ -21,6 +22,8 @@ export const ClientConfigProvider: React.FC = ({ const setTelemetry = useSetRecoilState(telemetryState); const setSupportChat = useSetRecoilState(supportChatState); + const setSentryConfig = useSetRecoilState(sentryConfigState); + const { data, loading } = useGetClientConfigQuery(); useEffect(() => { @@ -36,6 +39,10 @@ export const ClientConfigProvider: React.FC = ({ setBilling(data?.clientConfig.billing); setTelemetry(data?.clientConfig.telemetry); setSupportChat(data?.clientConfig.support); + + setSentryConfig({ + dsn: data?.clientConfig?.sentry?.dsn, + }); } }, [ data, @@ -45,6 +52,7 @@ export const ClientConfigProvider: React.FC = ({ setTelemetry, setSupportChat, setBilling, + setSentryConfig, ]); return loading ? <> : <>{children}; diff --git a/packages/twenty-front/src/modules/client-config/graphql/queries/getClientConfig.ts b/packages/twenty-front/src/modules/client-config/graphql/queries/getClientConfig.ts index 2c2e5aabc5..1637975f51 100644 --- a/packages/twenty-front/src/modules/client-config/graphql/queries/getClientConfig.ts +++ b/packages/twenty-front/src/modules/client-config/graphql/queries/getClientConfig.ts @@ -21,6 +21,9 @@ export const GET_CLIENT_CONFIG = gql` supportDriver supportFrontChatId } + sentry { + dsn + } } } `; diff --git a/packages/twenty-front/src/modules/client-config/states/sentryConfigState.ts b/packages/twenty-front/src/modules/client-config/states/sentryConfigState.ts new file mode 100644 index 0000000000..e88fd24839 --- /dev/null +++ b/packages/twenty-front/src/modules/client-config/states/sentryConfigState.ts @@ -0,0 +1,8 @@ +import { atom } from 'recoil'; + +import { Sentry } from '~/generated/graphql'; + +export const sentryConfigState = atom({ + key: 'sentryConfigState', + default: null, +}); diff --git a/packages/twenty-front/src/modules/error-handler/components/ExceptionHandlerProvider.tsx b/packages/twenty-front/src/modules/error-handler/components/ExceptionHandlerProvider.tsx new file mode 100644 index 0000000000..16cec36df1 --- /dev/null +++ b/packages/twenty-front/src/modules/error-handler/components/ExceptionHandlerProvider.tsx @@ -0,0 +1,12 @@ +import { SentryInitEffect } from '@/error-handler/components/SentryInitiEffect'; + +export const ExceptionHandlerProvider: React.FC = ({ + children, +}) => { + return ( + <> + + {children} + + ); +}; diff --git a/packages/twenty-front/src/modules/error-handler/components/SentryInitiEffect.tsx b/packages/twenty-front/src/modules/error-handler/components/SentryInitiEffect.tsx new file mode 100644 index 0000000000..f70caf4bc5 --- /dev/null +++ b/packages/twenty-front/src/modules/error-handler/components/SentryInitiEffect.tsx @@ -0,0 +1,34 @@ +import { useEffect, useState } from 'react'; +import * as Sentry from '@sentry/react'; +import { useRecoilValue } from 'recoil'; + +import { sentryConfigState } from '@/client-config/states/sentryConfigState'; +import { REACT_APP_SERVER_BASE_URL } from '~/config'; + +export const SentryInitEffect = () => { + const sentryConfig = useRecoilValue(sentryConfigState); + const [isSentryInitialized, setIsSentryInitialized] = useState(false); + + useEffect(() => { + if (sentryConfig?.dsn && !isSentryInitialized) { + Sentry.init({ + dsn: sentryConfig?.dsn, + integrations: [ + new Sentry.BrowserTracing({ + tracePropagationTargets: [ + 'localhost:3001', + REACT_APP_SERVER_BASE_URL, + ], + }), + new Sentry.Replay(), + ], + tracesSampleRate: 1.0, + replaysSessionSampleRate: 0.1, + replaysOnErrorSampleRate: 1.0, + }); + + setIsSentryInitialized(true); + } + }, [sentryConfig, isSentryInitialized]); + return <>; +}; diff --git a/packages/twenty-server/src/core/client-config/client-config.entity.ts b/packages/twenty-server/src/core/client-config/client-config.entity.ts index 404ea24c96..dc56ea37ab 100644 --- a/packages/twenty-server/src/core/client-config/client-config.entity.ts +++ b/packages/twenty-server/src/core/client-config/client-config.entity.ts @@ -39,6 +39,12 @@ class Support { supportFrontChatId: string | undefined; } +@ObjectType() +class Sentry { + @Field(() => String) + dsn: string | undefined; +} + @ObjectType() export class ClientConfig { @Field(() => AuthProviders, { nullable: false }) @@ -58,4 +64,7 @@ export class ClientConfig { @Field(() => Support) support: Support; + + @Field(() => Sentry) + sentry: Sentry; } diff --git a/packages/twenty-server/src/core/client-config/client-config.resolver.ts b/packages/twenty-server/src/core/client-config/client-config.resolver.ts index bb1a5674ac..120b271a3a 100644 --- a/packages/twenty-server/src/core/client-config/client-config.resolver.ts +++ b/packages/twenty-server/src/core/client-config/client-config.resolver.ts @@ -31,6 +31,9 @@ export class ClientConfigResolver { supportDriver: this.environmentService.getSupportDriver(), supportFrontChatId: this.environmentService.getSupportFrontChatId(), }, + sentry: { + dsn: this.environmentService.getSentryDSN(), + }, }; return Promise.resolve(clientConfig); diff --git a/packages/twenty-server/src/integrations/message-queue/jobs.module.ts b/packages/twenty-server/src/integrations/message-queue/jobs.module.ts index 4e7d727d6c..b10504b88c 100644 --- a/packages/twenty-server/src/integrations/message-queue/jobs.module.ts +++ b/packages/twenty-server/src/integrations/message-queue/jobs.module.ts @@ -1,6 +1,7 @@ -import { Module } from "@nestjs/common"; -import { ModuleRef } from "@nestjs/core"; -import { FetchMessagesJob } from "src/workspace/messaging/jobs/fetch-messages.job"; +import { Module } from '@nestjs/common'; +import { ModuleRef } from '@nestjs/core'; + +import { FetchMessagesJob } from 'src/workspace/messaging/jobs/fetch-messages.job'; @Module({ providers: [ diff --git a/packages/twenty-server/src/integrations/message-queue/utils/get-job-class-name.util.ts b/packages/twenty-server/src/integrations/message-queue/utils/get-job-class-name.util.ts index a5fb66c62f..9ee3922759 100644 --- a/packages/twenty-server/src/integrations/message-queue/utils/get-job-class-name.util.ts +++ b/packages/twenty-server/src/integrations/message-queue/utils/get-job-class-name.util.ts @@ -2,4 +2,4 @@ export function getJobClassName(name: string): string { const [, jobName] = name.split('.') ?? []; return jobName ?? name; -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index c1ebe74c84..7f8941432c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9969,6 +9969,17 @@ __metadata: languageName: node linkType: hard +"@sentry-internal/feedback@npm:7.90.0": + version: 7.90.0 + resolution: "@sentry-internal/feedback@npm:7.90.0" + dependencies: + "@sentry/core": "npm:7.90.0" + "@sentry/types": "npm:7.90.0" + "@sentry/utils": "npm:7.90.0" + checksum: 7de192316507dc6d82d1ec3ffe3208dc8423b83f93d432796b8337270241e05d35cc606de57b0c9e66a2b4f4cfdc0790a61b9b187040a5412da43d7ef278cf2e + languageName: node + linkType: hard + "@sentry-internal/tracing@npm:7.86.0": version: 7.86.0 resolution: "@sentry-internal/tracing@npm:7.86.0" @@ -9980,6 +9991,17 @@ __metadata: languageName: node linkType: hard +"@sentry-internal/tracing@npm:7.90.0": + version: 7.90.0 + resolution: "@sentry-internal/tracing@npm:7.90.0" + dependencies: + "@sentry/core": "npm:7.90.0" + "@sentry/types": "npm:7.90.0" + "@sentry/utils": "npm:7.90.0" + checksum: ab686bfd9ad22797b305c9077f5b932e2d7c4e2ef94805ba5ba0cdb42d9893a7c4a2a14acec511b8688019bb6d113de5afc1d82cf71579ae0313514609025cb8 + languageName: node + linkType: hard + "@sentry/browser@npm:6.19.7": version: 6.19.7 resolution: "@sentry/browser@npm:6.19.7" @@ -9992,6 +10014,20 @@ __metadata: languageName: node linkType: hard +"@sentry/browser@npm:7.90.0": + version: 7.90.0 + resolution: "@sentry/browser@npm:7.90.0" + dependencies: + "@sentry-internal/feedback": "npm:7.90.0" + "@sentry-internal/tracing": "npm:7.90.0" + "@sentry/core": "npm:7.90.0" + "@sentry/replay": "npm:7.90.0" + "@sentry/types": "npm:7.90.0" + "@sentry/utils": "npm:7.90.0" + checksum: d887af33e54dec97ada7ca3c3a0ca37e3125489e63c35d7cb2d89f79c0a900cbd68481037819e5cf2d8a58a6449634a7489ee0f223c853838ff6ced0fb576ac6 + languageName: node + linkType: hard + "@sentry/core@npm:6.19.7": version: 6.19.7 resolution: "@sentry/core@npm:6.19.7" @@ -10015,6 +10051,16 @@ __metadata: languageName: node linkType: hard +"@sentry/core@npm:7.90.0": + version: 7.90.0 + resolution: "@sentry/core@npm:7.90.0" + dependencies: + "@sentry/types": "npm:7.90.0" + "@sentry/utils": "npm:7.90.0" + checksum: 57b8c81ac953ecf88ab78b9b981f34f7168c3d7241eb6099d3d66768ae3eb1a93cdf2bac2824447246fd53f367fb9f1553afc01503b9ac58b3f64ef307c50a08 + languageName: node + linkType: hard + "@sentry/hub@npm:6.19.7": version: 6.19.7 resolution: "@sentry/hub@npm:6.19.7" @@ -10095,6 +10141,32 @@ __metadata: languageName: node linkType: hard +"@sentry/react@npm:^7.88.0": + version: 7.90.0 + resolution: "@sentry/react@npm:7.90.0" + dependencies: + "@sentry/browser": "npm:7.90.0" + "@sentry/types": "npm:7.90.0" + "@sentry/utils": "npm:7.90.0" + hoist-non-react-statics: "npm:^3.3.2" + peerDependencies: + react: 15.x || 16.x || 17.x || 18.x + checksum: 4e6e2b54fbb23e41e24a92154ca8f284d7c52fc0cf83f0b648c6798e0049bdf6a76d96585f7808cce76fec44e7696e40ddc444bcfcce83b5ce19424edd7b97e3 + languageName: node + linkType: hard + +"@sentry/replay@npm:7.90.0": + version: 7.90.0 + resolution: "@sentry/replay@npm:7.90.0" + dependencies: + "@sentry-internal/tracing": "npm:7.90.0" + "@sentry/core": "npm:7.90.0" + "@sentry/types": "npm:7.90.0" + "@sentry/utils": "npm:7.90.0" + checksum: 439bc7ee409b568806a163759924a54df28fc921ce5fce9749b088f7b6d962e6175e0b95c08220452970aadecb687cf0d93648811bd66fe97c5aa769028b3f35 + languageName: node + linkType: hard + "@sentry/tracing@npm:^7.66.0": version: 7.86.0 resolution: "@sentry/tracing@npm:7.86.0" @@ -10118,6 +10190,13 @@ __metadata: languageName: node linkType: hard +"@sentry/types@npm:7.90.0": + version: 7.90.0 + resolution: "@sentry/types@npm:7.90.0" + checksum: 6a3ea0dba33eb832845033cd345764689fc5a74f9b6a3f65ebed687250b4e177113eac8ecfc7b2f1299acddf77efa60470d0ff032780a6a5d63e3e771b2390e4 + languageName: node + linkType: hard + "@sentry/utils@npm:6.19.7": version: 6.19.7 resolution: "@sentry/utils@npm:6.19.7" @@ -10137,6 +10216,15 @@ __metadata: languageName: node linkType: hard +"@sentry/utils@npm:7.90.0": + version: 7.90.0 + resolution: "@sentry/utils@npm:7.90.0" + dependencies: + "@sentry/types": "npm:7.90.0" + checksum: 2eb167cf68e4b94ae320503e7b834bfebb5bcdc4281a7b315746d765e0c6e6cbed1c93c3bfa6d6a467d6a33b01d0bb438f596a8122cef5934dc92afe4e82351e + languageName: node + linkType: hard + "@sideway/address@npm:^4.1.3": version: 4.1.4 resolution: "@sideway/address@npm:4.1.4" @@ -41035,6 +41123,7 @@ __metadata: "@graphql-codegen/typescript-react-apollo": "npm:^3.3.7" "@hello-pangea/dnd": "npm:^16.2.0" "@hookform/resolvers": "npm:^3.1.1" + "@sentry/react": "npm:^7.88.0" "@sniptt/guards": "npm:^0.2.0" "@storybook/addon-actions": "npm:^7.6.3" "@storybook/addon-coverage": "npm:^1.0.0"