Skip to main content
Glama
SiroSuzume

MCP ts-morph Refactoring Tools

by SiroSuzume
remove-path-alias.ts3.48 kB
import type { Project, SourceFile, ImportDeclaration, ExportDeclaration, } from "ts-morph"; import { calculateRelativePath } from "../_utils/calculate-relative-path"; /** * モジュール指定子がパスエイリアスかどうかを判定する */ function isPathAlias(moduleSpecifier: string, alias: string[]): boolean { // paths のキー(例: "@/*", "@components/*", "exact-alias")に基づいて判定 return alias.some((alias) => { if (moduleSpecifier === alias) { return true; // 完全一致 } if (!alias.endsWith("/*")) { return false; // ワイルドカードエイリアスでない場合は false } const prefix = alias.substring(0, alias.length - 1); // 末尾の '*' を除く (例: "@/", "@components/") return moduleSpecifier.startsWith(prefix); }); } /** * 1つのソースファイル内のパスエイリアスを相対パスに置換する */ function processSourceFile( sourceFile: SourceFile, baseUrl: string, paths: Record<string, string[]>, dryRun: boolean, ): boolean { let changed = false; const sourceFilePath = sourceFile.getFilePath(); const alias = Object.keys(paths); const declarations: (ImportDeclaration | ExportDeclaration)[] = [ ...sourceFile.getImportDeclarations(), ...sourceFile.getExportDeclarations(), ]; for (const declaration of declarations) { const moduleSpecifierNode = declaration.getModuleSpecifier(); if (!moduleSpecifierNode) continue; const moduleSpecifier = moduleSpecifierNode.getLiteralText(); if (!isPathAlias(moduleSpecifier, alias)) { continue; } // TypeScript/ts-morph の解決結果を使用 const resolvedSourceFile = declaration.getModuleSpecifierSourceFile(); if (!resolvedSourceFile) { // console.warn(`[remove-path-alias] Could not resolve module specifier: ${moduleSpecifier} in ${sourceFilePath}`); continue; // 解決できないエイリアスはスキップ } const targetAbsolutePath = resolvedSourceFile.getFilePath(); const relativePath = calculateRelativePath( sourceFilePath, targetAbsolutePath, { simplifyIndex: false, removeExtensions: true, }, ); if (!dryRun) { declaration.setModuleSpecifier(relativePath); } changed = true; } return changed; } /** * 指定されたパス (ファイルまたはディレクトリ) 内のパスエイリアスを相対パスに置換する */ export async function removePathAlias({ project, targetPath, dryRun = false, baseUrl, paths, }: { project: Project; // Project インスタンスは呼び出し元で作成・管理 targetPath: string; dryRun?: boolean; baseUrl: string; paths: Record<string, string[]>; }): Promise<{ changedFiles: string[] }> { let filesToProcess: SourceFile[] = []; const directory = project.getDirectory(targetPath); if (directory) { filesToProcess = directory.getSourceFiles("**/*.{ts,tsx,js,jsx}"); } else { const sourceFile = project.getSourceFile(targetPath); if (!sourceFile) { throw new Error( `指定されたパスはプロジェクト内でディレクトリまたはソースファイルとして見つかりません: ${targetPath}`, ); } filesToProcess.push(sourceFile); } const changedFilePaths: string[] = []; for (const sourceFile of filesToProcess) { const modified = processSourceFile(sourceFile, baseUrl, paths, dryRun); if (!modified) { continue; } changedFilePaths.push(sourceFile.getFilePath()); } return { changedFiles: changedFilePaths }; }

Implementation Reference

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