Skip to main content
Glama
SiroSuzume

MCP ts-morph Refactoring Tools

by SiroSuzume
prepare-renames.ts3 kB
import logger from "../../utils/logger"; import type { PathMapping, RenameOperation } from "../types"; import * as path from "node:path"; import { performance } from "node:perf_hooks"; import type { Project } from "ts-morph"; function checkDestinationExists( project: Project, pathToCheck: string, signal?: AbortSignal, ): void { signal?.throwIfAborted(); if (project.getSourceFile(pathToCheck)) { throw new Error(`リネーム先パスに既にファイルが存在します: ${pathToCheck}`); } if (project.getDirectory(pathToCheck)) { throw new Error( `リネーム先パスに既にディレクトリが存在します: ${pathToCheck}`, ); } } export function prepareRenames( project: Project, renames: PathMapping[], signal?: AbortSignal, ): RenameOperation[] { const startTime = performance.now(); signal?.throwIfAborted(); const renameOperations: RenameOperation[] = []; const uniqueNewPaths = new Set<string>(); logger.debug({ count: renames.length }, "Starting rename preparation"); for (const rename of renames) { signal?.throwIfAborted(); const logRename = { old: rename.oldPath, new: rename.newPath }; logger.trace({ rename: logRename }, "Processing rename request"); const absoluteOldPath = path.resolve(rename.oldPath); const absoluteNewPath = path.resolve(rename.newPath); if (uniqueNewPaths.has(absoluteNewPath)) { throw new Error(`リネーム先のパスが重複しています: ${absoluteNewPath}`); } uniqueNewPaths.add(absoluteNewPath); checkDestinationExists(project, absoluteNewPath, signal); signal?.throwIfAborted(); const sourceFile = project.getSourceFile(absoluteOldPath); const directory = project.getDirectory(absoluteOldPath); if (sourceFile) { logger.trace({ path: absoluteOldPath }, "Identified as file rename"); renameOperations.push({ sourceFile, oldPath: absoluteOldPath, newPath: absoluteNewPath, }); } else if (directory) { logger.trace({ path: absoluteOldPath }, "Identified as directory rename"); signal?.throwIfAborted(); const filesInDir = directory.getDescendantSourceFiles(); logger.trace( { path: absoluteOldPath, count: filesInDir.length }, "Found files in directory to rename", ); for (const sf of filesInDir) { const oldFilePath = sf.getFilePath(); const relative = path.relative(absoluteOldPath, oldFilePath); const newFilePath = path.resolve(absoluteNewPath, relative); logger.trace( { oldFile: oldFilePath, newFile: newFilePath }, "Adding directory file to rename operations", ); renameOperations.push({ sourceFile: sf, oldPath: oldFilePath, newPath: newFilePath, }); } } else { throw new Error(`リネーム対象が見つかりません: ${absoluteOldPath}`); } } const durationMs = (performance.now() - startTime).toFixed(2); logger.debug( { operationCount: renameOperations.length, durationMs }, "Finished rename preparation", ); return renameOperations; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/SiroSuzume/mcp-ts-morph'

If you have feedback or need assistance with the MCP directory API, please join our Discord server