openpetswithchatandmcp/website/split-runboard.ts
OpenPets Dev 65ac83849e Add 'website/' from commit '966aea480ffe1c340553aa878def30131d2af827'
git-subtree-dir: website
git-subtree-mainline: 8d3849caea
git-subtree-split: 966aea480f
2026-06-17 20:48:39 +00:00

79 lines
No EOL
3.1 KiB
TypeScript
Executable file

import { Project, SyntaxKind } from 'ts-morph';
import * as fs from 'fs';
import * as path from 'path';
const project = new Project({ tsConfigFilePath: 'C:/ScriptoriumAI/scriptoriumai-ui/tsconfig.json' });
const sourceFile = project.getSourceFileOrThrow('C:/ScriptoriumAI/scriptoriumai-ui/src/pages/Runboard.tsx');
const pagesDir = 'C:/ScriptoriumAI/scriptoriumai-ui/src/pages/Runboard';
if (!fs.existsSync(pagesDir)) fs.mkdirSync(pagesDir, { recursive: true });
// 1. Extract purely logic helpers into Runboard/utils.tsx
const utilsFile = project.createSourceFile(pagesDir + '/utils.tsx', '', { overwrite: true });
// Collect all top-level functions (except Runboard)
const stmts = sourceFile.getStatements();
const toMove = stmts.filter(s =>
s.getKindName() !== 'ImportDeclaration' &&
s.getKindName() !== 'ExportDeclaration' &&
!(s.isKind(SyntaxKind.FunctionDeclaration) && s.getName() === 'Runboard')
);
toMove.forEach(s => {
// Ensure exported
if (s.isKind(SyntaxKind.FunctionDeclaration) || s.isKind(SyntaxKind.VariableStatement) || s.isKind(SyntaxKind.TypeAliasDeclaration) || s.isKind(SyntaxKind.InterfaceDeclaration)) {
if (!s.hasExportKeyword()) {
(s as any).setIsExported(true);
}
}
utilsFile.addStatements(s.getText());
s.remove();
});
// Steal imports
sourceFile.getImportDeclarations().forEach(imp => {
utilsFile.addImportDeclaration({
isTypeOnly: imp.isTypeOnly(),
defaultImport: imp.getDefaultImport()?.getText(),
namedImports: imp.getNamedImports().map(n => ({ name: n.getName(), alias: n.getAliasNode()?.getText() })),
moduleSpecifier: imp.getModuleSpecifierValue().startsWith('./') ? '../../' + imp.getModuleSpecifierValue().substring(2) : (imp.getModuleSpecifierValue().startsWith('../') ? '../../../' + imp.getModuleSpecifierValue().substring(3) : imp.getModuleSpecifierValue())
});
});
// Import them back into sourceFile
const namesToImport: string[] = [];
utilsFile.getStatements().forEach(s => {
if (s.isKind(SyntaxKind.FunctionDeclaration) || s.isKind(SyntaxKind.TypeAliasDeclaration) || s.isKind(SyntaxKind.InterfaceDeclaration)) {
const n = (s as any).getName?.();
if (n) namesToImport.push(n);
}
if (s.isKind(SyntaxKind.VariableStatement)) {
s.getDeclarations().forEach(d => namesToImport.push(d.getName()));
}
});
sourceFile.addImportDeclaration({
namedImports: namesToImport,
moduleSpecifier: './Runboard/utils'
});
// 2. Componentize the Layout shell:
// Let's create Layout.tsx which exports the wrapper
const layoutFile = project.createSourceFile(pagesDir + '/Layout.tsx', '', { overwrite: true });
layoutFile.addStatements(`
import React from 'react';
import { PlatformAuthProvider } from '../../auth/platform-auth';
import { SubscriptionGate } from '../../components/SubscriptionGate';
export function RunboardLayout({ children }: { children: React.ReactNode }) {
return (
<PlatformAuthProvider>
<SubscriptionGate>
{children}
</SubscriptionGate>
</PlatformAuthProvider>
);
}
`);
project.saveSync();
console.log('Runboard Componentization Phase 1 done: Splitting shell utils and wrappers.');