error.ts 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. import { onError } from '@apollo/client/link/error'
  3. import getErrorContext from '#shared/server/apollo/utils/getErrorContext.ts'
  4. import log from '#shared/utils/log.ts'
  5. import type { GraphQLErrorExtensionsHandler } from '#shared/types/error.ts'
  6. import { GraphQLErrorTypes } from '#shared/types/error.ts'
  7. import emitter from '#shared/utils/emitter.ts'
  8. import { recordCommunicationFailure } from '#shared/server/connection.ts'
  9. const errorLink = onError(({ graphQLErrors, networkError, operation }) => {
  10. const errorContext = getErrorContext(operation)
  11. const errorMessages: Array<string> = []
  12. if (graphQLErrors) {
  13. graphQLErrors.forEach(({ message, extensions, path }) => {
  14. const { type, backtrace }: GraphQLErrorExtensionsHandler = {
  15. type:
  16. (extensions?.type as GraphQLErrorTypes) ||
  17. GraphQLErrorTypes.NetworkError,
  18. backtrace: extensions?.backtrace as string,
  19. }
  20. errorMessages.push(
  21. `[GraphQL error - ${type}]: ${message}, Path: ${path}`,
  22. backtrace,
  23. )
  24. if (
  25. operation.operationName !== 'session' &&
  26. type === GraphQLErrorTypes.NotAuthorized
  27. ) {
  28. // Reset authenticated state after an unathenticated error type.
  29. emitter.emit('sessionInvalid')
  30. log.warn('Session invalid, trigger logout and show login page.')
  31. }
  32. })
  33. }
  34. if (networkError) {
  35. // Suppress error message in Capybara test context, as it can happen if the
  36. // test session is reset to 'about:blank' while requests are still running.
  37. if (!VITE_TEST_MODE) errorMessages.push(`[Network error]: ${networkError}`)
  38. // Network error implies application connection problems.
  39. // TODO: what's missing here is a detection of web socket disconnects.
  40. recordCommunicationFailure()
  41. }
  42. if (errorContext.logLevel === 'silent') return
  43. log[errorContext.logLevel](...errorMessages)
  44. })
  45. export default errorLink