106 lines
4.0 KiB
JavaScript
106 lines
4.0 KiB
JavaScript
import { Project, SyntaxKind } from "ts-morph";
|
|
import * as fs from "fs";
|
|
import * as path from "path";
|
|
|
|
const project = new Project();
|
|
const implFilePath = "src/preview/ops/implementation.ts";
|
|
const implFile = project.addSourceFileAtPath(implFilePath);
|
|
|
|
const mappings = {
|
|
"src/preview/ops/geometry.ts": [
|
|
"crop", "cropGeneric", "cropReformat", "cropStitch", "pad", "padOut",
|
|
"resize", "transform", "flipRotate", "cornerPin", "cameraShake", "distort", "spherize"
|
|
],
|
|
"src/preview/ops/blend.ts": [
|
|
"merge", "composite", "comp"
|
|
],
|
|
"src/preview/ops/masks.ts": [
|
|
"imageOpsMask", "channelApply"
|
|
],
|
|
"src/preview/ops/procedural.ts": [
|
|
"constant", "ramp", "noise", "grain", "text", "draw", "drawMask", "keyer", "stitch"
|
|
],
|
|
"src/preview/ops/video.ts": [
|
|
"channelSplit", "channelMerge"
|
|
]
|
|
};
|
|
|
|
const opsObjDecl = implFile.getVariableDeclarationOrThrow("ops");
|
|
const opsObj = opsObjDecl.getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression);
|
|
|
|
// Export all functions in implementation.ts so they can be imported
|
|
for (const func of implFile.getFunctions()) {
|
|
if (!func.isExported()) {
|
|
func.setIsExported(true);
|
|
}
|
|
}
|
|
|
|
let importsToAdd = {};
|
|
|
|
for (const [filePath, funcs] of Object.entries(mappings)) {
|
|
let extractedCode = "";
|
|
let extractedFuncs = [];
|
|
|
|
for (const prop of opsObj.getProperties()) {
|
|
if (prop.isKind(SyntaxKind.MethodDeclaration)) {
|
|
const name = prop.getName();
|
|
if (funcs.includes(name)) {
|
|
console.log(`Extracting ${name} to ${filePath}...`);
|
|
const text = prop.getText();
|
|
// Change methodName(...) or async methodName(...) to export [async] function methodName(...)
|
|
const isAsync = prop.isAsync() ? "async " : "";
|
|
|
|
// We use a regex that matches either name( or async name(
|
|
const regex = new RegExp(`^(async\\s+)?${name}\\s*\\(`);
|
|
const funcText = text.replace(regex, `export ${isAsync}function ${name}(`);
|
|
|
|
extractedCode += funcText + "\n\n";
|
|
extractedFuncs.push(name);
|
|
|
|
// Replace the method in opsObj with a property assignment
|
|
prop.replaceWithText(`${name}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (extractedCode) {
|
|
let destFile = project.addSourceFileAtPathIfExists(filePath);
|
|
if (!destFile) {
|
|
destFile = project.createSourceFile(filePath, "");
|
|
}
|
|
|
|
// Remove existing Extracted comment and below if script was run before
|
|
const currentText = destFile.getFullText();
|
|
const splitIndex = currentText.indexOf("// Extracted with ts-morph");
|
|
let newText = splitIndex !== -1 ? currentText.substring(0, splitIndex) : currentText;
|
|
|
|
// Ensure imports exist
|
|
if (!newText.includes("import type { ComfyNode }")) {
|
|
newText = `import type { ComfyNode } from "../../types.js";\n` + newText;
|
|
}
|
|
if (!newText.includes("import * as impl")) {
|
|
newText = `import * as impl from "./implementation.js";\n` + newText;
|
|
// Also need to rewrite the function body to use impl. for missing references, but that's too complex.
|
|
// A simpler approach: we'll just let the user fix the imports or we do it manually after.
|
|
}
|
|
|
|
destFile.replaceWithText(newText + "\n\n// Extracted with ts-morph\n\n" + extractedCode);
|
|
destFile.saveSync();
|
|
console.log(`Successfully appended to ${filePath}!`);
|
|
|
|
const moduleName = "./" + path.basename(filePath, ".ts") + ".js";
|
|
importsToAdd[moduleName] = extractedFuncs;
|
|
}
|
|
}
|
|
|
|
// Add imports to implementation.ts
|
|
for (const [moduleName, funcs] of Object.entries(importsToAdd)) {
|
|
implFile.addImportDeclaration({
|
|
namedImports: funcs,
|
|
moduleSpecifier: moduleName
|
|
});
|
|
}
|
|
|
|
implFile.saveSync();
|
|
console.log("Refactoring complete!");
|