{"version":3,"sources":["../../../src/server/request/fallback-params.ts"],"sourcesContent":["import { resolveRouteParamsFromTree } from '../../build/static-paths/utils'\nimport type { FallbackRouteParam } from '../../build/static-paths/types'\nimport type { DynamicParamTypesShort } from '../../shared/lib/app-router-types'\nimport { dynamicParamTypes } from '../app-render/get-short-dynamic-param-type'\nimport type AppPageRouteModule from '../route-modules/app-page/module'\nimport { parseAppRoute } from '../../shared/lib/router/routes/app'\nimport { extractPathnameRouteParamSegmentsFromLoaderTree } from '../../build/static-paths/app/extract-pathname-route-param-segments-from-loader-tree'\nimport { getParamProperties } from '../../shared/lib/router/utils/get-segment-param'\n\nexport type OpaqueFallbackRouteParamValue = [\n  /**\n   * The search value of the fallback route param. This is the opaque key\n   * that will be used to replace the dynamic param in the postponed state.\n   */\n  searchValue: string,\n\n  /**\n   * The dynamic param type of the fallback route param. This is the type of\n   * the dynamic param that will be used to replace the dynamic param in the\n   * postponed state.\n   */\n  dynamicParamType: DynamicParamTypesShort,\n]\n\n/**\n * An opaque fallback route params object. This is used to store the fallback\n * route params in a way that is not easily accessible to the client.\n */\nexport type OpaqueFallbackRouteParams = ReadonlyMap<\n  string,\n  OpaqueFallbackRouteParamValue\n>\n\n/**\n * The entries of the opaque fallback route params object.\n *\n * @param key the key of the fallback route param\n * @param value the value of the fallback route param\n */\nexport type OpaqueFallbackRouteParamEntries =\n  ReturnType<OpaqueFallbackRouteParams['entries']> extends MapIterator<\n    [infer K, infer V]\n  >\n    ? ReadonlyArray<[K, V]>\n    : never\n\n/**\n * Creates an opaque fallback route params object from the fallback route params.\n *\n * @param fallbackRouteParams the fallback route params\n * @returns the opaque fallback route params\n */\nexport function createOpaqueFallbackRouteParams(\n  fallbackRouteParams: readonly FallbackRouteParam[]\n): OpaqueFallbackRouteParams | null {\n  // If there are no fallback route params, we can return early.\n  if (fallbackRouteParams.length === 0) return null\n\n  // As we're creating unique keys for each of the dynamic route params, we only\n  // need to generate a unique ID once per request because each of the keys will\n  // be also be unique.\n  const uniqueID = Math.random().toString(16).slice(2)\n\n  const keys = new Map<string, OpaqueFallbackRouteParamValue>()\n\n  // Generate a unique key for the fallback route param, if this key is found\n  // in the static output, it represents a bug in cache components.\n  for (const { paramName, paramType } of fallbackRouteParams) {\n    keys.set(paramName, [\n      `%%drp:${paramName}:${uniqueID}%%`,\n      dynamicParamTypes[paramType],\n    ])\n  }\n\n  return keys\n}\n\nexport function buildDynamicSegmentPlaceholder(\n  param: Pick<FallbackRouteParam, 'paramName' | 'paramType'>\n): string {\n  const { repeat, optional } = getParamProperties(param.paramType)\n\n  if (optional) {\n    return `[[...${param.paramName}]]`\n  }\n\n  if (repeat) {\n    return `[...${param.paramName}]`\n  }\n\n  return `[${param.paramName}]`\n}\n\nexport function getPlaceholderFallbackRouteParams(\n  params: Record<string, undefined | string | string[]> | undefined,\n  fallbackRouteParams: readonly FallbackRouteParam[]\n): FallbackRouteParam[] {\n  return fallbackRouteParams.filter((param) => {\n    const placeholder = buildDynamicSegmentPlaceholder(param)\n    const value = params?.[param.paramName]\n\n    return (\n      value === placeholder ||\n      (Array.isArray(value) && value.length === 1 && value[0] === placeholder)\n    )\n  })\n}\n\n/**\n * Gets the fallback route params for a given page. This is an expensive\n * operation because it requires parsing the loader tree to extract the fallback\n * route params.\n *\n * @param page the page\n * @param routeModule the route module\n * @returns the opaque fallback route params\n */\nexport function getFallbackRouteParams(\n  page: string,\n  routeModule: AppPageRouteModule\n) {\n  const route = parseAppRoute(page, true)\n\n  // Extract the pathname-contributing segments from the loader tree. This\n  // mirrors the logic in buildAppStaticPaths where we determine which segments\n  // actually contribute to the pathname.\n  const { pathnameRouteParamSegments, params } =\n    extractPathnameRouteParamSegmentsFromLoaderTree(\n      routeModule.userland.loaderTree,\n      route\n    )\n\n  // Create fallback route params for the pathname segments.\n  const fallbackRouteParams: FallbackRouteParam[] =\n    pathnameRouteParamSegments.map(({ paramName, paramType }) => ({\n      paramName,\n      paramType,\n    }))\n\n  // Resolve route params from the loader tree. This mutates the\n  // fallbackRouteParams array to add any route params that are\n  // unknown at request time.\n  //\n  // The page parameter contains placeholders like [slug], which helps\n  // resolveRouteParamsFromTree determine which params are unknown.\n  resolveRouteParamsFromTree(\n    routeModule.userland.loaderTree,\n    params, // Static params extracted from the page\n    route, // The page pattern with placeholders\n    fallbackRouteParams // Will be mutated to add route params\n  )\n\n  // Convert the fallback route params to an opaque format that can be safely\n  // used in the postponed state without exposing implementation details.\n  return createOpaqueFallbackRouteParams(fallbackRouteParams)\n}\n"],"names":["buildDynamicSegmentPlaceholder","createOpaqueFallbackRouteParams","getFallbackRouteParams","getPlaceholderFallbackRouteParams","fallbackRouteParams","length","uniqueID","Math","random","toString","slice","keys","Map","paramName","paramType","set","dynamicParamTypes","param","repeat","optional","getParamProperties","params","filter","placeholder","value","Array","isArray","page","routeModule","route","parseAppRoute","pathnameRouteParamSegments","extractPathnameRouteParamSegmentsFromLoaderTree","userland","loaderTree","map","resolveRouteParamsFromTree"],"mappings":";;;;;;;;;;;;;;;;;IA6EgBA,8BAA8B;eAA9BA;;IAzBAC,+BAA+B;eAA/BA;;IAiEAC,sBAAsB;eAAtBA;;IAxBAC,iCAAiC;eAAjCA;;;uBA7F2B;0CAGT;qBAEJ;iEACkC;iCAC7B;AA6C5B,SAASF,gCACdG,mBAAkD;IAElD,8DAA8D;IAC9D,IAAIA,oBAAoBC,MAAM,KAAK,GAAG,OAAO;IAE7C,8EAA8E;IAC9E,8EAA8E;IAC9E,qBAAqB;IACrB,MAAMC,WAAWC,KAAKC,MAAM,GAAGC,QAAQ,CAAC,IAAIC,KAAK,CAAC;IAElD,MAAMC,OAAO,IAAIC;IAEjB,2EAA2E;IAC3E,iEAAiE;IACjE,KAAK,MAAM,EAAEC,SAAS,EAAEC,SAAS,EAAE,IAAIV,oBAAqB;QAC1DO,KAAKI,GAAG,CAACF,WAAW;YAClB,CAAC,MAAM,EAAEA,UAAU,CAAC,EAAEP,SAAS,EAAE,CAAC;YAClCU,2CAAiB,CAACF,UAAU;SAC7B;IACH;IAEA,OAAOH;AACT;AAEO,SAASX,+BACdiB,KAA0D;IAE1D,MAAM,EAAEC,MAAM,EAAEC,QAAQ,EAAE,GAAGC,IAAAA,mCAAkB,EAACH,MAAMH,SAAS;IAE/D,IAAIK,UAAU;QACZ,OAAO,CAAC,KAAK,EAAEF,MAAMJ,SAAS,CAAC,EAAE,CAAC;IACpC;IAEA,IAAIK,QAAQ;QACV,OAAO,CAAC,IAAI,EAAED,MAAMJ,SAAS,CAAC,CAAC,CAAC;IAClC;IAEA,OAAO,CAAC,CAAC,EAAEI,MAAMJ,SAAS,CAAC,CAAC,CAAC;AAC/B;AAEO,SAASV,kCACdkB,MAAiE,EACjEjB,mBAAkD;IAElD,OAAOA,oBAAoBkB,MAAM,CAAC,CAACL;QACjC,MAAMM,cAAcvB,+BAA+BiB;QACnD,MAAMO,QAAQH,0BAAAA,MAAQ,CAACJ,MAAMJ,SAAS,CAAC;QAEvC,OACEW,UAAUD,eACTE,MAAMC,OAAO,CAACF,UAAUA,MAAMnB,MAAM,KAAK,KAAKmB,KAAK,CAAC,EAAE,KAAKD;IAEhE;AACF;AAWO,SAASrB,uBACdyB,IAAY,EACZC,WAA+B;IAE/B,MAAMC,QAAQC,IAAAA,kBAAa,EAACH,MAAM;IAElC,wEAAwE;IACxE,6EAA6E;IAC7E,uCAAuC;IACvC,MAAM,EAAEI,0BAA0B,EAAEV,MAAM,EAAE,GAC1CW,IAAAA,gGAA+C,EAC7CJ,YAAYK,QAAQ,CAACC,UAAU,EAC/BL;IAGJ,0DAA0D;IAC1D,MAAMzB,sBACJ2B,2BAA2BI,GAAG,CAAC,CAAC,EAAEtB,SAAS,EAAEC,SAAS,EAAE,GAAM,CAAA;YAC5DD;YACAC;QACF,CAAA;IAEF,8DAA8D;IAC9D,6DAA6D;IAC7D,2BAA2B;IAC3B,EAAE;IACF,oEAAoE;IACpE,iEAAiE;IACjEsB,IAAAA,iCAA0B,EACxBR,YAAYK,QAAQ,CAACC,UAAU,EAC/Bb,QACAQ,OACAzB,oBAAoB,sCAAsC;;IAG5D,2EAA2E;IAC3E,uEAAuE;IACvE,OAAOH,gCAAgCG;AACzC","ignoreList":[0]}