# All files networkMessage.ts

90.19% Statements 46/51
55.55% Branches 10/18
87.5% Functions 7/8
91.48% Lines 43/47

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103

    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x
    4x

    4x
    4x
    4x
    4x
    4x
    4x
    4x

    4x
    4x
    4x

    1x
    1x

    1x

    1x

    1x

    1x
    1x

    1x

    2x
    2x
    2x
    1x

    2x

    2x
    2x
    2x
    1x

    2x

    9x
    6x

    3x

     import {
      RequestResponseData,
      INetworkMessage,
      httpMethod,
      RequestState,
    } from './types'
    /**
     * I know we're not using most of the information from this class
     * but it can be useful in the future if we will decide to display more stuff in our ui
     * */

    export default class NetworkMessage {
      id = ''
      name?: string = ''
      method: httpMethod = ''
      url = ''
      status = 0
      statusText?: string = ''
      cancelState?: 0 | 1 | 2 | 3 = 0
      readyState?: RequestState = 0
      header: { [key: string]: string } = {}
      responseType: XMLHttpRequest['responseType'] = ''
      requestType: 'xhr' | 'fetch' | 'ping' | 'custom' | 'beacon' | 'graphql' = 'xhr'
      requestHeader: HeadersInit = {}
      response: string
      responseSize = 0 // bytes
      responseSizeText = ''
      startTime = 0
      endTime = 0
      duration = 0
      getData: { [key: string]: string } = {}
      requestData: string | null = null

      constructor(
        private readonly ignoredHeaders: boolean | string[] = [],
        private readonly setSessionTokenHeader: (cb: (name: string, value: string) => void) => void,
        private readonly sanitize: (data: RequestResponseData) => RequestResponseData | null,
      ) {}

      getMessage(): INetworkMessage | null {
        const { reqHs, resHs } = this.writeHeaders()
        const request = {
          headers: reqHs,
          body: this.method === 'GET' ? JSON.stringify(this.getData) : this.requestData,
        }
        const response = { headers: resHs, body: this.response }

        const messageInfo = this.sanitize({
          url: this.url,
          method: this.method,
          status: this.status,
          request,
          response,
        })

        Iif (!messageInfo) return null;

        const isGraphql = messageInfo.url.includes("/graphql");
        Iif (isGraphql && messageInfo.response.body && typeof messageInfo.response.body === 'string') {
          const isError = messageInfo.response.body.includes("errors");
          messageInfo.status = isError ? 400 : 200;
          this.requestType = 'graphql';
        }

        return {
          requestType: this.requestType,
          method: messageInfo.method as httpMethod,
          url: messageInfo.url,
          request: JSON.stringify(messageInfo.request),
          response: JSON.stringify(messageInfo.response),
          status: messageInfo.status,
          startTime: this.startTime,
          duration: this.duration,
          responseSize: this.responseSize,
        }
      }

      writeHeaders() {
        const reqHs: Record<string, string> = {}
        Object.entries(this.requestHeader).forEach(([key, value]) => {
          if (this.isHeaderIgnored(key)) return
          reqHs[key] = value
        })
        this.setSessionTokenHeader((name, value) => {
          reqHs[name] = value
        })
        const resHs: Record<string, string> = {}
        Object.entries(this.header).forEach(([key, value]) => {
          if (this.isHeaderIgnored(key)) return
          resHs[key] = value
        })
        return { reqHs, resHs }
      }

      isHeaderIgnored(key: string) {
        if (Array.isArray(this.ignoredHeaders)) {
          return this.ignoredHeaders.map((k) => k.toLowerCase()).includes(key.toLowerCase())
        } else {
          return this.ignoredHeaders
        }
      }
    }