BaseHandler.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. import type { Ref } from 'vue'
  3. import type { ApolloError, OperationVariables } from '@apollo/client/core'
  4. import type {
  5. BaseHandlerOptions,
  6. CommonHandlerOptions,
  7. CommonHandlerOptionsParameter,
  8. OperationResult,
  9. OperationReturn,
  10. } from '@shared/types/server/apollo/handler'
  11. import type {
  12. GraphQLErrorReport,
  13. GraphQLHandlerError,
  14. } from '@shared/types/error'
  15. import { GraphQLErrorTypes } from '@shared/types/error'
  16. import {
  17. useNotifications,
  18. NotificationTypes,
  19. } from '@shared/components/CommonNotifications'
  20. export default abstract class BaseHandler<
  21. TResult = OperationResult,
  22. TVariables = OperationVariables,
  23. TOperationReturn extends OperationReturn<
  24. TResult,
  25. TVariables
  26. > = OperationReturn<TResult, TVariables>,
  27. THandlerOptions = BaseHandlerOptions,
  28. > {
  29. public operationResult!: TOperationReturn
  30. protected baseHandlerOptions: BaseHandlerOptions = {
  31. errorShowNotification: true,
  32. errorNotificationMessage: __('An error occured during the operation.'),
  33. errorNotificationType: NotificationTypes.Error,
  34. }
  35. public handlerOptions!: CommonHandlerOptions<THandlerOptions>
  36. constructor(
  37. operationResult: TOperationReturn,
  38. handlerOptions?: CommonHandlerOptionsParameter<THandlerOptions>,
  39. ) {
  40. this.operationResult = operationResult
  41. this.handlerOptions = this.mergedHandlerOptions(handlerOptions)
  42. this.initialize()
  43. }
  44. protected initialize(): void {
  45. this.operationResult.onError((error) => {
  46. this.handleError(error)
  47. })
  48. }
  49. public loading(): Ref<boolean> {
  50. return this.operationResult.loading
  51. }
  52. public operationError(): Ref<Maybe<ApolloError>> {
  53. return this.operationResult.error
  54. }
  55. public onError(callback: (error: ApolloError) => void): void {
  56. this.operationResult.onError(callback)
  57. }
  58. protected handleError(error: ApolloError): void {
  59. const options = this.handlerOptions
  60. let triggerNotification = options.errorShowNotification
  61. const { graphQLErrors, networkError } = error
  62. let errorHandler: GraphQLHandlerError
  63. if (graphQLErrors.length > 0) {
  64. const { message, extensions }: GraphQLErrorReport = graphQLErrors[0]
  65. const type =
  66. (extensions?.type as GraphQLErrorTypes) ||
  67. GraphQLErrorTypes.NetworkError
  68. errorHandler = {
  69. type:
  70. (extensions?.type as GraphQLErrorTypes) ||
  71. GraphQLErrorTypes.NetworkError,
  72. message,
  73. }
  74. triggerNotification = type !== GraphQLErrorTypes.NotAuthorized
  75. } else if (networkError) {
  76. errorHandler = {
  77. type: GraphQLErrorTypes.NetworkError,
  78. }
  79. } else {
  80. errorHandler = {
  81. type: GraphQLErrorTypes.UnkownError,
  82. }
  83. }
  84. if (options.errorCallback) {
  85. options.errorCallback(errorHandler)
  86. }
  87. if (triggerNotification) {
  88. // TODO enable and fix all tests
  89. // if (import.meta.env.DEV) {
  90. // console.error(error)
  91. // }
  92. useNotifications().notify({
  93. message: options.errorNotificationMessage,
  94. type: options.errorNotificationType,
  95. })
  96. }
  97. }
  98. protected mergedHandlerOptions(
  99. handlerOptions?: CommonHandlerOptionsParameter<THandlerOptions>,
  100. ): CommonHandlerOptions<THandlerOptions> {
  101. // The merged type is always safe as a 'CommonHandlerOptions<THandlerOptions>' type.
  102. return Object.assign(
  103. this.baseHandlerOptions,
  104. handlerOptions,
  105. ) as CommonHandlerOptions<THandlerOptions>
  106. }
  107. }