{"version":3,"sources":["../../../../src/build/static-paths/utils.ts"],"sourcesContent":["import type { LoaderTree } from '../../server/lib/app-dir-module'\nimport type { Params } from '../../server/request/params'\nimport type { AppPageRouteModule } from '../../server/route-modules/app-page/module.compiled'\nimport type { AppRouteRouteModule } from '../../server/route-modules/app-route/module.compiled'\nimport { isAppPageRouteModule } from '../../server/route-modules/checks'\nimport type { DynamicParamTypes } from '../../shared/lib/app-router-types'\nimport {\n  parseAppRouteSegment,\n  type NormalizedAppRoute,\n} from '../../shared/lib/router/routes/app'\nimport { parseLoaderTree } from '../../shared/lib/router/utils/parse-loader-tree'\nimport type { AppSegment } from '../segment-config/app/app-segments'\nimport { extractPathnameRouteParamSegmentsFromLoaderTree } from './app/extract-pathname-route-param-segments-from-loader-tree'\nimport { resolveParamValue } from '../../shared/lib/router/utils/resolve-param-value'\nimport type { FallbackRouteParam } from './types'\n\n/**\n * Encodes a parameter value using the provided encoder.\n *\n * @param value - The value to encode.\n * @param encoder - The encoder to use.\n * @returns The encoded value.\n */\nexport function encodeParam(\n  value: string | string[],\n  encoder: (value: string) => string\n) {\n  let replaceValue: string\n  if (Array.isArray(value)) {\n    replaceValue = value.map(encoder).join('/')\n  } else {\n    replaceValue = encoder(value)\n  }\n\n  return replaceValue\n}\n\n/**\n * Normalizes a pathname to a consistent format.\n *\n * @param pathname - The pathname to normalize.\n * @returns The normalized pathname.\n */\nexport function normalizePathname(pathname: string) {\n  return pathname.replace(/\\\\/g, '/').replace(/(?!^)\\/$/, '')\n}\n\n/**\n * Extracts segments that contribute to the pathname by traversing the loader tree\n * based on the route module type.\n *\n * @param routeModule - The app route module (page or route handler)\n * @param segments - Array of AppSegment objects collected from the route\n * @param page - The target pathname to match against, INCLUDING interception\n *               markers (e.g., \"/blog/[slug]\", \"/(.)photo/[id]\")\n * @returns Array of segments with param info that contribute to the pathname\n */\nexport function extractPathnameRouteParamSegments(\n  routeModule: AppRouteRouteModule | AppPageRouteModule,\n  segments: readonly Readonly<AppSegment>[],\n  route: NormalizedAppRoute\n): Array<{\n  readonly name: string\n  readonly paramName: string\n  readonly paramType: DynamicParamTypes\n}> {\n  // For AppPageRouteModule, use the loaderTree traversal approach\n  if (isAppPageRouteModule(routeModule)) {\n    const { pathnameRouteParamSegments } =\n      extractPathnameRouteParamSegmentsFromLoaderTree(\n        routeModule.userland.loaderTree,\n        route\n      )\n    return pathnameRouteParamSegments\n  }\n\n  return extractPathnameRouteParamSegmentsFromSegments(segments)\n}\n\nexport function extractPathnameRouteParamSegmentsFromSegments(\n  segments: readonly Readonly<AppSegment>[]\n): Array<{\n  readonly name: string\n  readonly paramName: string\n  readonly paramType: DynamicParamTypes\n}> {\n  // TODO: should we consider what values are already present in the page?\n\n  // For AppRouteRouteModule, filter the segments array to get the route params\n  // that contribute to the pathname.\n  const result: Array<{\n    readonly name: string\n    readonly paramName: string\n    readonly paramType: DynamicParamTypes\n  }> = []\n\n  for (const segment of segments) {\n    // Skip segments without param info.\n    if (!segment.paramName || !segment.paramType) continue\n\n    // Collect all the route param keys that contribute to the pathname.\n    result.push({\n      name: segment.name,\n      paramName: segment.paramName,\n      paramType: segment.paramType,\n    })\n  }\n\n  return result\n}\n\n/**\n * Resolves all route parameters from the loader tree. This function uses\n * tree-based traversal to correctly handle the hierarchical structure of routes\n * and accurately determine parameter values based on their depth in the tree.\n *\n * This processes both regular route parameters (from the main children route) and\n * parallel route parameters (from slots like @modal, @sidebar).\n *\n * Unlike interpolateParallelRouteParams (which has a complete URL at runtime),\n * this build-time function determines which route params are unknown.\n * The pathname may contain placeholders like [slug], making it incomplete.\n *\n * @param loaderTree - The loader tree structure containing route hierarchy\n * @param params - The current route parameters object (will be mutated)\n * @param route - The current route being processed\n * @param fallbackRouteParams - Array of fallback route parameters (will be mutated)\n */\nexport function resolveRouteParamsFromTree(\n  loaderTree: LoaderTree,\n  params: Params,\n  route: NormalizedAppRoute,\n  fallbackRouteParams: FallbackRouteParam[]\n): void {\n  // Stack-based traversal with depth tracking\n  const stack: Array<{\n    tree: LoaderTree\n    depth: number\n  }> = [{ tree: loaderTree, depth: 0 }]\n\n  while (stack.length > 0) {\n    const { tree, depth } = stack.pop()!\n    const { segment, parallelRoutes } = parseLoaderTree(tree)\n\n    const appSegment = parseAppRouteSegment(segment)\n\n    // If this segment is a route parameter, then we should process it if it's\n    // not already known and is not already marked as a fallback route param.\n    if (\n      appSegment?.type === 'dynamic' &&\n      !params.hasOwnProperty(appSegment.param.paramName) &&\n      !fallbackRouteParams.some(\n        (param) => param.paramName === appSegment.param.paramName\n      )\n    ) {\n      const { paramName, paramType } = appSegment.param\n\n      const paramValue = resolveParamValue(\n        paramName,\n        paramType,\n        depth,\n        route,\n        params\n      )\n\n      if (paramValue !== undefined) {\n        params[paramName] = paramValue\n      } else if (paramType !== 'optional-catchall') {\n        // If we couldn't resolve the param, mark it as a fallback\n        fallbackRouteParams.push({ paramName, paramType })\n      }\n    }\n\n    // Calculate next depth - increment if this is not a route group and not empty\n    let nextDepth = depth\n    if (\n      appSegment &&\n      appSegment.type !== 'route-group' &&\n      appSegment.type !== 'parallel-route'\n    ) {\n      nextDepth++\n    }\n\n    // Add all parallel routes to the stack for processing.\n    for (const parallelRoute of Object.values(parallelRoutes)) {\n      stack.push({ tree: parallelRoute, depth: nextDepth })\n    }\n  }\n}\n"],"names":["isAppPageRouteModule","parseAppRouteSegment","parseLoaderTree","extractPathnameRouteParamSegmentsFromLoaderTree","resolveParamValue","encodeParam","value","encoder","replaceValue","Array","isArray","map","join","normalizePathname","pathname","replace","extractPathnameRouteParamSegments","routeModule","segments","route","pathnameRouteParamSegments","userland","loaderTree","extractPathnameRouteParamSegmentsFromSegments","result","segment","paramName","paramType","push","name","resolveRouteParamsFromTree","params","fallbackRouteParams","stack","tree","depth","length","pop","parallelRoutes","appSegment","type","hasOwnProperty","param","some","paramValue","undefined","nextDepth","parallelRoute","Object","values"],"mappings":"AAIA,SAASA,oBAAoB,QAAQ,oCAAmC;AAExE,SACEC,oBAAoB,QAEf,qCAAoC;AAC3C,SAASC,eAAe,QAAQ,kDAAiD;AAEjF,SAASC,+CAA+C,QAAQ,+DAA8D;AAC9H,SAASC,iBAAiB,QAAQ,oDAAmD;AAGrF;;;;;;CAMC,GACD,OAAO,SAASC,YACdC,KAAwB,EACxBC,OAAkC;IAElC,IAAIC;IACJ,IAAIC,MAAMC,OAAO,CAACJ,QAAQ;QACxBE,eAAeF,MAAMK,GAAG,CAACJ,SAASK,IAAI,CAAC;IACzC,OAAO;QACLJ,eAAeD,QAAQD;IACzB;IAEA,OAAOE;AACT;AAEA;;;;;CAKC,GACD,OAAO,SAASK,kBAAkBC,QAAgB;IAChD,OAAOA,SAASC,OAAO,CAAC,OAAO,KAAKA,OAAO,CAAC,YAAY;AAC1D;AAEA;;;;;;;;;CASC,GACD,OAAO,SAASC,kCACdC,WAAqD,EACrDC,QAAyC,EACzCC,KAAyB;IAMzB,gEAAgE;IAChE,IAAInB,qBAAqBiB,cAAc;QACrC,MAAM,EAAEG,0BAA0B,EAAE,GAClCjB,gDACEc,YAAYI,QAAQ,CAACC,UAAU,EAC/BH;QAEJ,OAAOC;IACT;IAEA,OAAOG,8CAA8CL;AACvD;AAEA,OAAO,SAASK,8CACdL,QAAyC;IAMzC,wEAAwE;IAExE,6EAA6E;IAC7E,mCAAmC;IACnC,MAAMM,SAID,EAAE;IAEP,KAAK,MAAMC,WAAWP,SAAU;QAC9B,oCAAoC;QACpC,IAAI,CAACO,QAAQC,SAAS,IAAI,CAACD,QAAQE,SAAS,EAAE;QAE9C,oEAAoE;QACpEH,OAAOI,IAAI,CAAC;YACVC,MAAMJ,QAAQI,IAAI;YAClBH,WAAWD,QAAQC,SAAS;YAC5BC,WAAWF,QAAQE,SAAS;QAC9B;IACF;IAEA,OAAOH;AACT;AAEA;;;;;;;;;;;;;;;;CAgBC,GACD,OAAO,SAASM,2BACdR,UAAsB,EACtBS,MAAc,EACdZ,KAAyB,EACzBa,mBAAyC;IAEzC,4CAA4C;IAC5C,MAAMC,QAGD;QAAC;YAAEC,MAAMZ;YAAYa,OAAO;QAAE;KAAE;IAErC,MAAOF,MAAMG,MAAM,GAAG,EAAG;QACvB,MAAM,EAAEF,IAAI,EAAEC,KAAK,EAAE,GAAGF,MAAMI,GAAG;QACjC,MAAM,EAAEZ,OAAO,EAAEa,cAAc,EAAE,GAAGpC,gBAAgBgC;QAEpD,MAAMK,aAAatC,qBAAqBwB;QAExC,0EAA0E;QAC1E,yEAAyE;QACzE,IACEc,CAAAA,8BAAAA,WAAYC,IAAI,MAAK,aACrB,CAACT,OAAOU,cAAc,CAACF,WAAWG,KAAK,CAAChB,SAAS,KACjD,CAACM,oBAAoBW,IAAI,CACvB,CAACD,QAAUA,MAAMhB,SAAS,KAAKa,WAAWG,KAAK,CAAChB,SAAS,GAE3D;YACA,MAAM,EAAEA,SAAS,EAAEC,SAAS,EAAE,GAAGY,WAAWG,KAAK;YAEjD,MAAME,aAAaxC,kBACjBsB,WACAC,WACAQ,OACAhB,OACAY;YAGF,IAAIa,eAAeC,WAAW;gBAC5Bd,MAAM,CAACL,UAAU,GAAGkB;YACtB,OAAO,IAAIjB,cAAc,qBAAqB;gBAC5C,0DAA0D;gBAC1DK,oBAAoBJ,IAAI,CAAC;oBAAEF;oBAAWC;gBAAU;YAClD;QACF;QAEA,8EAA8E;QAC9E,IAAImB,YAAYX;QAChB,IACEI,cACAA,WAAWC,IAAI,KAAK,iBACpBD,WAAWC,IAAI,KAAK,kBACpB;YACAM;QACF;QAEA,uDAAuD;QACvD,KAAK,MAAMC,iBAAiBC,OAAOC,MAAM,CAACX,gBAAiB;YACzDL,MAAML,IAAI,CAAC;gBAAEM,MAAMa;gBAAeZ,OAAOW;YAAU;QACrD;IACF;AACF","ignoreList":[0]}