Last active
August 30, 2018 19:03
-
-
Save rifler/e6123e90e172814fe23d5a6a11ed5eb1 to your computer and use it in GitHub Desktop.
AbsoluteToRelative
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs'); | |
const nodePath = require('path'); | |
const paths = require('tsconfig-paths'); | |
// этот модуль умеет рекурсивно раскрывать extends | |
const tsconfig = require('tsconfig-extends'); | |
const Project = require('ts-simple-ast').default; | |
module.exports = async ({ | |
tsconfigPath: incomingTSConfigPath, | |
filesGlob, | |
cwd = process.cwd(), | |
}) => { | |
let tsconfigPath = incomingTSConfigPath; | |
if (!nodePath.isAbsolute(tsconfigPath)) { | |
tsconfigPath = nodePath.normalize(nodePath.join(cwd, tsconfigPath)); | |
} | |
const compilerOptions = tsconfig.load_file_sync(tsconfigPath); | |
const absoluteBaseUrl = nodePath.join(cwd, compilerOptions.baseUrl); | |
const matchPathFunc = paths.createMatchPath( | |
absoluteBaseUrl, | |
compilerOptions.paths || {}, | |
); | |
const project = new Project({ compilerOptions }); | |
project.addExistingSourceFiles(filesGlob); | |
const sourceFiles = project.getSourceFiles(); | |
let anyFileWasChanged = false; | |
for (const sourceFile of sourceFiles) { | |
// находим все импорты и экспорты | |
const importExportDeclarations = [ | |
...sourceFile.getImportDeclarations(), | |
...sourceFile.getExportDeclarations(), | |
]; | |
const sourceFileAbsolutePath = sourceFile.getFilePath(); | |
const sourceFileAbsoluteDirName = nodePath.dirname( | |
sourceFileAbsolutePath, | |
); | |
for (const declaration of importExportDeclarations) { | |
// у экспорта может не быть "module specifier", например: | |
// export { SomeClass }; | |
const isEmptyExportDeclaration = | |
declaration.hasModuleSpecifier && | |
!declaration.hasModuleSpecifier(); | |
// если модуль выглядит как абсолютный, например import ... from 'icons'; | |
if ( | |
!isEmptyExportDeclaration && | |
!declaration.isModuleSpecifierRelative() | |
) { | |
// получаем имя модуля | |
// (например: 'components', 'components/SomeModule', 'components/SomeModule/index') | |
const value = declaration.getModuleSpecifierValue(); | |
// Пробуем найти относительный модуль по имени | |
// Если имя - это существующий путь до папки - функция вернет относительный путь | |
// Если такой папки нет, то пробуем подставлять каждое расширение в конец строки | |
// и проверять существование файла (напр. components/SomeModule/index(.tsx|.ts|.js)) | |
// Если найден хоть один файл - возвращаем относительный путь до него | |
// Если файлы не найдены - undefined | |
const absolutePathToDepsModule = matchPathFunc( | |
value, | |
undefined, | |
fs.existsSync, | |
['.tsx', '.ts', '.jsx', '.js'], | |
); | |
// и если такое совпадение найдено | |
if (absolutePathToDepsModule) { | |
const resultPath = nodePath.relative( | |
sourceFileAbsoluteDirName, | |
absolutePathToDepsModule, | |
); | |
// применяем его | |
// import { IconToggler } from 'icons'; | |
// ↓ | |
// import { IconToggler } from '../../..'; | |
declaration.setModuleSpecifier(resultPath); | |
anyFileWasChanged = true; | |
} | |
} | |
} | |
} | |
if (anyFileWasChanged) { | |
await project.save(); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment