{"version":3,"sources":["../../src/fixAliasPlugin.ts"],"sourcesContent":["import { dirname, join, parse, relative, resolve } from \"path\";\nimport { type Plugin } from \"esbuild\";\nimport { loadTsConfig } from \"load-tsconfig\";\nimport { existsSync } from \"fs\";\n\n// Get the current working directory as the origin absolute path.\nconst originAbsolutePath = process.cwd();\n\n/**\n * Converts Windows backslashes to POSIX forward slashes\n */\nconst toPosix = (p: string) => p.replace(/\\\\/g, \"/\");\n\n/**\n * Normalizes import paths by converting to POSIX and cleaning up redundant segments\n */\nconst normalizeImportPath = (p: string) =>\n  toPosix(p)\n    .replace(/\\/\\.\\//g, \"/\")\n    .replace(/(^|[^:])\\/\\/+/g, \"$1/\");\n\n/**\n * Ensures relative imports have proper ./ or ../ prefix\n */\nconst ensureDotRelative = (p: string) => {\n  if (p.startsWith(\"./\") || p.startsWith(\"../\")) {\n    return p;\n  }\n  if (p.startsWith(\"/\")) {\n    return `.${p}`;\n  }\n  return `./${p}`;\n};\n\n/**\n * ESBuild plugin to forcefully replace path aliases with relative paths in the output files.\n * It reads the alias configuration from tsconfig.json and modifies the output files to resolve the aliases.\n * Also handles baseUrl-based imports when no explicit path aliases are configured.\n *\n * @returns {import('esbuild').Plugin} An ESBuild plugin object.\n */\nexport const fixAliasPlugin = (): Plugin => ({\n  name: \"fixAliasPlugin\",\n  setup: (build) => {\n    // Resolve the absolute path to the output directory.\n    const outDir = build.initialOptions.outdir ?? \"dist\";\n    const outDirAbsolutePath = resolve(originAbsolutePath, outDir);\n\n    // Determine the output file extension based on the build options.\n    const outExtension = build.initialOptions.outExtension?.[\".js\"] ?? \".js\";\n\n    // Import the tsconfig.json\n    const tsConfig = loadTsConfig(\n      originAbsolutePath,\n      build.initialOptions.tsconfig ?? \"./tsConfig.ts\"\n    );\n\n    // Extract the 'paths' from the tsconfig compilerOptions, or default to an empty object.\n    const alias = tsConfig?.data.compilerOptions?.paths ?? {};\n\n    // Extract the 'baseUrl' from the tsconfig compilerOptions\n    const baseUrl = tsConfig?.data.compilerOptions?.baseUrl;\n\n    // Hook into the 'onEnd' event of the build process.\n    build.onEnd((result) => {\n      // If there are errors, do not proceed.\n      if (result.errors.length > 0) {\n        return;\n      }\n\n      const entryFiles = (build.initialOptions.entryPoints ?? []) as string[];\n      const outputFiles = (result.outputFiles ?? []).filter((outputFile) =>\n        outputFile.path.endsWith(outExtension)\n      );\n\n      // Iterate over each output file generated by ESBuild.\n      for (const outputFile of outputFiles) {\n        // Only target files with the specified output extension.\n        // This ignores additional files emitted, like sourcemaps (e.g., \"*.js.map\").\n\n        // If `entry` field is defined in the tsup.config.ts. It will make dismatch between the output file path and the relative path.\n        // Result 'folder/index.mjs',\n        const relativeOutputPath = relative(\n          // '/Users/user/Documents/app/dist/esm/',\n          outDirAbsolutePath,\n          // '/Users/user/Documents/app/dist/esm/folder/index.mjs',\n          outputFile.path\n        );\n\n        // 'folder/index',\n        const relativeOutputPathWithoutExt =\n          getPathWithoutExtension(relativeOutputPath);\n\n        // 'src/folder/index.ts',\n        const entryFile =\n          entryFiles\n            .map(toPosix)\n            .find((filePath) =>\n              filePath.includes(relativeOutputPathWithoutExt)\n            ) ?? \"\";\n\n        // 'src/folder/index',\n        const entryFilePathWithoutExt = getPathWithoutExtension(entryFile);\n\n        // 'src/',\n        const ignoredPath = entryFilePathWithoutExt.replace(\n          relativeOutputPathWithoutExt,\n          \"\"\n        );\n\n        // Calculate the relative path from the output file to the output directory.\n        // '../',\n        const relativePath = relative(\n          // '/Users/user/Documents/app/dist/esm/folder',\n          dirname(outputFile.path),\n          // '/Users/user/Documents/app/dist/esm/',\n          outDirAbsolutePath\n        );\n\n        // Get the original file contents.\n        const fileContents = outputFile.text;\n        // Modify the file contents by replacing aliases with relative paths.\n        const nextFileContents = modifyAlias(\n          fileContents,\n          relativePath,\n          alias,\n          ignoredPath,\n          baseUrl,\n          originAbsolutePath\n        );\n\n        // Update the output file contents with the modified contents.\n        outputFile.contents = Buffer.from(nextFileContents);\n      }\n    });\n  },\n});\n\n/**\n * Gets the path without the file extension.\n *\n * @param {string} path - The path to process.\n * @returns {string} The path without the file extension.\n */\nexport const getPathWithoutExtension = (path: string): string => {\n  // Parse the file path\n  const parsedPath = parse(path);\n  // Reconstruct the path without the extension and convert to POSIX\n  return toPosix(join(parsedPath.dir, parsedPath.name));\n};\n\n// Regular expressions to match ESM import statements and CJS require statements.\nconst ESM_IMPORT_EXP = /from\\s*['\"]([^'\"]+)['\"]/g;\nconst CJS_REQUIRE_EXP = /require\\s*\\(\\s*['\"]([^'\"]+?)['\"]\\s*\\)/g;\n\n/**\n * Modifies the contents of a file by replacing path aliases with relative paths.\n *\n * @param {string} contents - The contents of the file to modify.\n * @param {string} relativePath - The relative path from the file to the output directory.\n * @param {Record<string, string[]>} alias - The alias configuration from tsconfig.json.\n * @param {string} ignoredPath - The ignored path from the entry file to the output file\n * @param {string} baseUrl - The baseUrl from the tsconfig compilerOptions\n * @param {string} originAbsolutePath - The origin absolute path\n * @returns {string} The modified file contents.\n */\nconst modifyAlias = (\n  contents: string,\n  relativePath: string,\n  alias: Record<string, string[]>,\n  ignoredPath: string,\n  baseUrl: string | undefined,\n  originAbsolutePath: string\n) => {\n  let result = contents;\n\n  // Replace ESM import paths that match aliases with the new relative paths.\n  result = result.replace(ESM_IMPORT_EXP, (match, importPath) => {\n    const newImportPath = replaceAliasInPath(\n      importPath,\n      relativePath,\n      alias,\n      ignoredPath,\n      baseUrl,\n      originAbsolutePath\n    );\n    return match.replace(importPath, newImportPath);\n  });\n\n  // Replace CJS require paths that match aliases with the new relative paths.\n  result = result.replace(CJS_REQUIRE_EXP, (match, importPath) => {\n    const newImportPath = replaceAliasInPath(\n      importPath,\n      relativePath,\n      alias,\n      ignoredPath,\n      baseUrl,\n      originAbsolutePath\n    );\n    return match.replace(importPath, newImportPath);\n  });\n\n  return result;\n};\n\n/**\n * Cleans up the path by removing redundant './' and '../' segments.\n *\n * @param {string} path - The path to clean up.\n * @returns {string} The cleaned up path.\n */\nconst cleanPath = (path: string) => normalizeImportPath(path);\n\n/**\n * Replaces an import path if it matches any alias with the corresponding relative path.\n *\n * @param {string} importPath - The original import path from the file.\n * @param {string} relativePath - The relative path from the file to the output directory.\n * @param {Record<string, string[]>} alias - The alias configuration from tsconfig.json.\n * @param {string} ignoredPath - The ignored path from the entry file to the output file\n * @param {string} baseUrl - The baseUrl from the tsconfig compilerOptions\n * @param {string} originAbsolutePath - The origin absolute path\n * @returns {string} The new import path with aliases replaced by relative paths.\n */\nconst replaceAliasInPath = (\n  importPath: string,\n  relativePath: string,\n  alias: Record<string, string[]>,\n  ignoredPath: string,\n  baseUrl: string | undefined,\n  originAbsolutePath: string\n) => {\n  // Iterate over each alias key in the alias configuration.\n  for (const aliasKey in alias) {\n    const aliasPatterns = alias[aliasKey]; // Array of alias paths\n\n    // Iterate over each pattern associated with the alias key.\n    for (const aliasPattern of aliasPatterns) {\n      const fixedAliasPattern = aliasPattern.replace(ignoredPath, \"\");\n\n      if (aliasKey.endsWith(\"*\")) {\n        // Handle wildcard aliases.\n        const aliasKeyBase = aliasKey.slice(0, -1);\n        const aliasPatternBase = fixedAliasPattern.slice(0, -1);\n\n        // Check if the import path starts with the alias base.\n        if (importPath.startsWith(aliasKeyBase)) {\n          const restOfPath = importPath.slice(aliasKeyBase.length);\n\n          // Construct the new relative path and ensure it's POSIX normalized.\n          const newRelativePath = `./${toPosix(\n            relativePath\n          )}/${aliasPatternBase}${restOfPath}`;\n\n          // Clean up the new relative path and ensure proper relative prefix.\n          let cleanedNewRelativePath = ensureDotRelative(\n            normalizeImportPath(newRelativePath)\n          );\n\n          return cleanedNewRelativePath;\n        }\n      } else if (importPath === aliasKey) {\n        // Construct the new relative path and ensure it's POSIX normalized.\n        const newRelativePath = `./${toPosix(\n          relativePath\n        )}/${fixedAliasPattern}`;\n\n        // Clean up the new relative path and ensure proper relative prefix.\n        let cleanedNewRelativePath = ensureDotRelative(\n          normalizeImportPath(newRelativePath)\n        );\n\n        return cleanedNewRelativePath;\n      }\n    }\n  }\n\n  // If no explicit alias matches and baseUrl is configured, try to handle baseUrl-based imports\n  if (\n    baseUrl &&\n    !isRelativeImport(importPath) &&\n    !isNodeModuleImport(importPath)\n  ) {\n    // Check if this could be a baseUrl-relative import\n    const resolvedBaseUrl = resolve(originAbsolutePath, baseUrl);\n\n    // Try to find the file with common extensions\n    const possibleExtensions = [\"\", \".ts\", \".tsx\", \".js\", \".jsx\", \".json\"];\n    let foundPath = null;\n\n    for (const ext of possibleExtensions) {\n      const fullPath = resolve(resolvedBaseUrl, importPath + ext);\n      if (existsSync(fullPath)) {\n        foundPath = fullPath;\n        break;\n      }\n\n      // Also try with index file\n      const indexPath = resolve(resolvedBaseUrl, importPath, \"index\" + ext);\n      if (existsSync(indexPath)) {\n        foundPath = indexPath;\n        break;\n      }\n    }\n\n    if (foundPath) {\n      // This is a valid baseUrl-based import, convert it to relative\n      const relativeToBase = relative(resolvedBaseUrl, foundPath);\n      const cleanedRelativeToBase = getPathWithoutExtension(relativeToBase);\n\n      // Construct the new relative path and ensure it's POSIX normalized.\n      const newRelativePath = `./${toPosix(\n        relativePath\n      )}/${cleanedRelativeToBase}`;\n      const cleanedNewRelativePath = ensureDotRelative(\n        normalizeImportPath(newRelativePath)\n      );\n\n      return cleanedNewRelativePath;\n    }\n  }\n\n  // Return the original import path if no alias matches.\n  return importPath;\n};\n\n/**\n * Checks if an import path is a relative import (starts with ./ or ../)\n */\nconst isRelativeImport = (importPath: string): boolean => {\n  return importPath.startsWith(\"./\") || importPath.startsWith(\"../\");\n};\n\n/**\n * Checks if an import path is a node module import (not relative and not absolute)\n * This is a simple heuristic - if it doesn't start with ./ or ../ or /,\n * and doesn't contain a file extension, it's likely a node module\n */\nconst isNodeModuleImport = (importPath: string): boolean => {\n  // If it starts with a dot or slash, it's not a node module\n  if (importPath.startsWith(\".\") || importPath.startsWith(\"/\")) {\n    return false;\n  }\n\n  // If it contains no slashes, it's likely a node module (e.g., 'react', 'lodash')\n  if (!importPath.includes(\"/\")) {\n    return true;\n  }\n\n  // If it starts with @, it's likely a scoped package (e.g., '@types/node')\n  if (importPath.startsWith(\"@\")) {\n    return true;\n  }\n\n  // Otherwise, we assume it could be a baseUrl-based import\n  return false;\n};\n"],"mappings":"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","names":["originAbsolutePath"]}