zammad/zammad

View on GitHub
app/frontend/shared/server/apollo/link/debug.ts

Summary

Maintainability
A
1 hr
Test Coverage
// Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/

import { ApolloLink } from '@apollo/client/core'
import { getMainDefinition } from '@apollo/client/utilities'
import { print } from 'graphql/language/printer'
import { capitalize, isEmpty } from 'lodash-es'

import type {
  DebugLinkRequestOutput,
  DebugLinkResponseOutput,
} from '#shared/types/server/apollo/client.ts'
import log from '#shared/utils/log.ts'

const debugLink = new ApolloLink((operation, forward) => {
  if (log.getLevel() < log.levels.DEBUG) return forward(operation)

  const requestContext = operation.getContext()

  const definition = getMainDefinition(operation.query)
  const opeationType =
    definition.kind === 'OperationDefinition'
      ? capitalize(definition.operation)
      : null

  const requestOutput: DebugLinkRequestOutput = {
    printedDocument: print(operation.query),
    document: operation.query,
  }

  if (!isEmpty(operation.variables)) {
    requestOutput.variables = operation.variables
  }

  if (!isEmpty(requestContext.headers)) {
    requestOutput.requestHeaders = requestContext.headers
  }

  // Called before operation is sent to server
  operation.setContext({ start: new Date() })

  log.debug(
    `[GraphQL - Request] - ${opeationType} - ${operation.operationName}:`,
    requestOutput,
  )

  return forward(operation).map((data) => {
    const context = operation.getContext()
    const end = new Date()

    const responseHeaders: Record<string, string> = {}
    if (context?.response?.headers) {
      context.response.headers.forEach((value: string, key: string) => {
        responseHeaders[key] = value
      })
    }

    const duration = end.getTime() - context.start.getTime()

    const responseOutput: DebugLinkResponseOutput = {
      data,
    }

    if (!isEmpty(responseHeaders)) {
      responseOutput.responseHeaders = responseHeaders
    }

    log.debug(
      `[GraphQL - Response] - ${opeationType} - ${operation.operationName} (took ${duration}ms):`,
      responseOutput,
    )
    return data
  })
})

export default debugLink