{"version":3,"sources":["../../../../src/client/components/router-reducer/set-cache-busting-search-param.ts"],"sourcesContent":["'use client'\n\nimport {\n  computeCacheBustingSearchParam,\n  computeLegacyCacheBustingSearchParam,\n} from '../../../shared/lib/router/utils/cache-busting-search-param'\nimport {\n  NEXT_ROUTER_PREFETCH_HEADER,\n  NEXT_ROUTER_SEGMENT_PREFETCH_HEADER,\n  NEXT_ROUTER_STATE_TREE_HEADER,\n  NEXT_URL,\n  NEXT_RSC_UNION_QUERY,\n} from '../app-router-headers'\nimport type { RequestHeaders } from './fetch-server-response'\n\nasync function computeClientCacheBustingSearchParam(\n  headers: RequestHeaders\n): Promise<string> {\n  if (typeof globalThis.crypto?.subtle?.digest === 'function') {\n    return computeCacheBustingSearchParam(\n      headers[NEXT_ROUTER_PREFETCH_HEADER],\n      headers[NEXT_ROUTER_SEGMENT_PREFETCH_HEADER],\n      headers[NEXT_ROUTER_STATE_TREE_HEADER],\n      headers[NEXT_URL]\n    )\n  }\n\n  return computeLegacyCacheBustingSearchParam(\n    headers[NEXT_ROUTER_PREFETCH_HEADER],\n    headers[NEXT_ROUTER_SEGMENT_PREFETCH_HEADER],\n    headers[NEXT_ROUTER_STATE_TREE_HEADER],\n    headers[NEXT_URL]\n  )\n}\n\n/**\n * Mutates the provided URL by adding a cache-busting search parameter for CDNs that don't\n * support custom headers. This helps avoid caching conflicts by making each request unique.\n *\n * Rather than relying on the Vary header which some CDNs ignore, we append a search param\n * to create a unique URL that forces a fresh request.\n *\n * Example:\n * URL before: https://example.com/path?query=1\n * URL after: https://example.com/path?query=1&_rsc=abc123\n *\n * Note: This function mutates the input URL directly and resolves once the\n * cache-busting value has been computed and applied.\n *\n * TODO: Since we need to use a search param anyway, we could simplify by removing the custom\n * headers approach entirely and just use search params.\n */\nexport const setCacheBustingSearchParam = async (\n  url: URL,\n  headers: RequestHeaders\n): Promise<void> => {\n  const uniqueCacheKey = await computeClientCacheBustingSearchParam(headers)\n  setCacheBustingSearchParamWithHash(url, uniqueCacheKey)\n}\n\n/**\n * Sets a cache-busting search parameter on a URL using a provided hash value.\n *\n * This function performs the same logic as `setCacheBustingSearchParam` but accepts\n * a pre-computed hash instead of computing it from headers.\n *\n * Example:\n * URL before: https://example.com/path?query=1\n * hash: \"abc123\"\n * URL after: https://example.com/path?query=1&_rsc=abc123\n *\n * If the hash is empty, we will set `_rsc` search param without a value.\n * Like this: https://example.com/path?query=1&_rsc\n *\n * Note: This function mutates the input URL directly and does not return anything.\n */\nexport const setCacheBustingSearchParamWithHash = (\n  url: URL,\n  hash: string\n): void => {\n  /**\n   * Note that we intentionally do not use `url.searchParams.set` here:\n   *\n   * const url = new URL('https://example.com/search?q=custom%20spacing');\n   * url.searchParams.set('_rsc', 'abc123');\n   * console.log(url.toString()); // Outputs: https://example.com/search?q=custom+spacing&_rsc=abc123\n   *                                                                             ^ <--- this is causing confusion\n   * This is in fact intended based on https://url.spec.whatwg.org/#interface-urlsearchparams, but\n   * we want to preserve the %20 as %20 if that's what the user passed in, hence the custom\n   * logic below.\n   */\n  const existingSearch = url.search\n  const rawQuery = existingSearch.startsWith('?')\n    ? existingSearch.slice(1)\n    : existingSearch\n\n  // Always remove any existing cache busting param and add a fresh one to ensure\n  // we have the correct value based on current request headers\n  const pairs = rawQuery\n    .split('&')\n    .filter((pair) => pair && !pair.startsWith(`${NEXT_RSC_UNION_QUERY}=`))\n\n  if (hash.length > 0) {\n    pairs.push(`${NEXT_RSC_UNION_QUERY}=${hash}`)\n  } else {\n    pairs.push(`${NEXT_RSC_UNION_QUERY}`)\n  }\n  url.search = pairs.length ? `?${pairs.join('&')}` : ''\n}\n"],"names":["computeCacheBustingSearchParam","computeLegacyCacheBustingSearchParam","NEXT_ROUTER_PREFETCH_HEADER","NEXT_ROUTER_SEGMENT_PREFETCH_HEADER","NEXT_ROUTER_STATE_TREE_HEADER","NEXT_URL","NEXT_RSC_UNION_QUERY","computeClientCacheBustingSearchParam","headers","globalThis","crypto","subtle","digest","setCacheBustingSearchParam","url","uniqueCacheKey","setCacheBustingSearchParamWithHash","hash","existingSearch","search","rawQuery","startsWith","slice","pairs","split","filter","pair","length","push","join"],"mappings":"AAAA;AAEA,SACEA,8BAA8B,EAC9BC,oCAAoC,QAC/B,8DAA6D;AACpE,SACEC,2BAA2B,EAC3BC,mCAAmC,EACnCC,6BAA6B,EAC7BC,QAAQ,EACRC,oBAAoB,QACf,wBAAuB;AAG9B,eAAeC,qCACbC,OAAuB;QAEZC,2BAAAA;IAAX,IAAI,SAAOA,qBAAAA,WAAWC,MAAM,sBAAjBD,4BAAAA,mBAAmBE,MAAM,qBAAzBF,0BAA2BG,MAAM,MAAK,YAAY;QAC3D,OAAOZ,+BACLQ,OAAO,CAACN,4BAA4B,EACpCM,OAAO,CAACL,oCAAoC,EAC5CK,OAAO,CAACJ,8BAA8B,EACtCI,OAAO,CAACH,SAAS;IAErB;IAEA,OAAOJ,qCACLO,OAAO,CAACN,4BAA4B,EACpCM,OAAO,CAACL,oCAAoC,EAC5CK,OAAO,CAACJ,8BAA8B,EACtCI,OAAO,CAACH,SAAS;AAErB;AAEA;;;;;;;;;;;;;;;;CAgBC,GACD,OAAO,MAAMQ,6BAA6B,OACxCC,KACAN;IAEA,MAAMO,iBAAiB,MAAMR,qCAAqCC;IAClEQ,mCAAmCF,KAAKC;AAC1C,EAAC;AAED;;;;;;;;;;;;;;;CAeC,GACD,OAAO,MAAMC,qCAAqC,CAChDF,KACAG;IAEA;;;;;;;;;;GAUC,GACD,MAAMC,iBAAiBJ,IAAIK,MAAM;IACjC,MAAMC,WAAWF,eAAeG,UAAU,CAAC,OACvCH,eAAeI,KAAK,CAAC,KACrBJ;IAEJ,+EAA+E;IAC/E,6DAA6D;IAC7D,MAAMK,QAAQH,SACXI,KAAK,CAAC,KACNC,MAAM,CAAC,CAACC,OAASA,QAAQ,CAACA,KAAKL,UAAU,CAAC,AAAC,KAAEf,uBAAqB;IAErE,IAAIW,KAAKU,MAAM,GAAG,GAAG;QACnBJ,MAAMK,IAAI,CAAC,AAAGtB,uBAAqB,MAAGW;IACxC,OAAO;QACLM,MAAMK,IAAI,CAAC,AAAC,KAAEtB;IAChB;IACAQ,IAAIK,MAAM,GAAGI,MAAMI,MAAM,GAAG,AAAC,MAAGJ,MAAMM,IAAI,CAAC,OAAS;AACtD,EAAC","ignoreList":[0]}