( lines: string[], lineIndex: number, lineNumber: number, backend: LogBackend | undefined, include: NetworkIncludeMode, maxPayloadChars: number, )
| 153 | } |
| 154 | |
| 155 | function parseNetworkLine( |
| 156 | lines: string[], |
| 157 | lineIndex: number, |
| 158 | lineNumber: number, |
| 159 | backend: LogBackend | undefined, |
| 160 | include: NetworkIncludeMode, |
| 161 | maxPayloadChars: number, |
| 162 | ): NetworkEntry | null { |
| 163 | const line = lines[lineIndex]?.trim(); |
| 164 | if (!line) return null; |
| 165 | const maybeJson = parseEmbeddedJson(line); |
| 166 | const jsonMethod = readJsonString(maybeJson, ['method', 'httpMethod']); |
| 167 | const jsonUrl = readJsonString(maybeJson, ['url', 'requestUrl']); |
| 168 | const jsonStatus = readJsonNumber(maybeJson, ['status', 'statusCode', 'responseCode']); |
| 169 | |
| 170 | const methodWithUrlMatch = METHOD_WITH_URL_REGEX.exec(line); |
| 171 | const methodFieldMatch = /\bmethod["'=: ]+([A-Z]+)\b/i.exec(line); |
| 172 | const method = (jsonMethod ?? methodFieldMatch?.[1] ?? methodWithUrlMatch?.[1])?.toUpperCase(); |
| 173 | |
| 174 | const urlMatch = URL_REGEX.exec(line); |
| 175 | const url = jsonUrl ?? urlMatch?.[0]; |
| 176 | if (!url) return null; |
| 177 | const inlineStatus = jsonStatus ?? parseStatusCode(line) ?? undefined; |
| 178 | const hasExplicitNetworkSignal = |
| 179 | Boolean(jsonMethod) || |
| 180 | Boolean(methodFieldMatch?.[1]) || |
| 181 | Boolean(methodWithUrlMatch?.[1]) || |
| 182 | inlineStatus !== undefined || |
| 183 | /\bURL["'=: ]+https?:\/\//i.test(line) || |
| 184 | /\bheaders?["'=: ]+/i.test(line) || |
| 185 | /\b(?:requestBody|responseBody|payload|request|response)["'=: ]+/i.test(line); |
| 186 | if (!hasExplicitNetworkSignal) { |
| 187 | return null; |
| 188 | } |
| 189 | |
| 190 | const result: NetworkEntry = { |
| 191 | method, |
| 192 | url, |
| 193 | status: inlineStatus, |
| 194 | timestamp: parseTimestamp(line), |
| 195 | packetId: parseAndroidPacketId(line) ?? undefined, |
| 196 | durationMs: parseAndroidDurationMs(line) ?? undefined, |
| 197 | raw: truncate(line, maxPayloadChars), |
| 198 | line: lineNumber, |
| 199 | }; |
| 200 | |
| 201 | if (backend === 'android') { |
| 202 | enrichFromAndroidAdjacentLines(result, lines, lineIndex); |
| 203 | } |
| 204 | |
| 205 | if (include === 'headers' || include === 'all') { |
| 206 | const headers = readHeaders(line, maybeJson); |
| 207 | if (headers) { |
| 208 | result.headers = truncate(headers, maxPayloadChars); |
| 209 | } |
| 210 | } |
| 211 | |
| 212 | if (include === 'body' || include === 'all') { |
no test coverage detected
searching dependent graphs…