@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.
- package/README.md +138 -108
- package/dist/{chunk-MWM2INVY.js → chunk-OMEBMR2V.js} +274 -560
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +16 -61
- package/dist/index.js +3 -9
- package/dist/{server-IBNLXRUS.js → server-JNIIN5S4.js} +1 -1
- package/package.json +1 -1
|
@@ -1368,7 +1368,7 @@ function calculateFilesHash(cwd) {
|
|
|
1368
1368
|
try {
|
|
1369
1369
|
const stat = statSync(fullPath);
|
|
1370
1370
|
const mtime = stat.mtimeMs;
|
|
1371
|
-
hashAccumulator
|
|
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
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
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:
|
|
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(
|
|
1590
|
+
matches.push(areaId);
|
|
1952
1591
|
}
|
|
1953
1592
|
}
|
|
1954
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
|
3130
|
-
import { join as
|
|
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
|
|
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 =
|
|
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 (
|
|
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 (
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
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{
|
|
4385
|
+
\u{1F3AF} Framework detectado: ${frameworkName}
|
|
4386
|
+
\u{1F4E6} \xC1reas configuradas: ${areasCount}
|
|
4630
4387
|
`;
|
|
4631
|
-
if (
|
|
4632
|
-
out += `\u{1F6AB} Padr\xF5es ignorados: ${
|
|
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
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
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
|
-
|
|
4647
|
-
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
5249
|
-
KEYWORD_PATTERNS,
|
|
5250
|
-
AREA_NAMES,
|
|
5251
|
-
AREA_DESCRIPTIONS,
|
|
4965
|
+
isFileIgnored,
|
|
5252
4966
|
detectFileAreas,
|
|
5253
4967
|
getAreaName,
|
|
5254
4968
|
getAreaDescription,
|