TeaWeb/shared/fix-imports.ts

78 lines
2.8 KiB
TypeScript

import * as ts from "tsd/libraries/typescript";
import {SourceFile, SyntaxKind, TransformerFactory} from "tsd/libraries/typescript";
import * as path from "path";
import * as fs from "fs-extra";
type ImportReplacement = { index: number, length: number, replacement: string };
let importReplacements: ImportReplacement[] = [];
const ImportTransformerFactory: (depth: number) => TransformerFactory<SourceFile> = fileDepth => context => source => {
const visit = (node: ts.Node, depth: number) => {
if(node.kind === SyntaxKind.ImportDeclaration) {
const decl = node as ts.ImportDeclaration;
if(decl.moduleSpecifier?.kind === SyntaxKind.StringLiteral) {
const module = decl.moduleSpecifier as ts.StringLiteral;
if(module.text.startsWith("tc-shared")) {
const rootPath = [...new Array(fileDepth)].map(() => "..").join("/");
const newPath = (rootPath || ".") + module.text.substr(9);
console.error("Import: %o -> %o", module.text, newPath);
importReplacements.push({
index: module.getStart(source, false) + 1,
length: module.getWidth(source) - 2,
replacement: newPath
});
}
}
}
if(depth > 5) {
/* no import decl possible */
return node;
}
return ts.visitEachChild(node, n => visit(n, depth + 1), context);
};
return ts.visitNode(source, n => visit(n, fileDepth));
}
async function processFile(file: string, fileDepth: number) {
if(path.extname(file) !== ".ts") {
return;
}
let sourceData = (await fs.readFile(file)).toString();
let source = ts.createSourceFile(
file,
sourceData,
ts.ScriptTarget.ES2015,
true
);
console.log("Transforming %s", file);
importReplacements = [];
ts.transform(source, [ImportTransformerFactory(fileDepth)]);
importReplacements.sort((a, b) => b.index - a.index);
importReplacements.forEach(replacement => {
sourceData = sourceData.substring(0, replacement.index) + replacement.replacement + sourceData.substring(replacement.index + replacement.length);
});
await fs.writeFile(file, sourceData);
}
async function processDirectory(directory: string, depth: number) {
const files = await fs.readdir(directory);
for(const file of files) {
let filePath = path.join(directory, file);
if((await fs.stat(filePath)).isDirectory()) {
await processDirectory(filePath, depth + 1);
} else {
await processFile(filePath, depth);
}
}
}
processDirectory(path.join(__dirname, "js"), 0).catch(error => {
console.error(error);
});