{"version":3,"sources":["../../../src/server/dev/log-requests.ts"],"sourcesContent":["import {\n  blue,\n  bold,\n  gray,\n  green,\n  red,\n  white,\n  yellow,\n} from '../../lib/picocolors'\nimport { stripNextRscUnionQuery } from '../../lib/url'\nimport type { FetchMetric } from '../base-http'\nimport type { NodeNextRequest, NodeNextResponse } from '../base-http/node'\nimport type { LoggingConfig } from '../config-shared'\nimport { getRequestMeta } from '../request-meta'\n\nexport interface RequestLoggingOptions {\n  readonly request: NodeNextRequest\n  readonly response: NodeNextResponse\n  readonly loggingConfig: LoggingConfig | undefined\n  readonly requestDurationInMs: number\n}\n\n/**\n * Returns true if the incoming request should be ignored for logging.\n */\nexport function ignoreLoggingIncomingRequests(\n  request: NodeNextRequest,\n  loggingConfig: LoggingConfig | undefined\n): boolean {\n  // If it's boolean use the boolean value\n  if (typeof loggingConfig?.incomingRequests === 'boolean') {\n    return !loggingConfig.incomingRequests\n  }\n\n  // Any of the value on the chain is falsy, will not ignore the request.\n  const ignore = loggingConfig?.incomingRequests?.ignore\n\n  // If ignore is not set, don't ignore anything\n  if (!ignore) {\n    return false\n  }\n\n  // If array of RegExp, ignore if any pattern matches\n  return ignore.some((pattern) => pattern.test(request.url))\n}\n\nexport function logRequests(options: RequestLoggingOptions): void {\n  const { request, response, loggingConfig, requestDurationInMs } = options\n\n  if (!ignoreLoggingIncomingRequests(request, loggingConfig)) {\n    logIncomingRequests({\n      request,\n      requestDurationInMs,\n      statusCode: response.statusCode,\n    })\n  }\n\n  if (request.fetchMetrics) {\n    for (const fetchMetric of request.fetchMetrics) {\n      logFetchMetric(fetchMetric, loggingConfig)\n    }\n  }\n}\n\ninterface IncomingRequestOptions {\n  readonly request: NodeNextRequest\n  readonly requestDurationInMs: number\n  readonly statusCode: number\n}\n\nfunction logIncomingRequests(options: IncomingRequestOptions): void {\n  const { request, requestDurationInMs, statusCode } = options\n  const isRSC = getRequestMeta(request, 'isRSCRequest')\n  const url = isRSC ? stripNextRscUnionQuery(request.url) : request.url\n\n  const statusCodeColor =\n    statusCode < 200\n      ? white\n      : statusCode < 300\n        ? green\n        : statusCode < 400\n          ? blue\n          : statusCode < 500\n            ? yellow\n            : red\n\n  const coloredStatus = statusCodeColor(statusCode.toString())\n\n  return writeLine(\n    `${request.method} ${url} ${coloredStatus} in ${requestDurationInMs}ms`\n  )\n}\n\nfunction logFetchMetric(\n  fetchMetric: FetchMetric,\n  loggingConfig: LoggingConfig | undefined\n): void {\n  let {\n    cacheReason,\n    cacheStatus,\n    cacheWarning,\n    end,\n    method,\n    start,\n    status,\n    url,\n  } = fetchMetric\n\n  if (cacheStatus === 'hmr' && !loggingConfig?.fetches?.hmrRefreshes) {\n    // Cache hits during HMR refreshes are intentionally not logged, unless\n    // explicitly enabled in the logging config.\n    return\n  }\n\n  if (loggingConfig?.fetches) {\n    if (url.length > 48 && !loggingConfig.fetches.fullUrl) {\n      url = truncateUrl(url)\n    }\n\n    writeLine(\n      white(\n        `${method} ${url} ${status} in ${Math.round(end - start)}ms ${formatCacheStatus(cacheStatus)}`\n      ),\n      1\n    )\n\n    if (cacheStatus === 'skip' || cacheStatus === 'miss') {\n      writeLine(\n        gray(\n          `Cache ${cacheStatus === 'skip' ? 'skipped' : 'missed'} reason: (${white(cacheReason)})`\n        ),\n        2\n      )\n    }\n  } else if (cacheWarning) {\n    // When logging for fetches is not enabled, we still want to print any\n    // associated warnings, so we print the request first to provide context.\n    writeLine(white(`${method} ${url}`), 1)\n  }\n\n  if (cacheWarning) {\n    writeLine(`${yellow(bold('⚠'))} ${white(cacheWarning)}`, 2)\n  }\n}\n\nfunction writeLine(text: string, indentationLevel = 0): void {\n  process.stdout.write(` ${'│ '.repeat(indentationLevel)}${text}\\n`)\n}\n\nfunction truncate(text: string, maxLength: number): string {\n  return maxLength !== undefined && text.length > maxLength\n    ? text.substring(0, maxLength) + '..'\n    : text\n}\n\nfunction truncateUrl(url: string): string {\n  const { protocol, host, pathname, search } = new URL(url)\n\n  return (\n    protocol +\n    '//' +\n    truncate(host, 16) +\n    truncate(pathname, 24) +\n    truncate(search, 16)\n  )\n}\n\nfunction formatCacheStatus(cacheStatus: FetchMetric['cacheStatus']): string {\n  switch (cacheStatus) {\n    case 'hmr':\n      return green('(HMR cache)')\n    case 'hit':\n      return green('(cache hit)')\n    case 'miss':\n    case 'skip':\n      return yellow(`(cache ${cacheStatus})`)\n    default:\n      return cacheStatus satisfies never\n  }\n}\n"],"names":["ignoreLoggingIncomingRequests","logRequests","request","loggingConfig","incomingRequests","ignore","some","pattern","test","url","options","response","requestDurationInMs","logIncomingRequests","statusCode","fetchMetrics","fetchMetric","logFetchMetric","isRSC","getRequestMeta","stripNextRscUnionQuery","statusCodeColor","white","green","blue","yellow","red","coloredStatus","toString","writeLine","method","cacheReason","cacheStatus","cacheWarning","end","start","status","fetches","hmrRefreshes","length","fullUrl","truncateUrl","Math","round","formatCacheStatus","gray","bold","text","indentationLevel","process","stdout","write","repeat","truncate","maxLength","undefined","substring","protocol","host","pathname","search","URL"],"mappings":"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","ignoreList":[0]}