Skip to content

Instantly share code, notes, and snippets.

@IkeyBenz
Created August 26, 2021 00:21
Show Gist options
  • Save IkeyBenz/8915df0c7f08bde5a6b50a9e374fcfba to your computer and use it in GitHub Desktop.
Save IkeyBenz/8915df0c7f08bde5a6b50a9e374fcfba to your computer and use it in GitHub Desktop.
make-relative-imports-absolute.ts
/**
* This script is intended to convert all relative imports in this project into
* absolute imports from the reference of the 'src' directory.
*
* Additional rules:
* - Files in src/core should not be effected
*/
import fs from 'fs';
import path from 'path';
const getAllFilePaths = (dirname: string) => {
return fs.readdirSync(dirname).reduce((files, fileOrFolder) => {
const subPath = path.join(dirname, fileOrFolder);
if (fs.lstatSync(subPath).isDirectory()) {
files.push(...getAllFilePaths(subPath));
} else {
files.push(subPath);
}
return files;
}, [] as string[]);
};
const filterFilePaths = (filePaths: string[]): string[] => {
return filePaths
.filter((filePath) => filePath.endsWith('.ts') || filePath.endsWith('.tsx'))
.filter((filePath) => !filePath.includes('src/core'));
};
const readFile = (filePath: string) =>
new Promise<string>((resolve, reject) => {
fs.readFile(filePath, { encoding: 'utf-8' }, (err, data) => {
if (err) reject(err);
resolve(data);
});
});
const writeFile = (filePath: string, text: string) =>
new Promise<void>((resolve, reject) => {
fs.writeFile(filePath, text, (err) => {
if (err) reject(err);
resolve();
});
});
const getRelativeImportsInText = (text: string): string[] => {
return (
text
// All cared about imports will be preceded by this string
.split("from '")
// Clean each part to remove the content after newlines
.map((part) => part.split('\n')[0])
// Filter out the pieces of text that come before the word "from '"
.filter((part) => part.endsWith("';"))
// Filter for paths that are at least one folder deep
// .filter((part) => part.includes('../'))
.filter((part) => part.includes('/core/'))
// Finally remove the '; that is still attached to the end of each import
.map((part) => part.replace("';", ''))
);
};
const resolveRelativeImport = (
inFilePath: string,
relativeImport: string,
intendedRoot = 'hover-core',
) => {
const dir = inFilePath.slice(0, inFilePath.lastIndexOf('/'));
return path.join(
intendedRoot,
path.join(dir, relativeImport).split(intendedRoot + '/')[1],
);
};
const makeRelativeImportsAbsolute = (filePath: string) => {
return readFile(filePath)
.then((fileText) => {
const pathsToReplace = getRelativeImportsInText(fileText);
return pathsToReplace.reduce((updatedFileText, relativeImport) => {
const absoluteImport = resolveRelativeImport(filePath, relativeImport);
console.log(relativeImport, ' => ', absoluteImport);
return updatedFileText.replace(relativeImport, absoluteImport);
}, fileText);
})
.then((fileTextWithAbsoluteImports) =>
writeFile(filePath, fileTextWithAbsoluteImports),
);
};
const makeImportsAbsolute = async () => {
const srcPath = 'src';
const filesToUpdate = filterFilePaths(getAllFilePaths(srcPath));
console.log(
'\n\nabout to update',
filesToUpdate.length,
'files to have absolute imports',
);
Promise.all(filesToUpdate.map(makeRelativeImportsAbsolute)).then(() => {
console.log('done');
});
};
makeImportsAbsolute();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment