@wtdlee/repomap 0.9.1 → 0.10.0

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.
@@ -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};
@@ -1,12 +1,12 @@
1
- import {a as a$2}from'./chunk-NQMJ3QRX.js';import {a as a$3}from'./chunk-VV3A3UE3.js';import {B,A,z,y}from'./chunk-QDVE7MT3.js';import {a,b}from'./chunk-2XZSFAJF.js';import {a as a$1}from'./chunk-WZAAA7DS.js';import {k}from'./chunk-H7VVRHQZ.js';import {simpleGit}from'simple-git';import*as T from'fs/promises';import*as R from'path';import {parseSync}from'@swc/core';import me from'express';import {Server}from'socket.io';import*as fe from'http';import {marked}from'marked';import*as ce from'net';var U=class{config;mermaidGenerator;markdownGenerator;constructor(t){this.config=t,this.mermaidGenerator=new a,this.markdownGenerator=new b;}async generate(){let t=[];for(let w of this.config.repositories)try{let g=await this.analyzeRepository(w);t.push(g);}catch(g){console.error(`\u274C ${w.name}: ${g.message}`);}let r=this.analyzeCrossRepo(t),e=t.map(w=>w.analysis),n=this.extractCrossRepoLinks(e),s=this.mermaidGenerator.generateAll(e,n),i={generatedAt:new Date().toISOString(),repositories:t,crossRepoAnalysis:r,diagrams:s};return await this.writeDocumentation(i),i}async analyzeRepository(t){let{version:r,commitHash:e}=await this.getRepoInfo(t),n=t.analyzers.map(y=>this.createAnalyzer(y,t)).filter(y=>y!==null),s=Date.now(),i=await Promise.all(n.map(y=>y.analyze())),w=((Date.now()-s)/1e3).toFixed(1);console.log(` Analyzed ${t.displayName} in ${w}s`);let g=this.mergeAnalysisResults(i,t.name,r,e);await this.enrichPagesWithHookGraphQL(g,t.path);let k={totalPages:g.pages.length,totalComponents:g.components.length,totalGraphQLOperations:g.graphqlOperations.length,totalDataFlows:g.dataFlows.length,authRequiredPages:g.pages.filter(y=>y.authentication.required).length,publicPages:g.pages.filter(y=>!y.authentication.required).length};return {name:t.name,displayName:t.displayName,version:r,commitHash:e,analysis:g,summary:k}}async getRepoInfo(t){try{let n=(await simpleGit(t.path).log({n:1})).latest?.hash||"unknown",s="unknown";try{let i=R.join(t.path,"package.json");s=JSON.parse(await T.readFile(i,"utf-8")).version||"unknown";}catch{}return {version:s,commitHash:n}}catch{return {version:"unknown",commitHash:"unknown"}}}createAnalyzer(t,r){switch(t){case "pages":if(r.type==="nextjs"||r.type==="rails"||r.type==="generic")return new y(r);break;case "graphql":return new z(r);case "dataflow":case "components":return new A(r);case "rest-api":case "api":return new B(r)}return null}mergeAnalysisResults(t,r,e,n){let s={repository:r,timestamp:new Date().toISOString(),version:e,commitHash:n,pages:[],graphqlOperations:[],apiCalls:[],components:[],dataFlows:[],apiEndpoints:[],models:[],crossRepoLinks:[]};for(let i of t)i.pages&&s.pages.push(...i.pages),i.graphqlOperations&&s.graphqlOperations.push(...i.graphqlOperations),i.apiCalls&&s.apiCalls.push(...i.apiCalls),i.components&&s.components.push(...i.components),i.dataFlows&&s.dataFlows.push(...i.dataFlows),i.apiEndpoints&&s.apiEndpoints.push(...i.apiEndpoints),i.models&&s.models.push(...i.models),i.crossRepoLinks&&s.crossRepoLinks.push(...i.crossRepoLinks);return s}analyzeCrossRepo(t){let r=[],e=[],n=[],s=[],i=new Map;for(let k of t)for(let y of k.analysis.graphqlOperations){let $=i.get(y.name)||[];$.push(k.name),i.set(y.name,$);}for(let[k,y]of i)y.length>1&&r.push(k);let w=t.filter(k=>k.analysis.pages.length>0),g=t.filter(k=>k.analysis.apiEndpoints.length>0);for(let k of w)for(let y of g)for(let $ of y.analysis.apiEndpoints)e.push({frontend:k.name,backend:y.name,endpoint:$.path,operations:k.analysis.graphqlOperations.filter(A=>A.usedIn.length>0).map(A=>A.name)});return {sharedTypes:r,apiConnections:e,navigationFlows:n,dataFlowAcrossRepos:s}}extractCrossRepoLinks(t){let r=[],e=new Map;for(let n of t)for(let s of n.graphqlOperations){let i=e.get(s.name)||[];i.push(n),e.set(s.name,i);}for(let[n,s]of e)s.length>1&&r.push({sourceRepo:s[0].repository,sourcePath:`graphql/${n}`,targetRepo:s[1].repository,targetPath:`graphql/${n}`,linkType:"graphql-operation",description:`Shared GraphQL operation: ${n}`});return r}async enrichPagesWithHookGraphQL(t,r){let e=t.graphqlOperations.filter(a=>a.type==="query"||a.type==="mutation"||a.type==="subscription"),n=/\.(ts|tsx|js|jsx)$/,s=a=>R.normalize(a).replace(/\\/g,"/"),i=(this.config.analysis?.include||["**/*.ts","**/*.tsx"]).map(String),w=(this.config.analysis?.exclude||[]).map(String),g=(await import('fast-glob')).default,k=await g(i,{cwd:r,ignore:["**/node_modules/**","**/.next/**","**/dist/**","**/build/**","**/coverage/**",...w],onlyFiles:true,unique:true,dot:false}),y=new Set(k.map(s)),$=new Map;for(let a of y){let o=a.replace(n,"");$.has(o)||$.set(o,a);}let A=new Set(["src/"]);for(let a of y){let o=a.indexOf("/src/");o!==-1&&A.add(a.slice(0,o+5));}let N=a=>{let o=s(a).replace(n,""),c=$.get(o);if(c)return c;let l=$.get(o+"/index");return l||null},he=async()=>{let a=["tsconfig.json","jsconfig.json"];for(let o of a)try{let c=await T.readFile(R.join(r,o),"utf-8"),p=JSON.parse(c)?.compilerOptions||{},f=typeof p.baseUrl=="string"?p.baseUrl:void 0,q=typeof p.paths=="object"&&p.paths?p.paths:void 0;return {baseUrl:f,paths:q}}catch{}return {}},{baseUrl:O,paths:X}=await he(),ge=a=>{if(!X)return [];let o=[];for(let[c,l]of Object.entries(X)){if(!c.includes("*")){a===c&&o.push(...l);continue}let[p,f]=c.split("*");if(!a.startsWith(p)||!a.endsWith(f))continue;let q=a.slice(p.length,a.length-f.length);for(let d of l)d.includes("*")?o.push(d.replace("*",q)):o.push(d);}return o},B=(a,o)=>{if(!o)return null;if(o.startsWith(".")){let l=R.dirname(a);return N(R.join(l,o))}if(o.startsWith("@/")){let l=o.replace("@/","");if(O){let p=N(R.join(O,l));if(p)return p}for(let p of A){let f=N(p+l);if(f)return f}return null}let c=ge(o);if(c.length>0)for(let l of c){let p=N(O?R.join(O,l):l);if(p)return p}if(O){let l=N(R.join(O,o));if(l)return l}return null},j=new Map,W=new Map,Z=async a=>{let o=s(a),c=W.get(o);if(c!==void 0)return c;try{let l=R.join(r,o),p=await T.readFile(l,"utf-8");return W.set(o,p),p}catch{return W.set(o,""),null}},ye=async a=>{let o=s(a),c=j.get(o);if(c)return c.map(m=>({spec:m,names:null}));let l=await Z(o);if(!l)return j.set(o,[]),[];let p;try{let m=o.endsWith(".ts")||o.endsWith(".tsx"),h=o.endsWith(".tsx")||o.endsWith(".jsx");p=parseSync(l,{syntax:m?"typescript":"ecmascript",tsx:h,jsx:h,comments:!1});}catch{return j.set(o,[]),[]}let f=new Set,q=[],d=(m,h)=>{typeof m!="string"||m.length===0||(f.add(m),q.push({spec:m,names:h}));},b=m=>{if(!m||typeof m!="object")return;let h=m,v=h;if(v.type==="ImportDeclaration"){if(!v.typeOnly){let x=v.source?.value,u=[],E=v.specifiers||[];for(let S of E){let C=S,I=C.type;if(I==="ImportDefaultSpecifier"||I==="ImportNamespaceSpecifier"){u=null;break}if(I==="ImportSpecifier"){let G=C.imported?.value,P=C.local?.value,z=G||P;z&&u.push(z);}}Array.isArray(u)&&u.length===0&&(u=null),d(x,u);}}else if(v.type==="ExportAllDeclaration")d(v.source?.value,null);else if(v.type==="ExportNamedDeclaration"){let x=v.source?.value,u=v.specifiers||[],E=[];for(let S of u){let C=S;if(C.type==="ExportSpecifier"){let G=C.exported?.value,P=C.orig?.value,z=G||P;z&&E.push(z);}}d(x,E.length>0?E:null);}else if(v.type==="CallExpression"){let x=v.callee||null;if(x?.type==="Identifier"&&x.value==="require"){let u=v.arguments?.[0]?.expression;u?.type==="StringLiteral"&&d(u.value,null);}if(x?.type==="Import"){let u=v.arguments?.[0]?.expression;u?.type==="StringLiteral"&&d(u.value,null);}}for(let x of Object.keys(h)){let u=h[x];if(Array.isArray(u))for(let E of u)b(E);else u&&typeof u=="object"&&b(u);}};b(p);let D=Array.from(f);return j.set(o,D),q.filter(m=>typeof m.spec=="string"&&m.spec.length>0)},Q=new Map,_=async a=>{let o=s(a),c=Q.get(o);if(c)return c;let l=await Z(o);if(!l){let m={named:new Map,stars:[],isBarrel:false};return Q.set(o,m),m}let p;try{let m=o.endsWith(".ts")||o.endsWith(".tsx"),h=o.endsWith(".tsx")||o.endsWith(".jsx");p=parseSync(l,{syntax:m?"typescript":"ecmascript",tsx:h,jsx:h,comments:!1});}catch{let m={named:new Map,stars:[],isBarrel:false};return Q.set(o,m),m}let f=new Map,q=[],d=true,b=p?.body;if(Array.isArray(b))for(let m of b){let h=m,v=h.type;if(v&&v!=="ImportDeclaration"){if(v==="ExportAllDeclaration"){let x=h.source?.value;typeof x=="string"&&q.push(x);continue}if(v==="ExportNamedDeclaration"){let x=h.source?.value,u=h.specifiers||[];if(typeof x=="string"&&Array.isArray(u))for(let E of u){let S=E;if(S.type!=="ExportSpecifier")continue;let I=S.exported?.value,G=S.orig?.value,P=I||G;P&&f.set(P,x);}continue}d=false;}}else d=false;let D={named:f,stars:q,isBarrel:d};return Q.set(o,D),D},V=async(a,o,c)=>{let l=s(a);if(c.has(l))return null;c.add(l);let p=await _(l),f=p.named.get(o);if(f)return B(l,f);for(let q of p.stars){let d=B(l,q);if(!d)continue;let b=await V(d,o,c);if(b)return b}return null},Y=new Map;for(let a of e){let o=new Set;a.filePath&&o.add(a.filePath);for(let c of a.usedIn||[])o.add(c);for(let c of o){let l=Y.get(c)||[];l.push({opName:a.name,opType:a.type}),Y.set(c,l);}}let ve=a=>{if(!a)return null;let o=[`src/pages/${a}`,`pages/${a}`,`src/app/${a}`,`app/${a}`,`frontend/src/pages/${a}`,`frontend/src/app/${a}`,`app/javascript/pages/${a}`,`app/javascript/app/${a}`];for(let p of o){if(y.has(p))return p;let f=N(p);if(f)return f}let c=[],l=[`/pages/${a}`,`/app/${a}`,`/${a}`];for(let p of y)for(let f of l)if(p.endsWith(f)&&!(f.startsWith("/pages/")&&!p.includes("/pages/"))&&!(f.startsWith("/app/")&&!p.includes("/app/"))){c.push(p);break}return c.length===0?null:(c.sort((p,f)=>p.length-f.length),c[0])},J=new Map,H=new Map;for(let a of t.pages){let o=ve(a.filePath);if(!o)continue;let c=new Map,l=new Set,p=[{f:o,depth:0}],f=30,q=2e4;for(;p.length>0;){let d=p.shift();if(!d)break;if(l.has(d.f))continue;if(l.add(d.f),l.size>=q)break;let b=Y.get(d.f);if(b)for(let m of b){let h=c.get(m.opName);(!h||d.depth<h.distance)&&c.set(m.opName,{opName:m.opName,opType:m.opType,sourceFile:d.f,distance:d.depth});}if(d.depth>=f)continue;let D=await ye(d.f);for(let m of D){let h=B(d.f,m.spec);if(h){if(l.has(h)||p.push({f:h,depth:d.depth+1}),Array.isArray(m.names)&&m.names.length>0){if((await _(h)).isBarrel)for(let x of m.names){let u=await V(h,x,new Set);u&&!l.has(u)&&p.push({f:u,depth:d.depth+2});}}else if(m.names===null){let v=await _(h);if(v.isBarrel){for(let x of v.stars){let u=B(h,x);u&&!l.has(u)&&p.push({f:u,depth:d.depth+2});}for(let x of v.named.values()){let u=B(h,x);u&&!l.has(u)&&p.push({f:u,depth:d.depth+2});}}}}}}J.set(a.path,{page:a,entryFile:o,bestByOp:c});for(let d of l)H.set(d,(H.get(d)||0)+1);}let we=J.size,xe=Array.from(H.values()).sort((a,o)=>a-o),be=((a,o)=>{if(a.length===0)return 0;let c=Math.min(a.length-1,Math.max(0,Math.floor(a.length*o)));return a[c]})(xe,.9),ke=Math.max(10,be),qe=Math.max(2,Math.floor(we*.05));for(let{page:a,bestByOp:o}of J.values()){let c=new Set((a.dataFetching||[]).map(l=>l.operationName?.replace(/^[→\->\s]+/,"")||""));for(let{opName:l,opType:p,sourceFile:f,distance:q}of o.values()){if(c.has(l))continue;c.add(l);let d=H.get(f)||0,b;q===0?b=void 0:d>=ke?b=`common:${f}`:q<=2||d<=qe?b=`close:${f}`:b=`indirect:${f}`,a.dataFetching.push({type:p==="mutation"?"useMutation":p==="subscription"?"useSubscription":"useQuery",operationName:l,source:b});}}}async writeDocumentation(t){let r=this.config.outputDir;await T.mkdir(r,{recursive:true});let e=this.markdownGenerator.generateDocumentation(t);for(let[s,i]of e){let w=R.join(r,s),g=R.dirname(w);await T.mkdir(g,{recursive:true}),await T.writeFile(w,i,"utf-8");}let n=R.join(r,"report.json");await T.writeFile(n,JSON.stringify(t,null,2),"utf-8");}};function Me(L){return new Promise(t=>{let r=ce.createServer();r.once("error",e=>{e.code,t(false);}),r.once("listening",()=>{r.close(),t(true);}),r.listen(L);})}async function de(L,t=10){for(let r=0;r<t;r++){let e=L+r;if(await Me(e))return e}throw new Error(`No available port found between ${L} and ${L+t-1}`)}var ue=class{config;port;app;server;io;engine;currentReport=null;envResult=null;railsAnalysis=null;constructor(t,r=3030){this.config=t,this.port=r,this.app=me(),this.server=fe.createServer(this.app),this.io=new Server(this.server),this.engine=new U(t),this.setupRoutes(),this.setupSocketIO();}setupRoutes(){this.app.use("/assets",me.static(R.join(this.config.outputDir,"assets"))),["common.css","page-map.css","docs.css","rails-map.css"].forEach(e=>{this.app.get(`/${e}`,async(n,s)=>{let i=[R.join(R.dirname(new URL(import.meta.url).pathname),"generators","assets",e),R.join(R.dirname(new URL(import.meta.url).pathname),"..","generators","assets",e),R.join(process.cwd(),"dist","generators","assets",e),R.join(process.cwd(),"src","generators","assets",e)];for(let w of i)try{let g=await T.readFile(w,"utf-8");s.type("text/css").send(g);return}catch{}s.status(404).send("CSS not found");});}),["favicon.ico","favicon.svg","favicon-96x96.png","apple-touch-icon.png","site.webmanifest","web-app-manifest-192x192.png","web-app-manifest-512x512.png"].forEach(e=>{(e==="favicon.ico"?[`/${e}`,`/favicon/${e}`]:[`/favicon/${e}`]).forEach(s=>{this.app.get(s,async(i,w)=>{let g=[R.join(R.dirname(new URL(import.meta.url).pathname),"generators","assets","favicon",e),R.join(R.dirname(new URL(import.meta.url).pathname),"..","generators","assets","favicon",e),R.join(process.cwd(),"dist","generators","assets","favicon",e),R.join(process.cwd(),"src","generators","assets","favicon",e)];for(let k of g)try{let y=await T.readFile(k),$=e.split(".").pop(),A={ico:"image/x-icon",svg:"image/svg+xml",png:"image/png",webmanifest:"application/manifest+json"};w.type(A[$||""]||"application/octet-stream").send(y);return}catch{}w.status(404).send("File not found");});});}),this.app.get("/",(e,n)=>{n.redirect("/page-map");}),this.app.get("/page-map",(e,n)=>{if(!this.currentReport){n.status(503).send("Documentation not ready yet");return}let s=new a$1;n.send(s.generatePageMapHtml(this.currentReport,{envResult:this.envResult,railsAnalysis:this.railsAnalysis}));}),this.app.get("/rails-map",(e,n)=>{if(!this.railsAnalysis){n.status(404).send("No Rails environment detected");return}let s=new a$2;n.send(s.generateFromResult(this.railsAnalysis));}),this.app.get("/docs",async(e,n)=>{n.send(await this.renderPage("index"));}),this.app.get("/docs/*path",async(e,n)=>{let s=e.params.path,i=Array.isArray(s)?s.join("/"):s||"index";n.send(await this.renderPage(i));}),this.app.get("/api/report",(e,n)=>{n.json(this.currentReport);}),this.app.get("/api/env",(e,n)=>{n.json(this.envResult);}),this.app.get("/api/rails",(e,n)=>{this.railsAnalysis?n.json(this.railsAnalysis):n.status(404).json({error:"No Rails analysis available"});}),this.app.get("/api/diagram/:name",(e,n)=>{let s=this.currentReport?.diagrams.find(i=>i.title.toLowerCase().replace(/\s+/g,"-")===e.params.name);s?n.json(s):n.status(404).json({error:"Diagram not found"});}),this.app.post("/api/regenerate",async(e,n)=>{try{await this.regenerate(),n.json({success:!0});}catch(s){n.status(500).json({error:s.message});}});}setupSocketIO(){this.io.on("connection",t=>{t.on("disconnect",()=>{});});}async renderPage(t){let r=t.replace(/\.md$/,""),e=R.join(this.config.outputDir,`${r}.md`),n="";try{let s=await T.readFile(e,"utf-8"),i=await marked.parse(s);i=i.replace(/<pre><code class="language-mermaid">([\s\S]*?)<\/code><\/pre>/g,'<div class="mermaid">$1</div>'),i=i.replace(/<table>/g,'<div class="table-wrapper"><table>'),i=i.replace(/<\/table>/g,"</table></div>"),n=i;}catch(s){let i=s;if(i.code==="ENOENT"){let w=this.currentReport?.repositories.map(g=>g.name)||[];n=`
1
+ import {a as a$2}from'./chunk-LHP2OKKA.js';import {a as a$3}from'./chunk-VV3A3UE3.js';import {C,B,A,z,b as b$1}from'./chunk-IGRCLYVZ.js';import {a,b}from'./chunk-QBSB6BIU.js';import {a as a$1}from'./chunk-ATRSGO6O.js';import {k}from'./chunk-H7VVRHQZ.js';import {simpleGit}from'simple-git';import*as L from'fs/promises';import*as M from'path';import {parseSync}from'@swc/core';import fe from'express';import {Server}from'socket.io';import*as ge from'http';import {marked}from'marked';import*as me from'net';var W=class{config;mermaidGenerator;markdownGenerator;constructor(s){this.config=s,this.mermaidGenerator=new a,this.markdownGenerator=new b;}async generate(){let s=[];for(let k of this.config.repositories)try{let x=await this.analyzeRepository(k);s.push(x);}catch(x){console.error(`\u274C ${k.name}: ${x.message}`);}let r=this.analyzeCrossRepo(s),e=s.map(k=>k.analysis),a=this.extractCrossRepoLinks(e),o=this.mermaidGenerator.generateAll(e,a),i={generatedAt:new Date().toISOString(),repositories:s,crossRepoAnalysis:r,diagrams:o};return await this.writeDocumentation(i),i}async analyzeRepository(s){let{version:r,commitHash:e}=await this.getRepoInfo(s),a=s.analyzers.map(b=>this.createAnalyzer(b,s)).filter(b=>b!==null),o=Date.now(),i=await Promise.all(a.map(b=>b.analyze())),k=((Date.now()-o)/1e3).toFixed(1);console.log(` Analyzed ${s.displayName} in ${k}s`);let x=this.mergeAnalysisResults(i,s.name,r,e);await this.enrichPagesWithHookGraphQL(x,s.path);let $={totalPages:x.pages.length,totalComponents:x.components.length,totalGraphQLOperations:x.graphqlOperations.length,totalDataFlows:x.dataFlows.length,authRequiredPages:x.pages.filter(b=>b.authentication.required).length,publicPages:x.pages.filter(b=>!b.authentication.required).length};return {name:s.name,displayName:s.displayName,version:r,commitHash:e,analysis:x,summary:$}}async getRepoInfo(s){try{let a=(await simpleGit(s.path).log({n:1})).latest?.hash||"unknown",o="unknown";try{let i=M.join(s.path,"package.json");o=JSON.parse(await L.readFile(i,"utf-8")).version||"unknown";}catch{}return {version:o,commitHash:a}}catch{return {version:"unknown",commitHash:"unknown"}}}createAnalyzer(s,r){switch(s){case "pages":if(r.type==="nextjs"||r.type==="rails"||r.type==="generic")return new z(r);break;case "graphql":return new A(r);case "dataflow":case "components":return new B(r);case "rest-api":case "api":return new C(r)}return null}mergeAnalysisResults(s,r,e,a){let o={repository:r,timestamp:new Date().toISOString(),version:e,commitHash:a,coverage:{tsFilesScanned:0,tsParseFailures:0,graphqlParseFailures:0,codegenFilesDetected:0,codegenFilesParsed:0,codegenExportsFound:0},pages:[],graphqlOperations:[],apiCalls:[],components:[],dataFlows:[],apiEndpoints:[],models:[],crossRepoLinks:[]};for(let i of s)i.coverage&&o.coverage&&(o.coverage.tsFilesScanned+=i.coverage.tsFilesScanned||0,o.coverage.tsParseFailures+=i.coverage.tsParseFailures||0,o.coverage.graphqlParseFailures+=i.coverage.graphqlParseFailures||0,o.coverage.codegenFilesDetected+=i.coverage.codegenFilesDetected||0,o.coverage.codegenFilesParsed+=i.coverage.codegenFilesParsed||0,o.coverage.codegenExportsFound+=i.coverage.codegenExportsFound||0),i.pages&&o.pages.push(...i.pages),i.graphqlOperations&&o.graphqlOperations.push(...i.graphqlOperations),i.apiCalls&&o.apiCalls.push(...i.apiCalls),i.components&&o.components.push(...i.components),i.dataFlows&&o.dataFlows.push(...i.dataFlows),i.apiEndpoints&&o.apiEndpoints.push(...i.apiEndpoints),i.models&&o.models.push(...i.models),i.crossRepoLinks&&o.crossRepoLinks.push(...i.crossRepoLinks);return o}analyzeCrossRepo(s){let r=[],e=[],a=[],o=[],i=new Map;for(let $ of s)for(let b of $.analysis.graphqlOperations){let E=i.get(b.name)||[];E.push($.name),i.set(b.name,E);}for(let[$,b]of i)b.length>1&&r.push($);let k=s.filter($=>$.analysis.pages.length>0),x=s.filter($=>$.analysis.apiEndpoints.length>0);for(let $ of k)for(let b of x)for(let E of b.analysis.apiEndpoints)e.push({frontend:$.name,backend:b.name,endpoint:E.path,operations:$.analysis.graphqlOperations.filter(N=>N.usedIn.length>0).map(N=>N.name)});return {sharedTypes:r,apiConnections:e,navigationFlows:a,dataFlowAcrossRepos:o}}extractCrossRepoLinks(s){let r=[],e=new Map;for(let a of s)for(let o of a.graphqlOperations){let i=e.get(o.name)||[];i.push(a),e.set(o.name,i);}for(let[a,o]of e)o.length>1&&r.push({sourceRepo:o[0].repository,sourcePath:`graphql/${a}`,targetRepo:o[1].repository,targetPath:`graphql/${a}`,linkType:"graphql-operation",description:`Shared GraphQL operation: ${a}`});return r}async enrichPagesWithHookGraphQL(s,r){let e=s.graphqlOperations.filter(n=>n.type==="query"||n.type==="mutation"||n.type==="subscription"),a=/\.(ts|tsx|js|jsx)$/,o=n=>M.normalize(n).replace(/\\/g,"/"),i=(this.config.analysis?.include||["**/*.ts","**/*.tsx"]).map(String),k=(this.config.analysis?.exclude||[]).map(String),x=(await import('fast-glob')).default,$=await x(i,{cwd:r,ignore:["**/node_modules/**","**/.next/**","**/dist/**","**/build/**","**/coverage/**",...k],onlyFiles:true,unique:true,dot:false}),b=new Set($.map(o)),E=new Map;for(let n of b){let t=n.replace(a,"");E.has(t)||E.set(t,n);}let N=new b$1(r,b),Z=new Set(["src/"]);for(let n of b){let t=n.indexOf("/src/");t!==-1&&Z.add(n.slice(0,t+5));}let O=n=>{let t=o(n).replace(a,""),p=E.get(t);if(p)return p;let c=E.get(t+"/index");return c||null},ye=async()=>{let n=["tsconfig.json","jsconfig.json"];for(let t of n)try{let p=await L.readFile(M.join(r,t),"utf-8"),l=JSON.parse(p)?.compilerOptions||{},d=typeof l.baseUrl=="string"?l.baseUrl:void 0,R=typeof l.paths=="object"&&l.paths?l.paths:void 0;return {baseUrl:d,paths:R}}catch{}return {}},{baseUrl:F,paths:V}=await ye(),ve=n=>{if(!V)return [];let t=[];for(let[p,c]of Object.entries(V)){if(!p.includes("*")){n===p&&t.push(...c);continue}let[l,d]=p.split("*");if(!n.startsWith(l)||!n.endsWith(d))continue;let R=n.slice(l.length,n.length-d.length);for(let w of c)w.includes("*")?t.push(w.replace("*",R)):t.push(w);}return t},B=(n,t)=>{if(!t)return null;let p=N.resolve(n,t);if(p)return p.file;if(t.startsWith(".")){let l=M.dirname(n);return O(M.join(l,t))}if(t.startsWith("@/")){let l=t.replace("@/","");if(F){let d=O(M.join(F,l));if(d)return d}for(let d of Z){let R=O(d+l);if(R)return R}return null}let c=ve(t);if(c.length>0)for(let l of c){let d=O(F?M.join(F,l):l);if(d)return d}if(F){let l=O(M.join(F,t));if(l)return l}return null},j=new Map,Y=new Map,Q=async n=>{let t=o(n),p=Y.get(t);if(p!==void 0)return p;try{let c=M.join(r,t),l=await L.readFile(c,"utf-8");return Y.set(t,l),l}catch{return Y.set(t,""),null}},we=async n=>{let t=o(n),p=j.get(t);if(p)return p.map(h=>({spec:h,names:null}));let c=await Q(t);if(!c)return j.set(t,[]),[];let l;try{let h=t.endsWith(".ts")||t.endsWith(".tsx"),g=t.endsWith(".tsx")||t.endsWith(".jsx");l=parseSync(c,{syntax:h?"typescript":"ecmascript",tsx:g,jsx:g,comments:!1});}catch{return j.set(t,[]),[]}let d=new Set,R=[],w=(h,g,m)=>{typeof h!="string"||h.length===0||(d.add(h),R.push({spec:h,names:g,pos:m}));},f=h=>{if(!h||typeof h!="object")return;let g=h,m=g;if(m.type==="ImportDeclaration"){if(!m.typeOnly){let v=m.source?.value,u=[],y=m.specifiers||[];for(let C of y){let q=C,D=q.type;if(D==="ImportDefaultSpecifier"||D==="ImportNamespaceSpecifier"){u=null;break}if(D==="ImportSpecifier"){let G=q.imported?.value,P=q.local?.value,z=G||P;z&&u.push(z);}}Array.isArray(u)&&u.length===0&&(u=null),w(v,u,m.span?.start);}}else if(m.type==="ExportAllDeclaration")w(m.source?.value,null,m.span?.start);else if(m.type==="ExportNamedDeclaration"){let v=m.source?.value,u=m.specifiers||[],y=[];for(let C of u){let q=C;if(q.type==="ExportSpecifier"){let G=q.exported?.value,P=q.orig?.value,z=G||P;z&&y.push(z);}}w(v,y.length>0?y:null,m.span?.start);}else if(m.type==="CallExpression"){let v=m.callee||null;if(v?.type==="Identifier"&&v.value==="require"){let u=m.arguments?.[0]?.expression;u?.type==="StringLiteral"&&w(u.value,null,m.span?.start);}if(v?.type==="Import"){let u=m.arguments?.[0]?.expression;u?.type==="StringLiteral"&&w(u.value,null,m.span?.start);}}for(let v of Object.keys(g)){let u=g[v];if(Array.isArray(u))for(let y of u)f(y);else u&&typeof u=="object"&&f(u);}};f(l);let A=Array.from(d);return j.set(t,A),R.filter(h=>typeof h.spec=="string"&&h.spec.length>0)},xe=(n,t)=>{if(t===void 0||t<0)return;let p=1;for(let c=0;c<n.length&&c<t;c++)n.charCodeAt(c)===10&&p++;return p},be=(n,t)=>{if(t<0)return;let p=1;for(let c=0;c<n.length&&c<t;c++)n.charCodeAt(c)===10&&p++;return p},H=new Map,_=async n=>{let t=o(n),p=H.get(t);if(p)return p;let c=await Q(t);if(!c){let h={named:new Map,stars:[],isBarrel:false};return H.set(t,h),h}let l;try{let h=t.endsWith(".ts")||t.endsWith(".tsx"),g=t.endsWith(".tsx")||t.endsWith(".jsx");l=parseSync(c,{syntax:h?"typescript":"ecmascript",tsx:g,jsx:g,comments:!1});}catch{let h={named:new Map,stars:[],isBarrel:false};return H.set(t,h),h}let d=new Map,R=[],w=true,f=l?.body;if(Array.isArray(f))for(let h of f){let g=h,m=g.type;if(m&&m!=="ImportDeclaration"){if(m==="ExportAllDeclaration"){let v=g.source?.value;typeof v=="string"&&R.push(v);continue}if(m==="ExportNamedDeclaration"){let v=g.source?.value,u=g.specifiers||[];if(typeof v=="string"&&Array.isArray(u))for(let y of u){let C=y;if(C.type!=="ExportSpecifier")continue;let D=C.exported?.value,G=C.orig?.value,P=D||G;P&&d.set(P,v);}continue}w=false;}}else w=false;let A={named:d,stars:R,isBarrel:w};return H.set(t,A),A},ee=async(n,t,p)=>{let c=o(n);if(p.has(c))return null;p.add(c);let l=await _(c),d=l.named.get(t);if(d)return B(c,d);for(let R of l.stars){let w=B(c,R);if(!w)continue;let f=await ee(w,t,p);if(f)return f}return null},K=new Map;for(let n of e){let t=new Set;n.filePath&&t.add(n.filePath);for(let p of n.usedIn||[])t.add(p);for(let p of t){let c=K.get(p)||[];c.push({opName:n.name,opType:n.type}),K.set(p,c);}}let ke=n=>{if(!n)return null;let t=[`src/pages/${n}`,`pages/${n}`,`src/app/${n}`,`app/${n}`,`frontend/src/pages/${n}`,`frontend/src/app/${n}`,`app/javascript/pages/${n}`,`app/javascript/app/${n}`];for(let l of t){if(b.has(l))return l;let d=O(l);if(d)return d}let p=[],c=[`/pages/${n}`,`/app/${n}`,`/${n}`];for(let l of b)for(let d of c)if(l.endsWith(d)&&!(d.startsWith("/pages/")&&!l.includes("/pages/"))&&!(d.startsWith("/app/")&&!l.includes("/app/"))){p.push(l);break}return p.length===0?null:(p.sort((l,d)=>l.length-d.length),p[0])},J=new Map,U=new Map;for(let n of s.pages){let t=ke(n.filePath);if(!t)continue;let p=new Map,c=new Set,l=[{f:t,depth:0}],d=new Map,R=30,w=2e4;for(;l.length>0;){let f=l.shift();if(!f)break;if(c.has(f.f))continue;if(c.add(f.f),c.size>=w)break;let A=K.get(f.f);if(A)for(let g of A){let m=p.get(g.opName);(!m||f.depth<m.distance)&&p.set(g.opName,{opName:g.opName,opType:g.opType,sourceFile:f.f,distance:f.depth});}if(f.depth>=R)continue;let h=await we(f.f);for(let g of h){let m=B(f.f,g.spec);if(m){if(!c.has(m)&&(l.push({f:m,depth:f.depth+1}),!d.has(m))){let v=await Q(f.f),u=v?xe(v,g.pos):void 0,y=Array.isArray(g.names)&&g.names.length>0?`names:${g.names.join(",")}`:void 0;d.set(m,{from:f.f,spec:g.spec,line:u,detail:y});}if(Array.isArray(g.names)&&g.names.length>0){if((await _(m)).isBarrel)for(let u of g.names){let y=await ee(m,u,new Set);y&&!c.has(y)&&(l.push({f:y,depth:f.depth+2}),d.has(y)||d.set(y,{from:m,spec:`re-export:${u}`,line:void 0,detail:"barrel"}));}}else if(g.names===null){let v=await _(m);if(v.isBarrel){for(let u of v.stars){let y=B(m,u);y&&!c.has(y)&&l.push({f:y,depth:f.depth+2});}for(let u of v.named.values()){let y=B(m,u);y&&!c.has(y)&&l.push({f:y,depth:f.depth+2});}}}}}}J.set(n.path,{page:n,entryFile:t,parent:d,bestByOp:p});for(let f of c)U.set(f,(U.get(f)||0)+1);}let qe=J.size,Re=Array.from(U.values()).sort((n,t)=>n-t),$e=((n,t)=>{if(n.length===0)return 0;let p=Math.min(n.length-1,Math.max(0,Math.floor(n.length*t)));return n[p]})(Re,.9),Me=Math.max(10,$e),Te=Math.max(2,Math.floor(qe*.05));for(let{page:n,entryFile:t,parent:p,bestByOp:c}of J.values()){let l=new Set((n.dataFetching||[]).map(d=>d.operationName?.replace(/^[→\->\s]+/,"")||""));for(let{opName:d,opType:R,sourceFile:w,distance:f}of c.values()){if(l.has(d))continue;l.add(d);let A=U.get(w)||0,h;f===0?h=void 0:A>=Me?h=`common:${w}`:f<=2||A<=Te?h=`close:${w}`:h=`indirect:${w}`;let g=f===0||f<=2?"certain":h?.startsWith("common:")?"unknown":"likely",m=[];if(f>0&&w!==t){let u=[],y=w,C=new Set;for(;y!==t&&!C.has(y);){C.add(y);let q=p.get(y);if(!q)break;u.push({from:q.from,to:y,spec:q.spec,line:q.line,detail:q.detail}),y=q.from;}u.reverse();for(let q of u)m.push({kind:"import-edge",file:q.from,line:q.line,detail:`${q.spec} -> ${q.to}${q.detail?` (${q.detail})`:""}`});}let v=await Q(w);if(v){let u=v.indexOf(`${d}Document`)>=0?v.indexOf(`${d}Document`):v.indexOf(d),y=u>=0?be(v,u):void 0;m.push({kind:"operation-reference",file:w,line:y,detail:`ref:${d}`});}else m.push({kind:"operation-reference",file:w,detail:`ref:${d}`});n.dataFetching.push({type:R==="mutation"?"useMutation":R==="subscription"?"useSubscription":"useQuery",operationName:d,source:h,confidence:g,evidence:m.length>0?m:void 0});}}}async writeDocumentation(s){let r=this.config.outputDir;await L.mkdir(r,{recursive:true});let e=this.markdownGenerator.generateDocumentation(s);for(let[o,i]of e){let k=M.join(r,o),x=M.dirname(k);await L.mkdir(x,{recursive:true}),await L.writeFile(k,i,"utf-8");}let a=M.join(r,"report.json");await L.writeFile(a,JSON.stringify(s,null,2),"utf-8");}};function Ae(S){return new Promise(s=>{let r=me.createServer();r.once("error",e=>{e.code,s(false);}),r.once("listening",()=>{r.close(),s(true);}),r.listen(S);})}async function ue(S,s=10){for(let r=0;r<s;r++){let e=S+r;if(await Ae(e))return e}throw new Error(`No available port found between ${S} and ${S+s-1}`)}var he=class{config;port;app;server;io;engine;currentReport=null;envResult=null;railsAnalysis=null;constructor(s,r=3030){this.config=s,this.port=r,this.app=fe(),this.server=ge.createServer(this.app),this.io=new Server(this.server),this.engine=new W(s),this.setupRoutes(),this.setupSocketIO();}setupRoutes(){this.app.use("/assets",fe.static(M.join(this.config.outputDir,"assets"))),["common.css","page-map.css","docs.css","rails-map.css"].forEach(e=>{this.app.get(`/${e}`,async(a,o)=>{let i=[M.join(M.dirname(new URL(import.meta.url).pathname),"generators","assets",e),M.join(M.dirname(new URL(import.meta.url).pathname),"..","generators","assets",e),M.join(process.cwd(),"dist","generators","assets",e),M.join(process.cwd(),"src","generators","assets",e)];for(let k of i)try{let x=await L.readFile(k,"utf-8");o.type("text/css").send(x);return}catch{}o.status(404).send("CSS not found");});}),["favicon.ico","favicon.svg","favicon-96x96.png","apple-touch-icon.png","site.webmanifest","web-app-manifest-192x192.png","web-app-manifest-512x512.png"].forEach(e=>{(e==="favicon.ico"?[`/${e}`,`/favicon/${e}`]:[`/favicon/${e}`]).forEach(o=>{this.app.get(o,async(i,k)=>{let x=[M.join(M.dirname(new URL(import.meta.url).pathname),"generators","assets","favicon",e),M.join(M.dirname(new URL(import.meta.url).pathname),"..","generators","assets","favicon",e),M.join(process.cwd(),"dist","generators","assets","favicon",e),M.join(process.cwd(),"src","generators","assets","favicon",e)];for(let $ of x)try{let b=await L.readFile($),E=e.split(".").pop(),N={ico:"image/x-icon",svg:"image/svg+xml",png:"image/png",webmanifest:"application/manifest+json"};k.type(N[E||""]||"application/octet-stream").send(b);return}catch{}k.status(404).send("File not found");});});}),this.app.get("/",(e,a)=>{a.redirect("/page-map");}),this.app.get("/page-map",(e,a)=>{if(!this.currentReport){a.status(503).send("Documentation not ready yet");return}let o=new a$1;a.send(o.generatePageMapHtml(this.currentReport,{envResult:this.envResult,railsAnalysis:this.railsAnalysis}));}),this.app.get("/rails-map",(e,a)=>{if(!this.railsAnalysis){a.status(404).send("No Rails environment detected");return}let o=new a$2;a.send(o.generateFromResult(this.railsAnalysis));}),this.app.get("/docs",async(e,a)=>{a.send(await this.renderPage("index"));}),this.app.get("/docs/*path",async(e,a)=>{let o=e.params.path,i=Array.isArray(o)?o.join("/"):o||"index";a.send(await this.renderPage(i));}),this.app.get("/api/report",(e,a)=>{a.json(this.currentReport);}),this.app.get("/api/env",(e,a)=>{a.json(this.envResult);}),this.app.get("/api/rails",(e,a)=>{this.railsAnalysis?a.json(this.railsAnalysis):a.status(404).json({error:"No Rails analysis available"});}),this.app.get("/api/diagram/:name",(e,a)=>{let o=this.currentReport?.diagrams.find(i=>i.title.toLowerCase().replace(/\s+/g,"-")===e.params.name);o?a.json(o):a.status(404).json({error:"Diagram not found"});}),this.app.post("/api/regenerate",async(e,a)=>{try{await this.regenerate(),a.json({success:!0});}catch(o){a.status(500).json({error:o.message});}});}setupSocketIO(){this.io.on("connection",s=>{s.on("disconnect",()=>{});});}async renderPage(s){let r=s.replace(/\.md$/,""),e=M.join(this.config.outputDir,`${r}.md`),a="";try{let o=await L.readFile(e,"utf-8"),i=await marked.parse(o);i=i.replace(/<pre><code class="language-mermaid">([\s\S]*?)<\/code><\/pre>/g,'<div class="mermaid">$1</div>'),i=i.replace(/<table>/g,'<div class="table-wrapper"><table>'),i=i.replace(/<\/table>/g,"</table></div>"),a=i;}catch(o){let i=o;if(i.code==="ENOENT"){let k=this.currentReport?.repositories.map(x=>x.name)||[];a=`
2
2
  <h1>Page not found</h1>
3
3
  <p>The requested path <code>${r}</code> does not exist.</p>
4
- ${w.length>0?`
4
+ ${k.length>0?`
5
5
  <p>Available repositories:</p>
6
- <ul>${w.map(g=>`<li><a href="/docs/repos/${g}">${g}</a></li>`).join("")}</ul>
6
+ <ul>${k.map(x=>`<li><a href="/docs/repos/${x}">${x}</a></li>`).join("")}</ul>
7
7
  `:""}
8
8
  <p><a href="/">\u2190 Back to home</a></p>
9
- `;}else console.error(`\u26A0\uFE0F Error reading ${e}: ${i.message}`),n=`<h1>Error</h1><p>Failed to load page: ${i.message}</p>`;}return this.getHtmlTemplate(n)}getGraphQLData(){if(!this.currentReport)return "[]";let t=[];for(let r of this.currentReport.repositories)for(let e of r.analysis?.graphqlOperations||[])t.push({name:e.name,type:e.type,returnType:e.returnType,variables:e.variables,fields:e.fields,usedIn:e.usedIn});return JSON.stringify(t)}getApiCallsData(){if(!this.currentReport)return "[]";let t=[];for(let r of this.currentReport.repositories)for(let e of r.analysis?.apiCalls||[])t.push({id:e.id,method:e.method,url:e.url,callType:e.callType,filePath:e.filePath,line:e.line,containingFunction:e.containingFunction,requiresAuth:e.requiresAuth});return JSON.stringify(t)}getHtmlTemplate(t){let r=this.getGraphQLData(),e=this.getApiCallsData();return `<!DOCTYPE html>
9
+ `;}else console.error(`\u26A0\uFE0F Error reading ${e}: ${i.message}`),a=`<h1>Error</h1><p>Failed to load page: ${i.message}</p>`;}return this.getHtmlTemplate(a)}getGraphQLData(){if(!this.currentReport)return "[]";let s=[];for(let r of this.currentReport.repositories)for(let e of r.analysis?.graphqlOperations||[])s.push({name:e.name,type:e.type,returnType:e.returnType,variables:e.variables,fields:e.fields,usedIn:e.usedIn});return JSON.stringify(s)}getApiCallsData(){if(!this.currentReport)return "[]";let s=[];for(let r of this.currentReport.repositories)for(let e of r.analysis?.apiCalls||[])s.push({id:e.id,method:e.method,url:e.url,callType:e.callType,filePath:e.filePath,line:e.line,containingFunction:e.containingFunction,requiresAuth:e.requiresAuth});return JSON.stringify(s)}getHtmlTemplate(s){let r=this.getGraphQLData(),e=this.getApiCallsData();return `<!DOCTYPE html>
10
10
  <html lang="en">
11
11
  <head>
12
12
  <meta charset="UTF-8">
@@ -104,11 +104,11 @@ import {a as a$2}from'./chunk-NQMJ3QRX.js';import {a as a$3}from'./chunk-VV3A3UE
104
104
  <div class="nav-group">
105
105
  <span class="nav-group-title">Documentation</span>
106
106
  <div class="nav-subitems">
107
- ${this.config.repositories.map(n=>`
108
- <a href="/docs/repos/${n.name}/pages">Pages</a>
109
- <a href="/docs/repos/${n.name}/components">Components</a>
110
- <a href="/docs/repos/${n.name}/graphql">GraphQL</a>
111
- <a href="/docs/repos/${n.name}/dataflow">Data Flow</a>
107
+ ${this.config.repositories.map(a=>`
108
+ <a href="/docs/repos/${a.name}/pages">Pages</a>
109
+ <a href="/docs/repos/${a.name}/components">Components</a>
110
+ <a href="/docs/repos/${a.name}/graphql">GraphQL</a>
111
+ <a href="/docs/repos/${a.name}/dataflow">Data Flow</a>
112
112
  `).join("")}
113
113
  </div>
114
114
  </div>
@@ -124,7 +124,7 @@ import {a as a$2}from'./chunk-NQMJ3QRX.js';import {a as a$3}from'./chunk-VV3A3UE
124
124
  </aside>
125
125
  <div class="content-area">
126
126
  <div class="content">
127
- ${t}
127
+ ${s}
128
128
  </div>
129
129
  </div>
130
130
  </div>
@@ -469,7 +469,9 @@ import {a as a$2}from'./chunk-NQMJ3QRX.js';import {a as a$3}from'./chunk-VV3A3UE
469
469
 
470
470
  if (op.usedIn?.length) {
471
471
  html += '<div class="detail-section"><h4>Used In</h4><div style="max-height:100px;overflow-y:auto">';
472
- op.usedIn.forEach(f => { html += \`<p style="font-size:12px;color:#666;margin:2px 0">\${f}</p>\`; });
472
+ op.usedIn.forEach(f => {
473
+ html += \`<p><code>\${escapeHtml(f)}</code></p>\`;
474
+ });
473
475
  html += '</div></div>';
474
476
  }
475
477
  } else {
@@ -508,7 +510,9 @@ import {a as a$2}from'./chunk-NQMJ3QRX.js';import {a as a$3}from'./chunk-VV3A3UE
508
510
 
509
511
  if (partialMatch.usedIn?.length) {
510
512
  html += '<div class="detail-section"><h4>Used In</h4><div style="max-height:100px;overflow-y:auto">';
511
- partialMatch.usedIn.forEach(f => { html += \`<p style="font-size:12px;color:#666;margin:2px 0">\${f}</p>\`; });
513
+ partialMatch.usedIn.forEach(f => {
514
+ html += \`<p><code>\${escapeHtml(f)}</code></p>\`;
515
+ });
512
516
  html += '</div></div>';
513
517
  }
514
518
  } else {
@@ -590,6 +594,15 @@ import {a as a$2}from'./chunk-NQMJ3QRX.js';import {a as a$3}from'./chunk-VV3A3UE
590
594
  return badges[type] || badges.unknown;
591
595
  }
592
596
 
597
+ function escapeHtml(str) {
598
+ return String(str ?? '')
599
+ .replace(/&/g, '&amp;')
600
+ .replace(/</g, '&lt;')
601
+ .replace(/>/g, '&gt;')
602
+ .replace(/"/g, '&quot;')
603
+ .replace(/'/g, '&#39;');
604
+ }
605
+
593
606
  function closeModal() {
594
607
  document.getElementById('detailModal').classList.remove('open');
595
608
  modalHistory = [];
@@ -634,7 +647,8 @@ import {a as a$2}from'./chunk-NQMJ3QRX.js';import {a as a$3}from'./chunk-VV3A3UE
634
647
  el.addEventListener('click', (e) => {
635
648
  e.stopPropagation();
636
649
  const opName = el.dataset.op || el.textContent?.replace(/^[QM]:\\s*/, '') || '';
637
- if (opName) showGraphQLDetail(opName, el);
650
+ const confidence = el.dataset.confidence || '';
651
+ if (opName) showGraphQLDetail(opName, el, confidence);
638
652
  });
639
653
  });
640
654
 
@@ -668,7 +682,7 @@ import {a as a$2}from'./chunk-NQMJ3QRX.js';import {a as a$3}from'./chunk-VV3A3UE
668
682
  });
669
683
  });
670
684
 
671
- function showGraphQLDetail(name, el) {
685
+ function showGraphQLDetail(name, el, confidence) {
672
686
  const modal = document.getElementById('detailModal');
673
687
  const title = document.getElementById('modalTitle');
674
688
  const body = document.getElementById('modalBody');
@@ -685,9 +699,16 @@ import {a as a$2}from'./chunk-NQMJ3QRX.js';import {a as a$3}from'./chunk-VV3A3UE
685
699
 
686
700
  if (op) {
687
701
  titleText = op.name;
702
+ const confBadge =
703
+ confidence === 'likely'
704
+ ? '<span class="detail-badge confidence likely" title="Likely: reachable via the import graph, but indirect (3+ steps)">LIKELY</span>'
705
+ : '';
688
706
  html = \`<div class="detail-section">
689
707
  <h4>Type</h4>
690
- <p><span class="detail-badge \${op.type}">\${op.type.toUpperCase()}</span></p>
708
+ <div class="detail-badges">
709
+ <span class="detail-badge \${op.type}">\${op.type.toUpperCase()}</span>
710
+ \${confBadge}
711
+ </div>
691
712
  </div>\`;
692
713
 
693
714
  if (op.returnType) {
@@ -716,8 +737,10 @@ import {a as a$2}from'./chunk-NQMJ3QRX.js';import {a as a$3}from'./chunk-VV3A3UE
716
737
  }
717
738
 
718
739
  if (op.usedIn?.length) {
719
- html += '<div class="detail-section"><h4>Used In</h4><div style="font-size:12px;color:#666;max-height:100px;overflow-y:auto">';
720
- op.usedIn.forEach(f => { html += \`<div style="margin:2px 0">\${f}</div>\`; });
740
+ html += '<div class="detail-section"><h4>Used In</h4><div style="max-height:100px;overflow-y:auto">';
741
+ op.usedIn.forEach(f => {
742
+ html += \`<p><code>\${escapeHtml(f)}</code></p>\`;
743
+ });
721
744
  html += '</div></div>';
722
745
  }
723
746
  } else {
@@ -730,7 +753,9 @@ import {a as a$2}from'./chunk-NQMJ3QRX.js';import {a as a$3}from'./chunk-VV3A3UE
730
753
  html = \`
731
754
  <div class="detail-section">
732
755
  <h4>Type</h4>
733
- <p><span class="detail-badge \${type}">\${type.toUpperCase()}</span></p>
756
+ <div class="detail-badges">
757
+ <span class="detail-badge \${type}">\${type.toUpperCase()}</span>
758
+ </div>
734
759
  </div>
735
760
  <div class="detail-section">
736
761
  <h4>Operation Name</h4>
@@ -856,8 +881,10 @@ import {a as a$2}from'./chunk-NQMJ3QRX.js';import {a as a$3}from'./chunk-VV3A3UE
856
881
  }
857
882
 
858
883
  if (op.usedIn?.length) {
859
- html += '<div class="detail-section"><h4>Used In</h4><div style="font-size:12px;color:#666;max-height:100px;overflow-y:auto">';
860
- op.usedIn.forEach(f => { html += \`<div style="margin:2px 0">\${f}</div>\`; });
884
+ html += '<div class="detail-section"><h4>Used In</h4><div style="max-height:100px;overflow-y:auto">';
885
+ op.usedIn.forEach(f => {
886
+ html += \`<p><code>\${escapeHtml(f)}</code></p>\`;
887
+ });
861
888
  html += '</div></div>';
862
889
  }
863
890
 
@@ -1085,11 +1112,11 @@ import {a as a$2}from'./chunk-NQMJ3QRX.js';import {a as a$3}from'./chunk-VV3A3UE
1085
1112
  }
1086
1113
  </script>
1087
1114
  </body>
1088
- </html>`}async start(t=true){let r=this.config.repositories[0]?.path||process.cwd();this.envResult=await a$3(r),this.currentReport=await this.engine.generate(),console.log();for(let e of this.currentReport.repositories){let n=e.summary;console.log(` \u2705 ${e.displayName}`),console.log(` ${n.totalPages} pages \xB7 ${n.totalComponents} components \xB7 ${n.totalGraphQLOperations} GraphQL \xB7 ${n.totalDataFlows} data flows`);}if(this.envResult.hasRails){console.log(`
1089
- Rails...`);try{this.railsAnalysis=await k(r);let e=this.railsAnalysis.summary;console.log(` ${e.totalRoutes} routes \xB7 ${e.totalControllers} controllers \xB7 ${e.totalModels} models \xB7 ${e.totalGrpcServices} gRPC`);}catch(e){console.error(" \u26A0\uFE0F Rails analysis failed:",e.message);}}try{let e=await de(this.port);e!==this.port&&console.log(`
1115
+ </html>`}async start(s=true){let r=this.config.repositories[0]?.path||process.cwd();this.envResult=await a$3(r),this.currentReport=await this.engine.generate(),console.log();for(let e of this.currentReport.repositories){let a=e.summary;console.log(` \u2705 ${e.displayName}`),console.log(` ${a.totalPages} pages \xB7 ${a.totalComponents} components \xB7 ${a.totalGraphQLOperations} GraphQL \xB7 ${a.totalDataFlows} data flows`);}if(this.envResult.hasRails){console.log(`
1116
+ Rails...`);try{this.railsAnalysis=await k(r);let e=this.railsAnalysis.summary;console.log(` ${e.totalRoutes} routes \xB7 ${e.totalControllers} controllers \xB7 ${e.totalModels} models \xB7 ${e.totalGrpcServices} gRPC`);}catch(e){console.error(" \u26A0\uFE0F Rails analysis failed:",e.message);}}try{let e=await ue(this.port);e!==this.port&&console.log(`
1090
1117
  \u26A0\uFE0F Port ${this.port} is in use, using port ${e} instead`),this.port=e;}catch(e){console.error(`
1091
1118
  \u274C Failed to find available port: ${e.message}`),process.exit(1);}if(this.server.listen(this.port,()=>{console.log(`
1092
1119
  \u{1F310} Documentation server running at http://localhost:${this.port}`),this.envResult?.hasRails&&this.envResult?.hasNextjs&&console.log(" \u{1F4CA} Multiple environments detected - use tabs to switch views"),console.log(` Press Ctrl+C to stop
1093
- `);}),t){let e=(await import('open')).default;await e(`http://localhost:${this.port}`);}this.config.watch.enabled&&this.watchForChanges();}async regenerate(){if(console.log(`
1094
- \u{1F504} Regenerating...`),this.currentReport=await this.engine.generate(),this.envResult?.hasRails){let t=this.config.repositories[0]?.path||process.cwd();try{this.railsAnalysis=await k(t);}catch(r){console.error("\u26A0\uFE0F Rails re-analysis failed:",r.message);}}for(let t of this.currentReport.repositories)console.log(` ${t.displayName}: ${t.summary.totalPages} pages \xB7 ${t.summary.totalComponents} components \xB7 ${t.summary.totalGraphQLOperations} GraphQL`);this.io.emit("reload"),console.log("\u2705 Done");}async watchForChanges(){let t=this.config.repositories.map(e=>e.path),r=null;for(let e of t)try{let n=T.watch(e,{recursive:!0});(async()=>{for await(let s of n)s.filename&&(s.filename.endsWith(".ts")||s.filename.endsWith(".tsx"))&&(r&&clearTimeout(r),r=setTimeout(async()=>{await this.regenerate();},this.config.watch.debounce));})();}catch(n){console.warn(`Warning: Could not watch directory ${e}:`,n.message);}}stop(){this.server.close(),console.log(`
1095
- \u{1F44B} Server stopped`);}};export{U as a,ue as b};
1120
+ `);}),s){let e=(await import('open')).default;await e(`http://localhost:${this.port}`);}this.config.watch.enabled&&this.watchForChanges();}async regenerate(){if(console.log(`
1121
+ \u{1F504} Regenerating...`),this.currentReport=await this.engine.generate(),this.envResult?.hasRails){let s=this.config.repositories[0]?.path||process.cwd();try{this.railsAnalysis=await k(s);}catch(r){console.error("\u26A0\uFE0F Rails re-analysis failed:",r.message);}}for(let s of this.currentReport.repositories)console.log(` ${s.displayName}: ${s.summary.totalPages} pages \xB7 ${s.summary.totalComponents} components \xB7 ${s.summary.totalGraphQLOperations} GraphQL`);this.io.emit("reload"),console.log("\u2705 Done");}async watchForChanges(){let s=this.config.repositories.map(e=>e.path),r=null;for(let e of s)try{let a=L.watch(e,{recursive:!0});(async()=>{for await(let o of a)o.filename&&(o.filename.endsWith(".ts")||o.filename.endsWith(".tsx"))&&(r&&clearTimeout(r),r=setTimeout(async()=>{await this.regenerate();},this.config.watch.debounce));})();}catch(a){console.warn(`Warning: Could not watch directory ${e}:`,a.message);}}stop(){this.server.close(),console.log(`
1122
+ \u{1F44B} Server stopped`);}};export{W as a,he as b};
@@ -0,0 +1 @@
1
+ var g=Object.create;var f=Object.defineProperty;var h=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var j=Object.getPrototypeOf,k=Object.prototype.hasOwnProperty;var m=(a=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(a,{get:(b,c)=>(typeof require<"u"?require:b)[c]}):a)(function(a){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+a+'" is not supported')});var n=(a,b)=>()=>(b||a((b={exports:{}}).exports,b),b.exports);var l=(a,b,c,e)=>{if(b&&typeof b=="object"||typeof b=="function")for(let d of i(b))!k.call(a,d)&&d!==c&&f(a,d,{get:()=>b[d],enumerable:!(e=h(b,d))||e.enumerable});return a};var o=(a,b,c)=>(c=a!=null?g(j(a)):{},l(b||!a||!a.__esModule?f(c,"default",{value:a,enumerable:true}):c,a));export{m as a,n as b,o as c};
package/dist/cli.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import {a,b}from'./chunk-6AZNHUOB.js';import'./chunk-NQMJ3QRX.js';import'./chunk-VV3A3UE3.js';import'./chunk-QDVE7MT3.js';import'./chunk-2XZSFAJF.js';import'./chunk-WZAAA7DS.js';import'./chunk-H7VVRHQZ.js';import {Command}from'commander';import s from'chalk';import*as c from'path';import*as n from'fs/promises';import*as v from'os';function P(){let e=v.tmpdir();return c.join(e,`repomap-${Date.now()}`)}function C(e){let t=async()=>{try{await n.rm(e,{recursive:!0,force:!0});}catch{}process.exit(0);};process.on("SIGINT",t),process.on("SIGTERM",t);}var d=new Command;d.name("repomap").description("Interactive documentation generator for code repositories").version("0.6.0");async function x(e){let t=c.basename(e),a=false,o=c.join(e,"Gemfile"),p=c.join(e,"config","routes.rb");try{await n.access(o),await n.access(p);let g=await n.readFile(o,"utf-8");a=g.includes("gem 'rails'")||g.includes('gem "rails"');}catch{}let r=c.join(e,"package.json"),i=false,l=false,m={};try{let g=JSON.parse(await n.readFile(r,"utf-8")),w={...g.dependencies,...g.devDependencies};i=!!w.react,l=!!w.next;let f=["src/pages","pages","app","src/app","frontend/src"];for(let u of f)try{await n.access(c.join(e,u)),m.pagesDir=u;break}catch{}let b=["src/features","features","src/modules","modules","frontend/src"];for(let u of b)try{await n.access(c.join(e,u)),m.featuresDir=u;break}catch{}let D=["src/components","components","src/common/components","frontend/src"];for(let u of D)try{await n.access(c.join(e,u)),m.componentsDir=u;break}catch{}}catch{}let h=[];(i||l)&&h.push("pages","graphql","dataflow","rest-api");let y="generic";return l?y="nextjs":a&&(y="rails"),!a&&!i&&!l?null:{name:t,displayName:t,description:a&&i?"Rails + React application":a?"Rails application":"",path:e,branch:"main",type:y,analyzers:h,settings:m}}async function E(e){let t=await x(e);if(!t)throw new Error("Could not detect project. Please create a repomap.config.ts file or run 'repomap init'.");return {outputDir:"./.repomap",site:{title:`${t.displayName} Documentation`,description:"Auto-generated documentation",baseUrl:"/docs"},repositories:[t],analysis:{include:["**/*.tsx","**/*.ts"],exclude:["**/node_modules/**","**/__tests__/**","**/*.test.*","**/*.spec.*","**/dist/**","**/.next/**"],maxDepth:5},diagrams:{enabled:true,types:["flowchart","sequence"],theme:"default"},watch:{enabled:false,debounce:1e3},integrations:{github:{enabled:false,organization:""},slack:{enabled:false}}}}async function $(e,t){let a=e?[e]:["repomap.config.ts","repomap.config.js","repomap.config.mjs"];for(let o of a){let p=c.resolve(t,o);try{await n.access(p);let r=await import(p);return r.config||r.default}catch{}}return E(t)}d.command("generate").description("Generate documentation from source code").option("-c, --config <path>","Path to config file").option("-o, --output <path>","Output directory").option("--temp","Use temporary directory (no files in repository)").option("--repo <name>","Analyze specific repository only").option("--watch","Watch for changes and regenerate").option("--format <type>","Output format: json, html, markdown (default: all)","all").option("--ci","CI mode: minimal output, exit codes for errors").option("--static","Generate standalone HTML files (for GitHub Pages)").action(async e=>{let t=e.ci||process.env.CI==="true";t||console.log(s.blue.bold(`
2
+ import {a,b}from'./chunk-YKPXOHWZ.js';import'./chunk-LHP2OKKA.js';import'./chunk-VV3A3UE3.js';import'./chunk-IGRCLYVZ.js';import'./chunk-QBSB6BIU.js';import'./chunk-ATRSGO6O.js';import'./chunk-H7VVRHQZ.js';import'./chunk-ZWRDP37E.js';import {Command}from'commander';import s from'chalk';import*as c from'path';import*as $ from'fs';import*as n from'fs/promises';import*as P from'os';function x(){let e=P.tmpdir();return c.join(e,`repomap-${Date.now()}`)}function N(e){let t=async()=>{try{await n.rm(e,{recursive:!0,force:!0});}catch{}process.exit(0);};process.on("SIGINT",t),process.on("SIGTERM",t);}function S(){try{let e=new URL("../package.json",import.meta.url),t=$.readFileSync(e,"utf-8");return JSON.parse(t).version||"0.0.0"}catch{return "0.0.0"}}var d=new Command;d.name("repomap").description("Interactive documentation generator for code repositories").version(S());async function C(e){let t=c.basename(e),r=false,o=c.join(e,"Gemfile"),p=c.join(e,"config","routes.rb");try{await n.access(o),await n.access(p);let g=await n.readFile(o,"utf-8");r=g.includes("gem 'rails'")||g.includes('gem "rails"');}catch{}let a=c.join(e,"package.json"),i=false,l=false,m={};try{let g=JSON.parse(await n.readFile(a,"utf-8")),w={...g.dependencies,...g.devDependencies};i=!!w.react,l=!!w.next;let f=["src/pages","pages","app","src/app","frontend/src"];for(let u of f)try{await n.access(c.join(e,u)),m.pagesDir=u;break}catch{}let b=["src/features","features","src/modules","modules","frontend/src"];for(let u of b)try{await n.access(c.join(e,u)),m.featuresDir=u;break}catch{}let D=["src/components","components","src/common/components","frontend/src"];for(let u of D)try{await n.access(c.join(e,u)),m.componentsDir=u;break}catch{}}catch{}let h=[];(i||l)&&h.push("pages","graphql","dataflow","rest-api");let y="generic";return l?y="nextjs":r&&(y="rails"),!r&&!i&&!l?null:{name:t,displayName:t,description:r&&i?"Rails + React application":r?"Rails application":"",path:e,branch:"main",type:y,analyzers:h,settings:m}}async function E(e){let t=await C(e);if(!t)throw new Error("Could not detect project. Please create a repomap.config.ts file or run 'repomap init'.");return {outputDir:"./.repomap",site:{title:`${t.displayName} Documentation`,description:"Auto-generated documentation",baseUrl:"/docs"},repositories:[t],analysis:{include:["**/*.tsx","**/*.ts"],exclude:["**/node_modules/**","**/__tests__/**","**/*.test.*","**/*.spec.*","**/dist/**","**/.next/**"],maxDepth:5},diagrams:{enabled:true,types:["flowchart","sequence"],theme:"default"},watch:{enabled:false,debounce:1e3},integrations:{github:{enabled:false,organization:""},slack:{enabled:false}}}}async function v(e,t){let r=e?[e]:["repomap.config.ts","repomap.config.js","repomap.config.mjs"];for(let o of r){let p=c.resolve(t,o);try{await n.access(p);let a=await import(p);return a.config||a.default}catch{}}return E(t)}d.command("generate").description("Generate documentation from source code").option("-c, --config <path>","Path to config file").option("-o, --output <path>","Output directory").option("--temp","Use temporary directory (no files in repository)").option("--repo <name>","Analyze specific repository only").option("--watch","Watch for changes and regenerate").option("--format <type>","Output format: json, html, markdown (default: all)","all").option("--ci","CI mode: minimal output, exit codes for errors").option("--static","Generate standalone HTML files (for GitHub Pages)").action(async e=>{let t=e.ci||process.env.CI==="true";t||console.log(s.blue.bold(`
3
3
  \u{1F4DA} Repomap
4
- `));try{let a$1=process.cwd(),o=await $(e.config,a$1);e.temp&&(o.outputDir=P(),t||console.log(s.cyan(`\u{1F4C1} Using temp directory: ${o.outputDir}
5
- `))),e.output&&(o.outputDir=e.output),e.repo&&(o.repositories=o.repositories.filter(r=>r.name===e.repo),o.repositories.length===0&&(console.error(s.red(`Repository "${e.repo}" not found in config`)),process.exit(1)));let p=new a(o);if(e.watch)console.log(s.yellow(`\u{1F440} Watch mode enabled. Press Ctrl+C to stop.
6
- `)),await F(p,o);else {let r=await p.generate();if(e.format==="json"||e.static){let i=c.join(o.outputDir,"report.json");await n.mkdir(o.outputDir,{recursive:!0}),await n.writeFile(i,JSON.stringify(r,null,2)),t||console.log(s.gray(` \u2192 ${i}`));}if(e.static&&await N(o,r,t),!t)S(r);else {let i=r.repositories.reduce((l,m)=>l+m.summary.totalPages,0);console.log(`\u2705 Generated: ${i} pages, ${r.repositories.length} repos`);}}}catch(a){console.error(t?`Error: ${a.message}`:s.red("Error:"),a.message),process.exit(1);}});async function N(e,t,a){let{PageMapGenerator:o}=await import('./page-map-generator-HROGGVAQ.js'),{detectEnvironments:p}=await import('./env-detector-BIWJ7OYF.js'),r=e.outputDir;await n.mkdir(r,{recursive:true});let i=e.repositories[0]?.path||process.cwd(),l=await p(i),m=null;if(l.hasRails){let{analyzeRailsApp:f}=await import('./rails-3HNUFTQV.js');m=await f(i);}let y=new o().generatePageMapHtml(t,{envResult:l,railsAnalysis:m,staticMode:true});if(await n.writeFile(c.join(r,"index.html"),y),a||console.log(s.gray(` \u2192 ${c.join(r,"index.html")}`)),m){let{RailsMapGenerator:f}=await import('./rails-map-generator-DF2YAXW4.js'),D=new f().generateFromResult(m);await n.writeFile(c.join(r,"rails-map.html"),D),a||console.log(s.gray(` \u2192 ${c.join(r,"rails-map.html")}`));}let g=["common.css","page-map.css","docs.css","rails-map.css"],w=c.join(r,"assets");await n.mkdir(w,{recursive:true});for(let f of g)try{let b=new URL(`./generators/assets/${f}`,import.meta.url),D=await n.readFile(b,"utf-8");await n.writeFile(c.join(w,f),D);}catch{}a||console.log(s.green(`
7
- \u2705 Static site generated: ${r}`));}d.command("serve").description("Start local documentation server with live reload").option("-c, --config <path>","Path to config file").option("--path <path>","Path to repository to analyze (auto-detect if no config)").option("-o, --output <path>","Output directory (default: .repomap in target path)").option("-p, --port <number>","Server port","3030").option("--temp","Use temporary directory (no files in repository)").option("--no-open","Don't open browser automatically").action(async e=>{console.log(s.blue.bold(`
4
+ `));try{let r=process.cwd(),o=await v(e.config,r);e.temp&&(o.outputDir=x(),t||console.log(s.cyan(`\u{1F4C1} Using temp directory: ${o.outputDir}
5
+ `))),e.output&&(o.outputDir=e.output),e.repo&&(o.repositories=o.repositories.filter(a=>a.name===e.repo),o.repositories.length===0&&(console.error(s.red(`Repository "${e.repo}" not found in config`)),process.exit(1)));let p=new a(o);if(e.watch)console.log(s.yellow(`\u{1F440} Watch mode enabled. Press Ctrl+C to stop.
6
+ `)),await k(p,o);else {let a=await p.generate();if(e.format==="json"||e.static){let i=c.join(o.outputDir,"report.json");await n.mkdir(o.outputDir,{recursive:!0}),await n.writeFile(i,JSON.stringify(a,null,2)),t||console.log(s.gray(` \u2192 ${i}`));}if(e.static&&await F(o,a,t),!t)O(a);else {let i=a.repositories.reduce((l,m)=>l+m.summary.totalPages,0);console.log(`\u2705 Generated: ${i} pages, ${a.repositories.length} repos`);}}}catch(r){console.error(t?`Error: ${r.message}`:s.red("Error:"),r.message),process.exit(1);}});async function F(e,t,r){let{PageMapGenerator:o}=await import('./page-map-generator-LTVRHSDC.js'),{detectEnvironments:p}=await import('./env-detector-RVGPBVNJ.js'),a=e.outputDir;await n.mkdir(a,{recursive:true});let i=e.repositories[0]?.path||process.cwd(),l=await p(i),m=null;if(l.hasRails){let{analyzeRailsApp:f}=await import('./rails-57MNOGHR.js');m=await f(i);}let y=new o().generatePageMapHtml(t,{envResult:l,railsAnalysis:m,staticMode:true});if(await n.writeFile(c.join(a,"index.html"),y),r||console.log(s.gray(` \u2192 ${c.join(a,"index.html")}`)),m){let{RailsMapGenerator:f}=await import('./rails-map-generator-JNU5QHX4.js'),D=new f().generateFromResult(m);await n.writeFile(c.join(a,"rails-map.html"),D),r||console.log(s.gray(` \u2192 ${c.join(a,"rails-map.html")}`));}let g=["common.css","page-map.css","docs.css","rails-map.css"],w=c.join(a,"assets");await n.mkdir(w,{recursive:true});for(let f of g)try{let b=new URL(`./generators/assets/${f}`,import.meta.url),D=await n.readFile(b,"utf-8");await n.writeFile(c.join(w,f),D);}catch{}r||console.log(s.green(`
7
+ \u2705 Static site generated: ${a}`));}d.command("serve").description("Start local documentation server with live reload").option("-c, --config <path>","Path to config file").option("--path <path>","Path to repository to analyze (auto-detect if no config)").option("-o, --output <path>","Output directory (default: .repomap in target path)").option("-p, --port <number>","Server port","3030").option("--temp","Use temporary directory (no files in repository)").option("--no-open","Don't open browser automatically").action(async e=>{console.log(s.blue.bold(`
8
8
  \u{1F310} Repomap
9
- `));try{let t=e.path||process.cwd(),a=await $(e.config,t);e.temp&&(a.outputDir=P(),console.log(s.cyan(`\u{1F4C1} Using temp directory: ${a.outputDir}
10
- `)),C(a.outputDir)),e.output&&(a.outputDir=c.resolve(e.output)),await new b(a,parseInt(e.port)).start(!e.open);}catch(t){console.error(s.red("Error:"),t.message),process.exit(1);}});d.command("init").description("Initialize repomap configuration").option("-f, --force","Overwrite existing config").action(async e=>{let t="./repomap.config.ts";try{if(await n.access(t).then(()=>!0).catch(()=>!1)&&!e.force){console.log(s.yellow("Config file already exists. Use --force to overwrite."));return}let o=await x(process.cwd()),p=o?.name||"my-project",r=o?.type||"nextjs",i=o?.settings.pagesDir||"src/pages",l=o?.settings.featuresDir||"src/features",m=o?.settings.componentsDir||"src/components",h=`import type { DocGeneratorConfig } from "repomap";
9
+ `));try{let t=e.path||process.cwd(),r=await v(e.config,t);e.temp&&(r.outputDir=x(),console.log(s.cyan(`\u{1F4C1} Using temp directory: ${r.outputDir}
10
+ `)),N(r.outputDir)),e.output&&(r.outputDir=c.resolve(e.output)),await new b(r,parseInt(e.port)).start(!e.open);}catch(t){console.error(s.red("Error:"),t.message),process.exit(1);}});d.command("init").description("Initialize repomap configuration").option("-f, --force","Overwrite existing config").action(async e=>{let t="./repomap.config.ts";try{if(await n.access(t).then(()=>!0).catch(()=>!1)&&!e.force){console.log(s.yellow("Config file already exists. Use --force to overwrite."));return}let o=await C(process.cwd()),p=o?.name||"my-project",a=o?.type||"nextjs",i=o?.settings.pagesDir||"src/pages",l=o?.settings.featuresDir||"src/features",m=o?.settings.componentsDir||"src/components",h=`import type { DocGeneratorConfig } from "repomap";
11
11
 
12
12
  export const config: DocGeneratorConfig = {
13
13
  outputDir: "./.repomap",
@@ -23,7 +23,7 @@ export const config: DocGeneratorConfig = {
23
23
  description: "Main repository",
24
24
  path: ".",
25
25
  branch: "main",
26
- type: "${r}",
26
+ type: "${a}",
27
27
  analyzers: ["pages", "graphql", "components", "dataflow"],
28
28
  settings: {
29
29
  pagesDir: "${i}",
@@ -54,12 +54,12 @@ export const config: DocGeneratorConfig = {
54
54
 
55
55
  export default config;
56
56
  `;await n.writeFile(t,h,"utf-8"),console.log(s.green(`\u2705 Created ${t}`)),console.log(s.gray(`
57
- Run 'npx repomap serve' to start the documentation server.`));}catch(a){console.error(s.red("Failed to create config:"),a.message);}});d.command("rails").description("Analyze a Rails application and generate interactive map").option("--path <path>","Path to Rails application").option("-o, --output <path>","Output HTML file path").action(async e=>{console.log(s.blue.bold(`
57
+ Run 'npx repomap serve' to start the documentation server.`));}catch(r){console.error(s.red("Failed to create config:"),r.message);}});d.command("rails").description("Analyze a Rails application and generate interactive map").option("--path <path>","Path to Rails application").option("-o, --output <path>","Output HTML file path").action(async e=>{console.log(s.blue.bold(`
58
58
  \u{1F6E4}\uFE0F Repomap Rails
59
- `));try{let t=e.path||process.cwd();try{await n.access(c.join(t,"config","routes.rb"));}catch{console.error(s.red("Not a Rails project (config/routes.rb not found)")),process.exit(1);}let{RailsMapGenerator:a}=await import('./rails-map-generator-DF2YAXW4.js'),o=e.output||c.join(t,"rails-map.html");await new a(t).generate({title:`${c.basename(t)} - Rails Map`,outputPath:o}),console.log(s.green(`\u2705 Rails map generated: ${o}`));let{exec:r}=await import('child_process');r(`open "${o}"`);}catch(t){console.error(s.red("Error:"),t.message),process.exit(1);}});d.command("diff").description("Show documentation changes since last generation").option("-c, --config <path>","Path to config file").action(async e=>{console.log(s.blue.bold(`
59
+ `));try{let t=e.path||process.cwd();try{await n.access(c.join(t,"config","routes.rb"));}catch{console.error(s.red("Not a Rails project (config/routes.rb not found)")),process.exit(1);}let{RailsMapGenerator:r}=await import('./rails-map-generator-JNU5QHX4.js'),o=e.output||c.join(t,"rails-map.html");await new r(t).generate({title:`${c.basename(t)} - Rails Map`,outputPath:o}),console.log(s.green(`\u2705 Rails map generated: ${o}`));let{exec:a}=await import('child_process');a(`open "${o}"`);}catch(t){console.error(s.red("Error:"),t.message),process.exit(1);}});d.command("diff").description("Show documentation changes since last generation").option("-c, --config <path>","Path to config file").action(async e=>{console.log(s.blue.bold(`
60
60
  \u{1F4CA} Documentation Diff
61
- `));try{let t=process.cwd(),a$1=await $(e.config,t),o=c.join(a$1.outputDir,"report.json");if(!await n.access(o).then(()=>!0).catch(()=>!1)){console.log(s.yellow("No previous report found. Run 'generate' first."));return}let r=JSON.parse(await n.readFile(o,"utf-8")),l=await new a(a$1).generate();k(r,l);}catch(t){console.error(s.red("Failed to generate diff:"),t.message);}});async function F(e,t){await e.generate();let a=t.repositories.map(o=>o.path);for(let o of a){let p=n.watch(o,{recursive:true}),r=null;for await(let i of p)i.filename&&(i.filename.endsWith(".ts")||i.filename.endsWith(".tsx"))&&(r&&clearTimeout(r),r=setTimeout(async()=>{console.log(s.yellow(`
62
- \u{1F504} Change detected: ${i.filename}`)),await e.generate();},t.watch.debounce));}}function S(e){console.log(s.green.bold(`
61
+ `));try{let t=process.cwd(),r=await v(e.config,t),o=c.join(r.outputDir,"report.json");if(!await n.access(o).then(()=>!0).catch(()=>!1)){console.log(s.yellow("No previous report found. Run 'generate' first."));return}let a$1=JSON.parse(await n.readFile(o,"utf-8")),l=await new a(r).generate();M(a$1,l);}catch(t){console.error(s.red("Failed to generate diff:"),t.message);}});async function k(e,t){await e.generate();let r=t.repositories.map(o=>o.path);for(let o of r){let p=n.watch(o,{recursive:true}),a=null;for await(let i of p)i.filename&&(i.filename.endsWith(".ts")||i.filename.endsWith(".tsx"))&&(a&&clearTimeout(a),a=setTimeout(async()=>{console.log(s.yellow(`
62
+ \u{1F504} Change detected: ${i.filename}`)),await e.generate();},t.watch.debounce));}}function O(e){console.log(s.green.bold(`
63
63
  \u2705 Complete
64
- `));for(let t of e.repositories)console.log(s.white(` ${t.displayName}`)),console.log(s.gray(` ${t.summary.totalPages} pages \xB7 ${t.summary.totalComponents} components \xB7 ${t.summary.totalGraphQLOperations} GraphQL ops`));console.log();}function k(e,t){console.log(s.cyan(`Changes detected:
65
- `));for(let a of t.repositories){let o=e.repositories.find(l=>l.name===a.name);if(!o){console.log(s.green(` + New repository: ${a.displayName}`));continue}let p=a.summary.totalPages-o.summary.totalPages,r=a.summary.totalComponents-o.summary.totalComponents,i=a.summary.totalGraphQLOperations-o.summary.totalGraphQLOperations;(p!==0||r!==0||i!==0)&&(console.log(s.yellow(` ~ ${a.displayName}:`)),p!==0&&console.log(` Pages: ${p>0?"+":""}${p}`),r!==0&&console.log(` Components: ${r>0?"+":""}${r}`),i!==0&&console.log(` GraphQL Ops: ${i>0?"+":""}${i}`));}}d.parse();
64
+ `));for(let t of e.repositories)console.log(s.white(` ${t.displayName}`)),console.log(s.gray(` ${t.summary.totalPages} pages \xB7 ${t.summary.totalComponents} components \xB7 ${t.summary.totalGraphQLOperations} GraphQL ops`));console.log();}function M(e,t){console.log(s.cyan(`Changes detected:
65
+ `));for(let r of t.repositories){let o=e.repositories.find(l=>l.name===r.name);if(!o){console.log(s.green(` + New repository: ${r.displayName}`));continue}let p=r.summary.totalPages-o.summary.totalPages,a=r.summary.totalComponents-o.summary.totalComponents,i=r.summary.totalGraphQLOperations-o.summary.totalGraphQLOperations;(p!==0||a!==0||i!==0)&&(console.log(s.yellow(` ~ ${r.displayName}:`)),p!==0&&console.log(` Pages: ${p>0?"+":""}${p}`),a!==0&&console.log(` Components: ${a>0?"+":""}${a}`),i!==0&&console.log(` GraphQL Ops: ${i>0?"+":""}${i}`));}}d.parse();
@@ -23,6 +23,20 @@ declare abstract class BaseAnalyzer {
23
23
  * Get setting value with fallback
24
24
  */
25
25
  protected getSetting(key: string, defaultValue?: string): string;
26
+ /**
27
+ * Get list-like setting value (comma/newline separated).
28
+ * Example: "useMyQuery, useMyMutation" -> ["useMyQuery", "useMyMutation"]
29
+ */
30
+ protected getListSetting(key: string, defaultValue?: string[]): string[];
31
+ /**
32
+ * Resolve effective GraphQL hook patterns by combining:
33
+ * - a preset selected by `settings.graphqlHookPreset` (default: "auto")
34
+ * - user-defined patterns from `settings.graphqlHookPatterns`
35
+ *
36
+ * Presets are meant to improve out-of-the-box support for common "production variants"
37
+ * (Relay/urql/custom wrappers) while keeping false positives low.
38
+ */
39
+ protected getGraphQLHookPatterns(): string[];
26
40
  /**
27
41
  * Log analysis progress (silent by default, set REPOMAP_VERBOSE=1 to enable)
28
42
  */
@@ -42,6 +56,8 @@ declare abstract class BaseAnalyzer {
42
56
  */
43
57
  declare class PagesAnalyzer extends BaseAnalyzer {
44
58
  private codegenMap;
59
+ private tsResolver;
60
+ private coverage;
45
61
  constructor(config: RepositoryConfig);
46
62
  getName(): string;
47
63
  analyze(): Promise<Partial<AnalysisResult>>;
@@ -190,6 +206,7 @@ declare class PagesAnalyzer extends BaseAnalyzer {
190
206
  * Uses @swc/core for fast parsing
191
207
  */
192
208
  declare class GraphQLAnalyzer extends BaseAnalyzer {
209
+ private coverage;
193
210
  constructor(config: RepositoryConfig);
194
211
  getName(): string;
195
212
  analyze(): Promise<Partial<AnalysisResult>>;
@@ -279,6 +296,7 @@ declare class GraphQLAnalyzer extends BaseAnalyzer {
279
296
  */
280
297
  declare class DataFlowAnalyzer extends BaseAnalyzer {
281
298
  private componentCache;
299
+ private coverage;
282
300
  constructor(config: RepositoryConfig);
283
301
  getName(): string;
284
302
  analyze(): Promise<Partial<AnalysisResult>>;
@@ -1 +1 @@
1
- export{a as detectEnvironments,b as getAnalyzersForEnvironments}from'./chunk-VV3A3UE3.js';
1
+ export{a as detectEnvironments,b as getAnalyzersForEnvironments}from'./chunk-VV3A3UE3.js';import'./chunk-ZWRDP37E.js';
@@ -597,6 +597,16 @@ body {
597
597
  font-size: 13px;
598
598
  }
599
599
 
600
+ .detail-badges {
601
+ padding: 8px 12px;
602
+ background: var(--docs-bg3);
603
+ border-radius: 4px;
604
+ display: flex;
605
+ flex-wrap: wrap;
606
+ gap: 6px;
607
+ align-items: center;
608
+ }
609
+
600
610
  .detail-badge {
601
611
  display: inline-block;
602
612
  padding: 4px 10px;
@@ -605,6 +615,10 @@ body {
605
615
  font-weight: 500;
606
616
  margin-right: 6px;
607
617
  }
618
+
619
+ .detail-badges .detail-badge {
620
+ margin-right: 0;
621
+ }
608
622
  .detail-badge.query {
609
623
  background: #dbeafe;
610
624
  color: #1d4ed8;
@@ -630,6 +644,14 @@ body {
630
644
  color: #475569;
631
645
  }
632
646
 
647
+ .detail-badge.confidence {
648
+ cursor: help;
649
+ color: #fff;
650
+ }
651
+ .detail-badge.confidence.likely {
652
+ background: #f59e0b;
653
+ }
654
+
633
655
  /* Regenerate Button */
634
656
  .regenerate-btn {
635
657
  background: var(--accent);