Skip to main content
Glama

compare_component

Check component availability and differences between HeroUI v2 and v3 versions to identify migration requirements and changes needed.

Instructions

Show presence/status of a component between v2 and v3, with alias lookup.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
componentYes

Implementation Reference

  • The `compareComponent` function handles the logic for comparing components between v2 and v3 versions, determining the status (same, renamed, removed, unknown, or compound) and identifying breaking changes, subcomponent mappings, and property changes.
    export async function compareComponent(component: string): Promise<ComponentComparisonResult> {
      const root = process.cwd();
      const idx2 = path.join(root, "data", "index", "components.v2.json");
      const idx3 = path.join(root, "data", "index", "components.v3.json");
      let list2: any[] = [];
      let list3: any[] = [];
      try { list2 = JSON.parse(await fs.readFile(idx2, 'utf8')); } catch { }
      try { list3 = JSON.parse(await fs.readFile(idx3, 'utf8')); } catch { }
    
      // normalize helper removes hyphen/underscore and lowercases
      const normalize = (s: string) => s.toLowerCase().replace(/[-_]/g, '');
      const targetNorm = normalize(component);
    
      const find = (list: any[]) =>
        list.find((e) => {
          if (normalize(e.slug) === targetNorm) return true;
          if (e.aliases && e.aliases.some((a: string) => normalize(a) === targetNorm)) return true;
          return false;
        });
    
      const e2 = find(list2);
      const e3 = find(list3);
      const exists2 = !!e2;
      const exists3 = !!e3;
    
      // build alias list using resolver if available
      const aliases: string[] = [];
      try {
        const { resolveAlias } = await import("../knowledge/aliases.js");
        const res = resolveAlias(component);
        if (res.alias) aliases.push(res.alias);
        if (res.canonical && res.canonical !== component) aliases.push(res.canonical);
      } catch { }
    
      // determine status
      let status: ComponentComparisonResult['status'];
      if (exists2 && exists3) {
        if (normalize(e2.slug) === normalize(e3.slug)) {
          status = 'same';
        } else {
          status = 'renamed';
        }
      } else if (exists2 && !exists3) {
        status = 'removed';
      } else if (!exists2 && exists3) {
        status = 'unknown';
      } else {
        status = 'unknown';
      }
    
      const breakingChanges: string[] = [];
      if (KNOWN_V2_IMPORTS[component]) {
        breakingChanges.push(KNOWN_V2_IMPORTS[component]);
      }
    
      // subcomponent mappings: any map entry starting with component name (case-insensitive) but not equal
      const subcomponentMappings: Array<{ legacy: string; replacement: string; note?: string }> = [];
      for (const [key, val] of Object.entries(KNOWN_V2_IMPORTS)) {
        if (key.toLowerCase().startsWith(component.toLowerCase()) && key.toLowerCase() !== component.toLowerCase()) {
          subcomponentMappings.push({ legacy: key, replacement: val, note: val });
        }
      }
    
      // prop changes relevant to this component
      const propChanges: Array<{ prop: string; replacement?: string; removed?: boolean; note: string }> = [];
      for (const p of KNOWN_V2_PROPS) {
        if (!p.components || p.components.some((c) => normalize(c) === targetNorm)) {
          propChanges.push({ prop: p.prop, replacement: p.replacement, removed: p.removed, note: p.note });
        }
      }
    
      // if component had subcomponent mappings but no v3 entry, it may have been
      // folded into a compound API rather than simply removed. We mark as
      // `compound` only if none of the mappings are just "NOT IN v3" notes.
      if (status === 'removed' && subcomponentMappings.length > 0) {
        const onlyNotIn = subcomponentMappings.every(m => /NOT IN v3/i.test(m.note || ''));
        if (!onlyNotIn) {
          status = 'compound';
        }
      }
    
      return {
        component,
        aliases,
        existsInV2: exists2,
        existsInV3: exists3,
        status,
        breakingChanges,
        subcomponentMappings,
        propChanges,
        sources: [e2?.source || '', e3?.source || ''].filter(Boolean),
      };

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