{"version":3,"file":"graph.cjs","names":[],"sources":["../src/graph.ts"],"sourcesContent":["/**\n * A callback that returns the direct imported module IDs for a given module.\n * Abstracts over both Vite's dev-mode module graph and rollup's build-mode graph,\n * allowing the graph walker to work in both contexts without coupling to either.\n *\n * @param moduleId - The absolute file path of the module to query.\n * @returns An array of absolute file paths that the given module imports directly.\n */\nexport type GetImportedModuleIds = (moduleId: string) => string[]\n\n/**\n * A callback that returns the direct importer module IDs for a given module\n * (the inverse of {@link GetImportedModuleIds}).\n *\n * @param moduleId - The absolute file path of the module to query.\n * @returns An array of absolute file paths of modules that directly import the given module.\n */\nexport type GetImporterModuleIds = (moduleId: string) => string[]\n\n/**\n * Walks upward from a target module through its importers using a breadth-first\n * search, returning the shortest import chain from a root module (one with no\n * importers) down to the target. Used in dev mode where the client entry is the\n * HTML file, which Vite's dev module graph does not expose traversable\n * `importedModules` on. The traversal direction is inverted to compensate.\n *\n * @param targetModuleId - The module ID to trace upward to a root.\n * @param getImporterModuleIds - Returns the direct importer IDs for a given module.\n * @returns An ordered array of module IDs from the nearest root to the target.\n *          Falls back to a single-element array containing only the target if no\n *          root is reachable (e.g. the target is the only node or sits inside a cycle).\n */\nexport function buildImportChainViaImporters(\n  targetModuleId: string,\n  getImporterModuleIds: GetImporterModuleIds\n): string[] {\n  const importsInChainMap = new Map<string, string>()\n  const visitedModuleIds = new Set<string>([targetModuleId])\n  const modulesToVisit: string[] = [targetModuleId]\n\n  while (modulesToVisit.length > 0) {\n    const currentModuleId = modulesToVisit.shift()!\n    const importerIds = getImporterModuleIds(currentModuleId)\n\n    if (importerIds.length === 0) {\n      return reconstructChainFromImportsMap(currentModuleId, importsInChainMap)\n    }\n\n    for (const importerId of importerIds) {\n      if (!visitedModuleIds.has(importerId)) {\n        visitedModuleIds.add(importerId)\n        importsInChainMap.set(importerId, currentModuleId)\n        modulesToVisit.push(importerId)\n      }\n    }\n  }\n\n  return [targetModuleId]\n}\n\n/**\n * Walks a forward-pointer map starting at the root, following each module to\n * the module it imports in the chain, until the walk terminates at a node with\n * no successor (the target).\n *\n * @param rootModuleId - The starting point of the walk.\n * @param importsInChainMap - Maps each module to the module it imports on the chain.\n * @returns The ordered chain of module IDs from root to target.\n */\nfunction reconstructChainFromImportsMap(rootModuleId: string, importsInChainMap: Map<string, string>): string[] {\n  const pathSegments: string[] = []\n  let currentModuleId: string | undefined = rootModuleId\n\n  while (currentModuleId !== undefined) {\n    pathSegments.push(currentModuleId)\n    currentModuleId = importsInChainMap.get(currentModuleId)\n  }\n\n  return pathSegments\n}\n\n/**\n * Seeds a BFS or DFS work queue with the given entry module IDs, marking each\n * as visited to prevent duplicate processing. Entry IDs already in the visited\n * set are skipped silently.\n */\nfunction seedWorkQueue(entryModuleIds: string[], visitedModuleIds: Set<string>, workQueue: string[]): void {\n  for (const entryModuleId of entryModuleIds) {\n    if (!visitedModuleIds.has(entryModuleId)) {\n      visitedModuleIds.add(entryModuleId)\n      workQueue.push(entryModuleId)\n    }\n  }\n}\n\n/**\n * Walks the module import graph starting from the given client entry points\n * using a depth-first traversal, collecting all transitively reachable module IDs.\n * Handles circular imports safely by tracking visited modules.\n *\n * @param clientEntryModuleIds - The absolute file paths of all client entry point modules.\n * @param getImportedModuleIds - Returns the direct imported module IDs for a given module ID.\n * @returns A Set containing every module ID reachable from the provided entry points.\n */\nexport function collectClientReachableModuleIds(\n  clientEntryModuleIds: string[],\n  getImportedModuleIds: GetImportedModuleIds\n): Set<string> {\n  const visitedModuleIds = new Set<string>()\n  const modulesToVisit: string[] = []\n\n  seedWorkQueue(clientEntryModuleIds, visitedModuleIds, modulesToVisit)\n\n  while (modulesToVisit.length > 0) {\n    const currentModuleId = modulesToVisit.pop()!\n\n    for (const importedModuleId of getImportedModuleIds(currentModuleId)) {\n      if (!visitedModuleIds.has(importedModuleId)) {\n        visitedModuleIds.add(importedModuleId)\n        modulesToVisit.push(importedModuleId)\n      }\n    }\n  }\n\n  return visitedModuleIds\n}\n\n/**\n * Finds the shortest import chain from any client entry point to the target module\n * using a breadth-first search. Returns the reconstructed path as an ordered array\n * of module IDs from the entry point to the target.\n *\n * @param targetModuleId - The module ID to trace back to a client entry point.\n * @param clientEntryModuleIds - The absolute file paths of all client entry point modules.\n * @param getImportedModuleIds - Returns the direct imported module IDs for a given module ID.\n * @returns An ordered array of module IDs forming the shortest path from an entry to the target,\n *          or a single-element array containing only the target if no chain can be found.\n */\nexport function buildImportChainToModule(\n  targetModuleId: string,\n  clientEntryModuleIds: string[],\n  getImportedModuleIds: GetImportedModuleIds\n): string[] {\n  const parentModuleMap = new Map<string, string | null>()\n  const visitedModuleIds = new Set<string>()\n  const modulesToVisit: string[] = []\n\n  seedWorkQueue(clientEntryModuleIds, visitedModuleIds, modulesToVisit)\n\n  while (modulesToVisit.length > 0) {\n    const currentModuleId = modulesToVisit.shift()!\n\n    if (currentModuleId === targetModuleId) {\n      return reconstructPathFromParentMap(targetModuleId, parentModuleMap)\n    }\n\n    for (const importedModuleId of getImportedModuleIds(currentModuleId)) {\n      if (!visitedModuleIds.has(importedModuleId)) {\n        visitedModuleIds.add(importedModuleId)\n        parentModuleMap.set(importedModuleId, currentModuleId)\n        modulesToVisit.push(importedModuleId)\n      }\n    }\n  }\n\n  return [targetModuleId]\n}\n\n/**\n * Reconstructs the path from an entry point to a target module by walking\n * backwards through a parent map built during BFS traversal.\n */\nfunction reconstructPathFromParentMap(targetModuleId: string, parentModuleMap: Map<string, string | null>): string[] {\n  const pathSegments: string[] = []\n  let currentModuleId: string | null = targetModuleId\n\n  while (currentModuleId !== null) {\n    pathSegments.unshift(currentModuleId)\n    currentModuleId = parentModuleMap.get(currentModuleId) ?? null\n  }\n\n  return pathSegments\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgCA,SAAgB,6BACd,gBACA,sBACU;CACV,MAAM,oCAAoB,IAAI,KAAqB;CACnD,MAAM,mBAAmB,IAAI,IAAY,CAAC,eAAe,CAAC;CAC1D,MAAM,iBAA2B,CAAC,eAAe;AAEjD,QAAO,eAAe,SAAS,GAAG;EAChC,MAAM,kBAAkB,eAAe,OAAO;EAC9C,MAAM,cAAc,qBAAqB,gBAAgB;AAEzD,MAAI,YAAY,WAAW,EACzB,QAAO,+BAA+B,iBAAiB,kBAAkB;AAG3E,OAAK,MAAM,cAAc,YACvB,KAAI,CAAC,iBAAiB,IAAI,WAAW,EAAE;AACrC,oBAAiB,IAAI,WAAW;AAChC,qBAAkB,IAAI,YAAY,gBAAgB;AAClD,kBAAe,KAAK,WAAW;;;AAKrC,QAAO,CAAC,eAAe;;;;;;;;;;;AAYzB,SAAS,+BAA+B,cAAsB,mBAAkD;CAC9G,MAAM,eAAyB,EAAE;CACjC,IAAI,kBAAsC;AAE1C,QAAO,oBAAoB,KAAA,GAAW;AACpC,eAAa,KAAK,gBAAgB;AAClC,oBAAkB,kBAAkB,IAAI,gBAAgB;;AAG1D,QAAO;;;;;;;AAQT,SAAS,cAAc,gBAA0B,kBAA+B,WAA2B;AACzG,MAAK,MAAM,iBAAiB,eAC1B,KAAI,CAAC,iBAAiB,IAAI,cAAc,EAAE;AACxC,mBAAiB,IAAI,cAAc;AACnC,YAAU,KAAK,cAAc;;;;;;;;;;;;AAcnC,SAAgB,gCACd,sBACA,sBACa;CACb,MAAM,mCAAmB,IAAI,KAAa;CAC1C,MAAM,iBAA2B,EAAE;AAEnC,eAAc,sBAAsB,kBAAkB,eAAe;AAErE,QAAO,eAAe,SAAS,GAAG;EAChC,MAAM,kBAAkB,eAAe,KAAK;AAE5C,OAAK,MAAM,oBAAoB,qBAAqB,gBAAgB,CAClE,KAAI,CAAC,iBAAiB,IAAI,iBAAiB,EAAE;AAC3C,oBAAiB,IAAI,iBAAiB;AACtC,kBAAe,KAAK,iBAAiB;;;AAK3C,QAAO;;;;;;;;;;;;;AAcT,SAAgB,yBACd,gBACA,sBACA,sBACU;CACV,MAAM,kCAAkB,IAAI,KAA4B;CACxD,MAAM,mCAAmB,IAAI,KAAa;CAC1C,MAAM,iBAA2B,EAAE;AAEnC,eAAc,sBAAsB,kBAAkB,eAAe;AAErE,QAAO,eAAe,SAAS,GAAG;EAChC,MAAM,kBAAkB,eAAe,OAAO;AAE9C,MAAI,oBAAoB,eACtB,QAAO,6BAA6B,gBAAgB,gBAAgB;AAGtE,OAAK,MAAM,oBAAoB,qBAAqB,gBAAgB,CAClE,KAAI,CAAC,iBAAiB,IAAI,iBAAiB,EAAE;AAC3C,oBAAiB,IAAI,iBAAiB;AACtC,mBAAgB,IAAI,kBAAkB,gBAAgB;AACtD,kBAAe,KAAK,iBAAiB;;;AAK3C,QAAO,CAAC,eAAe;;;;;;AAOzB,SAAS,6BAA6B,gBAAwB,iBAAuD;CACnH,MAAM,eAAyB,EAAE;CACjC,IAAI,kBAAiC;AAErC,QAAO,oBAAoB,MAAM;AAC/B,eAAa,QAAQ,gBAAgB;AACrC,oBAAkB,gBAAgB,IAAI,gBAAgB,IAAI;;AAG5D,QAAO"}