{
  "version": 3,
  "sources": ["../../../../src/packages/fs.indexed-pkg-importer/importIndexedDir.ts"],
  "sourcesContent": ["import fs from 'node:fs';\nimport util from 'node:util';\nimport { copySync } from 'fs-extra';\nimport path from 'node:path';\nimport { globalWarn, logger } from '../logger/index.ts';\nimport { sync as rimraf } from '@zkochan/rimraf';\nimport { sync as makeEmptyDir } from 'make-empty-dir';\nimport sanitizeFilename from 'sanitize-filename';\nimport { fastPathTemp as pathTemp } from 'path-temp';\nimport renameOverwrite from 'rename-overwrite';\n\nconst filenameConflictsLogger = logger('_filename-conflicts');\n\nexport type ImportFile = (src: string, dest: string) => void;\n\nexport function importIndexedDir(\n  importFile: ImportFile,\n  newDir: string,\n  filenames: Record<string, string>,\n  opts: {\n    keepModulesDir?: boolean | undefined;\n  }\n): void {\n  const stage = pathTemp(newDir);\n  try {\n    tryImportIndexedDir(importFile, stage, filenames);\n    if (opts.keepModulesDir === true) {\n      // Keeping node_modules is needed only when the hoisted node linker is used.\n      moveOrMergeModulesDirs(\n        path.join(newDir, 'node_modules'),\n        path.join(stage, 'node_modules')\n      );\n    }\n\n    renameOverwrite.sync(stage, newDir);\n  } catch (err: unknown) {\n    try {\n      rimraf(stage);\n    } catch {} // eslint-disable-line:no-empty\n\n    if (\n      util.types.isNativeError(err) &&\n      'code' in err &&\n      err.code === 'EEXIST'\n    ) {\n      const { uniqueFileMap, conflictingFileNames } =\n        getUniqueFileMap(filenames);\n\n      if (Object.keys(conflictingFileNames).length === 0) {\n        throw err;\n      }\n\n      filenameConflictsLogger.debug({\n        conflicts: conflictingFileNames,\n        writingTo: newDir,\n      });\n\n      globalWarn(\n        // biome-ignore lint/style/useTemplate: <explanation>\n        `Not all files were linked to \"${path.relative(process.cwd(), newDir)}\". ` +\n          'Some of the files have equal names in different case, ' +\n          'which is an issue on case-insensitive filesystems. ' +\n          `The conflicting file names are: ${JSON.stringify(conflictingFileNames)}`\n      );\n\n      importIndexedDir(importFile, newDir, uniqueFileMap, opts);\n\n      return;\n    }\n\n    if (\n      util.types.isNativeError(err) &&\n      'code' in err &&\n      err.code === 'ENOENT'\n    ) {\n      const { sanitizedFilenames, invalidFilenames } =\n        sanitizeFilenames(filenames);\n\n      if (invalidFilenames.length === 0) {\n        throw err;\n      }\n\n      globalWarn(`\\\nThe package linked to \"${path.relative(process.cwd(), newDir)}\" had \\\nfiles with invalid names: ${invalidFilenames.join(', ')}. \\\nThey were renamed.`);\n      importIndexedDir(importFile, newDir, sanitizedFilenames, opts);\n      return;\n    }\n\n    throw err;\n  }\n}\n\ntype SanitizeFilenamesResult = {\n  sanitizedFilenames: Record<string, string>;\n  invalidFilenames: string[];\n};\n\nfunction sanitizeFilenames(\n  filenames: Record<string, string>\n): SanitizeFilenamesResult {\n  const sanitizedFilenames: Record<string, string> = {};\n\n  const invalidFilenames: string[] = [];\n\n  for (const [filename, src] of Object.entries(filenames)) {\n    const sanitizedFilename = filename\n      .split('/')\n      .map((f) => sanitizeFilename(f))\n      .join('/');\n\n    if (sanitizedFilename !== filename) {\n      invalidFilenames.push(filename);\n    }\n\n    sanitizedFilenames[sanitizedFilename] = src;\n  }\n\n  return { sanitizedFilenames, invalidFilenames };\n}\n\nfunction tryImportIndexedDir(\n  importFile: ImportFile,\n  newDir: string,\n  filenames: Record<string, string>\n): void {\n  makeEmptyDir(newDir, { recursive: true });\n\n  const allDirs = new Set<string>();\n\n  for (const f in filenames) {\n    const dir = path.dirname(f);\n\n    if (dir === '.') continue;\n\n    allDirs.add(dir);\n  }\n\n  // biome-ignore lint/complexity/noForEach: <explanation>\n  Array.from(allDirs)\n    .sort((d1, d2) => d1.length - d2.length) // from shortest to longest\n    .forEach((dir) =>\n      fs.mkdirSync(path.join(newDir, dir), { recursive: true })\n    );\n\n  for (const [f, src] of Object.entries(filenames)) {\n    const dest = path.join(newDir, f);\n    importFile(src, dest);\n  }\n}\n\ninterface GetUniqueFileMapResult {\n  conflictingFileNames: Record<string, string>;\n  uniqueFileMap: Record<string, string>;\n}\n\nfunction getUniqueFileMap(\n  fileMap: Record<string, string>\n): GetUniqueFileMapResult {\n  const lowercaseFiles = new Map<string, string>();\n\n  const conflictingFileNames: Record<string, string> = {};\n\n  const uniqueFileMap: Record<string, string> = {};\n\n  for (const filename of Object.keys(fileMap).sort()) {\n    const lowercaseFilename = filename.toLowerCase();\n\n    if (lowercaseFiles.has(lowercaseFilename)) {\n      conflictingFileNames[filename] =\n        lowercaseFiles.get(lowercaseFilename) ?? '';\n\n      continue;\n    }\n\n    lowercaseFiles.set(lowercaseFilename, filename);\n\n    uniqueFileMap[filename] = fileMap[filename] ?? '';\n  }\n\n  return {\n    conflictingFileNames,\n    uniqueFileMap,\n  };\n}\n\nfunction moveOrMergeModulesDirs(src: string, dest: string): void {\n  try {\n    renameEvenAcrossDevices(src, dest);\n  } catch (err: unknown) {\n    switch (util.types.isNativeError(err) && 'code' in err && err.code) {\n      case 'ENOENT': {\n        // If src directory doesn't exist, there is nothing to do\n        return;\n      }\n\n      case 'ENOTEMPTY':\n      case 'EPERM': {\n        // This error code is thrown on Windows\n        // The newly added dependency might have node_modules if it has bundled dependencies.\n        mergeModulesDirs(src, dest);\n        return;\n      }\n\n      default: {\n        throw err;\n      }\n    }\n  }\n}\n\nfunction renameEvenAcrossDevices(src: string, dest: string): void {\n  try {\n    fs.renameSync(src, dest);\n  } catch (err: unknown) {\n    if (\n      !(util.types.isNativeError(err) && 'code' in err && err.code === 'EXDEV')\n    ) {\n      throw err;\n    }\n\n    copySync(src, dest);\n  }\n}\n\nfunction mergeModulesDirs(src: string, dest: string): void {\n  const srcFiles = fs.readdirSync(src);\n\n  const destFiles = new Set(fs.readdirSync(dest));\n\n  const filesToMove = srcFiles.filter((file) => !destFiles.has(file));\n\n  for (const file of filesToMove) {\n    renameEvenAcrossDevices(path.join(src, file), path.join(dest, file));\n  }\n}\n"],
  "mappings": "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",
  "names": []
}
