@wtdlee/repomap 0.9.1 → 0.10.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.
@@ -1,4 +1,4 @@
1
- var P=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,n){let r=[],f=n?.envResult,t=n?.railsAnalysis,l=n?.activeTab||"pages",e=s.repositories[0]?.displayName||s.repositories[0]?.name||"Repository";for(let p of s.repositories){this.graphqlOps.push(...p.analysis?.graphqlOperations||[]),this.apiCalls.push(...p.analysis?.apiCalls||[]);let u=p.analysis?.components||[];for(let a of u)this.components.push({name:a.name,filePath:a.filePath,type:a.type,dependencies:a.dependencies||[],hooks:a.hooks||[]});}for(let p of s.repositories){let u=p.analysis?.pages||[];for(let a of u)r.push({...a,repo:p.name,children:[],parent:null,depth:0});}let{rootPages:i,relations:o}=this.buildHierarchy(r);return this.renderPageMapHtml(r,i,o,e,{envResult:f,railsAnalysis:t,activeTab:l})}buildHierarchy(s){let n=new Map,r=[];for(let t of s)n.set(t.path,t);for(let t of s){let l=t.path.split("/").filter(Boolean);for(let e=l.length-1;e>=1;e--){let i="/"+l.slice(0,e).join("/"),o=n.get(i);if(o){t.parent=i,t.depth=o.depth+1,o.children.includes(t.path)||o.children.push(t.path),r.push({from:i,to:t.path,type:"parent-child",description:`Sub-page of ${i}`});break}}if(t.parent||(t.depth=Math.max(0,l.length-1)),t.layout)for(let e of s)e.path!==t.path&&e.layout===t.layout&&(r.find(o=>o.type==="same-layout"&&(o.from===t.path&&o.to===e.path||o.from===e.path&&o.to===t.path))||r.push({from:t.path,to:e.path,type:"same-layout",description:`Both use ${t.layout}`}));}return {rootPages:s.filter(t=>!t.parent).sort((t,l)=>t.path.localeCompare(l.path)),relations:r}}renderPageMapHtml(s,n,r,f,t){let l=t?.envResult,e=t?.railsAnalysis,i=t?.activeTab||"pages",o=JSON.stringify(this.graphqlOps.map(c=>({name:c.name,type:c.type,variables:c.variables,fields:c.fields,returnType:c.returnType,usedIn:c.usedIn}))),p=JSON.stringify(this.components),u=e?JSON.stringify(e.routes.routes):"[]",a=e?JSON.stringify(e.controllers.controllers):"[]",m=e?JSON.stringify(e.models.models):"[]",v=e?JSON.stringify(e.views):'{ "views": [], "pages": [], "summary": {} }',y=e?JSON.stringify(e.react):'{ "components": [], "entryPoints": [], "summary": {} }',d=e?JSON.stringify(e.grpc):'{ "services": [] }',C=e?JSON.stringify(e.summary):"null",h=l?.hasRails||false,b=l?.hasNextjs||false,w=l?.hasReact||false,x=new Map;for(let c of s){let g=c.path.split("/").filter(Boolean)[0]||"root";x.has(g)||x.set(g,[]),x.get(g)?.push(c);}return `<!DOCTYPE html>
1
+ var E=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(i,n){let r=[],u=n?.envResult,t=n?.railsAnalysis,o=n?.activeTab||"pages",e=i.repositories[0]?.displayName||i.repositories[0]?.name||"Repository";for(let p of i.repositories){this.graphqlOps.push(...p.analysis?.graphqlOperations||[]),this.apiCalls.push(...p.analysis?.apiCalls||[]);let g=p.analysis?.components||[];for(let a of g)this.components.push({name:a.name,filePath:a.filePath,type:a.type,dependencies:a.dependencies||[],hooks:a.hooks||[]});}for(let p of i.repositories){let g=p.analysis?.pages||[];for(let a of g)r.push({...a,repo:p.name,children:[],parent:null,depth:0});}let{rootPages:l,relations:s}=this.buildHierarchy(r);return this.renderPageMapHtml(r,l,s,e,{envResult:u,railsAnalysis:t,activeTab:o})}buildHierarchy(i){let n=new Map,r=[];for(let t of i)n.set(t.path,t);for(let t of i){let o=t.path.split("/").filter(Boolean);for(let e=o.length-1;e>=1;e--){let l="/"+o.slice(0,e).join("/"),s=n.get(l);if(s){t.parent=l,t.depth=s.depth+1,s.children.includes(t.path)||s.children.push(t.path),r.push({from:l,to:t.path,type:"parent-child",description:`Sub-page of ${l}`});break}}if(t.parent||(t.depth=Math.max(0,o.length-1)),t.layout)for(let e of i)e.path!==t.path&&e.layout===t.layout&&(r.find(s=>s.type==="same-layout"&&(s.from===t.path&&s.to===e.path||s.from===e.path&&s.to===t.path))||r.push({from:t.path,to:e.path,type:"same-layout",description:`Both use ${t.layout}`}));}return {rootPages:i.filter(t=>!t.parent).sort((t,o)=>t.path.localeCompare(o.path)),relations:r}}renderPageMapHtml(i,n,r,u,t){let o=t?.envResult,e=t?.railsAnalysis,l=t?.activeTab||"pages",s=c=>JSON.stringify(c).replace(/</g,"\\u003c"),p=s(this.graphqlOps.map(c=>({name:c.name,type:c.type,variables:c.variables,fields:c.fields,returnType:c.returnType,usedIn:c.usedIn}))),g=s(this.components),a=s(i),h=s(r),v=s(this.apiCalls),y=e?s(e.routes.routes):"[]",d=e?s(e.controllers.controllers):"[]",w=e?s(e.models.models):"[]",C=e?s(e.views):'{ "views": [], "pages": [], "summary": {} }',P=e?s(e.react):'{ "components": [], "entryPoints": [], "summary": {} }',x=e?s(e.grpc):'{ "services": [] }',S=e?s(e.summary):"null",m=o?.hasRails||false,f=o?.hasNextjs||false,R=o?.hasReact||false,b=new Map;for(let c of i){let k=c.path.split("/").filter(Boolean)[0]||"root";b.has(k)||b.set(k,[]),b.get(k)?.push(c);}return `<!DOCTYPE html>
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="UTF-8">
@@ -14,17 +14,17 @@ var P=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,n){let
14
14
  <body>
15
15
  <header class="header">
16
16
  <div style="display:flex;align-items:center;gap:24px">
17
- <h1 style="cursor:pointer" onclick="location.href='/'">\u{1F4CA} ${f}</h1>
17
+ <h1 style="cursor:pointer" onclick="location.href='/'">\u{1F4CA} ${u}</h1>
18
18
  <nav style="display:flex;gap:4px">
19
- <a href="/page-map" class="nav-link ${i==="pages"?"active":""}">Page Map</a>
20
- ${h?`<a href="/rails-map" class="nav-link ${i==="rails"?"active":""}">Rails Map</a>`:""}
19
+ <a href="/page-map" class="nav-link ${l==="pages"?"active":""}">Page Map</a>
20
+ ${m?`<a href="/rails-map" class="nav-link ${l==="rails"?"active":""}">Rails Map</a>`:""}
21
21
  <a href="/docs" class="nav-link">Docs</a>
22
22
  <a href="/api/report" class="nav-link" target="_blank">API</a>
23
23
  </nav>
24
24
  </div>
25
25
  <div style="display:flex;gap:12px;align-items:center">
26
26
  <!-- Environment filter badges -->
27
- ${h&&b?`<div class="env-filters" style="display:flex;gap:4px;margin-right:8px">
27
+ ${m&&f?`<div class="env-filters" style="display:flex;gap:4px;margin-right:8px">
28
28
  <button class="env-badge env-badge-active" data-env="all" onclick="filterByEnv('all')">All</button>
29
29
  <button class="env-badge" data-env="nextjs" onclick="filterByEnv('nextjs')">\u269B\uFE0F Next.js</button>
30
30
  <button class="env-badge" data-env="rails" onclick="filterByEnv('rails')">\u{1F6E4}\uFE0F Rails</button>
@@ -63,13 +63,13 @@ var P=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,n){let
63
63
  <!-- Frontend Stats -->
64
64
  <h3 style="margin-top:16px;font-size:10px;text-transform:uppercase;color:var(--text2);letter-spacing:1px">Frontend</h3>
65
65
  <div class="stats" id="stats-container">
66
- <div class="stat" data-filter="pages"><div class="stat-val">${s.length}</div><div class="stat-label">Pages</div></div>
66
+ <div class="stat" data-filter="pages"><div class="stat-val">${i.length}</div><div class="stat-label">Pages</div></div>
67
67
  <div class="stat" data-filter="hierarchies"><div class="stat-val">${r.filter(c=>c.type==="parent-child").length}</div><div class="stat-label">Hierarchies</div></div>
68
68
  <div class="stat" data-filter="graphql"><div class="stat-val">${this.graphqlOps.length}</div><div class="stat-label">GraphQL</div></div>
69
69
  <div class="stat" data-filter="restapi"><div class="stat-val">${this.apiCalls.length}</div><div class="stat-label">REST API</div></div>
70
70
  </div>
71
71
 
72
- ${h&&e?`
72
+ ${m&&e?`
73
73
  <!-- Rails Stats -->
74
74
  <h3 style="margin-top:16px;font-size:10px;text-transform:uppercase;color:var(--text2);letter-spacing:1px;cursor:pointer" onclick="switchToRailsTab()">Rails Backend</h3>
75
75
  <div class="stats" id="rails-stats">
@@ -84,19 +84,19 @@ var P=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,n){let
84
84
 
85
85
  <div class="content">
86
86
  <!-- Pages Tree View (for all screens - Next.js/React/Rails) -->
87
- <div class="tree-view ${i==="pages"?"active":""}" id="tree-view" data-tab="pages">
88
- ${s.length>0?this.buildTreeHtml(x,s):""}
89
- <div id="page-map-react-components-section" style="${h?"margin-top:20px;border-top:1px solid var(--bg3);padding-top:20px":""}">
87
+ <div class="tree-view ${l==="pages"?"active":""}" id="tree-view" data-tab="pages">
88
+ ${i.length>0?this.buildTreeHtml(b,i):""}
89
+ <div id="page-map-react-components-section" style="${m?"margin-top:20px;border-top:1px solid var(--bg3);padding-top:20px":""}">
90
90
  </div>
91
- <div id="page-map-rails-section" style="${s.length>0&&h?"margin-top:20px;border-top:1px solid var(--bg3);padding-top:20px":""}">
92
- ${h&&s.length===0?'<div class="empty-state-sm">Loading screens...</div>':""}
91
+ <div id="page-map-rails-section" style="${i.length>0&&m?"margin-top:20px;border-top:1px solid var(--bg3);padding-top:20px":""}">
92
+ ${m&&i.length===0?'<div class="empty-state-sm">Loading screens...</div>':""}
93
93
  </div>
94
94
  </div>
95
95
 
96
96
  <!-- Rails Routes View (dedicated) -->
97
- <div class="tree-view ${i==="rails"?"active":""}" id="rails-tree-view" data-tab="rails">
97
+ <div class="tree-view ${l==="rails"?"active":""}" id="rails-tree-view" data-tab="rails">
98
98
  <div id="rails-routes-container">
99
- ${h?'<div class="empty-state-sm">Loading Rails routes...</div>':'<div class="empty-state">No Rails environment detected</div>'}
99
+ ${m?'<div class="empty-state-sm">Loading Rails routes...</div>':'<div class="empty-state">No Rails environment detected</div>'}
100
100
  </div>
101
101
  </div>
102
102
 
@@ -138,33 +138,35 @@ var P=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,n){let
138
138
  <script>
139
139
  // Environment detection results
140
140
  const envInfo = {
141
- hasRails: ${h},
142
- hasNextjs: ${b},
143
- hasReact: ${w}
141
+ hasRails: ${m},
142
+ hasNextjs: ${f},
143
+ hasReact: ${R}
144
144
  };
145
145
 
146
146
  // Frontend data
147
- const pages = ${JSON.stringify(s)};
148
- const relations = ${JSON.stringify(r)};
149
- const graphqlOps = ${o};
150
- const components = ${p};
151
- const apiCallsData = ${JSON.stringify(this.apiCalls)};
147
+ const pages = ${a};
148
+ const relations = ${h};
149
+ const graphqlOps = ${p};
150
+ const components = ${g};
151
+ const apiCallsData = ${v};
152
152
  window.apiCalls = apiCallsData;
153
153
  const pageMap = new Map(pages.map(p => [p.path, p]));
154
154
  const gqlMap = new Map(graphqlOps.map(op => [op.name, op]));
155
155
  const compMap = new Map(components.map(c => [c.name, c]));
156
+ // Mapping metadata for UI debugging (key -> {confidence, evidence})
157
+ const opMetaMap = new Map();
156
158
 
157
159
  // Rails data (if available)
158
- const railsRoutes = ${u};
159
- const railsControllers = ${a};
160
- const railsModels = ${m};
161
- const railsViews = ${v};
162
- const railsReact = ${y};
163
- const railsGrpc = ${d};
164
- const railsSummary = ${C};
160
+ const railsRoutes = ${y};
161
+ const railsControllers = ${d};
162
+ const railsModels = ${w};
163
+ const railsViews = ${C};
164
+ const railsReact = ${P};
165
+ const railsGrpc = ${x};
166
+ const railsSummary = ${S};
165
167
 
166
168
  // Current active tab state
167
- let currentMainTab = '${i}';
169
+ let currentMainTab = '${l}';
168
170
 
169
171
  // Modal history stack for back navigation
170
172
  const modalHistory = [];
@@ -629,12 +631,18 @@ var P=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,n){let
629
631
  html += '<div class="route-stat" data-filter="grpc"><div class="route-stat-val cyan">' + totalWithGrpc + '</div><div class="route-stat-label">gRPC</div></div>';
630
632
  html += '</div>';
631
633
  // Analysis coverage indicator
632
- if (totalWithActionInfo > 0) {
633
- const coverage = Math.round((totalWithActionInfo / combinedData.length) * 100);
634
- const coverageTooltip = 'Percentage of routes successfully matched with controller actions to extract details (JSON/HTML rendering, redirects, etc). This is a tool analysis metric, not a code quality indicator.';
635
- const coverageClass = coverage > 70 ? 'coverage-high' : coverage > 40 ? 'coverage-mid' : 'coverage-low';
634
+ {
635
+ const totalRoutesAnalyzed = combinedData.length;
636
+ const totalWithControllerMatch = combinedData.filter(r => r.controllerInfo).length;
637
+ const overallCoverage = totalRoutesAnalyzed > 0 ? Math.round((totalWithActionInfo / totalRoutesAnalyzed) * 100) : 0;
638
+ const matchedCoverage = totalWithControllerMatch > 0 ? Math.round((totalWithActionInfo / totalWithControllerMatch) * 100) : 0;
639
+ const overallTooltip = 'Percentage of routes that were successfully matched with controller actions to extract details. This includes routes pointing to external controllers (gems/engines) which are not analyzable from app/controllers.';
640
+ const matchedTooltip = 'Percentage of routes with a matched app controller (app/controllers) where the target action method was found and parsed.';
641
+ const overallClass = overallCoverage > 70 ? 'coverage-high' : overallCoverage > 40 ? 'coverage-mid' : 'coverage-low';
642
+ const matchedClass = matchedCoverage > 70 ? 'coverage-high' : matchedCoverage > 40 ? 'coverage-mid' : 'coverage-low';
636
643
  html += '<div class="coverage-info">';
637
- html += '<div class="coverage-text" title="' + coverageTooltip + '">Action Details Coverage: <span class="' + coverageClass + '">' + coverage + '%</span> (' + totalWithActionInfo + '/' + combinedData.length + ' routes analyzed) \u2139\uFE0F</div>';
644
+ html += '<div class="coverage-text" title="' + overallTooltip + '">Action Details Coverage (overall): <span class="' + overallClass + '">' + overallCoverage + '%</span> (' + totalWithActionInfo + '/' + totalRoutesAnalyzed + ' routes analyzed) \u2139\uFE0F</div>';
645
+ html += '<div class="coverage-text" title="' + matchedTooltip + '">Action Details Coverage (matched controllers): <span class="' + matchedClass + '">' + matchedCoverage + '%</span> (' + totalWithActionInfo + '/' + totalWithControllerMatch + ' matched) \u2139\uFE0F</div>';
638
646
  html += '</div>';
639
647
  }
640
648
  html += '</div>';
@@ -2140,10 +2148,17 @@ var P=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,n){let
2140
2148
  const isQ = !op.type?.includes('Mutation');
2141
2149
  const sourceForModal = op.sourceDetail || op.sourcePath;
2142
2150
  const srcArg = op.sourcePath !== 'Direct' && sourceForModal
2143
- ? ",\\'"+sourceForModal.replace(/'/g, "\\\\'")+"\\'"
2144
- : '';
2151
+ ? "\\'"+sourceForModal.replace(/'/g, "\\\\'")+"\\'"
2152
+ : 'null';
2153
+
2154
+ // Store mapping metadata in a global map and pass only a key to onclick.
2155
+ const metaKey = op.queryName + '|' + (sourceForModal || '') + '|' + (op.type || '');
2156
+ if (op.confidence || (op.evidence && op.evidence.length)) {
2157
+ opMetaMap.set(metaKey, { confidence: op.confidence, evidence: op.evidence });
2158
+ }
2159
+ const metaArg = ",\\'"+metaKey.replace(/'/g, "\\\\'")+"\\'";
2145
2160
  // detail-item keeps base padding, adds indent
2146
- dataHtml += '<div class="detail-item data-op" style="padding:8px 10px 8px '+totalPadding+'px" onclick="showDataDetail(\\''+op.queryName.replace(/'/g, "\\\\'")+"\\'"+srcArg+')">' +
2161
+ dataHtml += '<div class="detail-item data-op" style="padding:8px 10px 8px '+totalPadding+'px" onclick="showDataDetail(\\''+op.queryName.replace(/'/g, "\\\\'")+"\\',"+srcArg+metaArg+')">' +
2147
2162
  '<span class="tag '+(isQ?'tag-query':'tag-mutation')+'" style="font-size:10px">'+(isQ?'Q':'M')+'</span> '+op.queryName+'</div>';
2148
2163
  });
2149
2164
 
@@ -2649,12 +2664,28 @@ var P=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,n){let
2649
2664
  btn.remove();
2650
2665
  };
2651
2666
 
2652
- function showDataDetail(rawName, sourcePath) {
2667
+ function showDataDetail(rawName, sourcePath, metaKeyOrJson) {
2653
2668
  // Clean up name: remove "\u2192 " prefix and " (ComponentName)" suffix
2654
2669
  const name = rawName
2655
2670
  .replace(/^[\u2192\\->\\s]+/, '')
2656
2671
  .replace(/\\s*\\([^)]+\\)\\s*$/, '');
2657
2672
 
2673
+ let meta = null;
2674
+ try {
2675
+ // New: lookup by meta key
2676
+ if (metaKeyOrJson && typeof metaKeyOrJson === 'string' && opMetaMap.has(metaKeyOrJson)) {
2677
+ meta = opMetaMap.get(metaKeyOrJson);
2678
+ }
2679
+ // Backward compatibility: if someone passes raw JSON string
2680
+ else if (metaKeyOrJson && typeof metaKeyOrJson === 'string' && metaKeyOrJson.trim().startsWith('{')) {
2681
+ meta = JSON.parse(metaKeyOrJson);
2682
+ } else if (metaKeyOrJson && typeof metaKeyOrJson === 'object') {
2683
+ meta = metaKeyOrJson;
2684
+ }
2685
+ } catch {
2686
+ meta = null;
2687
+ }
2688
+
2658
2689
  // Convert SCREAMING_CASE to PascalCase (e.g., COMPANY_QUERY \u2192 CompanyQuery)
2659
2690
  const toPascalCase = (str) => {
2660
2691
  if (!/^[A-Z][A-Z0-9_]*$/.test(str)) return str;
@@ -2726,7 +2757,90 @@ var P=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,n){let
2726
2757
 
2727
2758
  if (op) {
2728
2759
  // Found GraphQL operation
2729
- html = '<div class="detail-section"><h4>Type</h4><span class="tag '+(op.type==='mutation'?'tag-mutation':'tag-query')+'">'+op.type.toUpperCase()+'</span></div>';
2760
+ const confidence = meta?.confidence || '';
2761
+ const confidenceTheme = (level) => {
2762
+ if (level === 'certain') {
2763
+ return {
2764
+ label: 'CERTAIN',
2765
+ bg: '#22c55e',
2766
+ title: 'Certain: reached via a very close import path from the page (0\u20132 steps)',
2767
+ };
2768
+ }
2769
+ if (level === 'likely') {
2770
+ return {
2771
+ label: 'LIKELY',
2772
+ bg: '#f59e0b',
2773
+ title: 'Likely: reachable via the import graph, but indirect (3+ steps)',
2774
+ };
2775
+ }
2776
+ if (level === 'unknown') {
2777
+ return {
2778
+ label: 'COMMON',
2779
+ bg: '#64748b',
2780
+ title: 'Common: reached via widely shared modules across many pages',
2781
+ };
2782
+ }
2783
+ return null;
2784
+ };
2785
+
2786
+ const conf = confidenceTheme(confidence);
2787
+ const confidenceBadge =
2788
+ confidence === 'likely' && conf
2789
+ ? '<span class="tag" title="' +
2790
+ conf.title +
2791
+ '" style="cursor:help;font-size:10px;display:inline-flex;align-items:center;justify-content:center;height:18px;line-height:18px;padding:0 8px;border-radius:999px;background:' +
2792
+ conf.bg +
2793
+ ';color:white;opacity:0.95">' +
2794
+ conf.label +
2795
+ '</span>'
2796
+ : '';
2797
+
2798
+ html =
2799
+ '<div class="detail-section"><h4>Type</h4><div style="display:flex;align-items:center;gap:6px;flex-wrap:wrap">' +
2800
+ '<span class="tag ' +
2801
+ (op.type === 'mutation' ? 'tag-mutation' : 'tag-query') +
2802
+ '" style="display:inline-flex;align-items:center;justify-content:center;height:18px;line-height:18px;padding:0 8px;border-radius:999px">' +
2803
+ op.type.toUpperCase() +
2804
+ '</span>' +
2805
+ confidenceBadge +
2806
+ '</div></div>';
2807
+
2808
+ const escapeHtml = (s) => String(s ?? '')
2809
+ .replace(/&/g, '&amp;')
2810
+ .replace(/</g, '&lt;')
2811
+ .replace(/>/g, '&gt;')
2812
+ .replace(/"/g, '&quot;')
2813
+ .replace(/'/g, '&#39;');
2814
+
2815
+ // Prepare Evidence section HTML (render later, after GraphQL section)
2816
+ let evidenceSectionHtml = '';
2817
+ if (meta && meta.evidence && Array.isArray(meta.evidence) && meta.evidence.length > 0) {
2818
+ evidenceSectionHtml += '<div class="detail-section"><h4>Evidence</h4>';
2819
+ meta.evidence.slice(0, 12).forEach(ev => {
2820
+ const file = ev.file || '';
2821
+ const line = ev.line ? ':' + ev.line : '';
2822
+ const detailRaw = ev.detail ? String(ev.detail) : '';
2823
+
2824
+ // Escape then enhance arrows for readability
2825
+ const detailEsc = escapeHtml(detailRaw);
2826
+ const detailPretty = detailEsc.replace(/-&gt;|->/g, '<span style="color:#60a5fa;font-weight:700;padding:0 4px">\u2192</span>');
2827
+
2828
+ evidenceSectionHtml += '<div class="detail-item" style="font-size:11px;display:flex;flex-direction:column;gap:6px;align-items:flex-start;max-width:100%;overflow:hidden">' +
2829
+ '<code style="background:#0f172a;color:#93c5fd;padding:2px 6px;border-radius:3px;font-size:10px;display:block;max-width:100%;white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word">' +
2830
+ escapeHtml(file + line) +
2831
+ '</code>' +
2832
+ (detailRaw
2833
+ ? '<div style="opacity:0.92;max-width:100%;white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word">' + detailPretty + '</div>'
2834
+ : '') +
2835
+ '</div>';
2836
+ });
2837
+ if (meta.evidence.length > 12) {
2838
+ evidenceSectionHtml += '<div class="detail-item" style="font-size:11px;opacity:0.8">... '+(meta.evidence.length - 12)+' more</div>';
2839
+ }
2840
+ evidenceSectionHtml += '</div>';
2841
+ }
2842
+
2843
+ // Confidence is shown as a small badge next to Type to avoid taking extra vertical space.
2730
2844
 
2731
2845
  // Source info
2732
2846
  if (sourcePath) {
@@ -2738,7 +2852,15 @@ var P=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,n){let
2738
2852
  sourcePath.endsWith('.jsx');
2739
2853
  const isHook = !looksLikeFile && sourcePath.startsWith('use');
2740
2854
  const label = looksLikeFile ? 'File' : isHook ? 'Hook' : 'Component';
2741
- html += '<div class="detail-section"><h4>Source</h4><div class="detail-item" style="font-size:12px">via '+label+': <span class="text-accent">'+sourcePath+'</span></div></div>';
2855
+ html += '<div class="detail-section">' +
2856
+ '<h4 style="display:flex;justify-content:space-between;align-items:center">' +
2857
+ 'Source' +
2858
+ '<span class="tag tag-default" style="font-size:10px">via ' + label + '</span>' +
2859
+ '</h4>' +
2860
+ '<code style="background:#0f172a;color:#93c5fd;padding:8px 10px;border-radius:6px;font-family:monospace;font-size:11px;display:block;max-width:100%;white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word">' +
2861
+ escapeHtml(sourcePath) +
2862
+ '</code>' +
2863
+ '</div>';
2742
2864
  }
2743
2865
 
2744
2866
  // Operation Name with copy button
@@ -2763,10 +2885,14 @@ var P=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,n){let
2763
2885
 
2764
2886
  html += '<div class="detail-section"><h4 style="display:flex;justify-content:space-between;align-items:center">GraphQL<button class="copy-btn" onclick="copyGqlCode(this)" data-code="'+gqlCodeEscaped+'" title="Copy GraphQL">\u{1F4CB}</button></h4>';
2765
2887
  html += '<pre style="background:#0f172a;color:#e2e8f0;padding:12px;border-radius:6px;font-size:11px;overflow-x:auto;white-space:pre;max-height:300px;overflow-y:auto">' + gqlCode + '</pre></div>';
2888
+ // Evidence should appear right after GraphQL section
2889
+ if (evidenceSectionHtml) html += evidenceSectionHtml;
2766
2890
  } else if (op.variables?.length) {
2767
2891
  html += '<div class="detail-section"><h4>Variables</h4>';
2768
2892
  op.variables.forEach(v => { html += '<div class="detail-item">'+v.name+': <code style="background:#0f172a;color:#93c5fd;padding:2px 6px;border-radius:3px;font-family:monospace">'+v.type+'</code>'+(v.required?' (required)':'')+'</div>'; });
2769
2893
  html += '</div>';
2894
+ // Evidence should appear right after Variables section (when GraphQL block is absent)
2895
+ if (evidenceSectionHtml) html += evidenceSectionHtml;
2770
2896
  }
2771
2897
  if (op.usedIn?.length) {
2772
2898
  html += '<div class="detail-section"><h4>Used In ('+op.usedIn.length+' files)</h4>';
@@ -3569,12 +3695,12 @@ var P=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,n){let
3569
3695
  setTimeout(updatePageGqlCounts, 100);
3570
3696
  </script>
3571
3697
  </body>
3572
- </html>`}buildTreeHtml(s,n){let r=["#ef4444","#f97316","#eab308","#22c55e","#14b8a6","#3b82f6","#8b5cf6","#ec4899"],f=0;return Array.from(s.entries()).sort((t,l)=>t[0].localeCompare(l[0])).map(([t,l])=>{let e=r[f++%r.length],i=l.sort((a,m)=>a.path.localeCompare(m.path)),o=new Set(i.map(a=>a.path)),p=new Map;for(let a of i){let m=a.path.split("/").filter(Boolean),v=0;for(let y=m.length-1;y>=1;y--){let d="/"+m.slice(0,y).join("/");if(o.has(d)){v=(p.get(d)??0)+1;break}}p.set(a.path,v);}let u=i.map(a=>{let m=this.getPageType(a.path),v=p.get(a.path)??0,d=a.repo||"",C=n.some(g=>g.repo&&g.repo!==d),h=d.split("/").pop()?.split("-").map(g=>g.substring(0,4)).join("-")||d.substring(0,8),b=C&&d?`<span class="tag tag-repo" title="${d}">${h}</span>`:"",w=/^\/[A-Z]/.test(a.path)||a.filePath&&a.filePath.includes("components/pages"),x=w&&a.filePath?a.filePath.replace(/\.tsx?$/,"").replace(/^(frontend\/src\/|src\/)/,""):a.path,c=w?'<span class="tag tag-info" title="SPA Component Page">SPA</span>':"";return `<div class="page-item" data-path="${a.path}" data-repo="${d}" onclick="selectPage('${a.path}')" style="--depth:${v}">
3573
- <span class="page-type" style="--type-color:${m.color}">${m.label}</span>
3574
- <span class="page-path">${x}</span>
3698
+ </html>`}buildTreeHtml(i,n){let r=["#ef4444","#f97316","#eab308","#22c55e","#14b8a6","#3b82f6","#8b5cf6","#ec4899"],u=0;return Array.from(i.entries()).sort((t,o)=>t[0].localeCompare(o[0])).map(([t,o])=>{let e=r[u++%r.length],l=o.sort((a,h)=>a.path.localeCompare(h.path)),s=new Set(l.map(a=>a.path)),p=new Map;for(let a of l){let h=a.path.split("/").filter(Boolean),v=0;for(let y=h.length-1;y>=1;y--){let d="/"+h.slice(0,y).join("/");if(s.has(d)){v=(p.get(d)??0)+1;break}}p.set(a.path,v);}let g=l.map(a=>{let h=this.getPageType(a.path),v=p.get(a.path)??0,d=a.repo||"",w=n.some(f=>f.repo&&f.repo!==d),C=d.split("/").pop()?.split("-").map(f=>f.substring(0,4)).join("-")||d.substring(0,8),P=w&&d?`<span class="tag tag-repo" title="${d}">${C}</span>`:"",x=/^\/[A-Z]/.test(a.path)||a.filePath&&a.filePath.includes("components/pages"),S=x&&a.filePath?a.filePath.replace(/\.tsx?$/,"").replace(/^(frontend\/src\/|src\/)/,""):a.path,m=x?'<span class="tag tag-info" title="SPA Component Page">SPA</span>':"";return `<div class="page-item" data-path="${a.path}" data-repo="${d}" onclick="selectPage('${a.path}')" style="--depth:${v}">
3699
+ <span class="page-type" style="--type-color:${h.color}">${h.label}</span>
3700
+ <span class="page-path">${S}</span>
3575
3701
  <div class="page-tags">
3576
- ${b}
3577
- ${c}
3702
+ ${P}
3703
+ ${m}
3578
3704
  ${a.authentication?.required?'<span class="tag tag-auth">AUTH</span>':""}
3579
3705
  <span class="tag tag-query gql-count" data-page-path="${a.path}" style="display:none">Q:0</span>
3580
3706
  <span class="tag tag-mutation gql-count-m" data-page-path="${a.path}" style="display:none">M:0</span>
@@ -3583,7 +3709,7 @@ var P=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,n){let
3583
3709
  <div class="group-header" onclick="toggleGroup(this)" style="--group-color:${e}">
3584
3710
  <span class="group-arrow">\u25BC</span>
3585
3711
  <span class="group-name">/${t}</span>
3586
- <span class="group-count">${l.length}</span>
3712
+ <span class="group-count">${o.length}</span>
3587
3713
  </div>
3588
- <div class="group-content">${u}</div>
3589
- </div>`}).join("")}getPageType(s){let n=s.split("/").filter(Boolean).pop()||"";return n==="new"||s.endsWith("/new")?{label:"CREATE",color:"#22c55e"}:n==="edit"||s.includes("/edit")?{label:"EDIT",color:"#f59e0b"}:n.startsWith("[")||n.startsWith(":")?{label:"DETAIL",color:"#3b82f6"}:s.includes("setting")?{label:"SETTINGS",color:"#6b7280"}:{label:"LIST",color:"#06b6d4"}}};export{P as a};
3714
+ <div class="group-content">${g}</div>
3715
+ </div>`}).join("")}getPageType(i){let n=i.split("/").filter(Boolean).pop()||"";return n==="new"||i.endsWith("/new")?{label:"CREATE",color:"#22c55e"}:n==="edit"||i.includes("/edit")?{label:"EDIT",color:"#f59e0b"}:n.startsWith("[")||n.startsWith(":")?{label:"DETAIL",color:"#3b82f6"}:i.includes("setting")?{label:"SETTINGS",color:"#6b7280"}:{label:"LIST",color:"#06b6d4"}}};export{E as a};
@@ -813,7 +813,7 @@ import {k}from'./chunk-H7VVRHQZ.js';import*as c from'fs';import*as d from'path';
813
813
  <div class="panel-header">
814
814
  <div class="panel-title">gRPC Services <span class="panel-count">(\${Math.min(grpcDisplayCount, filteredGrpc.length)} / \${filteredGrpc.length})</span></div>
815
815
  </div>
816
- <div style="display:grid;gap:12px">
816
+ <div class="model-card-grid">
817
817
  \${displayedGrpc.map((svc, idx) => \`
818
818
  <div class="model-card" onclick="showGrpcDetail(\${idx})">
819
819
  <div class="model-name">
@@ -1,20 +1,20 @@
1
- var v=class{generateAll(s,e){let n=[];for(let r of s)n.push(this.generateNavigationDiagram(r)),n.push(this.generateDataFlowDiagram(r)),n.push(this.generateComponentDiagram(r)),n.push(this.generateGraphQLDiagram(r));return s.length>1&&n.push(this.generateCrossRepoDiagram(s,e)),n}generateNavigationDiagram(s){let e=["flowchart TB"," %% Page Navigation Flow - Grouped by Category"],n=new Map,r=0,i=new Map;for(let a of s.pages){let c=a.path.split("/").filter(Boolean)[0]||"root",p=i.get(c)||[];p.push(a),i.set(c,p);}for(let[a,u]of i){let c=a.replace(/[^a-zA-Z0-9]/g,"_"),p=a==="root"?"Root Pages":`/${a}`;e.push(""),e.push(` subgraph ${c}["${p}"]`),e.push(" direction TB");for(let l of u){let d=`P${r++}`;n.set(l.path,d);let D=l.path.split("/").filter(Boolean),m=D.length>1?D.slice(1).join("/"):l.path,f=l.authentication.required?" AUTH":"";e.push(` ${d}["${m}${f}"]`);}e.push(" end");}let t=0,o=30;e.push(""),e.push(" %% Navigation Links");for(let a of s.pages){if(t>=o)break;let u=n.get(a.path);for(let c of a.linkedPages.slice(0,2)){if(t>=o)break;let p=n.get(c);u&&p&&u!==p&&(e.push(` ${u} --> ${p}`),t++);}}e.push(""),e.push(" %% Styling"),e.push(" classDef authRequired fill:#fee2e2,stroke:#ef4444,color:#991b1b"),e.push(" classDef public fill:#dcfce7,stroke:#22c55e,color:#166534");for(let a of s.pages){let u=n.get(a.path);u&&(a.authentication.required?e.push(` class ${u} authRequired`):e.push(` class ${u} public`));}return {type:"flowchart",title:`${s.repository} - Page Navigation`,content:e.join(`
2
- `),relatedFiles:s.pages.map(a=>a.filePath)}}generateDataFlowDiagram(s){let e=["flowchart LR"," %% Data Flow Diagram"],n=new Map,r=0,i=p=>{let l=`${p.type}:${p.name}`;if(!n.has(l)){let d=p.type.charAt(0).toUpperCase();n.set(l,`${d}${r++}`);}return n.get(l)??`N${r++}`},o=p=>p.replace(/[\u{1F4E1}\u{270F}\u{FE0F}\u{1F504}\u{1F4E6}]/gu,"").trim().substring(0,40),a=s.dataFlows.filter(p=>p.name.includes("\u{1F4E1}")||p.operations.some(l=>l.includes("Query"))),u=s.dataFlows.filter(p=>p.name.includes("\u270F\uFE0F")||p.operations.some(l=>l.includes("Mutation"))),c=s.dataFlows.filter(p=>p.name.includes("\u{1F504}")||p.source.type==="context"||p.operations.some(l=>l.includes("Context")));if(a.length>0){e.push(""),e.push(" subgraph Queries[\u{1F4E1} Queries]"),e.push(" direction TB");for(let p of a.slice(0,20)){let l=i(p.source),d=i(p.target),D=o(p.source.name),m=o(p.target.name);e.push(` ${l}(("${D}"))`),e.push(` ${d}["${m}"]`),e.push(` ${l} --> ${d}`);}e.push(" end");}if(u.length>0){e.push(""),e.push(" subgraph Mutations[\u270F\uFE0F Mutations]"),e.push(" direction TB");for(let p of u.slice(0,20)){let l=i(p.source),d=i(p.target),D=o(p.source.name),m=o(p.target.name);e.push(` ${l}["${D}"]`),e.push(` ${d}(("${m}"))`),e.push(` ${l} --> ${d}`);}e.push(" end");}if(c.length>0){e.push(""),e.push(" subgraph Context[\u{1F504} Context]"),e.push(" direction TB");for(let p of c.slice(0,15)){let l=i(p.source),d=i(p.target),D=o(p.source.name),m=o(p.target.name);e.push(` ${l}{{"${D}"}}`),e.push(` ${d}["${m}"]`),e.push(` ${l} -.-> ${d}`);}e.push(" end");}return e.push(""),e.push(" %% Styling"),e.push(" classDef query fill:#dbeafe,stroke:#3b82f6,color:#1e40af"),e.push(" classDef mutation fill:#fce7f3,stroke:#ec4899,color:#9d174d"),e.push(" classDef context fill:#d1fae5,stroke:#10b981,color:#065f46"),{type:"flowchart",title:`${s.repository} - Data Flow`,content:e.join(`
1
+ var b=class{generateAll(s,e){let n=[];for(let r of s)n.push(this.generateNavigationDiagram(r)),n.push(this.generateDataFlowDiagram(r)),n.push(this.generateComponentDiagram(r)),n.push(this.generateGraphQLDiagram(r));return s.length>1&&n.push(this.generateCrossRepoDiagram(s,e)),n}generateNavigationDiagram(s){let e=["flowchart TB"," %% Page Navigation Flow - Grouped by Category"],n=new Map,r=0,i=new Map;for(let a of s.pages){let c=a.path.split("/").filter(Boolean)[0]||"root",p=i.get(c)||[];p.push(a),i.set(c,p);}for(let[a,u]of i){let c=a.replace(/[^a-zA-Z0-9]/g,"_"),p=a==="root"?"Root Pages":`/${a}`;e.push(""),e.push(` subgraph ${c}["${p}"]`),e.push(" direction TB");for(let l of u){let d=`P${r++}`;n.set(l.path,d);let q=l.path.split("/").filter(Boolean),m=q.length>1?q.slice(1).join("/"):l.path,f=l.authentication.required?" AUTH":"";e.push(` ${d}["${m}${f}"]`);}e.push(" end");}let t=0,o=30;e.push(""),e.push(" %% Navigation Links");for(let a of s.pages){if(t>=o)break;let u=n.get(a.path);for(let c of a.linkedPages.slice(0,2)){if(t>=o)break;let p=n.get(c);u&&p&&u!==p&&(e.push(` ${u} --> ${p}`),t++);}}e.push(""),e.push(" %% Styling"),e.push(" classDef authRequired fill:#fee2e2,stroke:#ef4444,color:#991b1b"),e.push(" classDef public fill:#dcfce7,stroke:#22c55e,color:#166534");for(let a of s.pages){let u=n.get(a.path);u&&(a.authentication.required?e.push(` class ${u} authRequired`):e.push(` class ${u} public`));}return {type:"flowchart",title:`${s.repository} - Page Navigation`,content:e.join(`
2
+ `),relatedFiles:s.pages.map(a=>a.filePath)}}generateDataFlowDiagram(s){let e=["flowchart LR"," %% Data Flow Diagram"],n=new Map,r=0,i=p=>{let l=`${p.type}:${p.name}`;if(!n.has(l)){let d=p.type.charAt(0).toUpperCase();n.set(l,`${d}${r++}`);}return n.get(l)??`N${r++}`},o=p=>p.replace(/[\u{1F4E1}\u{270F}\u{FE0F}\u{1F504}\u{1F4E6}]/gu,"").trim().substring(0,40),a=s.dataFlows.filter(p=>p.name.includes("\u{1F4E1}")||p.operations.some(l=>l.includes("Query"))),u=s.dataFlows.filter(p=>p.name.includes("\u270F\uFE0F")||p.operations.some(l=>l.includes("Mutation"))),c=s.dataFlows.filter(p=>p.name.includes("\u{1F504}")||p.source.type==="context"||p.operations.some(l=>l.includes("Context")));if(a.length>0){e.push(""),e.push(" subgraph Queries[\u{1F4E1} Queries]"),e.push(" direction TB");for(let p of a.slice(0,20)){let l=i(p.source),d=i(p.target),q=o(p.source.name),m=o(p.target.name);e.push(` ${l}(("${q}"))`),e.push(` ${d}["${m}"]`),e.push(` ${l} --> ${d}`);}e.push(" end");}if(u.length>0){e.push(""),e.push(" subgraph Mutations[\u270F\uFE0F Mutations]"),e.push(" direction TB");for(let p of u.slice(0,20)){let l=i(p.source),d=i(p.target),q=o(p.source.name),m=o(p.target.name);e.push(` ${l}["${q}"]`),e.push(` ${d}(("${m}"))`),e.push(` ${l} --> ${d}`);}e.push(" end");}if(c.length>0){e.push(""),e.push(" subgraph Context[\u{1F504} Context]"),e.push(" direction TB");for(let p of c.slice(0,15)){let l=i(p.source),d=i(p.target),q=o(p.source.name),m=o(p.target.name);e.push(` ${l}{{"${q}"}}`),e.push(` ${d}["${m}"]`),e.push(` ${l} -.-> ${d}`);}e.push(" end");}return e.push(""),e.push(" %% Styling"),e.push(" classDef query fill:#dbeafe,stroke:#3b82f6,color:#1e40af"),e.push(" classDef mutation fill:#fce7f3,stroke:#ec4899,color:#9d174d"),e.push(" classDef context fill:#d1fae5,stroke:#10b981,color:#065f46"),{type:"flowchart",title:`${s.repository} - Data Flow`,content:e.join(`
3
3
  `),relatedFiles:s.dataFlows.map(p=>p.source.name)}}generateComponentDiagram(s){let e=["flowchart TB"," %% Component Hierarchy"],n=new Map;for(let t of s.components){let o=n.get(t.type)||[];o.push(t),n.set(t.type,o);}for(let[t,o]of n){e.push(` subgraph ${t.charAt(0).toUpperCase()+t.slice(1)}s`);for(let a of o.slice(0,20)){let u=a.name.replace(/[^a-zA-Z0-9]/g,"_");e.push(` ${u}["${a.name}"]`);}e.push(" end");}let r=0,i=50;for(let t of s.components){if(r>=i)break;let o=t.name.replace(/[^a-zA-Z0-9]/g,"_");for(let a of t.dependencies.slice(0,3)){if(r>=i)break;let u=a.replace(/[^a-zA-Z0-9]/g,"_");e.push(` ${o} --> ${u}`),r++;}}return {type:"flowchart",title:`${s.repository} - Component Hierarchy`,content:e.join(`
4
4
  `),relatedFiles:s.components.map(t=>t.filePath)}}generateGraphQLDiagram(s){let e=["flowchart LR"," %% GraphQL Operations"],n=s.graphqlOperations.filter(t=>t.type==="query"),r=s.graphqlOperations.filter(t=>t.type==="mutation"),i=s.graphqlOperations.filter(t=>t.type==="fragment");if(e.push(' API[("GraphQL API")]'),n.length>0){e.push(" subgraph Queries");for(let t of n.slice(0,15)){let o=`Q_${t.name.replace(/[^a-zA-Z0-9]/g,"_")}`;e.push(` ${o}["${t.name}"]`),e.push(` ${o} --> API`);}e.push(" end");}if(r.length>0){e.push(" subgraph Mutations");for(let t of r.slice(0,15)){let o=`M_${t.name.replace(/[^a-zA-Z0-9]/g,"_")}`;e.push(` ${o}["${t.name}"]`),e.push(` ${o} --> API`);}e.push(" end");}if(i.length>0){e.push(" subgraph Fragments");for(let t of i.slice(0,10)){let o=`F_${t.name.replace(/[^a-zA-Z0-9]/g,"_")}`;e.push(` ${o}[/"${t.name}"/]`);}e.push(" end");}return {type:"flowchart",title:`${s.repository} - GraphQL Operations`,content:e.join(`
5
5
  `),relatedFiles:s.graphqlOperations.map(t=>t.filePath)}}generateCrossRepoDiagram(s,e){let n=["flowchart TB"," %% Cross-Repository Architecture"];for(let r of s){let i=r.repository.replace(/[^a-zA-Z0-9]/g,"_");n.push(` subgraph ${i}["${r.repository}"]`),n.push(` ${i}_pages["\u{1F4C4} ${r.pages.length} Pages"]`),n.push(` ${i}_gql["\u{1F537} ${r.graphqlOperations.length} GraphQL Ops"]`),n.push(` ${i}_comp["\u{1F9E9} ${r.components.length} Components"]`),n.push(" end");}for(let r of e){let i=r.sourceRepo.replace(/[^a-zA-Z0-9]/g,"_"),t=r.targetRepo.replace(/[^a-zA-Z0-9]/g,"_"),o="-->";r.linkType==="api-call"?o="==>":r.linkType==="graphql-operation"&&(o="-..->"),n.push(` ${i}_gql ${o}|"${r.linkType}"| ${t}_gql`);}return {type:"flowchart",title:"Cross-Repository Architecture",content:n.join(`
6
6
  `),relatedFiles:s.map(r=>r.repository)}}generateSequenceDiagram(s){let e=["sequenceDiagram",` %% ${s.name}`],n=[s.source,...s.via,s.target];for(let t of n)e.push(` participant ${t.name}`);let r=s.source;for(let t=0;t<s.via.length;t++){let o=s.via[t],a=s.operations[t]||"data";e.push(` ${r.name}->>+${o.name}: ${a}`),r=o;}let i=s.operations[s.operations.length-1]||"data";return e.push(` ${r.name}->>+${s.target.name}: ${i}`),e.push(` ${s.target.name}-->>-${s.source.name}: response`),{type:"sequence",title:s.name,content:e.join(`
7
7
  `),relatedFiles:[]}}};var A=class{generateDocumentation(s){let e=new Map;e.set("index.md",this.generateIndex(s));for(let n of s.repositories)e.set(`repos/${n.name}/index.md`,this.generateRepoIndex(n)),e.set(`repos/${n.name}/pages.md`,this.generatePagesDoc(n)),e.set(`repos/${n.name}/components.md`,this.generateComponentsDoc(n)),e.set(`repos/${n.name}/graphql.md`,this.generateGraphQLDoc(n)),e.set(`repos/${n.name}/dataflow.md`,this.generateDataFlowDoc(n));return s.repositories.length>1&&e.set("cross-repo.md",this.generateCrossRepoDoc(s)),e.set("diagrams.md",this.generateDiagramsDoc(s.diagrams)),e}generateIndex(s){let n=[`# ${s.repositories.length===1?`${s.repositories[0].displayName} Documentation`:"Project Documentation"}`,"",`Generated: ${s.generatedAt}`,"",s.repositories.length>1?"## Repositories":"## Overview",""];for(let r of s.repositories)n.push(`### [${r.displayName}](/docs/repos/${r.name}/index)`),n.push(""),n.push(`- **Version**: ${r.version}`),n.push(`- **Commit**: \`${r.commitHash.substring(0,7)}\``),n.push(`- **Pages**: ${r.summary.totalPages}`),n.push(`- **Components**: ${r.summary.totalComponents}`),n.push(`- **GraphQL Ops**: ${r.summary.totalGraphQLOperations}`),n.push("");return n.push("## Quick Links"),n.push(""),s.repositories.length>1&&n.push("- [Cross Repository](/docs/cross-repo)"),n.push("- [Diagrams](/docs/diagrams)"),n.push("- [Page Map (Interactive)](/page-map)"),n.push(""),n.join(`
8
- `)}generateRepoIndex(s){return [`# ${s.displayName}`,"",`Version: ${s.version} | Commit: \`${s.commitHash.substring(0,7)}\``,"","## Overview","","| Metric | Count |","|--------|-------|",`| Pages | ${s.summary.totalPages} |`,`| Components | ${s.summary.totalComponents} |`,`| GraphQL Operations | ${s.summary.totalGraphQLOperations} |`,`| Data Flows | ${s.summary.totalDataFlows} |`,`| Auth Required | ${s.summary.authRequiredPages} |`,`| Public | ${s.summary.publicPages} |`,"","## Documentation","",`- [Pages](/docs/repos/${s.name}/pages)`,`- [Components](/docs/repos/${s.name}/components)`,`- [GraphQL](/docs/repos/${s.name}/graphql)`,`- [Data Flow](/docs/repos/${s.name}/dataflow)`,"","## Quick Access","","- [Page Map](/page-map)","- [Diagrams](/docs/diagrams)",""].join(`
9
- `)}generatePagesDoc(s){let e=[`# ${s.displayName} - Pages`,""],n=s.analysis.pages.filter(o=>o.authentication.required).length,r=s.analysis.pages.filter(o=>o.dataFetching.some(a=>!a.type.includes("Mutation"))).length,i=s.analysis.pages.filter(o=>o.dataFetching.some(a=>a.type.includes("Mutation"))).length;e.push("| Metric | Value |"),e.push("|--------|-------|"),e.push(`| Total | **${s.analysis.pages.length}** |`),e.push(`| Auth Required | ${n} |`),e.push(`| With Queries | ${r} |`),e.push(`| With Mutations | ${i} |`),e.push("");let t=new Map;for(let o of s.analysis.pages){let a=o.path.split("/")[1]||"root",u=t.get(a)||[];u.push(o),t.set(a,u);}for(let[o,a]of t){e.push(`## /${o}`),e.push(""),e.push("| Page | Auth | Layout |"),e.push("|------|------|--------|");for(let u of a){let c=u.path.replace(`/${o}`,"")||"/",p=u.authentication.required?"Required":"Public",l=u.layout||"-";e.push(`| \`${c}\` | ${p} | ${l} |`);}e.push("");for(let u of a){let c=u.dataFetching||[];if(c.length===0)continue;let p=new Map,l=(m,f,h)=>{p.has(m)||p.set(m,{label:f,open:h,queries:new Set,mutations:new Set});let g=p.get(m);if(!g){let $={label:f,open:h,queries:new Set,mutations:new Set};return p.set(m,$),$}return g};for(let m of c){let h=(m.operationName||"").replace(/^[→\->\s]+/,"").trim();if(!h||h.length<2)continue;let g=m.type.includes("Mutation"),$=m.source||"",q="direct",C="Direct (this page)",y=true;$.startsWith("close:")?(q="close",C="Close (related)",y=true):$.startsWith("indirect:")||$.startsWith("usedIn:")||$.startsWith("import:")?(q="indirect",C="Indirect",y=false):$.startsWith("common:")?(q="common",C="Common (shared)",y=false):$.startsWith("hook:")?(q="hook",C="Hook",y=false):$.startsWith("component:")&&(q="component",C="Component",y=false);let P=l(q,C,y);g?P.mutations.add(h):P.queries.add(h);}let d=Array.from(p.values()).reduce((m,f)=>m+f.queries.size+f.mutations.size,0);if(d===0)continue;let D=["direct","close","component","hook","indirect","common"];e.push(`### ${u.path}`),e.push(""),e.push(`> ${u.filePath}`),e.push(""),e.push(`**Data Operations (${d})**`),e.push("");for(let m of D){let f=p.get(m);if(!f)continue;let h=f.queries.size+f.mutations.size;if(h!==0){if(e.push(`<details class="ops-group${f.open?" is-open":""}"${f.open?" open":""}>`),e.push(`<summary class="ops-group__summary"><span class="ops-group__title">${f.label}</span><span class="ops-group__count">${h}</span></summary>`),e.push(""),f.queries.size>0){e.push(`**Queries (${f.queries.size})**`),e.push(""),e.push('<div class="gql-ops-list">');for(let g of Array.from(f.queries).sort())e.push(`<span class="gql-op" data-op="${g}">${g}</span>`);e.push("</div>"),e.push("");}if(f.mutations.size>0){e.push(`**Mutations (${f.mutations.size})**`),e.push(""),e.push('<div class="gql-ops-list">');for(let g of Array.from(f.mutations).sort())e.push(`<span class="gql-op mutation" data-op="${g}">${g}</span>`);e.push("</div>"),e.push("");}e.push("</details>"),e.push("");}}e.push("");}}return e.join(`
8
+ `)}generateRepoIndex(s){return [`# ${s.displayName}`,"",`Version: ${s.version} | Commit: \`${s.commitHash.substring(0,7)}\``,"","## Overview","","| Metric | Count |","|--------|-------|",`| Pages | ${s.summary.totalPages} |`,`| Components | ${s.summary.totalComponents} |`,`| GraphQL Operations | ${s.summary.totalGraphQLOperations} |`,`| Data Flows | ${s.summary.totalDataFlows} |`,`| Auth Required | ${s.summary.authRequiredPages} |`,`| Public | ${s.summary.publicPages} |`,"","## Coverage","","| Metric | Value |","|--------|-------|",`| TS/JS Files Scanned | ${s.analysis.coverage?.tsFilesScanned??0} |`,`| TS Parse Failures | ${s.analysis.coverage?.tsParseFailures??0} |`,`| GraphQL Parse Failures | ${s.analysis.coverage?.graphqlParseFailures??0} |`,`| Codegen Files Detected | ${s.analysis.coverage?.codegenFilesDetected??0} |`,`| Codegen Files Parsed | ${s.analysis.coverage?.codegenFilesParsed??0} |`,`| Codegen Exports Found | ${s.analysis.coverage?.codegenExportsFound??0} |`,"","## Documentation","",`- [Pages](/docs/repos/${s.name}/pages)`,`- [Components](/docs/repos/${s.name}/components)`,`- [GraphQL](/docs/repos/${s.name}/graphql)`,`- [Data Flow](/docs/repos/${s.name}/dataflow)`,"","## Quick Access","","- [Page Map](/page-map)","- [Diagrams](/docs/diagrams)",""].join(`
9
+ `)}generatePagesDoc(s){let e=[`# ${s.displayName} - Pages`,""],n=s.analysis.pages.filter(o=>o.authentication.required).length,r=s.analysis.pages.filter(o=>o.dataFetching.some(a=>!a.type.includes("Mutation"))).length,i=s.analysis.pages.filter(o=>o.dataFetching.some(a=>a.type.includes("Mutation"))).length;e.push("| Metric | Value |"),e.push("|--------|-------|"),e.push(`| Total | **${s.analysis.pages.length}** |`),e.push(`| Auth Required | ${n} |`),e.push(`| With Queries | ${r} |`),e.push(`| With Mutations | ${i} |`),e.push("");let t=new Map;for(let o of s.analysis.pages){let a=o.path.split("/")[1]||"root",u=t.get(a)||[];u.push(o),t.set(a,u);}for(let[o,a]of t){e.push(`## /${o}`),e.push(""),e.push("| Page | Auth | Layout |"),e.push("|------|------|--------|");for(let u of a){let c=u.path.replace(`/${o}`,"")||"/",p=u.authentication.required?"Required":"Public",l=u.layout||"-";e.push(`| \`${c}\` | ${p} | ${l} |`);}e.push("");for(let u of a){let c=u.dataFetching||[];if(c.length===0)continue;let p=new Map,l=(m,f,g)=>{p.has(m)||p.set(m,{label:f,open:g,queries:new Set,mutations:new Set});let h=p.get(m);if(!h){let y={label:f,open:g,queries:new Set,mutations:new Set};return p.set(m,y),y}return h};for(let m of c){let g=(m.operationName||"").replace(/^[→\->\s]+/,"").trim();if(!g||g.length<2)continue;let h=m.type.includes("Mutation"),y=m.source||"",D="direct",$="Direct (this page)",C=true;y.startsWith("close:")?(D="close",$="Close (related)",C=true):y.startsWith("indirect:")||y.startsWith("usedIn:")||y.startsWith("import:")?(D="indirect",$="Indirect",C=false):y.startsWith("common:")?(D="common",$="Common (shared)",C=false):y.startsWith("hook:")?(D="hook",$="Hook",C=false):y.startsWith("component:")&&(D="component",$="Component",C=false);let P=l(D,$,C);h?P.mutations.add(g):P.queries.add(g);}let d=Array.from(p.values()).reduce((m,f)=>m+f.queries.size+f.mutations.size,0);if(d===0)continue;let q=["direct","close","component","hook","indirect","common"];e.push(`### ${u.path}`),e.push(""),e.push(`> ${u.filePath}`),e.push(""),e.push(`**Data Operations (${d})**`),e.push("");for(let m of q){let f=p.get(m);if(!f)continue;let g=f.queries.size+f.mutations.size;if(g!==0){if(e.push(`<details class="ops-group${f.open?" is-open":""}"${f.open?" open":""}>`),e.push(`<summary class="ops-group__summary"><span class="ops-group__title">${f.label}</span><span class="ops-group__count">${g}</span></summary>`),e.push(""),f.queries.size>0){e.push(`**Queries (${f.queries.size})**`),e.push(""),e.push('<div class="gql-ops-list">');for(let h of Array.from(f.queries).sort()){let D=c.some($=>($.operationName||"").replace(/^[→\->\s]+/,"").trim()===h&&$.confidence==="likely")?' data-confidence="likely"':"";e.push(`<span class="gql-op" data-op="${h}"${D}>${h}</span>`);}e.push("</div>"),e.push("");}if(f.mutations.size>0){e.push(`**Mutations (${f.mutations.size})**`),e.push(""),e.push('<div class="gql-ops-list">');for(let h of Array.from(f.mutations).sort()){let D=c.some($=>($.operationName||"").replace(/^[→\->\s]+/,"").trim()===h&&$.confidence==="likely")?' data-confidence="likely"':"";e.push(`<span class="gql-op mutation" data-op="${h}"${D}>${h}</span>`);}e.push("</div>"),e.push("");}e.push("</details>"),e.push("");}}e.push("");}}return e.join(`
10
10
  `)}generateComponentsDoc(s){let e=[`# ${s.displayName} - Components`,""],n=new Map;for(let i of s.analysis.components){let t=n.get(i.type)||[];t.push(i),n.set(i.type,t);}e.push("| Type | Count |"),e.push("|------|-------|"),e.push(`| Container | ${n.get("container")?.length||0} |`),e.push(`| Presentational | ${n.get("presentational")?.length||0} |`),e.push(`| Layout | ${n.get("layout")?.length||0} |`),e.push(`| Hook | ${n.get("hook")?.length||0} |`),e.push(`| **Total** | **${s.analysis.components.length}** |`),e.push("");let r=new Map;for(let i of s.analysis.pages)r.set(i.path,[]);for(let i of s.analysis.components)for(let t of s.analysis.pages){let o=this.extractFeatureFromPage(t.filePath),a=this.extractFeatureFromComponent(i.filePath);o&&a&&o===a&&r.get(t.path)?.push(i);}e.push("## By Page"),e.push("");for(let[i,t]of r){if(t.length===0)continue;let o=t.filter(c=>c.type==="container"),a=t.filter(c=>c.type==="presentational"),u=t.filter(c=>c.type==="hook");e.push(`### ${i}`),e.push(""),e.push("| Component | Type | Data |"),e.push("|-----------|------|------|");for(let c of o){let p=this.formatComponentDataOps(c,s.analysis.graphqlOperations);e.push(`| ${c.name} | Container | ${p||"-"} |`);}for(let c of a.slice(0,10)){let p=this.formatComponentDataOps(c,s.analysis.graphqlOperations);e.push(`| ${c.name} | UI | ${p||"-"} |`);}for(let c of u){let p=this.formatComponentDataOps(c,s.analysis.graphqlOperations);e.push(`| ${c.name} | Hook | ${p||"-"} |`);}if(e.push(""),a.length>10){let c=a.slice(10),p=`more-ui-${i.replace(/[^a-zA-Z0-9]/g,"-")}`;e.push(`<details id="${p}">`),e.push(`<summary style="cursor:pointer;color:var(--accent);padding:8px 0">Show ${c.length} more UI components</summary>`),e.push(""),e.push("| Component | Type | Data |"),e.push("|-----------|------|------|");for(let l of c){let d=this.formatComponentDataOps(l,s.analysis.graphqlOperations);e.push(`| ${l.name} | UI | ${d||"-"} |`);}e.push(""),e.push("</details>"),e.push("");}}e.push("## By Type"),e.push("");for(let[i,t]of n){e.push(`### ${i.charAt(0).toUpperCase()+i.slice(1)} (${t.length})`),e.push(""),e.push("| Name | File | Data |"),e.push("|------|------|------|");for(let o of t.slice(0,25)){let a=o.filePath.replace("src/features/","").replace("src/",""),u=this.formatComponentDataOps(o,s.analysis.graphqlOperations);e.push(`| ${o.name} | ${a} | ${u||"-"} |`);}if(e.push(""),t.length>25){let o=t.slice(25),a=`more-${i}-components`;e.push(`<details id="${a}">`),e.push(`<summary style="cursor:pointer;color:var(--accent);padding:8px 0">Show ${o.length} more ${i} components</summary>`),e.push(""),e.push("| Name | File | Data |"),e.push("|------|------|------|");for(let u of o){let c=u.filePath.replace("src/features/","").replace("src/",""),p=this.formatComponentDataOps(u,s.analysis.graphqlOperations);e.push(`| ${u.name} | ${c} | ${p||"-"} |`);}e.push(""),e.push("</details>"),e.push("");}}return e.join(`
11
11
  `)}extractFeatureFromPage(s){let e=s.split("/");return e.length>1?e[0]:null}extractFeatureFromComponent(s){let e=s.match(/src\/features\/([^/]+)/);return e?e[1]:null}formatComponentDataOps(s,e){let n=[],r=[];if(e&&s.filePath)for(let a of e)a.type!=="query"&&a.type!=="mutation"||!(a.filePath===s.filePath||a.usedIn&&a.usedIn.includes(s.filePath))||(a.type==="mutation"?r.push(a.name):n.push(a.name));for(let a of s.hooks){let u=a.match(/(?:useQuery|Query):\s*(\w+)/),c=a.match(/(?:useMutation|Mutation):\s*(\w+)/);u&&u[1]&&u[1].trim().length>=2?n.push(u[1]):c&&c[1]&&c[1].trim().length>=2&&r.push(c[1]);}let i=Array.from(new Set(n.filter(a=>a&&a.trim().length>=2))),t=Array.from(new Set(r.filter(a=>a&&a.trim().length>=2)));if(i.length===0&&t.length===0)return "";let o=[];for(let a of i.sort())o.push(`<span class="gql-op" data-op="${a}">${a}</span>`);for(let a of t.sort())o.push(`<span class="gql-op mutation" data-op="${a}">${a}</span>`);return `<div class="gql-ops-inline">${o.join(" ")}</div>`}generateGraphQLDoc(s){let e=[`# ${s.displayName} - GraphQL`,""],n=s.analysis.graphqlOperations.filter(t=>t.type==="query"),r=s.analysis.graphqlOperations.filter(t=>t.type==="mutation"),i=s.analysis.graphqlOperations.filter(t=>t.type==="fragment");if(e.push("| Type | Count |"),e.push("|------|-------|"),e.push(`| Query | ${n.length} |`),e.push(`| Mutation | ${r.length} |`),e.push(`| Fragment | ${i.length} |`),e.push(`| **Total** | **${s.analysis.graphqlOperations.length}** |`),e.push(""),n.length>0){e.push("## Queries"),e.push("");for(let t of n.slice(0,80)){e.push(`### ${t.name}`),e.push("");let o=t.returnType||"unknown",a=t.variables.length,u=t.usedIn.length;if(e.push(`> Return: \`${o}\` | Variables: ${a} | Used: ${u} files`),e.push(""),t.variables.length>0){e.push("| Variable | Type |"),e.push("|----------|------|");for(let c of t.variables)e.push(`| ${c.name} | \`${c.type}\` |`);e.push("");}t.fields&&t.fields.length>0&&(e.push("```graphql"),e.push(this.formatGraphQLFields(t.fields,0)),e.push("```"),e.push(""));}n.length>80&&e.push(`*+${n.length-80} more queries*
12
12
  `);}if(r.length>0){e.push("## Mutations"),e.push("");for(let t of r.slice(0,80)){e.push(`### ${t.name}`),e.push("");let o=t.variables.length,a=t.usedIn.length;if(e.push(`> Variables: ${o} | Used: ${a} files`),e.push(""),t.variables.length>0){e.push("| Variable | Type |"),e.push("|----------|------|");for(let u of t.variables)e.push(`| ${u.name} | \`${u.type}\` |`);e.push("");}t.fields&&t.fields.length>0&&(e.push("```graphql"),e.push(this.formatGraphQLFields(t.fields,0)),e.push("```"),e.push(""));}r.length>80&&e.push(`*+${r.length-80} more mutations*
13
13
  `);}if(i.length>0){e.push("## Fragments"),e.push(""),e.push("| Name | Type | Fields |"),e.push("|------|------|--------|");for(let t of i.slice(0,50)){let o=t.fields?.length||0;e.push(`| ${t.name} | ${t.returnType||"-"} | ${o} |`);}i.length>50&&e.push(`| *+${i.length-50} more* | | |`),e.push("");}return e.join(`
14
14
  `)}formatGraphQLFields(s,e){if(!s||s.length===0)return "";let n=[];for(let r of s){let i=" ".repeat(e);r.fields&&r.fields.length>0?(n.push(`${i}${r.name} {`),n.push(this.formatGraphQLFields(r.fields,e+1)),n.push(`${i}}`)):n.push(`${i}${r.name}`);}return n.join(`
15
15
  `)}generateDataFlowDoc(s){let e=[`# ${s.displayName} - Data Flow`,""],n=s.analysis.dataFlows.filter(o=>o.name.includes("\u{1F4E1}")||o.operations.some(a=>a.includes("Query"))),r=s.analysis.dataFlows.filter(o=>o.name.includes("\u270F\uFE0F")||o.operations.some(a=>a.includes("Mutation"))),i=s.analysis.dataFlows.filter(o=>o.source.type==="context");e.push("## Overview"),e.push(""),e.push("| Type | Count | Direction |"),e.push("|------|-------|-----------|"),e.push(`| \`QUERY\` | ${n.length} | Server \u2192 Component |`),e.push(`| \`MUTATION\` | ${r.length} | Component \u2192 Server |`),e.push(`| \`CONTEXT\` | ${i.length} | Provider \u2192 Consumer |`),e.push(`| **Total** | **${s.analysis.dataFlows.length}** | |`),e.push(""),e.push("## Architecture"),e.push(""),e.push("```mermaid"),e.push("flowchart LR"),e.push(' subgraph Server["GraphQL Server"]'),e.push(" API[(API)]"),e.push(" end"),e.push(' subgraph Client["React Application"]'),e.push(" Apollo[Apollo Client]"),e.push(" Container[Container Component]"),e.push(" View[View Component]"),e.push(" end"),e.push(" API -->|Query Response| Apollo"),e.push(" Apollo -->|Cache/Data| Container"),e.push(" Container -->|Props| View"),e.push(" View -->|User Action| Container"),e.push(" Container -->|Mutation| Apollo"),e.push(" Apollo -->|GraphQL Request| API"),e.push("```"),e.push(""),e.push("## Page Data Flows"),e.push(""),e.push('<div class="dataflow-page-flows">'),e.push(['<div class="ops-filters" data-filter-scope="dataflow">',' <span class="ops-filters__label">Show:</span>',' <label class="ops-toggle"><input type="checkbox" data-filter="direct" checked> Direct</label>',' <label class="ops-toggle"><input type="checkbox" data-filter="close" checked> Close</label>',' <label class="ops-toggle"><input type="checkbox" data-filter="indirect" checked> Indirect</label>',' <label class="ops-toggle"><input type="checkbox" data-filter="common"> Common</label>',"</div>"].join(`
16
- `)),e.push("");for(let o of s.analysis.pages){let a=this.extractFeatureFromPage(o.filePath),u=s.analysis.components.filter(h=>this.extractFeatureFromComponent(h.filePath)===a);if(!(o.dataFetching.length>0||u.some(h=>h.stateManagement.some(g=>g.includes("Apollo")||g.includes("Context")))))continue;e.push(`### ${o.path}`),e.push(""),e.push(`\`FILE: ${o.filePath}\``),e.push("");let p=this.getPageOperationGroups(o),l=this.flattenGroups(p,"queries"),d=this.flattenGroups(p,"mutations");if(l.length>0||d.length>0){let h=o.path.replace(/[^a-zA-Z0-9]/g,"_"),g=o.path.replace(/"/g,"'");e.push(`<pre class="mermaid" data-mermaid-scope="dataflow" data-mermaid-page="${h}">`),e.push("flowchart LR"),e.push(` Page${h}["${g}"]`),e.push("");let $=10,q=["direct","close","indirect","common"];for(let C of q){let y=p[C];y.queries.length===0&&y.mutations.length===0||(e.push(`%%DFG_GROUP:${C}:start%%`),y.queries.slice(0,$).forEach((P,w)=>{let b=`Q${h}_${C}_${w}`,F=P.replace(/"/g,"'").replace(/[<>]/g,"");e.push(` ${b}["${F}"]:::query --> Page${h}`);}),y.mutations.slice(0,$).forEach((P,w)=>{let b=`M${h}_${C}_${w}`,F=P.replace(/"/g,"'").replace(/[<>]/g,"");e.push(` Page${h} --> ${b}["${F}"]:::mutation`);}),e.push(`%%DFG_GROUP:${C}:end%%`),e.push(""));}e.push(" classDef query fill:#dbeafe,stroke:#1d4ed8,color:#1e40af"),e.push(" classDef mutation fill:#fce7f3,stroke:#be185d,color:#9d174d"),e.push("</pre>"),e.push("");}let D=["direct","close","indirect","common"],m={direct:{label:"Direct (this page)",open:true,defaultVisible:true},close:{label:"Close (related)",open:true,defaultVisible:true},indirect:{label:"Indirect (via imports)",open:false,defaultVisible:true},common:{label:"Common (shared)",open:false,defaultVisible:false}};if(D.some(h=>p[h].queries.length>0||p[h].mutations.length>0))for(let h of D){let g=p[h],$=m[h];if(g.queries.length===0&&g.mutations.length===0)continue;let q=$.open?" open":"",C=$.defaultVisible?"":' style="display:none"';if(e.push(`<details class="ops-group" data-ops-scope="dataflow" data-ops-group="${h}"${q}${C}>`),e.push(`<summary class="ops-group__summary"><span class="ops-group__title">${$.label}</span><span class="ops-group__count">${g.queries.length+g.mutations.length}</span></summary>`),g.queries.length>0){e.push(`<p><strong>Queries (${g.queries.length})</strong></p>`),e.push('<div class="gql-ops-list">');for(let y of g.queries)e.push(`<span class="gql-op" data-op="${y}">${y}</span>`);e.push("</div>");}if(g.mutations.length>0){e.push(`<p><strong>Mutations (${g.mutations.length})</strong></p>`),e.push('<div class="gql-ops-list">');for(let y of g.mutations)e.push(`<span class="gql-op mutation" data-op="${y}">${y}</span>`);e.push("</div>");}e.push("</details>"),e.push("");}e.push("---"),e.push("");}e.push("</div>");let t=new Set;for(let o of i)t.add(o.source.name);if(t.size>0){e.push("## Context Providers"),e.push(""),e.push("| Provider | Description |"),e.push("|----------|-------------|");for(let o of t)e.push(`| \`${o}\` | Provides shared state |`);e.push("");}return e.join(`
16
+ `)),e.push("");for(let o of s.analysis.pages){let a=this.extractFeatureFromPage(o.filePath),u=s.analysis.components.filter(g=>this.extractFeatureFromComponent(g.filePath)===a);if(!(o.dataFetching.length>0||u.some(g=>g.stateManagement.some(h=>h.includes("Apollo")||h.includes("Context")))))continue;e.push(`### ${o.path}`),e.push(""),e.push(`\`FILE: ${o.filePath}\``),e.push("");let p=this.getPageOperationGroups(o),l=this.flattenGroups(p,"queries"),d=this.flattenGroups(p,"mutations");if(l.length>0||d.length>0){let g=o.path.replace(/[^a-zA-Z0-9]/g,"_"),h=o.path.replace(/"/g,"'");e.push(`<pre class="mermaid" data-mermaid-scope="dataflow" data-mermaid-page="${g}">`),e.push("flowchart LR"),e.push(` Page${g}["${h}"]`),e.push("");let y=10,D=["direct","close","indirect","common"];for(let $ of D){let C=p[$];C.queries.length===0&&C.mutations.length===0||(e.push(`%%DFG_GROUP:${$}:start%%`),C.queries.slice(0,y).forEach((P,F)=>{let w=`Q${g}_${$}_${F}`,v=P.replace(/"/g,"'").replace(/[<>]/g,"");e.push(` ${w}["${v}"]:::query --> Page${g}`);}),C.mutations.slice(0,y).forEach((P,F)=>{let w=`M${g}_${$}_${F}`,v=P.replace(/"/g,"'").replace(/[<>]/g,"");e.push(` Page${g} --> ${w}["${v}"]:::mutation`);}),e.push(`%%DFG_GROUP:${$}:end%%`),e.push(""));}e.push(" classDef query fill:#dbeafe,stroke:#1d4ed8,color:#1e40af"),e.push(" classDef mutation fill:#fce7f3,stroke:#be185d,color:#9d174d"),e.push("</pre>"),e.push("");}let q=["direct","close","indirect","common"],m={direct:{label:"Direct (this page)",open:true,defaultVisible:true},close:{label:"Close (related)",open:true,defaultVisible:true},indirect:{label:"Indirect (via imports)",open:false,defaultVisible:true},common:{label:"Common (shared)",open:false,defaultVisible:false}};if(q.some(g=>p[g].queries.length>0||p[g].mutations.length>0))for(let g of q){let h=p[g],y=m[g];if(h.queries.length===0&&h.mutations.length===0)continue;let D=y.open?" open":"",$=y.defaultVisible?"":' style="display:none"';if(e.push(`<details class="ops-group" data-ops-scope="dataflow" data-ops-group="${g}"${D}${$}>`),e.push(`<summary class="ops-group__summary"><span class="ops-group__title">${y.label}</span><span class="ops-group__count">${h.queries.length+h.mutations.length}</span></summary>`),h.queries.length>0){e.push(`<p><strong>Queries (${h.queries.length})</strong></p>`),e.push('<div class="gql-ops-list">');for(let C of h.queries)e.push(`<span class="gql-op" data-op="${C}">${C}</span>`);e.push("</div>");}if(h.mutations.length>0){e.push(`<p><strong>Mutations (${h.mutations.length})</strong></p>`),e.push('<div class="gql-ops-list">');for(let C of h.mutations)e.push(`<span class="gql-op mutation" data-op="${C}">${C}</span>`);e.push("</div>");}e.push("</details>"),e.push("");}e.push("---"),e.push("");}e.push("</div>");let t=new Set;for(let o of i)t.add(o.source.name);if(t.size>0){e.push("## Context Providers"),e.push(""),e.push("| Provider | Description |"),e.push("|----------|-------------|");for(let o of t)e.push(`| \`${o}\` | Provides shared state |`);e.push("");}return e.join(`
17
17
  `)}getPageOperationGroups(s){let e={direct:{queries:new Set,mutations:new Set},close:{queries:new Set,mutations:new Set},indirect:{queries:new Set,mutations:new Set},common:{queries:new Set,mutations:new Set}},n=t=>{if(!t)return false;let o=t.trim();return o.length>=2&&/[a-zA-Z]/.test(o)},r=t=>{if(!t)return "direct";let o=t.trim();return o.startsWith("common:")?"common":o.startsWith("close:")?"close":o.startsWith("indirect:")?"indirect":"direct"};for(let t of s.dataFetching||[]){let a=(t.operationName?.replace(/^[→\->\s]+/,"")||"").replace(/Document$/g,"").trim();if(!n(a))continue;let u=r(t.source);t.type?.includes("Mutation")??false?e[u].mutations.add(a):e[u].queries.add(a);}let i=t=>Array.from(t).filter(n).sort((o,a)=>o.localeCompare(a));return {direct:{queries:i(e.direct.queries),mutations:i(e.direct.mutations)},close:{queries:i(e.close.queries),mutations:i(e.close.mutations)},indirect:{queries:i(e.indirect.queries),mutations:i(e.indirect.mutations)},common:{queries:i(e.common.queries),mutations:i(e.common.mutations)}}}flattenGroups(s,e){let n=new Set;for(let r of Object.values(s))for(let i of r[e])n.add(i);return Array.from(n).sort((r,i)=>r.localeCompare(i))}generateCrossRepoDoc(s){let e=["# Cross Repository Analysis","","## Architecture Overview","","```mermaid","flowchart TB"];for(let n of s.repositories){let r=n.name.replace(/[^a-zA-Z0-9]/g,"_");e.push(` subgraph ${r}["${n.displayName}"]`),e.push(` ${r}_core["Core"]`),e.push(" end");}e.push("```"),e.push(""),e.push("## API Connections"),e.push("");for(let n of s.crossRepoAnalysis.apiConnections)e.push(`- **${n.frontend}** \u2192 **${n.backend}**: \`${n.endpoint}\``);e.push(""),e.push("## Shared Types"),e.push("");for(let n of s.crossRepoAnalysis.sharedTypes)e.push(`- \`${n}\``);return e.push(""),e.join(`
18
18
  `)}createPageDataFlowDiagram(s,e,n){let r=[],i=[],t=[],o=[];for(let a of e){a.type==="container"&&o.push(a.name);for(let u of a.hooks){if(u.includes("Query")||u.includes("\u{1F4E1}")){let c=u.includes(":")?u.split(":")[1].trim():u;i.includes(c)||i.push(c);}if(u.includes("Mutation")||u.includes("\u270F\uFE0F")){let c=u.includes(":")?u.split(":")[1].trim():u;t.includes(c)||t.push(c);}}}for(let a of s.dataFetching){let u=a.operationName.replace(/^→\s*/,"");a.type.includes("Query")&&!i.includes(u)?i.push(u):a.type.includes("Mutation")&&!t.includes(u)&&t.push(u);}if(r.push(`[Page: ${s.path}]`),r.push("\u2502"),i.length>0||t.length>0){r.push("\u251C\u2500 \u{1F4E1} Data Fetching (Query)");for(let a of i.slice(0,5))r.push(`\u2502 \u251C\u2500 ${a.substring(0,40)}`),r.push("\u2502 \u2502 \u2514\u2500 GraphQL Server \u2192 Apollo Cache \u2192 Component");if(i.length>5&&r.push(`\u2502 \u2514\u2500 ... and ${i.length-5} more`),t.length>0){r.push("\u2502"),r.push("\u251C\u2500 \u270F\uFE0F Data Mutation (Mutation)");for(let a of t.slice(0,5))r.push(`\u2502 \u251C\u2500 ${a.substring(0,40)}`),r.push("\u2502 \u2502 \u2514\u2500 Component \u2192 GraphQL Server \u2192 Apollo Cache");t.length>5&&r.push(`\u2502 \u2514\u2500 ... and ${t.length-5} more`);}}if(o.length>0){r.push("\u2502"),r.push("\u251C\u2500 \u{1F4E6} Container Components");for(let a of o.slice(0,5))r.push(`\u2502 \u2514\u2500 ${a}`);o.length>5&&r.push(`\u2502 \u2514\u2500 ... and ${o.length-5} more`);}return r.push("\u2502"),r.push("\u2514\u2500 [Render]"),r.join(`
19
19
  `)}generateDiagramsDoc(s){let e=["# Diagrams",""];e.push("## Overview"),e.push(""),e.push("| Diagram | Type | Description |"),e.push("|---------|------|-------------|");for(let n of s)e.push(`| ${n.title} | \`${n.type.toUpperCase()}\` | Auto-generated |`);e.push("");for(let n of s)e.push(`## ${n.title}`),e.push(""),e.push(`\`TYPE: ${n.type.toUpperCase()}\``),e.push(""),e.push("```mermaid"),e.push(n.content),e.push("```"),e.push("");return e.join(`
20
- `)}};export{v as a,A as b};
20
+ `)}};export{b as a,A as b};