Skip to main content
Glama

scan_project

Scans directories to identify files containing legacy HeroUI/NextUI components for migration to HeroUI v3 beta.

Instructions

Recursively scans a directory for files using legacy HeroUI/NextUI components.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
directoryYes

Implementation Reference

  • The `scanProject` function implements the logic to scan a project directory for legacy components (based on `KNOWN_V2_IMPORTS`), calculate a priority level for each file, and maintain a scan cache.
    export async function scanProject(directory: string, options: { force?: boolean } = {}) {
      const { force = false } = options;
      const patterns = ["**/*.{ts,tsx,js,jsx}"];
      const files = await fg(patterns, {
        cwd: directory,
        absolute: true,
        onlyFiles: true,
        ignore: ["**/node_modules/**", "**/dist/**", "**/.next/**"]
      });
    
      const report: { file: string, components: string[]; priority?: string }[] = [];
      const v2Keys = Object.keys(KNOWN_V2_IMPORTS);
      const joint = v2Keys.map(k => k.replace(/[.*+?^${}()|[\\]\\]/g, '\\$&')).join("|");
      const quick = new RegExp(joint);
    
      // simple cache stored at repo root
      const cacheFile = path.join(process.cwd(), '.scan-cache.json');
      let cache: Record<string, { mtime: number; components: string[] }> = {};
      if (!force) {
        try { cache = JSON.parse(await fs.readFile(cacheFile, 'utf8')); } catch { };
      }
    
      for (const file of files) {
        const rel = path.relative(directory, file);
        const stat = await fs.stat(file);
        const m = stat.mtimeMs;
    
        if (!force && cache[rel] && cache[rel].mtime === m) {
          if (cache[rel].components.length) {
            report.push({ file: rel, components: cache[rel].components });
          }
          continue;
        }
    
        const content = await fs.readFile(file, "utf8");
        if (!quick.test(content)) {
          cache[rel] = { mtime: m, components: [] };
          continue;
        }
        const found: string[] = [];
        for (const key of v2Keys) {
          if (content.includes(key)) {
            found.push(key);
          }
        }
        if (found.length > 0) {
          // assign priority: P0 if any component is structural or manual-only
          const pri = found.some(key => {
            const cat = getTransformationCategory(key);
            if (cat !== 'safe_rename') return true;
            const suggestion = KNOWN_V2_IMPORTS[key] || '';
            if (suggestion.includes('legacy') || suggestion.startsWith('NOT IN')) return true;
            return false;
          }) ? 'P0' : 'P1';
          report.push({ file: rel, components: found, priority: pri });
        }
        cache[rel] = { mtime: m, components: found };
      }
    
      try {
        await fs.writeFile(cacheFile, JSON.stringify(cache, null, 2));
      } catch { /* ignore */ }
    
      return {
        content: [],
        structuredContent: { report, totalFiles: files.length, affectedFiles: report.length }
      };
    }

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/sctg-development/heroui-migration-mcp'

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