UNPKG

dts-paths

Version:

Replace alias paths with relative paths after typescript compilation.

156 lines (151 loc) 4.83 kB
/** * @module dts-paths * @package dts-paths * @license MIT * @version 1.1.8 * @author nuintun <nuintun@qq.com> * @description Replace alias paths with relative paths after typescript compilation. * @see https://github.com/nuintun/dts-paths#readme */ 'use strict'; const node_path = require('node:path'); const tsMorph = require('ts-morph'); /** * @module index */ const EXT_RE = /\.(?:(?:d\.)?([cm]?tsx?)|([cm]?jsx?))$/i; function resolveModuleName(moduleName, containingFile, extensions, compilerOptions, moduleResolutionHost) { for (const extension of extensions) { for (const suffix of [extension, `/index${extension}`]) { const { resolvedModule } = tsMorph.ts.resolveModuleName( // Module name. `${moduleName}${suffix}`, // Containing file. containingFile, // Compiler options. compilerOptions, // Module resolution host. moduleResolutionHost ); if (resolvedModule) { return resolvedModule; } } } const { resolvedModule } = tsMorph.ts.resolveModuleName( // Module name. moduleName, // Containing file. containingFile, // Compiler options. compilerOptions, // Module resolution host. moduleResolutionHost ); return resolvedModule; } function getRelativeModulePath(resolvedFilePath, sourceFile) { const relativePath = sourceFile.getRelativePathTo(resolvedFilePath); const modulePath = relativePath.replace(EXT_RE, (match, tsExt, jsExt) => { const fileExt = tsExt || jsExt; if (fileExt) { switch (fileExt.toLowerCase()) { case 'js': case 'ts': case 'jsx': case 'tsx': return '.js'; case 'cjs': case 'cts': case 'cjsx': case 'ctsx': return '.cjs'; case 'mjs': case 'mts': case 'mjsx': case 'mtsx': return '.mjs'; default: return match; } } return match; }); return modulePath.startsWith('.') ? modulePath : `./${modulePath}`; } /** * @function resolvePaths * @description Resolve dts import paths. * @param root The root directory of dts. * @param options The options of resolve. * @return {Promise<Set<string>>} */ async function resolvePaths( root, { compilerOptions, exclude = ['node_modules'], tsConfigFilePath = 'tsconfig.json', extensions = ['.ts', '.cts', '.mts', '.d.ts', '.d.cts', '.d.mts'] } = {} ) { const changed = new Set(); const moduleResolution = new Map(); const project = new tsMorph.Project({ compilerOptions, skipAddingFilesFromTsConfig: true, skipFileDependencyResolution: true, tsConfigFilePath: node_path.resolve(tsConfigFilePath), resolutionHost(moduleResolutionHost, getCompilerOptions) { const compilerOptions = getCompilerOptions(); return { resolveModuleNames(moduleNames, containingFile) { const resolvedModules = []; const resolvedImports = moduleResolution.get(containingFile) || new Map(); if (!moduleResolution.has(containingFile)) { moduleResolution.set(containingFile, resolvedImports); } for (const moduleName of moduleNames) { const resolvedModule = resolveModuleName( moduleName, containingFile, extensions, compilerOptions, moduleResolutionHost ); resolvedModules.push(resolvedModule); if (resolvedModule && !resolvedModule.isExternalLibraryImport) { resolvedImports.set(moduleName, resolvedModule.resolvedFileName); } } return resolvedModules; } }; } }); exclude = exclude.map(pattern => `!${pattern}`); const include = node_path.resolve(root, '**/*.{ts,cts,mts,tsx,ctsx,mtsx}'); const sourceFiles = project.addSourceFilesAtPaths([include, ...exclude]); project.resolveSourceFileDependencies(); for (const sourceFile of sourceFiles) { const sourceFilePath = sourceFile.getFilePath(); const resolvedImports = moduleResolution.get(sourceFilePath); if (resolvedImports) { const importLiterals = sourceFile.getImportStringLiterals(); for (const importLiteral of importLiterals) { const moduleName = importLiteral.getLiteralValue(); const resolvedFilePath = resolvedImports.get(moduleName); if (resolvedFilePath) { const relativeModulePath = getRelativeModulePath(resolvedFilePath, sourceFile); if (relativeModulePath !== moduleName) { changed.add(sourceFilePath); importLiteral.setLiteralValue(relativeModulePath); } } } } } await project.save(); return changed; } exports.resolvePaths = resolvePaths;