{"version":3,"sources":["../../src/client/route-params.ts"],"sourcesContent":["import type { DynamicParamTypesShort } from '../shared/lib/app-router-types'\nimport {\n  addSearchParamsIfPageSegment,\n  DEFAULT_SEGMENT_KEY,\n  PAGE_SEGMENT_KEY,\n} from '../shared/lib/segment'\nimport { ROOT_SEGMENT_REQUEST_KEY } from '../shared/lib/segment-cache/segment-value-encoding'\nimport {\n  NEXT_REWRITTEN_PATH_HEADER,\n  NEXT_REWRITTEN_QUERY_HEADER,\n  NEXT_RSC_UNION_QUERY,\n} from './components/app-router-headers'\nimport type {\n  NormalizedPathname,\n  NormalizedSearch,\n} from './components/segment-cache/cache-key'\nimport type { RSCResponse } from './components/router-reducer/fetch-server-response'\nimport type { ParsedUrlQuery } from 'querystring'\n\nexport type RouteParamValue = string | Array<string> | null\n\nexport function getRenderedSearch(\n  response: RSCResponse<unknown> | Response\n): NormalizedSearch {\n  // If the server performed a rewrite, the search params used to render the\n  // page will be different from the params in the request URL. In this case,\n  // the response will include a header that gives the rewritten search query.\n  const rewrittenQuery = response.headers.get(NEXT_REWRITTEN_QUERY_HEADER)\n  if (rewrittenQuery !== null) {\n    return (\n      rewrittenQuery === '' ? '' : '?' + rewrittenQuery\n    ) as NormalizedSearch\n  }\n  // If the header is not present, there was no rewrite, so we use the search\n  // query of the response URL.\n  return urlToUrlWithoutFlightMarker(new URL(response.url))\n    .search as NormalizedSearch\n}\n\nexport function getRenderedPathname(\n  response: RSCResponse<unknown> | Response\n): NormalizedPathname {\n  // If the server performed a rewrite, the pathname used to render the\n  // page will be different from the pathname in the request URL. In this case,\n  // the response will include a header that gives the rewritten pathname.\n  const rewrittenPath = response.headers.get(NEXT_REWRITTEN_PATH_HEADER)\n  return (rewrittenPath ??\n    urlToUrlWithoutFlightMarker(new URL(response.url))\n      .pathname) as NormalizedPathname\n}\n\nexport function parseDynamicParamFromURLPart(\n  paramType: DynamicParamTypesShort,\n  pathnameParts: Array<string>,\n  partIndex: number\n): RouteParamValue {\n  // This needs to match the behavior in get-dynamic-param.ts.\n  switch (paramType) {\n    // Catchalls\n    case 'c': {\n      // Catchalls receive all the remaining URL parts. If there are no\n      // remaining pathname parts, return an empty array.\n      return partIndex < pathnameParts.length\n        ? pathnameParts.slice(partIndex).map((s) => encodeURIComponent(s))\n        : []\n    }\n    // Catchall intercepted\n    case 'ci(..)(..)':\n    case 'ci(.)':\n    case 'ci(..)':\n    case 'ci(...)': {\n      const prefix = paramType.length - 2\n      return partIndex < pathnameParts.length\n        ? pathnameParts.slice(partIndex).map((s, i) => {\n            if (i === 0) {\n              return encodeURIComponent(s.slice(prefix))\n            }\n\n            return encodeURIComponent(s)\n          })\n        : []\n    }\n    // Optional catchalls\n    case 'oc': {\n      // Optional catchalls receive all the remaining URL parts, unless this is\n      // the end of the pathname, in which case they return null.\n      return partIndex < pathnameParts.length\n        ? pathnameParts.slice(partIndex).map((s) => encodeURIComponent(s))\n        : null\n    }\n    // Dynamic\n    case 'd': {\n      if (partIndex >= pathnameParts.length) {\n        // The route tree expected there to be more parts in the URL than there\n        // actually are. This could happen if the x-nextjs-rewritten-path header\n        // is incorrectly set, or potentially due to bug in Next.js. TODO:\n        // Should this be a hard error? During a prefetch, we can just abort.\n        // During a client navigation, we could trigger a hard refresh. But if\n        // it happens during initial render, we don't really have any\n        // recovery options.\n        return ''\n      }\n      return encodeURIComponent(pathnameParts[partIndex])\n    }\n    // Dynamic intercepted\n    case 'di(..)(..)':\n    case 'di(.)':\n    case 'di(..)':\n    case 'di(...)': {\n      const prefix = paramType.length - 2\n      if (partIndex >= pathnameParts.length) {\n        // The route tree expected there to be more parts in the URL than there\n        // actually are. This could happen if the x-nextjs-rewritten-path header\n        // is incorrectly set, or potentially due to bug in Next.js. TODO:\n        // Should this be a hard error? During a prefetch, we can just abort.\n        // During a client navigation, we could trigger a hard refresh. But if\n        // it happens during initial render, we don't really have any\n        // recovery options.\n        return ''\n      }\n\n      return encodeURIComponent(pathnameParts[partIndex].slice(prefix))\n    }\n    default:\n      paramType satisfies never\n      return ''\n  }\n}\n\nexport function doesStaticSegmentAppearInURL(segment: string): boolean {\n  // This is not a parameterized segment; however, we need to determine\n  // whether or not this segment appears in the URL. For example, this route\n  // groups do not appear in the URL, so they should be skipped. Any other\n  // special cases must be handled here.\n  // TODO: Consider encoding this directly into the router tree instead of\n  // inferring it on the client based on the segment type. Something like\n  // a `doesAppearInURL` flag in FlightRouterState.\n  if (\n    segment === ROOT_SEGMENT_REQUEST_KEY ||\n    // For some reason, the loader tree sometimes includes extra __PAGE__\n    // \"layouts\" when part of a parallel route. But it's not a leaf node.\n    // Otherwise, we wouldn't need this special case because pages are\n    // always leaf nodes.\n    // TODO: Investigate why the loader produces these fake page segments.\n    segment.startsWith(PAGE_SEGMENT_KEY) ||\n    // Route groups.\n    (segment[0] === '(' && segment.endsWith(')')) ||\n    segment === DEFAULT_SEGMENT_KEY ||\n    segment === '/_not-found'\n  ) {\n    return false\n  } else {\n    // All other segment types appear in the URL\n    return true\n  }\n}\n\nexport function getCacheKeyForDynamicParam(\n  paramValue: RouteParamValue,\n  renderedSearch: NormalizedSearch\n): string {\n  // This needs to match the logic in get-dynamic-param.ts, until we're able to\n  // unify the various implementations so that these are always computed on\n  // the client.\n  if (typeof paramValue === 'string') {\n    // TODO: Refactor or remove this helper function to accept a string rather\n    // than the whole segment type. Also we can probably just append the\n    // search string instead of turning it into JSON.\n    const pageSegmentWithSearchParams = addSearchParamsIfPageSegment(\n      paramValue,\n      Object.fromEntries(new URLSearchParams(renderedSearch))\n    ) as string\n    return pageSegmentWithSearchParams\n  } else if (paramValue === null) {\n    return ''\n  } else {\n    return paramValue.join('/')\n  }\n}\n\nexport function urlToUrlWithoutFlightMarker(url: URL): URL {\n  const urlWithoutFlightParameters = new URL(url)\n  urlWithoutFlightParameters.searchParams.delete(NEXT_RSC_UNION_QUERY)\n  if (process.env.NODE_ENV === 'production') {\n    if (\n      process.env.__NEXT_CONFIG_OUTPUT === 'export' &&\n      urlWithoutFlightParameters.pathname.endsWith('.txt')\n    ) {\n      const { pathname } = urlWithoutFlightParameters\n      const length = pathname.endsWith('/index.txt') ? 10 : 4\n      // Slice off `/index.txt` or `.txt` from the end of the pathname\n      urlWithoutFlightParameters.pathname = pathname.slice(0, -length)\n    }\n  }\n  return urlWithoutFlightParameters\n}\n\nexport function getParamValueFromCacheKey(\n  paramCacheKey: string,\n  paramType: DynamicParamTypesShort\n) {\n  // Turn the cache key string sent by the server (as part of FlightRouterState)\n  // into a value that can be passed to `useParams` and client components.\n  const isCatchAll = paramType === 'c' || paramType === 'oc'\n  if (isCatchAll) {\n    // Catch-all param keys are a concatenation of the path segments.\n    // See equivalent logic in `getSelectedParams`.\n    // TODO: We should just pass the array directly, rather than concatenate\n    // it to a string and then split it back to an array. It needs to be an\n    // array in some places, like when passing a key React, but we can convert\n    // it at runtime in those places.\n    return paramCacheKey.split('/')\n  }\n  return paramCacheKey\n}\n\nexport function urlSearchParamsToParsedUrlQuery(\n  searchParams: URLSearchParams\n): ParsedUrlQuery {\n  // Converts a URLSearchParams object to the same type used by the server when\n  // creating search params props, i.e. the type returned by Node's\n  // \"querystring\" module.\n  const result: ParsedUrlQuery = {}\n  for (const [key, value] of searchParams.entries()) {\n    if (result[key] === undefined) {\n      result[key] = value\n    } else if (Array.isArray(result[key])) {\n      result[key].push(value)\n    } else {\n      result[key] = [result[key], value]\n    }\n  }\n  return result\n}\n"],"names":["doesStaticSegmentAppearInURL","getCacheKeyForDynamicParam","getParamValueFromCacheKey","getRenderedPathname","getRenderedSearch","parseDynamicParamFromURLPart","urlSearchParamsToParsedUrlQuery","urlToUrlWithoutFlightMarker","response","rewrittenQuery","headers","get","NEXT_REWRITTEN_QUERY_HEADER","URL","url","search","rewrittenPath","NEXT_REWRITTEN_PATH_HEADER","pathname","paramType","pathnameParts","partIndex","length","slice","map","s","encodeURIComponent","prefix","i","segment","ROOT_SEGMENT_REQUEST_KEY","startsWith","PAGE_SEGMENT_KEY","endsWith","DEFAULT_SEGMENT_KEY","paramValue","renderedSearch","pageSegmentWithSearchParams","addSearchParamsIfPageSegment","Object","fromEntries","URLSearchParams","join","urlWithoutFlightParameters","searchParams","delete","NEXT_RSC_UNION_QUERY","process","env","NODE_ENV","__NEXT_CONFIG_OUTPUT","paramCacheKey","isCatchAll","split","result","key","value","entries","undefined","Array","isArray","push"],"mappings":"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","ignoreList":[0]}