error.ts 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  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 { recordCommunicationFailure } from '#shared/server/connection.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 log from '#shared/utils/log.ts'
  9. const errorLink = onError(
  10. ({ graphQLErrors, networkError, operation, forward }) => {
  11. const errorContext = getErrorContext(operation)
  12. const errorMessages: Array<string> = []
  13. // If the error is an AbortError, ignore it and forward the operation to avoid communication failure
  14. if (networkError?.name === 'AbortError') return forward(operation)
  15. if (graphQLErrors) {
  16. graphQLErrors.forEach(({ message, extensions, path }) => {
  17. const { type, backtrace }: GraphQLErrorExtensionsHandler = {
  18. type:
  19. (extensions?.type as GraphQLErrorTypes) ||
  20. GraphQLErrorTypes.NetworkError,
  21. backtrace: extensions?.backtrace as string,
  22. }
  23. errorMessages.push(
  24. `[GraphQL error - ${type}]: ${message}, Path: ${path}`,
  25. backtrace,
  26. )
  27. if (
  28. operation.operationName !== 'session' &&
  29. type === GraphQLErrorTypes.NotAuthorized
  30. ) {
  31. // Reset authenticated state after an unathenticated error type.
  32. emitter.emit('sessionInvalid')
  33. log.warn('Session invalid, trigger logout and show login page.')
  34. }
  35. })
  36. }
  37. if (networkError) {
  38. // Suppress error message in Capybara test context, as it can happen if the
  39. // test session is reset to 'about:blank' while requests are still running.
  40. if (!VITE_TEST_MODE)
  41. errorMessages.push(`[Network error]: ${networkError}`)
  42. // Network error implies application connection problems.
  43. // TODO: what's missing here is a detection of web socket disconnects.
  44. recordCommunicationFailure()
  45. }
  46. if (errorContext.logLevel === 'silent') return
  47. log[errorContext.logLevel](...errorMessages)
  48. },
  49. )
  50. export default errorLink