139 lines
4.7 KiB
JavaScript
Executable file
139 lines
4.7 KiB
JavaScript
Executable file
const fs = require('fs');
|
||
const { Project, SyntaxKind } = require('ts-morph');
|
||
console.log('Starting refactoring...');
|
||
|
||
const project = new Project({
|
||
tsConfigFilePath: 'C:/ScriptoriumAI/scriptoriumai-ui/tsconfig.json'
|
||
});
|
||
|
||
const runboardFile = project.getSourceFile('src/pages/Runboard.tsx');
|
||
if (!runboardFile) throw new Error('Runboard.tsx not found');
|
||
|
||
// 1. Textual split for exact formatting preservation
|
||
const runboardPath = 'C:/ScriptoriumAI/scriptoriumai-ui/src/pages/Runboard.tsx';
|
||
let lines = fs.readFileSync(runboardPath, 'utf8').split('\n');
|
||
|
||
let splitLineIdx = lines.findIndex(line => line.startsWith('export function Runboard('));
|
||
if (splitLineIdx === -1) throw new Error('Not found: main Runboard component');
|
||
|
||
let helperLines = [...lines.slice(0, splitLineIdx)];
|
||
const exportsList = [];
|
||
|
||
for (let i = 0; i < helperLines.length; i++) {
|
||
let line = helperLines[i];
|
||
|
||
// adjust relative imports
|
||
if (line.includes(rom './)) {
|
||
line = line.replace(/from '\.\//g, rom '../pages/);
|
||
line = line.replace(/from "\.\//g, rom "../pages/);
|
||
}
|
||
|
||
// Auto-export top level declarations
|
||
if (/^(function|const|let|var|type|interface|enum) /.test(line)) {
|
||
line = 'export ' + line;
|
||
}
|
||
|
||
// Collect all exports
|
||
const match = line.match(/^export (?:default )?(?:function|type|const|let|var|interface|enum) ([a-zA-Z0-9_]+)/);
|
||
if (match) {
|
||
exportsList.push(match[1]);
|
||
}
|
||
|
||
helperLines[i] = line;
|
||
}
|
||
|
||
const uniqueExports = Array.from(new Set(exportsList));
|
||
|
||
fs.writeFileSync('C:/ScriptoriumAI/scriptoriumai-ui/src/utils/runboard-route-logic.tsx', helperLines.join('\n'));
|
||
|
||
const runboardLines = lines.slice(splitLineIdx);
|
||
|
||
const topImports = [];
|
||
let inImport = false;
|
||
for (let i = 0; i < lines.slice(0, splitLineIdx).length; i++) {
|
||
let line = lines[i];
|
||
if (line.startsWith('import ')) {
|
||
inImport = true;
|
||
}
|
||
if (inImport || line.startsWith('import ')) {
|
||
topImports.push(line);
|
||
if (line.includes('from ') || line.includes('\'') || line.includes('"')) {
|
||
if (line.includes('from ')) inImport = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
const newRunboardContent = [
|
||
...topImports,
|
||
import { + uniqueExports.join(',\n ') + } from '../utils/runboard-route-logic';,
|
||
'',
|
||
...runboardLines
|
||
].join('\n');
|
||
|
||
fs.writeFileSync(runboardPath, newRunboardContent);
|
||
console.log('File split done. Exports extracted: ' + uniqueExports.length);
|
||
|
||
// 2. Reload project and fix imports via ts-morph
|
||
// We need to recreate the project to pick up the filesystem changes
|
||
const project2 = new Project({
|
||
tsConfigFilePath: 'C:/ScriptoriumAI/scriptoriumai-ui/tsconfig.json'
|
||
});
|
||
|
||
const logicFile = project2.getSourceFileOrThrow('src/utils/runboard-route-logic.tsx');
|
||
const exportedDecls = logicFile.getExportedDeclarations();
|
||
const exportedNames = new Set(Array.from(exportedDecls.keys()));
|
||
|
||
console.log(Found + exportedNames.size + exported symbols in utils file via AST.);
|
||
|
||
const sourceFiles = project2.getSourceFiles();
|
||
for (const sf of sourceFiles) {
|
||
if (sf.getFilePath() === logicFile.getFilePath() || sf.getFilePath() === runboardPath) {
|
||
continue;
|
||
}
|
||
|
||
const imports = sf.getImportDeclarations();
|
||
let changed = false;
|
||
|
||
for (const imp of imports) {
|
||
const moduleSpecifier = imp.getModuleSpecifierValue();
|
||
if (moduleSpecifier.endsWith('pages/Runboard')) {
|
||
const namedImports = imp.getNamedImports();
|
||
const toMove = [];
|
||
for (const named of namedImports) {
|
||
const name = named.getName();
|
||
if (uniqueExports.includes(name) || exportedNames.has(name)) {
|
||
toMove.push({
|
||
name: name,
|
||
alias: named.getAliasNode() ? named.getAliasNode().getText() : undefined
|
||
});
|
||
}
|
||
}
|
||
|
||
if (toMove.length > 0) {
|
||
changed = true;
|
||
const relativePathToUtils = moduleSpecifier.replace('pages/Runboard', 'utils/runboard-route-logic');
|
||
|
||
sf.addImportDeclaration({
|
||
namedImports: toMove,
|
||
moduleSpecifier: relativePathToUtils
|
||
});
|
||
|
||
for (const named of namedImports) {
|
||
if (toMove.some(m => m.name === named.getName())) {
|
||
named.remove();
|
||
}
|
||
}
|
||
|
||
if (imp.getNamedImports().length === 0 && !imp.getDefaultImport()) {
|
||
imp.remove();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (changed) {
|
||
sf.saveSync();
|
||
console.log(Updated imports in + sf.getBaseName());
|
||
}
|
||
}
|
||
|
||
console.log('Complete!');
|