Created
August 2, 2019 12:19
-
-
Save ArminBu/e03c79291de585b0d732b1e2d198d8aa to your computer and use it in GitHub Desktop.
This script should replace all absolute alias imports with relative imports. It expects 1 argument for the root directory
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 path = require("path"); | |
const args = process.argv; | |
const rootName = args[2]; | |
const rootPath = path.resolve(process.cwd(), rootName); | |
const alias = "@"; | |
if (!rootPath || !alias) return; | |
const { promisify } = require("util"); | |
const fs = require("fs"); | |
const readFileAsync = promisify(fs.readFile); | |
const readDirAsync = promisify(fs.readdir); | |
const writeFileAsync = promisify(fs.writeFile); | |
const statsAsync = promisify(fs.stat); | |
function testForAliasImport(file) { | |
if (!file.content) return file; | |
const regex = /"@(\/\w+[\w\/.]+)"/gi; | |
let match, | |
search = file.content; | |
while ((match = regex.exec(search))) { | |
const matchString = match[0]; | |
console.log(`found alias import ${matchString} in ${file.filepath}`); | |
file.content = file.content.replace( | |
matchString, | |
aliasToRelative(file, matchString) | |
); | |
search = search.substring(match.index + matchString.length); | |
} | |
return file; | |
} | |
function aliasToRelative(file, importString) { | |
let importPath = importString | |
.replace(alias, "") | |
.split('"') | |
.join(""); | |
const hasExtension = !!path.parse(importString).ext; | |
if (!hasExtension) { | |
importPath += ".ext"; | |
} | |
const filepath = file.filepath | |
.replace(rootPath, "") | |
.split("\\") | |
.join("/"); | |
let relativeImport = path.posix.relative(path.dirname(filepath), importPath); | |
if (!hasExtension) { | |
relativeImport = relativeImport.replace(".ext", ""); | |
} | |
if (!relativeImport.startsWith("../")) { | |
relativeImport = "./" + relativeImport; | |
} | |
relativeImport = `"${relativeImport}"`; | |
console.log(`replaced alias import ${importString} with ${relativeImport}`); | |
return relativeImport; | |
} | |
async function writeFile(file) { | |
if (!file || !file.content || !file.filepath) return file; | |
try { | |
console.log(`writing new contents to file ${file.filepath}...`); | |
await writeFileAsync(file.filepath, file.content); | |
} catch (e) { | |
console.error(e); | |
} | |
} | |
async function prepareFile(filepath) { | |
const stat = await statsAsync(filepath); | |
return { stat, filepath }; | |
} | |
async function processFile(file) { | |
if (file.stat.isFile()) { | |
console.log(`reading file ${file.filepath}...`); | |
file.content = await readFileAsync(file.filepath); | |
file.content = file.content.toString(); | |
} else if (file.stat.isDirectory()) { | |
console.log(`traversing dir ${file.filepath}...`); | |
await traverseDir(file.filepath); | |
} | |
return file; | |
} | |
async function traverseDir(dirPath) { | |
try { | |
const filenames = await readDirAsync(dirPath); | |
const filepaths = filenames.map(name => path.join(dirPath, name)); | |
const fileStats = await Promise.all(filepaths.map(prepareFile)); | |
const files = await Promise.all(fileStats.map(processFile)); | |
await Promise.all(files.map(testForAliasImport).map(writeFile)); | |
} catch (e) { | |
console.error(e); | |
} | |
} | |
traverseDir(rootPath) | |
.then(() => console.log("done")) | |
.catch(console.error); |
no. using regex to parse sources is just wrong
eslint is the best tool for javascript codemods, so...
https://github.com/johvin/eslint-import-resolver-alias - resolve alias imports, ...
https://github.com/dword-design/eslint-plugin-import-alias - enforce the use of import aliases
https://github.com/joshuajaco/eslint-plugin-workspaces/blob/main/lib/rules/no-absolute-imports.js - absolute to relative imports
https://github.com/joshuajaco/eslint-plugin-workspaces/blob/main/lib/rules/no-relative-imports.js - relative to absolute imports
https://github.com/qdanik/eslint-plugin-path/blob/main/lib/rules/no-relative-imports.js - relative to absolute imports
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for that script 🙏
Worked perfectly for me except that I had to change
"
with'
so would be great to have a quote sign option. Also, I had to change path.posix.relative with path.relative – the path.posix didn't work for me on mac. Result script isUsed it as
"replaceimports": "node rename.js src"
, though for some reason I had to rerun it a lot of times because it replaced imports partially (not every import was replaced at once, but several per file). Didn't dig into it.