@justmpm/ai-tool 0.7.10 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1368,7 +1368,7 @@ function calculateFilesHash(cwd) {
1368
1368
  try {
1369
1369
  const stat = statSync(fullPath);
1370
1370
  const mtime = stat.mtimeMs;
1371
- hashAccumulator ^= Math.floor(mtime);
1371
+ hashAccumulator += Math.floor(mtime);
1372
1372
  fileCount++;
1373
1373
  if (mtime > maxTimestamp) {
1374
1374
  maxTimestamp = mtime;
@@ -1382,13 +1382,14 @@ function calculateFilesHash(cwd) {
1382
1382
  }
1383
1383
  }
1384
1384
  scanDir(cwd, 0);
1385
- try {
1386
- const configPath = join2(cwd, CACHE_DIR, "areas.config.json");
1387
- if (existsSync2(configPath)) {
1388
- const stat = statSync(configPath);
1389
- hashAccumulator ^= Math.floor(stat.mtimeMs);
1385
+ const configExists2 = existsSync2(join2(cwd, CACHE_DIR, "areas.config.json"));
1386
+ hashAccumulator += configExists2 ? 1 : 0;
1387
+ if (configExists2) {
1388
+ try {
1389
+ const stat = statSync(join2(cwd, CACHE_DIR, "areas.config.json"));
1390
+ hashAccumulator += Math.floor(stat.mtimeMs);
1391
+ } catch {
1390
1392
  }
1391
- } catch {
1392
1393
  }
1393
1394
  return `${fileCount}-${hashAccumulator}-${maxTimestamp}`;
1394
1395
  }
@@ -1502,7 +1503,7 @@ var DEFAULT_CONFIG = {
1502
1503
  areas: {},
1503
1504
  descriptions: {},
1504
1505
  settings: {
1505
- autoDetect: true,
1506
+ autoDetect: false,
1506
1507
  inferDescriptions: true,
1507
1508
  groupByCategory: true
1508
1509
  }
@@ -1563,370 +1564,13 @@ function getFileDescription(cwd, filePath) {
1563
1564
  const config = readConfig(cwd);
1564
1565
  return config.descriptions?.[filePath];
1565
1566
  }
1567
+ function getIgnorePatterns(cwd) {
1568
+ const config = readConfig(cwd);
1569
+ return config.ignore || [];
1570
+ }
1566
1571
 
1567
1572
  // src/areas/detector.ts
1568
1573
  import { minimatch } from "minimatch";
1569
-
1570
- // src/areas/patterns.ts
1571
- var FOLDER_PATTERNS = [
1572
- // ============================================================================
1573
- // NEXT.JS APP ROUTER - Rotas genéricas (alta prioridade)
1574
- // ============================================================================
1575
- { pattern: /app\/.*\/dashboard\//, area: "dashboard", priority: 100 },
1576
- { pattern: /app\/.*\/admin\//, area: "admin", priority: 100 },
1577
- { pattern: /app\/.*\/login\//, area: "auth", priority: 100 },
1578
- { pattern: /app\/.*\/cadastro\//, area: "auth", priority: 100 },
1579
- { pattern: /app\/.*\/signup\//, area: "auth", priority: 100 },
1580
- { pattern: /app\/.*\/register\//, area: "auth", priority: 100 },
1581
- { pattern: /app\/.*\/auth\//, area: "auth", priority: 100 },
1582
- { pattern: /app\/.*\/perfil\//, area: "profile", priority: 100 },
1583
- { pattern: /app\/.*\/profile\//, area: "profile", priority: 100 },
1584
- { pattern: /app\/.*\/configuracoes\//, area: "settings", priority: 100 },
1585
- { pattern: /app\/.*\/settings\//, area: "settings", priority: 100 },
1586
- { pattern: /app\/.*\/onboarding/, area: "onboarding", priority: 100 },
1587
- { pattern: /app\/.*\/precos\//, area: "pricing", priority: 100 },
1588
- { pattern: /app\/.*\/pricing\//, area: "pricing", priority: 100 },
1589
- { pattern: /app\/.*\/checkout\//, area: "checkout", priority: 100 },
1590
- { pattern: /app\/.*\/cart\//, area: "cart", priority: 100 },
1591
- { pattern: /app\/.*\/shop\//, area: "shop", priority: 100 },
1592
- { pattern: /app\/.*\/products\//, area: "products", priority: 100 },
1593
- { pattern: /app\/.*\/orders\//, area: "orders", priority: 100 },
1594
- { pattern: /app\/.*\/blog\//, area: "blog", priority: 100 },
1595
- { pattern: /app\/.*\/docs\//, area: "docs", priority: 100 },
1596
- { pattern: /app\/.*\/legal\//, area: "legal", priority: 100 },
1597
- { pattern: /app\/.*\/privacy\//, area: "legal", priority: 100 },
1598
- { pattern: /app\/.*\/terms\//, area: "legal", priority: 100 },
1599
- { pattern: /app\/.*\/about\//, area: "about", priority: 100 },
1600
- { pattern: /app\/.*\/contact\//, area: "contact", priority: 100 },
1601
- { pattern: /app\/.*\/faq\//, area: "faq", priority: 100 },
1602
- { pattern: /app\/.*\/help\//, area: "help", priority: 100 },
1603
- { pattern: /app\/.*\/support\//, area: "support", priority: 100 },
1604
- // ============================================================================
1605
- // VITE / CRA - src/pages/ ou src/views/ (alta prioridade)
1606
- // ============================================================================
1607
- { pattern: /src\/pages\/[Dd]ashboard/, area: "dashboard", priority: 100 },
1608
- { pattern: /src\/pages\/[Aa]dmin/, area: "admin", priority: 100 },
1609
- { pattern: /src\/pages\/[Aa]uth/, area: "auth", priority: 100 },
1610
- { pattern: /src\/pages\/[Ll]ogin/, area: "auth", priority: 100 },
1611
- { pattern: /src\/pages\/[Rr]egister/, area: "auth", priority: 100 },
1612
- { pattern: /src\/pages\/[Ss]ignup/, area: "auth", priority: 100 },
1613
- { pattern: /src\/pages\/[Pp]rofile/, area: "profile", priority: 100 },
1614
- { pattern: /src\/pages\/[Ss]ettings/, area: "settings", priority: 100 },
1615
- { pattern: /src\/pages\/[Pp]ricing/, area: "pricing", priority: 100 },
1616
- { pattern: /src\/pages\/[Cc]heckout/, area: "checkout", priority: 100 },
1617
- { pattern: /src\/pages\/[Cc]art/, area: "cart", priority: 100 },
1618
- { pattern: /src\/pages\/[Ss]hop/, area: "shop", priority: 100 },
1619
- { pattern: /src\/pages\/[Pp]roducts?/, area: "products", priority: 100 },
1620
- { pattern: /src\/pages\/[Oo]rders?/, area: "orders", priority: 100 },
1621
- { pattern: /src\/pages\/[Bb]log/, area: "blog", priority: 100 },
1622
- { pattern: /src\/views\/[Dd]ashboard/, area: "dashboard", priority: 100 },
1623
- { pattern: /src\/views\/[Aa]dmin/, area: "admin", priority: 100 },
1624
- { pattern: /src\/views\/[Aa]uth/, area: "auth", priority: 100 },
1625
- // ============================================================================
1626
- // REMIX - app/routes/
1627
- // ============================================================================
1628
- { pattern: /app\/routes\/dashboard/, area: "dashboard", priority: 100 },
1629
- { pattern: /app\/routes\/admin/, area: "admin", priority: 100 },
1630
- { pattern: /app\/routes\/auth/, area: "auth", priority: 100 },
1631
- { pattern: /app\/routes\/login/, area: "auth", priority: 100 },
1632
- { pattern: /app\/routes\/_auth/, area: "auth", priority: 100 },
1633
- // ============================================================================
1634
- // NUXT - pages/ (sem src/)
1635
- // ============================================================================
1636
- { pattern: /^pages\/dashboard/, area: "dashboard", priority: 100 },
1637
- { pattern: /^pages\/admin/, area: "admin", priority: 100 },
1638
- { pattern: /^pages\/auth/, area: "auth", priority: 100 },
1639
- // ============================================================================
1640
- // SVELTEKIT - src/routes/
1641
- // ============================================================================
1642
- { pattern: /src\/routes\/dashboard/, area: "dashboard", priority: 100 },
1643
- { pattern: /src\/routes\/admin/, area: "admin", priority: 100 },
1644
- { pattern: /src\/routes\/auth/, area: "auth", priority: 100 },
1645
- { pattern: /src\/routes\/\(auth\)/, area: "auth", priority: 100 },
1646
- { pattern: /src\/routes\/\(app\)/, area: "app", priority: 90 },
1647
- // ============================================================================
1648
- // ASTRO - src/pages/
1649
- // ============================================================================
1650
- { pattern: /src\/pages\/blog/, area: "blog", priority: 100 },
1651
- { pattern: /src\/pages\/docs/, area: "docs", priority: 100 },
1652
- // ============================================================================
1653
- // COMPONENTS - Por subpasta (alta prioridade)
1654
- // Funciona em qualquer framework (com ou sem src/)
1655
- // ============================================================================
1656
- { pattern: /components\/chat\//, area: "chat", priority: 90 },
1657
- { pattern: /components\/auth\//, area: "auth", priority: 90 },
1658
- { pattern: /components\/admin\//, area: "admin", priority: 90 },
1659
- { pattern: /components\/landing\//, area: "landing", priority: 90 },
1660
- { pattern: /components\/marketing\//, area: "landing", priority: 90 },
1661
- { pattern: /components\/dashboard\//, area: "dashboard", priority: 90 },
1662
- { pattern: /components\/subscription\//, area: "billing", priority: 90 },
1663
- { pattern: /components\/stripe\//, area: "billing", priority: 90 },
1664
- { pattern: /components\/payment\//, area: "billing", priority: 90 },
1665
- { pattern: /components\/checkout\//, area: "checkout", priority: 90 },
1666
- { pattern: /components\/cart\//, area: "cart", priority: 90 },
1667
- { pattern: /components\/notification\//, area: "notifications", priority: 90 },
1668
- { pattern: /components\/seo\//, area: "seo", priority: 90 },
1669
- { pattern: /components\/blog\//, area: "blog", priority: 90 },
1670
- { pattern: /components\/docs\//, area: "docs", priority: 90 },
1671
- { pattern: /components\/legal\//, area: "legal", priority: 90 },
1672
- { pattern: /components\/onboarding\//, area: "onboarding", priority: 90 },
1673
- { pattern: /components\/settings\//, area: "settings", priority: 90 },
1674
- { pattern: /components\/profile\//, area: "profile", priority: 90 },
1675
- { pattern: /components\/user\//, area: "user", priority: 90 },
1676
- { pattern: /components\/products?\//, area: "products", priority: 90 },
1677
- { pattern: /components\/orders?\//, area: "orders", priority: 90 },
1678
- { pattern: /components\/shop\//, area: "shop", priority: 90 },
1679
- { pattern: /components\/forms?\//, area: "forms", priority: 85 },
1680
- { pattern: /components\/tables?\//, area: "tables", priority: 85 },
1681
- { pattern: /components\/modals?\//, area: "modals", priority: 85 },
1682
- { pattern: /components\/dialogs?\//, area: "modals", priority: 85 },
1683
- // Componentes compartilhados (baixa prioridade)
1684
- { pattern: /components\/ui\//, area: "shared-ui", priority: 30 },
1685
- { pattern: /components\/common\//, area: "shared-ui", priority: 30 },
1686
- { pattern: /components\/shared\//, area: "shared-ui", priority: 30 },
1687
- { pattern: /components\/base\//, area: "shared-ui", priority: 30 },
1688
- { pattern: /components\/core\//, area: "shared-ui", priority: 30 },
1689
- { pattern: /components\/primitives\//, area: "shared-ui", priority: 30 },
1690
- { pattern: /components\/providers\//, area: "core", priority: 40 },
1691
- { pattern: /components\/layout\//, area: "layout", priority: 40 },
1692
- { pattern: /components\/layouts\//, area: "layout", priority: 40 },
1693
- // ============================================================================
1694
- // FEATURES (padrão comum em projetos maiores)
1695
- // ============================================================================
1696
- { pattern: /features\/auth\//, area: "auth", priority: 95 },
1697
- { pattern: /features\/dashboard\//, area: "dashboard", priority: 95 },
1698
- { pattern: /features\/admin\//, area: "admin", priority: 95 },
1699
- { pattern: /features\/checkout\//, area: "checkout", priority: 95 },
1700
- { pattern: /features\/cart\//, area: "cart", priority: 95 },
1701
- { pattern: /features\/products?\//, area: "products", priority: 95 },
1702
- { pattern: /features\/orders?\//, area: "orders", priority: 95 },
1703
- { pattern: /features\/user\//, area: "user", priority: 95 },
1704
- { pattern: /features\/settings\//, area: "settings", priority: 95 },
1705
- { pattern: /features\/notifications?\//, area: "notifications", priority: 95 },
1706
- { pattern: /features\/blog\//, area: "blog", priority: 95 },
1707
- // ============================================================================
1708
- // MODULES (outro padrão comum)
1709
- // ============================================================================
1710
- { pattern: /modules\/auth\//, area: "auth", priority: 95 },
1711
- { pattern: /modules\/dashboard\//, area: "dashboard", priority: 95 },
1712
- { pattern: /modules\/admin\//, area: "admin", priority: 95 },
1713
- { pattern: /modules\/checkout\//, area: "checkout", priority: 95 },
1714
- { pattern: /modules\/products?\//, area: "products", priority: 95 },
1715
- // ============================================================================
1716
- // LIB - Módulos específicos
1717
- // ============================================================================
1718
- { pattern: /lib\/firebase\//, area: "firebase", priority: 80 },
1719
- { pattern: /lib\/stripe\//, area: "billing", priority: 80 },
1720
- { pattern: /lib\/i18n\//, area: "i18n", priority: 80 },
1721
- { pattern: /lib\/analytics\//, area: "analytics", priority: 80 },
1722
- // ============================================================================
1723
- // HOOKS - Por nome genérico
1724
- // ============================================================================
1725
- { pattern: /hooks\/.*[Aa]uth/, area: "auth", priority: 70 },
1726
- { pattern: /hooks\/.*[Ss]ubscription/, area: "billing", priority: 70 },
1727
- { pattern: /hooks\/.*[Nn]otification/, area: "notifications", priority: 70 },
1728
- // ============================================================================
1729
- // STORE - Por nome genérico
1730
- // ============================================================================
1731
- { pattern: /store\/.*[Aa]uth/, area: "auth", priority: 70 },
1732
- { pattern: /store\/.*[Uu]ser/, area: "user", priority: 70 },
1733
- // ============================================================================
1734
- // FIREBASE CLOUD FUNCTIONS (expandido)
1735
- // ============================================================================
1736
- { pattern: /functions\/src\//, area: "cloud-functions", priority: 80 },
1737
- { pattern: /functions\/src\/triggers\//, area: "triggers", priority: 95 },
1738
- { pattern: /functions\/src\/callable\//, area: "callable", priority: 95 },
1739
- { pattern: /functions\/src\/scheduled\//, area: "scheduled", priority: 95 },
1740
- { pattern: /functions\/src\/firestore\//, area: "firestore-triggers", priority: 95 },
1741
- { pattern: /functions\/src\/auth\//, area: "auth-triggers", priority: 95 },
1742
- { pattern: /functions\/src\/storage\//, area: "storage-triggers", priority: 95 },
1743
- { pattern: /functions\/src\/pubsub\//, area: "pubsub", priority: 95 },
1744
- { pattern: /functions\/src\/https\//, area: "callable", priority: 95 },
1745
- // ============================================================================
1746
- // OUTROS
1747
- // ============================================================================
1748
- { pattern: /messages\//, area: "i18n", priority: 60 },
1749
- { pattern: /i18n\//, area: "i18n", priority: 60 },
1750
- { pattern: /locales\//, area: "i18n", priority: 60 },
1751
- { pattern: /public\//, area: "assets", priority: 50 },
1752
- { pattern: /scripts\//, area: "scripts", priority: 50 }
1753
- ];
1754
- var KEYWORD_PATTERNS = [
1755
- // Auth (genérico)
1756
- { keyword: /[Aa]uth(?!or)/, area: "auth", priority: 60 },
1757
- // auth mas não author
1758
- { keyword: /[Ll]ogin/, area: "auth", priority: 60 },
1759
- { keyword: /[Rr]egister/, area: "auth", priority: 60 },
1760
- { keyword: /[Ss]ignup/, area: "auth", priority: 60 },
1761
- { keyword: /[Ss]ignin/, area: "auth", priority: 60 },
1762
- { keyword: /[Ss]ignout/, area: "auth", priority: 60 },
1763
- { keyword: /[Ll]ogout/, area: "auth", priority: 60 },
1764
- // Billing/Payments (genérico)
1765
- { keyword: /[Ss]tripe/, area: "billing", priority: 65 },
1766
- { keyword: /[Ss]ubscription/, area: "billing", priority: 60 },
1767
- { keyword: /[Pp]ayment/, area: "billing", priority: 60 },
1768
- { keyword: /[Bb]illing/, area: "billing", priority: 65 },
1769
- { keyword: /[Ii]nvoice/, area: "billing", priority: 60 },
1770
- // Checkout (genérico)
1771
- { keyword: /[Cc]heckout/, area: "checkout", priority: 60 },
1772
- // Pricing (genérico)
1773
- { keyword: /[Pp]ricing/, area: "pricing", priority: 60 },
1774
- // Notifications (genérico)
1775
- { keyword: /[Nn]otification/, area: "notifications", priority: 60 },
1776
- { keyword: /[Ff][Cc][Mm]/, area: "notifications", priority: 65 },
1777
- // i18n (genérico)
1778
- { keyword: /[Ii]18n/, area: "i18n", priority: 60 },
1779
- { keyword: /[Ll]ocale/, area: "i18n", priority: 55 },
1780
- { keyword: /[Tt]ranslat/, area: "i18n", priority: 55 },
1781
- // SEO (genérico)
1782
- { keyword: /[Ss][Ee][Oo]/, area: "seo", priority: 60 },
1783
- { keyword: /[Ss]itemap/, area: "seo", priority: 60 },
1784
- // Analytics (genérico)
1785
- { keyword: /[Aa]nalytics/, area: "analytics", priority: 60 },
1786
- // Admin (genérico)
1787
- { keyword: /[Aa]dmin/, area: "admin", priority: 55 },
1788
- // PWA (genérico)
1789
- { keyword: /[Pp][Ww][Aa]/, area: "pwa", priority: 60 },
1790
- { keyword: /[Ss]ervice[Ww]orker/, area: "pwa", priority: 60 },
1791
- { keyword: /[Mm]anifest/, area: "pwa", priority: 55 },
1792
- // PDF (genérico)
1793
- { keyword: /[Pp]df[Ee]xport/, area: "export", priority: 60 },
1794
- { keyword: /[Dd]ocx[Ee]xport/, area: "export", priority: 60 },
1795
- // Firebase Cloud Functions triggers
1796
- { keyword: /[Oo]nCall/, area: "callable", priority: 70 },
1797
- { keyword: /[Oo]nRequest/, area: "callable", priority: 70 },
1798
- { keyword: /[Oo]nSchedule/, area: "scheduled", priority: 70 },
1799
- { keyword: /[Oo]n[A-Z].*Created/, area: "triggers", priority: 70 },
1800
- { keyword: /[Oo]n[A-Z].*Updated/, area: "triggers", priority: 70 },
1801
- { keyword: /[Oo]n[A-Z].*Deleted/, area: "triggers", priority: 70 },
1802
- { keyword: /[Oo]n[A-Z].*Written/, area: "triggers", priority: 70 },
1803
- { keyword: /[Oo]nObject/, area: "storage-triggers", priority: 70 },
1804
- { keyword: /[Oo]nMessage/, area: "pubsub", priority: 70 }
1805
- ];
1806
- var AREA_NAMES = {
1807
- // Autenticação e usuário
1808
- auth: "Autentica\xE7\xE3o",
1809
- user: "Usu\xE1rio",
1810
- profile: "Perfil",
1811
- settings: "Configura\xE7\xF5es",
1812
- onboarding: "Onboarding",
1813
- // E-commerce / Billing
1814
- billing: "Pagamentos",
1815
- checkout: "Checkout",
1816
- cart: "Carrinho",
1817
- shop: "Loja",
1818
- products: "Produtos",
1819
- orders: "Pedidos",
1820
- pricing: "Pre\xE7os",
1821
- // Comunicação
1822
- notifications: "Notifica\xE7\xF5es",
1823
- chat: "Chat",
1824
- feedback: "Feedback",
1825
- support: "Suporte",
1826
- help: "Ajuda",
1827
- faq: "FAQ",
1828
- contact: "Contato",
1829
- // Firebase
1830
- firebase: "Firebase",
1831
- // Conteúdo
1832
- blog: "Blog",
1833
- docs: "Documenta\xE7\xE3o",
1834
- legal: "P\xE1ginas Legais",
1835
- about: "Sobre",
1836
- // Marketing e SEO
1837
- landing: "Landing Pages",
1838
- seo: "SEO",
1839
- analytics: "Analytics",
1840
- // Admin e Dashboard
1841
- admin: "Admin",
1842
- dashboard: "Dashboard",
1843
- // Técnico
1844
- i18n: "Internacionaliza\xE7\xE3o",
1845
- pwa: "PWA",
1846
- export: "Exporta\xE7\xE3o",
1847
- core: "Core",
1848
- layout: "Layout",
1849
- "shared-ui": "UI Compartilhada",
1850
- "cloud-functions": "Cloud Functions",
1851
- triggers: "Triggers Firebase",
1852
- callable: "Callable Functions",
1853
- scheduled: "Scheduled Functions",
1854
- "firestore-triggers": "Firestore Triggers",
1855
- "auth-triggers": "Auth Triggers",
1856
- "storage-triggers": "Storage Triggers",
1857
- pubsub: "Pub/Sub",
1858
- assets: "Assets",
1859
- scripts: "Scripts",
1860
- // UI patterns
1861
- forms: "Formul\xE1rios",
1862
- tables: "Tabelas",
1863
- modals: "Modais",
1864
- // Genéricos
1865
- app: "Aplica\xE7\xE3o"
1866
- };
1867
- var AREA_DESCRIPTIONS = {
1868
- // Autenticação e usuário
1869
- auth: "Autentica\xE7\xE3o e gerenciamento de sess\xE3o",
1870
- user: "Gerenciamento de dados do usu\xE1rio",
1871
- profile: "Perfil do usu\xE1rio",
1872
- settings: "Configura\xE7\xF5es do usu\xE1rio",
1873
- onboarding: "Fluxo de onboarding de novos usu\xE1rios",
1874
- // E-commerce / Billing
1875
- billing: "Sistema de pagamentos e assinaturas",
1876
- checkout: "Fluxo de checkout e finaliza\xE7\xE3o",
1877
- cart: "Carrinho de compras",
1878
- shop: "Loja e cat\xE1logo",
1879
- products: "Gerenciamento de produtos",
1880
- orders: "Gerenciamento de pedidos",
1881
- pricing: "P\xE1gina de pre\xE7os e planos",
1882
- // Comunicação
1883
- notifications: "Sistema de notifica\xE7\xF5es",
1884
- chat: "Sistema de chat e mensagens",
1885
- feedback: "Coleta de feedback",
1886
- support: "Suporte ao cliente",
1887
- help: "Central de ajuda",
1888
- faq: "Perguntas frequentes",
1889
- contact: "P\xE1gina de contato",
1890
- // Firebase
1891
- firebase: "Configura\xE7\xE3o e servi\xE7os Firebase",
1892
- // Conteúdo
1893
- blog: "Blog e artigos",
1894
- docs: "Documenta\xE7\xE3o e guias",
1895
- legal: "Termos de uso, privacidade e pol\xEDticas",
1896
- about: "P\xE1gina sobre",
1897
- // Marketing e SEO
1898
- landing: "Landing pages e marketing",
1899
- seo: "SEO, meta tags e sitemaps",
1900
- analytics: "Analytics e tracking",
1901
- // Admin e Dashboard
1902
- admin: "Painel administrativo",
1903
- dashboard: "Dashboard do usu\xE1rio",
1904
- // Técnico
1905
- i18n: "Internacionaliza\xE7\xE3o e tradu\xE7\xF5es",
1906
- pwa: "Progressive Web App",
1907
- export: "Exporta\xE7\xE3o de documentos",
1908
- core: "Providers e configura\xE7\xE3o principal",
1909
- layout: "Layout e navega\xE7\xE3o",
1910
- "shared-ui": "Componentes de UI compartilhados",
1911
- "cloud-functions": "Firebase Cloud Functions (serverless)",
1912
- triggers: "Event-driven Firebase triggers",
1913
- callable: "HTTPS callable functions (frontend SDK)",
1914
- scheduled: "Scheduled/cron functions",
1915
- "firestore-triggers": "Triggers para eventos do Firestore",
1916
- "auth-triggers": "Triggers para eventos de autentica\xE7\xE3o",
1917
- "storage-triggers": "Triggers para eventos do Storage",
1918
- pubsub: "Triggers para mensagens Pub/Sub",
1919
- assets: "Assets p\xFAblicos",
1920
- scripts: "Scripts de automa\xE7\xE3o",
1921
- // UI patterns
1922
- forms: "Componentes de formul\xE1rio",
1923
- tables: "Componentes de tabela",
1924
- modals: "Modais e dialogs",
1925
- // Genéricos
1926
- app: "\xC1rea principal da aplica\xE7\xE3o"
1927
- };
1928
-
1929
- // src/areas/detector.ts
1930
1574
  function isFileIgnored(filePath, config) {
1931
1575
  const ignorePatterns = config.ignore || [];
1932
1576
  if (ignorePatterns.length === 0) return false;
@@ -1941,38 +1585,12 @@ function isFileIgnored(filePath, config) {
1941
1585
  function detectFileAreas(filePath, config) {
1942
1586
  const normalizedPath = filePath.replace(/\\/g, "/");
1943
1587
  const matches = [];
1944
- const autoDetect = config.settings?.autoDetect !== false;
1945
- if (filePath.includes("useAuth.ts")) {
1946
- console.error(`[DEBUG] autoDetect for ${filePath}:`, autoDetect);
1947
- console.error(`[DEBUG] config.settings:`, JSON.stringify(config.settings));
1948
- }
1949
1588
  for (const [areaId, areaConfig] of Object.entries(config.areas)) {
1950
1589
  if (matchesAreaConfig(normalizedPath, areaConfig)) {
1951
- matches.push({ area: areaId, priority: 200, source: "config" });
1590
+ matches.push(areaId);
1952
1591
  }
1953
1592
  }
1954
- if (!autoDetect) {
1955
- const unique2 = [...new Set(matches.map((m) => m.area))];
1956
- return unique2;
1957
- }
1958
- for (const { pattern, area: area2, priority } of FOLDER_PATTERNS) {
1959
- if (pattern.test(normalizedPath)) {
1960
- if (!matches.some((m) => m.area === area2 && m.source === "config")) {
1961
- matches.push({ area: area2, priority, source: "folder" });
1962
- }
1963
- }
1964
- }
1965
- const fileName = normalizedPath.split("/").pop() || "";
1966
- for (const { keyword, area: area2, priority } of KEYWORD_PATTERNS) {
1967
- if (keyword.test(fileName) || keyword.test(normalizedPath)) {
1968
- if (!matches.some((m) => m.area === area2)) {
1969
- matches.push({ area: area2, priority, source: "keyword" });
1970
- }
1971
- }
1972
- }
1973
- const sorted = matches.sort((a, b) => b.priority - a.priority);
1974
- const unique = [...new Set(sorted.map((m) => m.area))];
1975
- return unique;
1593
+ return matches;
1976
1594
  }
1977
1595
  function matchesAreaConfig(filePath, config) {
1978
1596
  if (config.exclude) {
@@ -2001,16 +1619,10 @@ function getAreaName(areaId, config) {
2001
1619
  if (config.areas[areaId]?.name) {
2002
1620
  return config.areas[areaId].name;
2003
1621
  }
2004
- if (AREA_NAMES[areaId]) {
2005
- return AREA_NAMES[areaId];
2006
- }
2007
1622
  return areaId.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
2008
1623
  }
2009
1624
  function getAreaDescription(areaId, config) {
2010
- if (config.areas[areaId]?.description) {
2011
- return config.areas[areaId].description;
2012
- }
2013
- return AREA_DESCRIPTIONS[areaId];
1625
+ return config.areas[areaId]?.description;
2014
1626
  }
2015
1627
  function inferFileDescription(filePath, category) {
2016
1628
  const fileName = filePath.split("/").pop() || "";
@@ -2215,6 +1827,21 @@ function detectAreasInfo(cwd, filePaths) {
2215
1827
 
2216
1828
  // src/commands/dead.ts
2217
1829
  import { execSync } from "child_process";
1830
+ import { writeFileSync as writeFileSync3, unlinkSync, existsSync as existsSync4 } from "fs";
1831
+ import { join as join4 } from "path";
1832
+ function generateKnipConfig(cwd) {
1833
+ const ignorePatterns = getIgnorePatterns(cwd);
1834
+ if (ignorePatterns.length === 0) {
1835
+ return null;
1836
+ }
1837
+ const knipConfig = {
1838
+ $schema: "https://unpkg.com/knip@5/schema.json",
1839
+ ignore: ignorePatterns
1840
+ };
1841
+ const configPath = join4(cwd, ".knip.ai-tool.json");
1842
+ writeFileSync3(configPath, JSON.stringify(knipConfig, null, 2), "utf-8");
1843
+ return configPath;
1844
+ }
2218
1845
  async function dead(options = {}) {
2219
1846
  const cwd = options.cwd || process.cwd();
2220
1847
  const format = options.format || "text";
@@ -2231,8 +1858,10 @@ async function dead(options = {}) {
2231
1858
  }
2232
1859
  try {
2233
1860
  let knipOutput;
1861
+ const knipConfigPath = generateKnipConfig(cwd);
1862
+ const configFlag = knipConfigPath ? `--config=${knipConfigPath}` : "";
2234
1863
  try {
2235
- const output = execSync("npx knip --reporter=json", {
1864
+ const output = execSync(`npx knip ${configFlag} --reporter=json`, {
2236
1865
  cwd,
2237
1866
  encoding: "utf-8",
2238
1867
  maxBuffer: 50 * 1024 * 1024,
@@ -2250,6 +1879,13 @@ async function dead(options = {}) {
2250
1879
  } else {
2251
1880
  knipOutput = {};
2252
1881
  }
1882
+ } finally {
1883
+ if (knipConfigPath && existsSync4(knipConfigPath)) {
1884
+ try {
1885
+ unlinkSync(knipConfigPath);
1886
+ } catch {
1887
+ }
1888
+ }
2253
1889
  }
2254
1890
  const rawFiles = knipOutput.files || [];
2255
1891
  const { filtered: filteredFiles, excluded: excludedFunctions } = filterCloudFunctionsFalsePositives(rawFiles, cwd);
@@ -3126,8 +2762,8 @@ function formatNotFound2(target, allFiles) {
3126
2762
  }
3127
2763
 
3128
2764
  // src/commands/context.ts
3129
- import { existsSync as existsSync4, readdirSync as readdirSync3, statSync as statSync3 } from "fs";
3130
- import { join as join5, resolve as resolve2, basename, extname as extname3 } from "path";
2765
+ import { existsSync as existsSync5, readdirSync as readdirSync3, statSync as statSync3 } from "fs";
2766
+ import { join as join6, resolve as resolve2, basename, extname as extname3 } from "path";
3131
2767
 
3132
2768
  // src/ts/extractor.ts
3133
2769
  import { Project, SyntaxKind } from "ts-morph";
@@ -3335,7 +2971,7 @@ function extractExports(sourceFile) {
3335
2971
 
3336
2972
  // src/ts/indexer.ts
3337
2973
  import { readdirSync as readdirSync2, statSync as statSync2 } from "fs";
3338
- import { join as join4, extname as extname2, resolve } from "path";
2974
+ import { join as join5, extname as extname2, resolve } from "path";
3339
2975
  import { Project as Project2, SyntaxKind as SyntaxKind2, Node as Node2 } from "ts-morph";
3340
2976
  var CODE_EXTENSIONS2 = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
3341
2977
  var DEBUG = process.env.DEBUG_ANALYZE === "true";
@@ -3773,7 +3409,7 @@ function getAllCodeFiles(dir, files = [], baseDir = dir) {
3773
3409
  try {
3774
3410
  const entries = readdirSync2(dir);
3775
3411
  for (const entry of entries) {
3776
- const fullPath = join4(dir, entry);
3412
+ const fullPath = join5(dir, entry);
3777
3413
  if (IGNORED_DIRS.has(entry) || entry.startsWith(".")) {
3778
3414
  continue;
3779
3415
  }
@@ -4005,12 +3641,12 @@ var CODE_EXTENSIONS3 = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".
4005
3641
  function findTargetFile3(target, cwd) {
4006
3642
  const normalizedTarget = target.replace(/\\/g, "/");
4007
3643
  const directPath = resolve2(cwd, normalizedTarget);
4008
- if (existsSync4(directPath) && isCodeFile2(directPath)) {
3644
+ if (existsSync5(directPath) && isCodeFile2(directPath)) {
4009
3645
  return normalizedTarget;
4010
3646
  }
4011
3647
  for (const ext of CODE_EXTENSIONS3) {
4012
3648
  const withExt = directPath + ext;
4013
- if (existsSync4(withExt)) {
3649
+ if (existsSync5(withExt)) {
4014
3650
  return normalizedTarget + ext;
4015
3651
  }
4016
3652
  }
@@ -4040,7 +3676,7 @@ function getAllCodeFiles2(dir, files = [], baseDir = dir) {
4040
3676
  try {
4041
3677
  const entries = readdirSync3(dir);
4042
3678
  for (const entry of entries) {
4043
- const fullPath = join5(dir, entry);
3679
+ const fullPath = join6(dir, entry);
4044
3680
  if (shouldIgnore(entry)) {
4045
3681
  continue;
4046
3682
  }
@@ -4251,7 +3887,7 @@ function findRealAreaIdFromIndex(target, areaFiles, config) {
4251
3887
 
4252
3888
  // src/commands/areas.ts
4253
3889
  import { readdirSync as readdirSync4, statSync as statSync4 } from "fs";
4254
- import { join as join6, extname as extname4 } from "path";
3890
+ import { join as join7, extname as extname4 } from "path";
4255
3891
  var CODE_EXTENSIONS4 = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
4256
3892
  var IGNORED_DIRS2 = /* @__PURE__ */ new Set([
4257
3893
  "node_modules",
@@ -4339,7 +3975,7 @@ function getAllCodeFiles3(dir, files = [], baseDir = dir) {
4339
3975
  try {
4340
3976
  const entries = readdirSync4(dir);
4341
3977
  for (const entry of entries) {
4342
- const fullPath = join6(dir, entry);
3978
+ const fullPath = join7(dir, entry);
4343
3979
  if (IGNORED_DIRS2.has(entry) || entry.startsWith(".")) {
4344
3980
  continue;
4345
3981
  }
@@ -4364,7 +4000,7 @@ function getAllCodeFiles3(dir, files = [], baseDir = dir) {
4364
4000
 
4365
4001
  // src/commands/area.ts
4366
4002
  import { readdirSync as readdirSync5, statSync as statSync5 } from "fs";
4367
- import { join as join7, extname as extname5 } from "path";
4003
+ import { join as join8, extname as extname5 } from "path";
4368
4004
  var CODE_EXTENSIONS5 = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
4369
4005
  var IGNORED_DIRS3 = /* @__PURE__ */ new Set([
4370
4006
  "node_modules",
@@ -4389,12 +4025,6 @@ function resolveAreaId(target, config, allFiles) {
4389
4025
  return id;
4390
4026
  }
4391
4027
  }
4392
- for (const [id, name] of Object.entries(AREA_NAMES)) {
4393
- const nameNormalized = name.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
4394
- if (nameNormalized === targetLower) {
4395
- return id;
4396
- }
4397
- }
4398
4028
  for (const id of Object.keys(config.areas)) {
4399
4029
  if (id.toLowerCase().includes(targetLower)) {
4400
4030
  return id;
@@ -4531,7 +4161,7 @@ function getAllCodeFiles4(dir, files = [], baseDir = dir) {
4531
4161
  try {
4532
4162
  const entries = readdirSync5(dir);
4533
4163
  for (const entry of entries) {
4534
- const fullPath = join7(dir, entry);
4164
+ const fullPath = join8(dir, entry);
4535
4165
  if (IGNORED_DIRS3.has(entry) || entry.startsWith(".")) {
4536
4166
  continue;
4537
4167
  }
@@ -4556,7 +4186,7 @@ function getAllCodeFiles4(dir, files = [], baseDir = dir) {
4556
4186
 
4557
4187
  // src/commands/areas-init.ts
4558
4188
  import { readdirSync as readdirSync6, statSync as statSync6 } from "fs";
4559
- import { join as join8, extname as extname6 } from "path";
4189
+ import { join as join9, extname as extname6 } from "path";
4560
4190
  var CODE_EXTENSIONS6 = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
4561
4191
  var IGNORED_DIRS4 = /* @__PURE__ */ new Set([
4562
4192
  "node_modules",
@@ -4570,6 +4200,160 @@ var IGNORED_DIRS4 = /* @__PURE__ */ new Set([
4570
4200
  ".vercel",
4571
4201
  ".analyze"
4572
4202
  ]);
4203
+ function createInitialConfig(files) {
4204
+ const suggestedIgnore = detectSuggestedIgnorePatterns(files);
4205
+ const framework = detectFramework(files);
4206
+ return {
4207
+ $schema: "./areas.schema.json",
4208
+ version: "1.0.0",
4209
+ ignore: suggestedIgnore,
4210
+ areas: getFrameworkAreas(framework),
4211
+ descriptions: {},
4212
+ settings: {
4213
+ autoDetect: false,
4214
+ inferDescriptions: true,
4215
+ groupByCategory: true
4216
+ }
4217
+ };
4218
+ }
4219
+ function detectFramework(files) {
4220
+ const hasAppDir = files.some((f) => f.startsWith("app/"));
4221
+ const hasPagesDir = files.some((f) => f.startsWith("pages/"));
4222
+ const hasSrcDir = files.some((f) => f.startsWith("src/"));
4223
+ if (hasAppDir) return "nextjs-app";
4224
+ if (hasPagesDir) return "nextjs-pages";
4225
+ if (hasSrcDir) return "vite";
4226
+ return "generic";
4227
+ }
4228
+ function getFrameworkAreas(framework) {
4229
+ switch (framework) {
4230
+ case "nextjs-app":
4231
+ return {
4232
+ auth: {
4233
+ name: "Autentica\xE7\xE3o",
4234
+ description: "Login, signup e gerenciamento de sess\xE3o",
4235
+ patterns: [
4236
+ "app/**/auth/**",
4237
+ "app/**/login/**",
4238
+ "app/**/signup/**",
4239
+ "app/**/cadastro/**",
4240
+ "components/auth/**"
4241
+ ],
4242
+ keywords: ["auth", "login", "signup", "signin"]
4243
+ },
4244
+ dashboard: {
4245
+ name: "Dashboard",
4246
+ description: "Painel principal do usu\xE1rio",
4247
+ patterns: ["app/**/dashboard/**", "components/dashboard/**"],
4248
+ keywords: ["dashboard"]
4249
+ },
4250
+ admin: {
4251
+ name: "Administra\xE7\xE3o",
4252
+ description: "Painel administrativo",
4253
+ patterns: ["app/**/admin/**", "components/admin/**"],
4254
+ keywords: ["admin"]
4255
+ },
4256
+ profile: {
4257
+ name: "Perfil",
4258
+ description: "Perfil e configura\xE7\xF5es do usu\xE1rio",
4259
+ patterns: ["app/**/profile/**", "app/**/perfil/**", "app/**/settings/**", "app/**/configuracoes/**"],
4260
+ keywords: ["profile", "perfil", "settings", "configuracoes"]
4261
+ },
4262
+ billing: {
4263
+ name: "Pagamentos",
4264
+ description: "Sistema de pagamentos e assinaturas",
4265
+ patterns: ["components/stripe/**", "components/payment/**", "lib/stripe/**"],
4266
+ keywords: ["stripe", "payment", "billing", "subscription", "checkout"]
4267
+ },
4268
+ checkout: {
4269
+ name: "Checkout",
4270
+ description: "Fluxo de checkout e finaliza\xE7\xE3o de compra",
4271
+ patterns: ["app/**/checkout/**", "components/checkout/**"],
4272
+ keywords: ["checkout"]
4273
+ },
4274
+ "shared-ui": {
4275
+ name: "UI Compartilhada",
4276
+ description: "Componentes de UI reutiliz\xE1veis (bot\xF5es, inputs, etc)",
4277
+ patterns: ["components/ui/**", "components/common/**", "components/shared/**"],
4278
+ keywords: []
4279
+ },
4280
+ api: {
4281
+ name: "API Routes",
4282
+ description: "Rotas de API do Next.js",
4283
+ patterns: ["app/**/api/**"],
4284
+ keywords: ["api"]
4285
+ }
4286
+ };
4287
+ case "nextjs-pages":
4288
+ return {
4289
+ auth: {
4290
+ name: "Autentica\xE7\xE3o",
4291
+ description: "Login, signup e gerenciamento de sess\xE3o",
4292
+ patterns: [
4293
+ "pages/**/auth/**",
4294
+ "pages/**/login/**",
4295
+ "pages/**/signup/**",
4296
+ "components/auth/**"
4297
+ ],
4298
+ keywords: ["auth", "login", "signup"]
4299
+ },
4300
+ dashboard: {
4301
+ name: "Dashboard",
4302
+ description: "Painel principal do usu\xE1rio",
4303
+ patterns: ["pages/**/dashboard/**", "components/dashboard/**"],
4304
+ keywords: ["dashboard"]
4305
+ },
4306
+ api: {
4307
+ name: "API Routes",
4308
+ description: "Rotas de API do Next.js (pages/api)",
4309
+ patterns: ["pages/api/**"],
4310
+ keywords: ["api"]
4311
+ },
4312
+ "shared-ui": {
4313
+ name: "UI Compartilhada",
4314
+ description: "Componentes de UI reutiliz\xE1veis",
4315
+ patterns: ["components/ui/**", "components/common/**"],
4316
+ keywords: []
4317
+ }
4318
+ };
4319
+ case "vite":
4320
+ return {
4321
+ auth: {
4322
+ name: "Autentica\xE7\xE3o",
4323
+ description: "Login, signup e gerenciamento de sess\xE3o",
4324
+ patterns: ["src/pages/**/auth/**", "src/pages/**/login/**", "components/auth/**"],
4325
+ keywords: ["auth", "login", "signup"]
4326
+ },
4327
+ dashboard: {
4328
+ name: "Dashboard",
4329
+ description: "Painel principal do usu\xE1rio",
4330
+ patterns: ["src/pages/**/dashboard/**", "components/dashboard/**"],
4331
+ keywords: ["dashboard"]
4332
+ },
4333
+ "shared-ui": {
4334
+ name: "UI Compartilhada",
4335
+ description: "Componentes de UI reutiliz\xE1veis",
4336
+ patterns: ["components/ui/**", "components/common/**"],
4337
+ keywords: []
4338
+ }
4339
+ };
4340
+ default:
4341
+ return {
4342
+ auth: {
4343
+ name: "Autentica\xE7\xE3o",
4344
+ description: "Login e sess\xE3o",
4345
+ patterns: ["**/auth/**", "**/login/**"],
4346
+ keywords: ["auth", "login"]
4347
+ },
4348
+ "shared-ui": {
4349
+ name: "UI Compartilhada",
4350
+ description: "Componentes reutiliz\xE1veis",
4351
+ patterns: ["components/ui/**", "components/common/**"],
4352
+ keywords: []
4353
+ }
4354
+ };
4355
+ }
4356
+ }
4573
4357
  async function areasInit(options = {}) {
4574
4358
  const cwd = options.cwd || process.cwd();
4575
4359
  const force = options.force ?? false;
@@ -4585,159 +4369,92 @@ Ou edite manualmente o arquivo existente.
4585
4369
  `.trim();
4586
4370
  }
4587
4371
  const allFiles = getAllCodeFiles5(cwd);
4588
- const currentConfig = readConfig(cwd);
4589
- const areaCounts = /* @__PURE__ */ new Map();
4590
- for (const filePath of allFiles) {
4591
- const areas2 = detectFileAreas(filePath, currentConfig);
4592
- for (const areaId of areas2) {
4593
- if (!areaCounts.has(areaId)) {
4594
- areaCounts.set(areaId, /* @__PURE__ */ new Set());
4595
- }
4596
- areaCounts.get(areaId).add(filePath);
4597
- }
4598
- }
4599
- const generatedAreas = {};
4600
- for (const [areaId, files] of areaCounts) {
4601
- const patterns = inferPatternsFromFiles([...files]);
4602
- generatedAreas[areaId] = {
4603
- name: getAreaName(areaId, currentConfig),
4604
- description: getAreaDescription(areaId, currentConfig),
4605
- patterns
4606
- };
4607
- }
4608
- const suggestedIgnore = detectSuggestedIgnorePatterns(allFiles);
4609
- const newConfig = {
4610
- $schema: "./areas.schema.json",
4611
- version: "1.0.0",
4612
- ignore: suggestedIgnore,
4613
- areas: generatedAreas,
4614
- descriptions: {},
4615
- settings: {
4616
- autoDetect: true,
4617
- inferDescriptions: true,
4618
- groupByCategory: true
4619
- }
4620
- };
4372
+ const newConfig = createInitialConfig(allFiles);
4621
4373
  writeConfig(cwd, newConfig);
4622
- const unmappedCount = allFiles.filter(
4623
- (f) => detectFileAreas(f, newConfig).length === 0
4624
- ).length;
4625
- const sortedAreas = [...areaCounts.entries()].sort((a, b) => b[1].size - a[1].size);
4374
+ const framework = detectFramework(allFiles);
4375
+ const frameworkName = {
4376
+ "nextjs-app": "Next.js (App Router)",
4377
+ "nextjs-pages": "Next.js (Pages Router)",
4378
+ "vite": "Vite/CRA",
4379
+ "generic": "Gen\xE9rico"
4380
+ }[framework] || framework;
4381
+ const areasCount = Object.keys(newConfig.areas).length;
4626
4382
  let out = `
4627
4383
  \u2705 Arquivo criado: .analyze/areas.config.json
4628
4384
 
4629
- \u{1F4E6} \xC1reas detectadas: ${sortedAreas.length}
4385
+ \u{1F3AF} Framework detectado: ${frameworkName}
4386
+ \u{1F4E6} \xC1reas configuradas: ${areasCount}
4630
4387
  `;
4631
- if (suggestedIgnore.length > 0) {
4632
- out += `\u{1F6AB} Padr\xF5es ignorados: ${suggestedIgnore.length}
4388
+ if (newConfig.ignore && newConfig.ignore.length > 0) {
4389
+ out += `\u{1F6AB} Padr\xF5es ignorados: ${newConfig.ignore.length}
4633
4390
  `;
4634
4391
  }
4635
4392
  out += `
4636
- `;
4637
- for (const [areaId, files] of sortedAreas.slice(0, 15)) {
4638
- const name = getAreaName(areaId, newConfig);
4639
- out += ` ${name.padEnd(25)} ${files.size} arquivos
4640
- `;
4641
- }
4642
- if (sortedAreas.length > 15) {
4643
- out += ` ... e mais ${sortedAreas.length - 15}
4644
- `;
4393
+ \u{1F4DD} Pr\xF3ximos passos:
4394
+
4395
+ 1\uFE0F\u20E3 Personalize as \xE1reas:
4396
+ Edite .analyze/areas.config.json e ajuste:
4397
+ - Adicione suas \xE1reas de neg\xF3cio (ex: "pets", "veterinary", "activities")
4398
+ - Ajuste os padr\xF5es (patterns) para cada \xE1rea
4399
+ - Renomeie \xE1reas conforme seu dom\xEDnio
4400
+
4401
+ 2\uFE0F\u20E3 Adicione descri\xE7\xF5es (opcional):
4402
+ "descriptions": {
4403
+ "src/hooks/useAuth.ts": "Hook principal de autentica\xE7\xE3o",
4404
+ "src/services/petService.ts": "Servi\xE7o de gerenciamento de pets"
4405
+ }
4406
+
4407
+ 3\uFE0F\u20E3 Valide a configura\xE7\xE3o:
4408
+ ai-tool areas # Ver todas as \xE1reas
4409
+ ai-tool area auth # Ver arquivos de uma \xE1rea
4410
+ ai-tool map # Ver resumo do projeto
4411
+
4412
+ \u{1F4A1} Dicas:
4413
+
4414
+ \u2022 Use patterns para pastas: "app/dashboard/**"
4415
+ \u2022 Use keywords para arquivos espalhados: ["auth", "login"]
4416
+ \u2022 Um arquivo pode pertencer a m\xFAltiplas \xE1reas
4417
+ \u2022 Use "exclude" para remover arquivos espec\xEDficos de uma \xE1rea
4418
+
4419
+ \u{1F4D6} Exemplo completo:
4420
+
4421
+ {
4422
+ "areas": {
4423
+ "meus-pets": {
4424
+ "name": "Meus Pets",
4425
+ "description": "Listagem e gerenciamento de pets do usu\xE1rio",
4426
+ "patterns": [
4427
+ "app/meus-pets/**",
4428
+ "components/pets/**",
4429
+ "hooks/usePets.*",
4430
+ "services/petService.*"
4431
+ ],
4432
+ "keywords": ["pet", "animal"],
4433
+ "exclude": ["components/pets/shared/**"] // opcional
4434
+ },
4435
+ "auth": {
4436
+ "name": "Autentica\xE7\xE3o",
4437
+ "patterns": ["app/**/auth/**", "components/auth/**"],
4438
+ "keywords": ["auth", "login"]
4645
4439
  }
4646
- if (unmappedCount > 0) {
4647
- out += `
4648
- \u26A0\uFE0F ${unmappedCount} arquivos sem \xE1rea definida
4649
- Use 'ai-tool areas' para ver detalhes
4650
- `;
4651
- }
4652
- if (suggestedIgnore.length > 0) {
4653
- out += `
4654
- \u{1F4CB} Padr\xF5es adicionados ao ignore:
4655
- `;
4656
- for (const pattern of suggestedIgnore) {
4657
- out += ` \u2022 ${pattern}
4440
+ }
4441
+ }
4658
4442
  `;
4659
- }
4660
- }
4661
- out += `
4662
- \u{1F4A1} Boas pr\xE1ticas:
4663
- - Ideal: 5-15 \xE1reas (muitas \xE1reas \xE9 dif\xEDcil de navegar)
4664
- - Use patterns para pastas, keywords para arquivos espalhados
4665
- - Se uma \xE1rea tem <3 arquivos, considere mesclar com outra
4666
- - Se tem >50 arquivos, considere dividir em sub-\xE1reas
4667
-
4668
- \u{1F4DD} Como customizar:
4669
- 1. Renomear \xE1reas: altere o campo "name"
4670
- 2. Ajustar padr\xF5es: edite "patterns" (glob) ou "keywords"
4671
- 3. Adicionar descri\xE7\xF5es: campo "description" explica o dom\xEDnio
4672
- 4. Descri\xE7\xF5es de arquivos: use "descriptions" para documentos espec\xEDficos
4673
-
4674
- \u{1F4A1} Exemplo de customiza\xE7\xE3o:
4675
-
4676
- Antes (nome gen\xE9rico detectado):
4677
- "user-profile": { "name": "User Profile", ... }
4678
-
4679
- Depois (renomeado para dom\xEDnio de neg\xF3cio):
4680
- "meu-perfil": { "name": "Meu Perfil", "description": "Edi\xE7\xE3o de perfil do usu\xE1rio" }
4681
-
4682
- \u2699\uFE0F Quando usar autoDetect: false
4683
- - Quando quer controle total das \xE1reas
4684
- - Quando a detec\xE7\xE3o autom\xE1tica est\xE1 muito imprecisa
4685
- - Quando o projeto tem dom\xEDnios muito espec\xEDficos
4686
-
4687
- \u{1F4A1} Casos especiais:
4688
- - Arquivos compartilhados: adicione a m\xFAltiplas \xE1reas
4689
- - Utils globais: crie \xE1rea 'shared' ou use 'ignore'
4690
- - Monorepo: use 'patterns' com caminhos relativos \xE0 raiz
4691
-
4692
- \u{1F527} Manuten\xE7\xE3o:
4693
- - Atualize o config ao criar/mover arquivos
4694
- - Use 'ai-tool areas' para verificar arquivos sem \xE1rea
4695
- - Use 'ai-tool area <nome>' para ver o que foi detectado
4696
-
4697
- \u{1F4CB} Pr\xF3ximos passos:
4698
- \u2192 Execute 'ai-tool areas' para ver o resultado
4699
- \u2192 Use 'ai-tool area <nome>' para validar uma \xE1rea espec\xEDfica
4700
- \u2192 Execute 'ai-tool map' para ver o resumo atualizado
4701
- `;
4702
4443
  return out.trim();
4703
4444
  } catch (error) {
4704
4445
  const message = error instanceof Error ? error.message : String(error);
4705
4446
  throw new Error(`Erro ao executar areas init: ${message}`);
4706
4447
  }
4707
4448
  }
4708
- function inferPatternsFromFiles(files) {
4709
- const patterns = /* @__PURE__ */ new Set();
4710
- const folderGroups = /* @__PURE__ */ new Map();
4711
- for (const file of files) {
4712
- const parts = file.split("/");
4713
- if (parts.length > 1) {
4714
- const folder = parts.slice(0, Math.min(3, parts.length - 1)).join("/");
4715
- if (!folderGroups.has(folder)) {
4716
- folderGroups.set(folder, []);
4717
- }
4718
- folderGroups.get(folder).push(file);
4719
- }
4720
- }
4721
- for (const [folder, folderFiles] of folderGroups) {
4722
- if (folderFiles.length >= 2) {
4723
- patterns.add(`${folder}/**`);
4724
- } else {
4725
- patterns.add(folderFiles[0]);
4726
- }
4727
- }
4728
- for (const file of files) {
4729
- if (!file.includes("/")) {
4730
- patterns.add(file);
4731
- }
4732
- }
4733
- return [...patterns].sort();
4734
- }
4735
4449
  function detectSuggestedIgnorePatterns(files) {
4736
4450
  const patterns = [];
4451
+ patterns.push("node_modules/**");
4737
4452
  if (files.some((f) => f.includes("functions/lib/"))) {
4738
4453
  patterns.push("functions/lib/**");
4739
4454
  }
4740
- const testCount = files.filter((f) => /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(f)).length;
4455
+ const testCount = files.filter(
4456
+ (f) => /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(f)
4457
+ ).length;
4741
4458
  if (testCount > 3) {
4742
4459
  patterns.push("**/*.test.{ts,tsx,js,jsx}");
4743
4460
  patterns.push("**/*.spec.{ts,tsx,js,jsx}");
@@ -4758,7 +4475,7 @@ function getAllCodeFiles5(dir, files = [], baseDir = dir) {
4758
4475
  try {
4759
4476
  const entries = readdirSync6(dir);
4760
4477
  for (const entry of entries) {
4761
- const fullPath = join8(dir, entry);
4478
+ const fullPath = join9(dir, entry);
4762
4479
  if (IGNORED_DIRS4.has(entry) || entry.startsWith(".")) {
4763
4480
  continue;
4764
4481
  }
@@ -5245,10 +4962,7 @@ export {
5245
4962
  removeArea,
5246
4963
  setFileDescription,
5247
4964
  getFileDescription,
5248
- FOLDER_PATTERNS,
5249
- KEYWORD_PATTERNS,
5250
- AREA_NAMES,
5251
- AREA_DESCRIPTIONS,
4965
+ isFileIgnored,
5252
4966
  detectFileAreas,
5253
4967
  getAreaName,
5254
4968
  getAreaDescription,