@wtdlee/repomap 0.4.1 → 0.5.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.
@@ -1,5 +1,5 @@
1
- import { B as BaseAnalyzer } from '../dataflow-analyzer-LeE44O3x.js';
2
- export { D as DataFlowAnalyzer, G as GraphQLAnalyzer, P as PagesAnalyzer } from '../dataflow-analyzer-LeE44O3x.js';
1
+ import { B as BaseAnalyzer } from '../dataflow-analyzer-mlxaq5qn.js';
2
+ export { D as DataFlowAnalyzer, G as GraphQLAnalyzer, P as PagesAnalyzer } from '../dataflow-analyzer-mlxaq5qn.js';
3
3
  import { RepositoryConfig, AnalysisResult } from '../types.js';
4
4
 
5
5
  /**
@@ -1 +1 @@
1
- export{a as BaseAnalyzer,d as DataFlowAnalyzer,c as GraphQLAnalyzer,b as PagesAnalyzer,e as RestApiAnalyzer}from'../chunk-PSM6AV63.js';
1
+ export{a as BaseAnalyzer,d as DataFlowAnalyzer,c as GraphQLAnalyzer,b as PagesAnalyzer,e as RestApiAnalyzer}from'../chunk-WJIBUCXB.js';
@@ -1,4 +1,4 @@
1
- var S=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,r){let c=[],v=r?.envResult,t=r?.railsAnalysis,l=r?.activeTab||"pages",e=s.repositories[0]?.displayName||s.repositories[0]?.name||"Repository";for(let p of s.repositories){this.graphqlOps.push(...p.analysis?.graphqlOperations||[]),this.apiCalls.push(...p.analysis?.apiCalls||[]);let f=p.analysis?.components||[];for(let a of f)this.components.push({name:a.name,filePath:a.filePath,type:a.type,dependencies:a.dependencies||[]});}for(let p of s.repositories){let f=p.analysis?.pages||[];for(let a of f)c.push({...a,repo:p.name,children:[],parent:null,depth:0});}let{rootPages:i,relations:o}=this.buildHierarchy(c);return this.renderPageMapHtml(c,i,o,e,{envResult:v,railsAnalysis:t,activeTab:l})}buildHierarchy(s){let r=new Map,c=[];for(let t of s)r.set(t.path,t);for(let t of s){let l=t.path.split("/").filter(Boolean);for(let e=l.length-1;e>=1;e--){let i="/"+l.slice(0,e).join("/"),o=r.get(i);if(o){t.parent=i,t.depth=o.depth+1,o.children.includes(t.path)||o.children.push(t.path),c.push({from:i,to:t.path,type:"parent-child",description:`Sub-page of ${i}`});break}}if(t.parent||(t.depth=Math.max(0,l.length-1)),t.layout)for(let e of s)e.path!==t.path&&e.layout===t.layout&&(c.find(o=>o.type==="same-layout"&&(o.from===t.path&&o.to===e.path||o.from===e.path&&o.to===t.path))||c.push({from:t.path,to:e.path,type:"same-layout",description:`Both use ${t.layout}`}));}return {rootPages:s.filter(t=>!t.parent).sort((t,l)=>t.path.localeCompare(l.path)),relations:c}}renderPageMapHtml(s,r,c,v,t){let l=t?.envResult,e=t?.railsAnalysis,i=t?.activeTab||"pages",o=JSON.stringify(this.graphqlOps.map(d=>({name:d.name,type:d.type,variables:d.variables,fields:d.fields,returnType:d.returnType,usedIn:d.usedIn}))),p=JSON.stringify(this.components),f=e?JSON.stringify(e.routes.routes):"[]",a=e?JSON.stringify(e.controllers.controllers):"[]",m=e?JSON.stringify(e.models.models):"[]",u=e?JSON.stringify(e.views):'{ "views": [], "pages": [], "summary": {} }',h=e?JSON.stringify(e.react):'{ "components": [], "entryPoints": [], "summary": {} }',y=e?JSON.stringify(e.grpc):'{ "services": [] }',P=e?JSON.stringify(e.summary):"null",n=l?.hasRails||false,w=l?.hasNextjs||false,C=l?.hasReact||false,x=new Map;for(let d of s){let b=d.path.split("/").filter(Boolean)[0]||"root";x.has(b)||x.set(b,[]),x.get(b)?.push(d);}return `<!DOCTYPE html>
1
+ var P=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,n){let r=[],u=n?.envResult,t=n?.railsAnalysis,l=n?.activeTab||"pages",e=s.repositories[0]?.displayName||s.repositories[0]?.name||"Repository";for(let p of s.repositories){this.graphqlOps.push(...p.analysis?.graphqlOperations||[]),this.apiCalls.push(...p.analysis?.apiCalls||[]);let f=p.analysis?.components||[];for(let a of f)this.components.push({name:a.name,filePath:a.filePath,type:a.type,dependencies:a.dependencies||[],hooks:a.hooks||[]});}for(let p of s.repositories){let f=p.analysis?.pages||[];for(let a of f)r.push({...a,repo:p.name,children:[],parent:null,depth:0});}let{rootPages:i,relations:o}=this.buildHierarchy(r);return this.renderPageMapHtml(r,i,o,e,{envResult:u,railsAnalysis:t,activeTab:l})}buildHierarchy(s){let n=new Map,r=[];for(let t of s)n.set(t.path,t);for(let t of s){let l=t.path.split("/").filter(Boolean);for(let e=l.length-1;e>=1;e--){let i="/"+l.slice(0,e).join("/"),o=n.get(i);if(o){t.parent=i,t.depth=o.depth+1,o.children.includes(t.path)||o.children.push(t.path),r.push({from:i,to:t.path,type:"parent-child",description:`Sub-page of ${i}`});break}}if(t.parent||(t.depth=Math.max(0,l.length-1)),t.layout)for(let e of s)e.path!==t.path&&e.layout===t.layout&&(r.find(o=>o.type==="same-layout"&&(o.from===t.path&&o.to===e.path||o.from===e.path&&o.to===t.path))||r.push({from:t.path,to:e.path,type:"same-layout",description:`Both use ${t.layout}`}));}return {rootPages:s.filter(t=>!t.parent).sort((t,l)=>t.path.localeCompare(l.path)),relations:r}}renderPageMapHtml(s,n,r,u,t){let l=t?.envResult,e=t?.railsAnalysis,i=t?.activeTab||"pages",o=JSON.stringify(this.graphqlOps.map(c=>({name:c.name,type:c.type,variables:c.variables,fields:c.fields,returnType:c.returnType,usedIn:c.usedIn}))),p=JSON.stringify(this.components),f=e?JSON.stringify(e.routes.routes):"[]",a=e?JSON.stringify(e.controllers.controllers):"[]",h=e?JSON.stringify(e.models.models):"[]",v=e?JSON.stringify(e.views):'{ "views": [], "pages": [], "summary": {} }',y=e?JSON.stringify(e.react):'{ "components": [], "entryPoints": [], "summary": {} }',d=e?JSON.stringify(e.grpc):'{ "services": [] }',C=e?JSON.stringify(e.summary):"null",m=l?.hasRails||false,b=l?.hasNextjs||false,w=l?.hasReact||false,x=new Map;for(let c of s){let g=c.path.split("/").filter(Boolean)[0]||"root";x.has(g)||x.set(g,[]),x.get(g)?.push(c);}return `<!DOCTYPE html>
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="UTF-8">
@@ -9,17 +9,17 @@ var S=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,r){let
9
9
  <body>
10
10
  <header class="header">
11
11
  <div style="display:flex;align-items:center;gap:24px">
12
- <h1 style="cursor:pointer" onclick="location.href='/'">\u{1F4CA} ${v}</h1>
12
+ <h1 style="cursor:pointer" onclick="location.href='/'">\u{1F4CA} ${u}</h1>
13
13
  <nav style="display:flex;gap:4px">
14
14
  <a href="/page-map" class="nav-link ${i==="pages"?"active":""}">Page Map</a>
15
- ${n?`<a href="/rails-map" class="nav-link ${i==="rails"?"active":""}">Rails Map</a>`:""}
15
+ ${m?`<a href="/rails-map" class="nav-link ${i==="rails"?"active":""}">Rails Map</a>`:""}
16
16
  <a href="/docs" class="nav-link">Docs</a>
17
17
  <a href="/api/report" class="nav-link" target="_blank">API</a>
18
18
  </nav>
19
19
  </div>
20
20
  <div style="display:flex;gap:12px;align-items:center">
21
21
  <!-- Environment filter badges -->
22
- ${n&&w?`<div class="env-filters" style="display:flex;gap:4px;margin-right:8px">
22
+ ${m&&b?`<div class="env-filters" style="display:flex;gap:4px;margin-right:8px">
23
23
  <button class="env-badge env-badge-active" data-env="all" onclick="filterByEnv('all')">All</button>
24
24
  <button class="env-badge" data-env="nextjs" onclick="filterByEnv('nextjs')">\u269B\uFE0F Next.js</button>
25
25
  <button class="env-badge" data-env="rails" onclick="filterByEnv('rails')">\u{1F6E4}\uFE0F Rails</button>
@@ -59,12 +59,12 @@ var S=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,r){let
59
59
  <h3 style="margin-top:16px;font-size:10px;text-transform:uppercase;color:var(--text2);letter-spacing:1px">Frontend</h3>
60
60
  <div class="stats" id="stats-container">
61
61
  <div class="stat" data-filter="pages"><div class="stat-val">${s.length}</div><div class="stat-label">Pages</div></div>
62
- <div class="stat" data-filter="hierarchies"><div class="stat-val">${c.filter(d=>d.type==="parent-child").length}</div><div class="stat-label">Hierarchies</div></div>
62
+ <div class="stat" data-filter="hierarchies"><div class="stat-val">${r.filter(c=>c.type==="parent-child").length}</div><div class="stat-label">Hierarchies</div></div>
63
63
  <div class="stat" data-filter="graphql"><div class="stat-val">${this.graphqlOps.length}</div><div class="stat-label">GraphQL</div></div>
64
64
  <div class="stat" data-filter="restapi"><div class="stat-val">${this.apiCalls.length}</div><div class="stat-label">REST API</div></div>
65
65
  </div>
66
66
 
67
- ${n&&e?`
67
+ ${m&&e?`
68
68
  <!-- Rails Stats -->
69
69
  <h3 style="margin-top:16px;font-size:10px;text-transform:uppercase;color:var(--text2);letter-spacing:1px;cursor:pointer" onclick="switchToRailsTab()">Rails Backend</h3>
70
70
  <div class="stats" id="rails-stats">
@@ -81,17 +81,17 @@ var S=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,r){let
81
81
  <!-- Pages Tree View (for all screens - Next.js/React/Rails) -->
82
82
  <div class="tree-view ${i==="pages"?"active":""}" id="tree-view" data-tab="pages">
83
83
  ${s.length>0?this.buildTreeHtml(x,s):""}
84
- <div id="page-map-react-components-section" style="${n?"margin-top:20px;border-top:1px solid var(--bg3);padding-top:20px":""}">
84
+ <div id="page-map-react-components-section" style="${m?"margin-top:20px;border-top:1px solid var(--bg3);padding-top:20px":""}">
85
85
  </div>
86
- <div id="page-map-rails-section" style="${s.length>0&&n?"margin-top:20px;border-top:1px solid var(--bg3);padding-top:20px":""}">
87
- ${n&&s.length===0?'<div class="empty-state-sm">Loading screens...</div>':""}
86
+ <div id="page-map-rails-section" style="${s.length>0&&m?"margin-top:20px;border-top:1px solid var(--bg3);padding-top:20px":""}">
87
+ ${m&&s.length===0?'<div class="empty-state-sm">Loading screens...</div>':""}
88
88
  </div>
89
89
  </div>
90
90
 
91
91
  <!-- Rails Routes View (dedicated) -->
92
92
  <div class="tree-view ${i==="rails"?"active":""}" id="rails-tree-view" data-tab="rails">
93
93
  <div id="rails-routes-container">
94
- ${n?'<div class="empty-state-sm">Loading Rails routes...</div>':'<div class="empty-state">No Rails environment detected</div>'}
94
+ ${m?'<div class="empty-state-sm">Loading Rails routes...</div>':'<div class="empty-state">No Rails environment detected</div>'}
95
95
  </div>
96
96
  </div>
97
97
 
@@ -133,14 +133,14 @@ var S=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,r){let
133
133
  <script>
134
134
  // Environment detection results
135
135
  const envInfo = {
136
- hasRails: ${n},
137
- hasNextjs: ${w},
138
- hasReact: ${C}
136
+ hasRails: ${m},
137
+ hasNextjs: ${b},
138
+ hasReact: ${w}
139
139
  };
140
140
 
141
141
  // Frontend data
142
142
  const pages = ${JSON.stringify(s)};
143
- const relations = ${JSON.stringify(c)};
143
+ const relations = ${JSON.stringify(r)};
144
144
  const graphqlOps = ${o};
145
145
  const components = ${p};
146
146
  const apiCallsData = ${JSON.stringify(this.apiCalls)};
@@ -152,11 +152,11 @@ var S=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,r){let
152
152
  // Rails data (if available)
153
153
  const railsRoutes = ${f};
154
154
  const railsControllers = ${a};
155
- const railsModels = ${m};
156
- const railsViews = ${u};
157
- const railsReact = ${h};
158
- const railsGrpc = ${y};
159
- const railsSummary = ${P};
155
+ const railsModels = ${h};
156
+ const railsViews = ${v};
157
+ const railsReact = ${y};
158
+ const railsGrpc = ${d};
159
+ const railsSummary = ${C};
160
160
 
161
161
  // Current active tab state
162
162
  let currentMainTab = '${i}';
@@ -1926,11 +1926,63 @@ var S=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,r){let
1926
1926
  }
1927
1927
 
1928
1928
  // Data operations - show grouped by source path, sorted by depth
1929
+ // Also include GraphQL from related components (including their dependencies)
1929
1930
  let dataHtml = '';
1930
- if (page.dataFetching && page.dataFetching.length > 0) {
1931
+
1932
+ // Recursively extract GraphQL from component and its dependencies
1933
+ function extractComponentGraphQL(comp, visited = new Set(), depth = 0) {
1934
+ const results = [];
1935
+ if (!comp || visited.has(comp.name) || depth > 10) return results;
1936
+ visited.add(comp.name);
1937
+
1938
+ // Extract GraphQL from this component's hooks
1939
+ if (comp.hooks) {
1940
+ comp.hooks.forEach(hook => {
1941
+ if (hook.includes('Query') || hook.includes('Mutation')) {
1942
+ let queryName = hook.replace('Query: ', '').replace('Mutation: ', '').trim();
1943
+ // Skip empty names or hooks without actual operation names
1944
+ if (!queryName) {
1945
+ return;
1946
+ }
1947
+ const isM = hook.includes('Mutation');
1948
+ const depthArrows = '\u2192 '.repeat(depth + 1);
1949
+ results.push({
1950
+ type: isM ? 'useMutation' : 'useQuery',
1951
+ operationName: depthArrows + queryName + ' (via ' + comp.name + ')',
1952
+ variables: []
1953
+ });
1954
+ }
1955
+ });
1956
+ }
1957
+
1958
+ // Recursively check dependencies
1959
+ if (comp.dependencies) {
1960
+ comp.dependencies.forEach(depName => {
1961
+ const depComp = componentByName.get(depName);
1962
+ if (depComp) {
1963
+ results.push(...extractComponentGraphQL(depComp, visited, depth + 1));
1964
+ }
1965
+ });
1966
+ }
1967
+
1968
+ return results;
1969
+ }
1970
+
1971
+ // Get GraphQL from page's components (including dependencies)
1972
+ const pageComps = getPageComponents(page);
1973
+ const componentGraphQL = [];
1974
+ const visited = new Set();
1975
+ pageComps.forEach(comp => {
1976
+ componentGraphQL.push(...extractComponentGraphQL(comp, visited, 0));
1977
+ });
1978
+
1979
+ // Combine direct dataFetching with component GraphQL
1980
+ const allDataFetching = [...(page.dataFetching || []), ...componentGraphQL];
1981
+
1982
+ if (allDataFetching.length > 0) {
1931
1983
  // Separate actual GraphQL operations from component references
1932
- const graphqlOps = page.dataFetching.filter(df => df.type !== 'component');
1933
- const componentRefs = page.dataFetching.filter(df => df.type === 'component');
1984
+ const graphqlOps = allDataFetching.filter(df => df.type !== 'component');
1985
+ const componentRefs = allDataFetching.filter(df => df.type === 'component');
1934
1986
 
1935
1987
  // Parse operations to extract path info and depth
1936
1988
  const parsedOps = graphqlOps.map(df => {
@@ -2014,9 +2066,16 @@ var S=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,r){let
2014
2066
 
2015
2067
  dataHtml = '';
2016
2068
 
2069
+ // Count direct vs component queries for header
2070
+ const directOps = groupedByPath.get('Direct') || [];
2071
+ const componentOpCount = uniqueOps.length - directOps.length;
2072
+
2017
2073
  // Show grouped GraphQL operations
2018
2074
  if (sortedPaths.length > 0) {
2019
- dataHtml += '<div class="detail-section"><h4>Data Operations</h4>';
2075
+ const countLabel = componentOpCount > 0
2076
+ ? directOps.length + ' direct, +' + componentOpCount + ' from components'
2077
+ : directOps.length + ' total';
2078
+ dataHtml += '<div class="detail-section"><h4>Data Operations <span style="font-weight:normal;font-size:11px;color:var(--text2)">(' + countLabel + ')</span></h4>';
2020
2079
 
2021
2080
  sortedPaths.forEach(pathName => {
2022
2081
  const ops = groupedByPath.get(pathName);
@@ -2105,11 +2164,110 @@ var S=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,r){let
2105
2164
  let currentFilter = null;
2106
2165
 
2107
2166
  // Build sets for filtering
2108
- const pagesWithGraphQL = new Set(pages.filter(p =>
2109
- p.dataFetching && p.dataFetching.some(df =>
2110
- df.type === 'useQuery' || df.type === 'useMutation' || df.type === 'useLazyQuery'
2111
- )
2112
- ).map(p => p.path));
2167
+ // Build component lookup maps for dependency tracking
2168
+ const componentByFile = new Map();
2169
+ const componentByName = new Map();
2170
+ components.forEach(c => {
2171
+ if (c.filePath) componentByFile.set(c.filePath, c);
2172
+ if (c.name) componentByName.set(c.name, c);
2173
+ });
2174
+
2175
+ // Check if a component (or its dependencies) uses GraphQL
2176
+ function componentUsesGraphQL(comp, visited = new Set()) {
2177
+ if (!comp || visited.has(comp.name)) return false;
2178
+ visited.add(comp.name);
2179
+
2180
+ // Check hooks for GraphQL queries
2181
+ if (comp.hooks && comp.hooks.some(h =>
2182
+ h.includes('Query') || h.includes('Mutation')
2183
+ )) {
2184
+ return true;
2185
+ }
2186
+
2187
+ // Check dependencies recursively (limit depth to avoid infinite loops)
2188
+ if (comp.dependencies && visited.size < 20) {
2189
+ for (const dep of comp.dependencies) {
2190
+ const depComp = componentByName.get(dep);
2191
+ if (depComp && componentUsesGraphQL(depComp, visited)) {
2192
+ return true;
2193
+ }
2194
+ }
2195
+ }
2196
+
2197
+ return false;
2198
+ }
2199
+
2200
+ // Find components related to a page (strict matching only)
2201
+ function getPageComponents(page) {
2202
+ const relatedComps = [];
2203
+
2204
+ // 1. Find by page file path (exact match)
2205
+ if (page.filePath) {
2206
+ const pageComp = componentByFile.get(page.filePath);
2207
+ if (pageComp) relatedComps.push(pageComp);
2208
+
2209
+ // Check for PageContainer pattern based on file name
2210
+ const baseName = page.filePath.split('/').pop()?.replace(/\\.(tsx?|jsx?)$/, '') || '';
2211
+ const containerName = baseName.charAt(0).toUpperCase() + baseName.slice(1) + 'PageContainer';
2212
+ const container = componentByName.get(containerName);
2213
+ if (container) relatedComps.push(container);
2214
+
2215
+ // Check for feature-based container: /pages/app/agencies \u2192 AgenciesPageContainer
2216
+ const pathParts = page.filePath.split('/');
2217
+ const pageIndex = pathParts.indexOf('pages');
2218
+ if (pageIndex >= 0 && pathParts.length > pageIndex + 2) {
2219
+ // Get the main feature segment (e.g., 'agencies' from '/pages/app/agencies/...')
2220
+ const featureSegment = pathParts[pageIndex + 2];
2221
+ if (featureSegment && !featureSegment.startsWith('[')) {
2222
+ const featurePascal = featureSegment.split(/[-_]/).map(w => w.charAt(0).toUpperCase() + w.slice(1)).join('');
2223
+ const featureContainer = componentByName.get(featurePascal + 'PageContainer');
2224
+ if (featureContainer) relatedComps.push(featureContainer);
2225
+ }
2226
+ }
2227
+ }
2228
+
2229
+ // 2. Find by component name from page data
2230
+ if (page.component) {
2231
+ const comp = componentByName.get(page.component);
2232
+ if (comp) relatedComps.push(comp);
2233
+
2234
+ // Also check for Container pattern
2235
+ const containerName = page.component + 'Container';
2236
+ const container = componentByName.get(containerName);
2237
+ if (container) relatedComps.push(container);
2238
+ }
2239
+
2240
+ return relatedComps;
2241
+ }
2242
+
2243
+ // Include pages with direct GraphQL usage OR pages whose components use GraphQL
2244
+ const pagesWithGraphQL = new Set([
2245
+ // Pages with direct dataFetching
2246
+ ...pages.filter(p =>
2247
+ p.dataFetching && p.dataFetching.some(df =>
2248
+ df.type === 'useQuery' || df.type === 'useMutation' || df.type === 'useLazyQuery' ||
2249
+ df.type === 'getServerSideProps' || df.type === 'getStaticProps'
2250
+ )
2251
+ ).map(p => p.path),
2252
+ // Pages whose components (or dependencies) use GraphQL
2253
+ ...pages.filter(p => {
2254
+ const pageComps = getPageComponents(p);
2255
+ return pageComps.some(comp => componentUsesGraphQL(comp));
2256
+ }).map(p => p.path),
2257
+ // Pages whose files are referenced in GraphQL operation usedIn
2258
+ ...pages.filter(p => {
2259
+ if (!p.filePath) return false;
2260
+ return Object.values(gqlMap).some(op =>
2261
+ op.usedIn && op.usedIn.some(u => u === p.filePath || u.endsWith('/' + p.filePath))
2262
+ );
2263
+ }).map(p => p.path)
2264
+ ]);
2265
+
2266
+ // Debug: log pagesWithGraphQL count
2267
+ console.log('\u{1F4CA} GraphQL Stats: totalComponents=' + components.length +
2268
+ ', componentsWithGraphQL=' + components.filter(c => c.hooks && c.hooks.some(h => h.includes('Query') || h.includes('Mutation'))).length +
2269
+ ', pagesWithGraphQL=' + pagesWithGraphQL.size +
2270
+ ', totalPages=' + pages.length);
2113
2271
 
2114
2272
  const pagesWithRestApi = new Set(pages.filter(p => {
2115
2273
  // Check if any API call is in this page's file or related feature directory
@@ -2331,7 +2489,14 @@ var S=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,r){let
2331
2489
  });
2332
2490
  }
2333
2491
 
2492
+ // Track expanded state for GraphQL list
2493
+ let gqlListExpanded = { queries: false, mutations: false, fragments: false };
2494
+
2334
2495
  function showGraphQLList() {
2496
+ renderGraphQLList();
2497
+ }
2498
+
2499
+ function renderGraphQLList() {
2335
2500
  // Show GraphQL operations in detail panel
2336
2501
  let html = '<div class="detail-section"><h4>All GraphQL Operations ('+Object.keys(Object.fromEntries(gqlMap)).length+')</h4>';
2337
2502
 
@@ -2339,36 +2504,55 @@ var S=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,r){let
2339
2504
  const mutations = Array.from(gqlMap.values()).filter(o => o.type === 'mutation');
2340
2505
  const fragments = Array.from(gqlMap.values()).filter(o => o.type === 'fragment');
2341
2506
 
2507
+ const initialLimit = 20;
2508
+ const mutationLimit = 10;
2509
+ const fragmentLimit = 5;
2510
+
2342
2511
  if (queries.length > 0) {
2343
2512
  html += '<div class="subtext-accent">Queries ('+queries.length+')</div>';
2344
- queries.slice(0, 20).forEach(op => {
2513
+ const showCount = gqlListExpanded.queries ? queries.length : Math.min(initialLimit, queries.length);
2514
+ queries.slice(0, showCount).forEach(op => {
2345
2515
  html += '<div class="detail-item data-op" onclick="event.stopPropagation(); showDataDetail(\\''+op.name.replace(/'/g, "\\\\'")+'\\')">' +
2346
2516
  '<span class="tag tag-query">QUERY</span> '+op.name+'</div>';
2347
2517
  });
2348
- if (queries.length > 20) {
2349
- html += '<div style="color:var(--text2);font-size:10px;padding:4px">... and '+(queries.length-20)+' more queries</div>';
2518
+ if (queries.length > initialLimit) {
2519
+ if (gqlListExpanded.queries) {
2520
+ html += '<div class="more-link" onclick="event.stopPropagation(); toggleGqlSection(\\'queries\\', false)">\u25B2 Show less</div>';
2521
+ } else {
2522
+ html += '<div class="more-link" onclick="event.stopPropagation(); toggleGqlSection(\\'queries\\', true)">... and '+(queries.length-initialLimit)+' more queries \u25BC</div>';
2523
+ }
2350
2524
  }
2351
2525
  }
2352
2526
 
2353
2527
  if (mutations.length > 0) {
2354
- html += '<div class="subtext-accent">Mutations ('+mutations.length+')</div>';
2355
- mutations.slice(0, 10).forEach(op => {
2528
+ html += '<div class="subtext-accent" style="margin-top:12px">Mutations ('+mutations.length+')</div>';
2529
+ const showCount = gqlListExpanded.mutations ? mutations.length : Math.min(mutationLimit, mutations.length);
2530
+ mutations.slice(0, showCount).forEach(op => {
2356
2531
  html += '<div class="detail-item data-op" onclick="event.stopPropagation(); showDataDetail(\\''+op.name.replace(/'/g, "\\\\'")+'\\')">' +
2357
2532
  '<span class="tag tag-mutation">MUTATION</span> '+op.name+'</div>';
2358
2533
  });
2359
- if (mutations.length > 10) {
2360
- html += '<div style="color:var(--text2);font-size:10px;padding:4px">... and '+(mutations.length-10)+' more mutations</div>';
2534
+ if (mutations.length > mutationLimit) {
2535
+ if (gqlListExpanded.mutations) {
2536
+ html += '<div class="more-link" onclick="event.stopPropagation(); toggleGqlSection(\\'mutations\\', false)">\u25B2 Show less</div>';
2537
+ } else {
2538
+ html += '<div class="more-link" onclick="event.stopPropagation(); toggleGqlSection(\\'mutations\\', true)">... and '+(mutations.length-mutationLimit)+' more mutations \u25BC</div>';
2539
+ }
2361
2540
  }
2362
2541
  }
2363
2542
 
2364
2543
  if (fragments.length > 0) {
2365
- html += '<div class="subtext-accent">Fragments ('+fragments.length+')</div>';
2366
- fragments.slice(0, 5).forEach(op => {
2544
+ html += '<div class="subtext-accent" style="margin-top:12px">Fragments ('+fragments.length+')</div>';
2545
+ const showCount = gqlListExpanded.fragments ? fragments.length : Math.min(fragmentLimit, fragments.length);
2546
+ fragments.slice(0, showCount).forEach(op => {
2367
2547
  html += '<div class="detail-item data-op" onclick="event.stopPropagation(); showDataDetail(\\''+op.name.replace(/'/g, "\\\\'")+'\\')">' +
2368
2548
  '<span class="tag tag-default">FRAGMENT</span> '+op.name+'</div>';
2369
2549
  });
2370
- if (fragments.length > 5) {
2371
- html += '<div style="color:var(--text2);font-size:10px;padding:4px">... and '+(fragments.length-5)+' more fragments</div>';
2550
+ if (fragments.length > fragmentLimit) {
2551
+ if (gqlListExpanded.fragments) {
2552
+ html += '<div class="more-link" onclick="event.stopPropagation(); toggleGqlSection(\\'fragments\\', false)">\u25B2 Show less</div>';
2553
+ } else {
2554
+ html += '<div class="more-link" onclick="event.stopPropagation(); toggleGqlSection(\\'fragments\\', true)">... and '+(fragments.length-fragmentLimit)+' more fragments \u25BC</div>';
2555
+ }
2372
2556
  }
2373
2557
  }
2374
2558
 
@@ -2379,6 +2563,11 @@ var S=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,r){let
2379
2563
  document.getElementById('detail').classList.add('open');
2380
2564
  }
2381
2565
 
2566
+ window.toggleGqlSection = function(section, expand) {
2567
+ gqlListExpanded[section] = expand;
2568
+ renderGraphQLList();
2569
+ };
2570
+
2382
2571
  function showRestApiList() {
2383
2572
  const apis = window.apiCalls || [];
2384
2573
  let html = '<div class="detail-section"><h4>REST API Calls ('+apis.length+')</h4>';
@@ -2499,14 +2688,26 @@ var S=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,r){let
2499
2688
  }
2500
2689
 
2501
2690
  // If not found, try removing common suffixes (Query, Mutation, Document)
2502
- // But don't remove if it would result in an empty string
2503
2691
  if (!op) {
2504
2692
  const baseName = name.replace(/Query$|Mutation$|Document$/, '');
2505
- if (baseName) { // Only try if baseName is not empty
2693
+ if (baseName) {
2506
2694
  op = gqlMap.get(baseName);
2507
2695
  }
2508
2696
  }
2509
2697
 
2698
+ // Try with "Get" prefix (common GraphQL naming convention)
2699
+ if (!op) {
2700
+ const pascalName = toPascalCase(name);
2701
+ op = gqlMap.get('Get' + pascalName) || gqlMap.get('Get' + pascalName + 'Query');
2702
+ }
2703
+
2704
+ // Try removing Fragment suffix or adding it
2705
+ if (!op) {
2706
+ const pascalName = toPascalCase(name);
2707
+ const withoutFragment = pascalName.replace(/Fragment$/, '');
2708
+ op = gqlMap.get(withoutFragment) || gqlMap.get('Get' + withoutFragment) || gqlMap.get('Get' + withoutFragment + 'Fragment');
2709
+ }
2710
+
2510
2711
  // Also try with suffix if original didn't have one
2511
2712
  if (!op && !name.match(/Query$|Mutation$/)) {
2512
2713
  op = gqlMap.get(name + 'Query') || gqlMap.get(name + 'Mutation');
@@ -2520,6 +2721,17 @@ var S=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,r){let
2520
2721
  }
2521
2722
  }
2522
2723
 
2724
+ // Fuzzy search: find operation whose name contains the search term
2725
+ if (!op) {
2726
+ const searchLower = toPascalCase(name).toLowerCase();
2727
+ for (const [opName, opData] of gqlMap.entries()) {
2728
+ if (opName.toLowerCase().includes(searchLower) || searchLower.includes(opName.toLowerCase().replace(/^get/, ''))) {
2729
+ op = opData;
2730
+ break;
2731
+ }
2732
+ }
2733
+ }
2734
+
2523
2735
  let html = '';
2524
2736
 
2525
2737
  // Check if this is a known component
@@ -3315,17 +3527,76 @@ var S=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,r){let
3315
3527
  selectedNode = null;
3316
3528
  drawGraph();
3317
3529
  }
3530
+
3531
+ // Calculate and display Q/M counts for each page in list
3532
+ function updatePageGqlCounts() {
3533
+ document.querySelectorAll('.page-item').forEach(item => {
3534
+ const pagePath = item.getAttribute('data-path');
3535
+ const page = pageMap.get(pagePath);
3536
+ if (!page) return;
3537
+
3538
+ // Get page's components and calculate total GraphQL
3539
+ const pageComps = getPageComponents(page);
3540
+ const visited = new Set();
3541
+ let queries = 0;
3542
+ let mutations = 0;
3543
+
3544
+ // Count from direct dataFetching
3545
+ (page.dataFetching || []).forEach(df => {
3546
+ if (df.type?.includes('Mutation')) {
3547
+ mutations++;
3548
+ } else if (df.type && !df.type.includes('component')) {
3549
+ queries++;
3550
+ }
3551
+ });
3552
+
3553
+ // Count from component hooks (simplified - just count hooks)
3554
+ pageComps.forEach(comp => {
3555
+ if (!comp || visited.has(comp.name)) return;
3556
+ visited.add(comp.name);
3557
+ (comp.hooks || []).forEach(hook => {
3558
+ if (hook.includes('Mutation:')) mutations++;
3559
+ else if (hook.includes('Query:')) queries++;
3560
+ });
3561
+ });
3562
+
3563
+ // Update Q tag
3564
+ const qTag = item.querySelector('.tag-query');
3565
+ if (qTag) {
3566
+ if (queries > 0) {
3567
+ qTag.textContent = 'Q:' + queries;
3568
+ qTag.style.display = '';
3569
+ } else {
3570
+ qTag.style.display = 'none';
3571
+ }
3572
+ }
3573
+
3574
+ // Update M tag
3575
+ const mTag = item.querySelector('.tag-mutation');
3576
+ if (mTag) {
3577
+ if (mutations > 0) {
3578
+ mTag.textContent = 'M:' + mutations;
3579
+ mTag.style.display = '';
3580
+ } else {
3581
+ mTag.style.display = 'none';
3582
+ }
3583
+ }
3584
+ });
3585
+ }
3586
+
3587
+ // Initialize Q/M counts on page load
3588
+ setTimeout(updatePageGqlCounts, 100);
3318
3589
  </script>
3319
3590
  </body>
3320
- </html>`}buildTreeHtml(s,r){let c=["#ef4444","#f97316","#eab308","#22c55e","#14b8a6","#3b82f6","#8b5cf6","#ec4899"],v=0;return Array.from(s.entries()).sort((t,l)=>t[0].localeCompare(l[0])).map(([t,l])=>{let e=c[v++%c.length],i=l.sort((a,m)=>a.path.localeCompare(m.path)),o=new Set(i.map(a=>a.path)),p=new Map;for(let a of i){let m=a.path.split("/").filter(Boolean),u=0;for(let h=m.length-1;h>=1;h--){let y="/"+m.slice(0,h).join("/");if(o.has(y)){u=(p.get(y)??0)+1;break}}p.set(a.path,u);}let f=i.map(a=>{let m=this.getPageType(a.path),u=(a.dataFetching||[]).filter(g=>!g.type?.includes("Mutation")).length,h=(a.dataFetching||[]).filter(g=>g.type?.includes("Mutation")).length,y=p.get(a.path)??0,n=a.repo||"",w=r.some(g=>g.repo&&g.repo!==n),C=n.split("/").pop()?.split("-").map(g=>g.substring(0,4)).join("-")||n.substring(0,8),x=w&&n?`<span class="tag tag-repo" title="${n}">${C}</span>`:"",d=/^\/[A-Z]/.test(a.path)||a.filePath&&a.filePath.includes("components/pages"),b=d&&a.filePath?a.filePath.replace(/\.tsx?$/,"").replace(/^(frontend\/src\/|src\/)/,""):a.path,R=d?'<span class="tag tag-info" title="SPA Component Page">SPA</span>':"";return `<div class="page-item" data-path="${a.path}" data-repo="${n}" onclick="selectPage('${a.path}')" style="--depth:${y}">
3321
- <span class="page-type" style="--type-color:${m.color}">${m.label}</span>
3322
- <span class="page-path">${b}</span>
3591
+ </html>`}buildTreeHtml(s,n){let r=["#ef4444","#f97316","#eab308","#22c55e","#14b8a6","#3b82f6","#8b5cf6","#ec4899"],u=0;return Array.from(s.entries()).sort((t,l)=>t[0].localeCompare(l[0])).map(([t,l])=>{let e=r[u++%r.length],i=l.sort((a,h)=>a.path.localeCompare(h.path)),o=new Set(i.map(a=>a.path)),p=new Map;for(let a of i){let h=a.path.split("/").filter(Boolean),v=0;for(let y=h.length-1;y>=1;y--){let d="/"+h.slice(0,y).join("/");if(o.has(d)){v=(p.get(d)??0)+1;break}}p.set(a.path,v);}let f=i.map(a=>{let h=this.getPageType(a.path),v=p.get(a.path)??0,d=a.repo||"",C=n.some(g=>g.repo&&g.repo!==d),m=d.split("/").pop()?.split("-").map(g=>g.substring(0,4)).join("-")||d.substring(0,8),b=C&&d?`<span class="tag tag-repo" title="${d}">${m}</span>`:"",w=/^\/[A-Z]/.test(a.path)||a.filePath&&a.filePath.includes("components/pages"),x=w&&a.filePath?a.filePath.replace(/\.tsx?$/,"").replace(/^(frontend\/src\/|src\/)/,""):a.path,c=w?'<span class="tag tag-info" title="SPA Component Page">SPA</span>':"";return `<div class="page-item" data-path="${a.path}" data-repo="${d}" onclick="selectPage('${a.path}')" style="--depth:${v}">
3592
+ <span class="page-type" style="--type-color:${h.color}">${h.label}</span>
3593
+ <span class="page-path">${x}</span>
3323
3594
  <div class="page-tags">
3324
- ${x}
3325
- ${R}
3595
+ ${b}
3596
+ ${c}
3326
3597
  ${a.authentication?.required?'<span class="tag tag-auth">AUTH</span>':""}
3327
- ${u>0?`<span class="tag tag-query">Q:${u}</span>`:""}
3328
- ${h>0?`<span class="tag tag-mutation">M:${h}</span>`:""}
3598
+ <span class="tag tag-query gql-count" data-page-path="${a.path}" style="display:none">Q:0</span>
3599
+ <span class="tag tag-mutation gql-count-m" data-page-path="${a.path}" style="display:none">M:0</span>
3329
3600
  </div>
3330
3601
  </div>`}).join("");return `<div class="group">
3331
3602
  <div class="group-header" onclick="toggleGroup(this)" style="--group-color:${e}">
@@ -3334,4 +3605,4 @@ var S=class{graphqlOps=[];apiCalls=[];components=[];generatePageMapHtml(s,r){let
3334
3605
  <span class="group-count">${l.length}</span>
3335
3606
  </div>
3336
3607
  <div class="group-content">${f}</div>
3337
- </div>`}).join("")}getPageType(s){let r=s.split("/").filter(Boolean).pop()||"";return r==="new"||s.endsWith("/new")?{label:"CREATE",color:"#22c55e"}:r==="edit"||s.includes("/edit")?{label:"EDIT",color:"#f59e0b"}:r.startsWith("[")||r.startsWith(":")?{label:"DETAIL",color:"#3b82f6"}:s.includes("setting")?{label:"SETTINGS",color:"#6b7280"}:{label:"LIST",color:"#06b6d4"}}};export{S as a};
3608
+ </div>`}).join("")}getPageType(s){let n=s.split("/").filter(Boolean).pop()||"";return n==="new"||s.endsWith("/new")?{label:"CREATE",color:"#22c55e"}:n==="edit"||s.includes("/edit")?{label:"EDIT",color:"#f59e0b"}:n.startsWith("[")||n.startsWith(":")?{label:"DETAIL",color:"#3b82f6"}:s.includes("setting")?{label:"SETTINGS",color:"#6b7280"}:{label:"LIST",color:"#06b6d4"}}};export{P as a};
@@ -1,4 +1,4 @@
1
- import {a as a$2}from'./chunk-H4YGP3GL.js';import {a as a$3}from'./chunk-VV3A3UE3.js';import {e,d as d$1,c,b as b$2}from'./chunk-PSM6AV63.js';import {a,b as b$1}from'./chunk-XWZH2RDG.js';import {a as a$1}from'./chunk-MOEA75XK.js';import {k}from'./chunk-PTR5IROV.js';import {simpleGit}from'simple-git';import*as d from'fs/promises';import*as m from'path';import H from'fast-glob';import*as w from'crypto';import F from'express';import {Server}from'socket.io';import*as z from'http';import {marked}from'marked';import*as P from'net';var C="1.1",x=class{cacheDir;manifest;manifestPath;dirty=false;constructor(a){this.cacheDir=m.join(a,".repomap-cache"),this.manifestPath=m.join(this.cacheDir,"manifest.json"),this.manifest={version:C,entries:{}};}async init(){try{await d.mkdir(this.cacheDir,{recursive:!0});}catch(a){console.warn(` Warning: Could not create cache directory: ${a.message}`);return}try{let a=await d.readFile(this.manifestPath,"utf-8"),t=JSON.parse(a);t.version===C?this.manifest=t:(console.log(" Cache version mismatch, clearing cache..."),await this.clear());}catch{}}async computeFileHash(a){try{let t=await d.readFile(a,"utf-8");return w.createHash("md5").update(t).digest("hex")}catch{return ""}}async computeFilesHash(a){let t=[...a].sort(),e=50,o;t.length<=e*2?o=t:o=[...t.slice(0,e),...t.slice(-e)];let s=await Promise.all(o.map(i=>this.computeFileHash(i))),n=w.createHash("md5").update(String(t.length)).digest("hex");return w.createHash("md5").update(s.join("")+n).digest("hex")}get(a,t){let e=this.manifest.entries[a];return e&&e.hash===t?e.data:null}set(a,t,e){this.manifest.entries[a]={hash:t,timestamp:Date.now(),data:e},this.dirty=true;}async save(){if(this.dirty)try{await d.mkdir(this.cacheDir,{recursive:!0}),await d.writeFile(this.manifestPath,JSON.stringify(this.manifest,null,2)),this.dirty=!1;}catch(a){console.warn(" Warning: Failed to save cache:",a.message);}}async clear(){this.manifest={version:C,entries:{}},this.dirty=true;try{await d.rm(this.cacheDir,{recursive:!0,force:!0}),await d.mkdir(this.cacheDir,{recursive:!0});}catch{}}getStats(){let a=Object.keys(this.manifest.entries).length,t=JSON.stringify(this.manifest).length;return {entries:a,size:t>1024*1024?`${(t/1024/1024).toFixed(1)}MB`:`${(t/1024).toFixed(1)}KB`}}};var b=class{config;mermaidGenerator;markdownGenerator;noCache;constructor(a$1,t){this.config=a$1,this.mermaidGenerator=new a,this.markdownGenerator=new b$1,this.noCache=t?.noCache??false;}async generate(){console.log(`\u{1F680} Starting documentation generation...
1
+ import {a as a$2}from'./chunk-H4YGP3GL.js';import {a as a$3}from'./chunk-VV3A3UE3.js';import {e,d as d$1,c,b as b$2}from'./chunk-WJIBUCXB.js';import {a,b as b$1}from'./chunk-XWZH2RDG.js';import {a as a$1}from'./chunk-QZWPOG5B.js';import {k}from'./chunk-PTR5IROV.js';import {simpleGit}from'simple-git';import*as d from'fs/promises';import*as m from'path';import H from'fast-glob';import*as w from'crypto';import F from'express';import {Server}from'socket.io';import*as z from'http';import {marked}from'marked';import*as P from'net';var C="1.1",x=class{cacheDir;manifest;manifestPath;dirty=false;constructor(a){this.cacheDir=m.join(a,".repomap-cache"),this.manifestPath=m.join(this.cacheDir,"manifest.json"),this.manifest={version:C,entries:{}};}async init(){try{await d.mkdir(this.cacheDir,{recursive:!0});}catch(a){console.warn(` Warning: Could not create cache directory: ${a.message}`);return}try{let a=await d.readFile(this.manifestPath,"utf-8"),t=JSON.parse(a);t.version===C?this.manifest=t:(console.log(" Cache version mismatch, clearing cache..."),await this.clear());}catch{}}async computeFileHash(a){try{let t=await d.readFile(a,"utf-8");return w.createHash("md5").update(t).digest("hex")}catch{return ""}}async computeFilesHash(a){let t=[...a].sort(),e=50,o;t.length<=e*2?o=t:o=[...t.slice(0,e),...t.slice(-e)];let s=await Promise.all(o.map(i=>this.computeFileHash(i))),n=w.createHash("md5").update(String(t.length)).digest("hex");return w.createHash("md5").update(s.join("")+n).digest("hex")}get(a,t){let e=this.manifest.entries[a];return e&&e.hash===t?e.data:null}set(a,t,e){this.manifest.entries[a]={hash:t,timestamp:Date.now(),data:e},this.dirty=true;}async save(){if(this.dirty)try{await d.mkdir(this.cacheDir,{recursive:!0}),await d.writeFile(this.manifestPath,JSON.stringify(this.manifest,null,2)),this.dirty=!1;}catch(a){console.warn(" Warning: Failed to save cache:",a.message);}}async clear(){this.manifest={version:C,entries:{}},this.dirty=true;try{await d.rm(this.cacheDir,{recursive:!0,force:!0}),await d.mkdir(this.cacheDir,{recursive:!0});}catch{}}getStats(){let a=Object.keys(this.manifest.entries).length,t=JSON.stringify(this.manifest).length;return {entries:a,size:t>1024*1024?`${(t/1024/1024).toFixed(1)}MB`:`${(t/1024).toFixed(1)}KB`}}};var b=class{config;mermaidGenerator;markdownGenerator;noCache;constructor(a$1,t){this.config=a$1,this.mermaidGenerator=new a,this.markdownGenerator=new b$1,this.noCache=t?.noCache??false;}async generate(){console.log(`\u{1F680} Starting documentation generation...
2
2
  `);let a=[];for(let i of this.config.repositories)try{console.log(`
3
3
  \u{1F4E6} Analyzing ${i.displayName}...`);let r=await this.analyzeRepository(i);a.push(r),console.log(`\u2705 Completed ${i.displayName}`);}catch(r){console.error(`\u274C Failed to analyze ${i.name}:`,r.message);}console.log(`
4
4
  \u{1F517} Running cross-repository analysis...`);let t=this.analyzeCrossRepo(a);console.log(`
@@ -0,0 +1,2 @@
1
+ import {Project,Node,SyntaxKind}from'ts-morph';import Q from'fast-glob';import*as b from'path';import*as G from'fs';import*as _ from'fs/promises';import {parse}from'graphql';import {parseSync}from'@swc/core';var w=class{config;basePath;constructor(e){this.config=e,this.basePath=e.path;}resolvePath(e){return `${this.basePath}/${e}`}getSetting(e,t=""){return this.config.settings[e]??t}log(e){console.log(`[${this.getName()}] ${e}`);}warn(e){console.warn(`[${this.getName()}] \u26A0\uFE0F ${e}`);}error(e,t){console.error(`[${this.getName()}] \u274C ${e}`,t?.message||"");}};async function E(F,e,t=8){let s=new Array(F.length).fill(null),i=0;async function o(){for(;i<F.length;){let n=i++;if(n<F.length)try{s[n]=await e(F[n],n);}catch{s[n]=null;}}}let a=Array(Math.min(t,F.length)).fill(null).map(()=>o());return await Promise.all(a),s.filter(n=>n!==null)}var q=class extends w{project;codegenMap=new Map;constructor(e){super(e),this.project=new Project({tsConfigFilePath:this.resolvePath("tsconfig.json"),skipAddingFilesFromTsConfig:true});}extractOperationNameFromGql(e){let t=e.match(/(?:query|mutation|subscription)\s+(\w+)/);if(t&&t[1])return t[1];let s=e.match(/`\s*(?:query|mutation|subscription)\s+(\w+)/);if(s&&s[1])return s[1];let i=e.match(/GraphQL[^`]*`\s*(?:\n\s*)?(?:query|mutation|subscription)\s+(\w+)/);return i&&i[1]?i[1]:null}findOperationNameFromVariable(e,t){let s=e.getVariableDeclaration(t);if(!s){let n=e.getExportedDeclarations().get(t);if(n&&n.length>0){let r=n[0];Node.isVariableDeclaration(r)&&(s=r);}}if(s||(s=e.getVariableDeclarations().find(n=>n.getName()===t)),!s){let a=e.getFullText(),n=[new RegExp(`(?:const|let|var)\\s+${t}\\s*=\\s*gql\\s*\\(\\s*/\\*[^*]*\\*/\\s*\`\\s*(?:query|mutation|subscription)\\s+(\\w+)`,"s"),new RegExp(`(?:const|let|var)\\s+${t}\\s*=\\s*gql\`\\s*(?:query|mutation|subscription)\\s+(\\w+)`,"s"),new RegExp(`(?:const|let|var)\\s+${t}\\s*=\\s*gql\\s*\\(\`\\s*(?:query|mutation|subscription)\\s+(\\w+)`,"s"),new RegExp(`(?:const|let|var)\\s+${t}\\s*=\\s*graphql\\s*\\(\`\\s*(?:query|mutation|subscription)\\s+(\\w+)`,"s")];for(let r of n){let c=a.match(r);if(c&&c[1])return c[1]}return null}let i=s.getInitializer();if(!i)return null;let o=i.getText();return this.extractOperationNameFromGql(o)}getName(){return "PagesAnalyzer"}async analyze(){this.log("Starting page analysis..."),await this.loadCodegenMapping(),await this.analyzeAppFile();let e=await this.findPageFiles();this.log(`Found ${e.length} page files`);for(let i of e)try{this.project.addSourceFileAtPath(i);}catch{}let s=(await E(e,async i=>{let o=this.detectPagesRoot(i);return this.analyzePageFile(i,o)},4)).filter(i=>i!==null);return this.log(`Analyzed ${s.length} pages successfully`),{pages:s}}async analyzePageFile(e,t){let s=this.project.getSourceFile(e);if(!s)return null;let i=b.relative(t,e),o=this.filePathToRoutePath(i),a=this.findPageComponent(s);if(!a)return null;let n=this.extractRouteParams(o),r=this.extractLayout(s),c=this.extractAuthRequirement(s),l=this.extractPermissions(s),g=this.extractDataFetching(s),u=this.extractNavigation(s),m=this.extractLinkedPages(s),P=this.extractSteps(s);return {path:o,filePath:i,component:a,params:n,layout:r,authentication:c,permissions:l,dataFetching:g,navigation:u,linkedPages:m,steps:P.length>0?P:void 0}}detectPagesRoot(e){let t=["/src/pages/","/pages/","/src/app/","/app/","/frontend/src/pages/","/app/javascript/pages/"];for(let s of t){let i=e.indexOf(s);if(i!==-1)return e.substring(0,i+s.length-1)}return this.basePath}filePathToRoutePath(e){return "/"+e.replace(/\.tsx?$/,"").replace(/\/index$/,"").replace(/\[\.\.\.(\w+)\]/g,"*").replace(/\[(\w+)\]/g,":$1")}extractRouteParams(e){let t=[],s=/:(\w+)/g,i;for(;(i=s.exec(e))!==null;)t.push(i[1]);return t}findPageComponent(e){let t=e.getDefaultExportSymbol();if(t){let n=t.getName();if(n!=="default")return n}let s=e.getExportAssignment(n=>!n.isExportEquals());if(s){let n=s.getExpression();if(n){let r=n.getText();if(/^[A-Z][a-zA-Z0-9]*$/.test(r))return r;if(Node.isFunctionExpression(n)||Node.isArrowFunction(n))return "default"}}let i=e.getFunctions();for(let n of i)if(n.isDefaultExport())return n.getName()||"default";if(e.getVariableDeclaration("Page"))return "Page";let a=e.getVariableDeclarations();for(let n of a){let r=n.getTypeNode();if(r){let c=r.getText();if(c.includes("NextPage")||c.includes("FC")||c.includes("React.FC"))return n.getName()}}for(let n of a){let r=n.getName();if(/^[A-Z][a-zA-Z0-9]*$/.test(r)){let c=n.getInitializer();if(c&&(Node.isArrowFunction(c)||Node.isFunctionExpression(c))){let l=c.getText();if(l.includes("return")&&(l.includes("<")||l.includes("jsx")))return r}}}return null}extractLayout(e){let t=e.getDescendantsOfKind(SyntaxKind.PropertyAccessExpression).find(s=>s.getName()==="getLayout");if(t){let s=t.getParent();if(Node.isBinaryExpression(s)){let o=s.getRight().getDescendantsOfKind(SyntaxKind.JsxOpeningElement);if(o.length>0)return o[0].getTagNameNode().getText()}}}extractAuthRequirement(e){let s=e.getFilePath().split("/").pop()||"",a={required:!["404.tsx","permission-denied.tsx","_app.tsx","_document.tsx","_error.tsx"].some(n=>s===n)};try{let n=["RequiredCondition","ProtectedRoute","AuthGuard","PrivateRoute","WithAuth","RequireAuth","Authenticated","Authorized"],r=e.getDescendantsOfKind(SyntaxKind.JsxOpeningElement).find(c=>{let l=c.getTagNameNode().getText();return n.some(g=>l.includes(g))});if(r){a.condition="Additional permissions required";let c=r.getAttributes();for(let l of c)if(l.isKind(SyntaxKind.JsxAttribute))try{let g=l.getNameNode().getText();if(["condition","roles","permissions","requiredRoles","allowedRoles"].includes(g)){let u=l.getInitializer();if(u){a.condition=u.getText();let m=this.extractRolesFromCondition(u.getText());m.length>0&&(a.roles=m);}}}catch{}}}catch{}return a}extractRolesFromCondition(e){let t=[],s=/(\w+Role|\w+Permission)\.(\w+)/g,i;for(;(i=s.exec(e))!==null;)t.push(i[2]);let o=/['"]([a-zA-Z_-]+)['"]/g;for(;(i=o.exec(e))!==null;){let n=i[1];/admin|user|owner|member|guest|manager|editor|viewer/i.test(n)&&t.push(n);}let a=/\b(ROLE_\w+|[A-Z]+_ROLE)\b/g;for(;(i=a.exec(e))!==null;)t.push(i[1]);return [...new Set(t)]}extractPermissions(e){let t=[],s=e.getDescendantsOfKind(SyntaxKind.PropertyAccessExpression).filter(i=>{let o=i.getText();return o.includes("Permission")||o.includes("Role")||o.includes("isAdmin")});for(let i of s){let o=i.getText();t.includes(o)||t.push(o);}return t}extractDataFetching(e){let t=[],s=new Map,i=["useQuery","useMutation","useLazyQuery","useSubscription"];for(let y of e.getImportDeclarations()){let p=y.getModuleSpecifierValue();if(p.includes("@apollo/client")||p.includes("apollo"))for(let f of y.getNamedImports()){let d=f.getName(),h=f.getAliasNode()?.getText()||d;i.includes(d)&&s.set(h,d);}}let o=s.size>0||e.getImportDeclarations().some(y=>{let p=y.getModuleSpecifierValue();return p.includes("@apollo/client")||p.includes("apollo")}),a=e.getDescendantsOfKind(SyntaxKind.CallExpression).filter(y=>{let p=y.getExpression().getText();return !!(s.has(p)||i.includes(p)||/^use[A-Z].*Query$/.test(p)&&!p.includes("Params")&&!p.includes("String")||/^use[A-Z].*Mutation$/.test(p))});for(let y of a){let p=y.getExpression().getText(),f;s.has(p)?f=s.get(p):p.includes("Mutation")?f="useMutation":p.includes("Lazy")?f="useLazyQuery":f="useQuery";let d=y.getArguments();if(d.length===0){if(/^use[A-Z]/.test(p)){let C=p.replace(/^use/,"").replace(/Query$|Mutation$/,"");t.push({type:f,operationName:C,variables:[]});}continue}let x=d[0].getText();if(x.startsWith("[")||x.startsWith("{")||x.startsWith("'")||x.startsWith('"')||x.startsWith("`")||!(o||x.endsWith("Document")||x.endsWith("Query")||x.endsWith("Mutation")||x.includes("gql")||/^[A-Z_]+$/.test(x)))continue;let v=x.replace(/Document$/,"").replace(/Query$|Mutation$/,""),N=[];if(d.length>1){let $=d[1].getDescendantsOfKind(SyntaxKind.PropertyAssignment).find(T=>{try{return T.getName()==="variables"}catch{return false}});if($){let T=$.getInitializer();if(T){let z=T.getDescendantsOfKind(SyntaxKind.PropertyAssignment);for(let H of z)try{N.push(H.getName());}catch{}}}}t.push({type:f,operationName:v,variables:N});}let n=e.getVariableDeclaration("getServerSideProps"),r=e.getFunction("getServerSideProps"),c=n||r;if(c){let y=e.getImportDeclarations();for(let d of y){let h=d.getNamedImports();for(let x of h){let S=x.getName();if(S.endsWith("Document")&&e.getDescendantsOfKind(SyntaxKind.Identifier).filter(N=>N.getText()===S).length>0){let N=S.replace(/Document$/,"");t.push({type:"getServerSideProps",operationName:`\u2192 ${N}`});}}}let f=c.getText().match(/query:\s*(\w+)/g);if(f)for(let d of f){let h=d.replace(/query:\s*/,"");t.some(x=>x.operationName?.includes(h.replace(/Document$/,"")))||t.push({type:"getServerSideProps",operationName:`\u2192 ${h.replace(/Document$/,"")}`});}}let l=e.getVariableDeclaration("getStaticProps"),g=e.getFunction("getStaticProps");(l||g)&&t.push({type:"getStaticProps",operationName:"getStaticProps"});let u=e.getImportDeclarations(),m=e.getFilePath(),P=b.dirname(m);for(let y of u){let p=y.getModuleSpecifierValue(),f=p.startsWith(".")||p.startsWith("/"),d=!p.includes("node_modules")&&!p.startsWith("@types/")&&p.startsWith("@")===false;if(f||d){if(p.includes("__generated__")||p.includes("/generated/"))continue;let h=[],x=y.getNamedImports();for(let v of x){let N=v.getName();this.isComponentName(N)&&h.push(N);}let S=y.getDefaultImport();if(S){let v=S.getText();this.isComponentName(v)&&h.push(v);}for(let v of h){let N=this.analyzeImportedComponent(P,p,v);if(N.length>0)for(let C of N)t.push({type:C.type,operationName:C.operationName.startsWith("\u2192")?`\u2192 ${C.operationName} (${v})`:`\u2192 ${C.operationName} (${v})`,variables:C.variables});else t.push({type:"component",operationName:v,variables:[]});}}}return t}symbolTraceCache=new Map;analyzeImportedComponent(e,t,s,i=new Set,o=0){if(o>10)return [];let n=[];try{let r=b.resolve(e,t),c=`${r}:${s}`;if(i.has(c))return [];i.add(c);let l=this.symbolTraceCache.get(c);if(l!==void 0)return l;let g=[`${r}.tsx`,`${r}.ts`,`${r}/index.tsx`,`${r}/index.ts`,`${r}/${s}.tsx`,`${r}/${s}.ts`],u,m;for(let p of g)try{if(u=this.project.addSourceFileAtPath(p),u){m=p;break}}catch{}if(!u||!m)return n;if(m.endsWith("index.tsx")||m.endsWith("index.ts")){let p=this.followReExport(u,s,b.dirname(m));p&&(u=p);}let P=u.getImportDeclarations().some(p=>{let f=p.getModuleSpecifierValue();return f.includes("@apollo/client")||f.includes("apollo")||f.includes("gql")||f.includes("graphql")||f.includes("__generated__")}),y=u.getImportDeclarations().filter(p=>{let f=p.getModuleSpecifierValue();return f.startsWith("./")||f.startsWith("../")});for(let p of y){let f=p.getModuleSpecifierValue(),d=p.getNamedImports().map(h=>h.getName()).filter(h=>/^use[A-Z]/.test(h));for(let h of d){let x=this.analyzeCustomHook(b.dirname(u.getFilePath()),f,h,i,o+1);n.push(...x);}}for(let p of y){let f=p.getModuleSpecifierValue(),d=p.getNamedImports().map(S=>S.getName()),h=p.getDefaultImport()?.getText(),x=d.filter(S=>/^[A-Z]/.test(S)&&this.isComponentName(S));for(let S of x){let v=this.analyzeImportedComponent(b.dirname(u.getFilePath()),f,S,i,o+1);n.push(...v);}if(h&&/^[A-Z]/.test(h)&&this.isComponentName(h)){let S=this.analyzeImportedComponent(b.dirname(u.getFilePath()),f,h,i,o+1);n.push(...S);}}if(P){let p=u.getDescendantsOfKind(SyntaxKind.CallExpression).filter(f=>{let d=f.getExpression().getText();return ["useQuery","useMutation","useLazyQuery","useSubscription"].includes(d)});for(let f of p){let d=f.getExpression().getText(),h=f.getArguments();if(h.length===0)continue;let S=h[0].getText(),v=S,N=null,C=this.resolveDocumentName(S);if(C)v=C.operationName,N=C.operationType;else if(S.endsWith("Document"))v=S.replace(/Document$/,"");else if(/^[A-Za-z]/.test(S)){let T=this.findOperationNameFromVariable(u,S);if(T&&(v=T),v===S&&S!=="Query"&&S!=="Mutation"){let z=S.match(/^(.+?)(Query|Mutation|Subscription)$/);z&&(v=z[1]);}}v!=="Query"&&v!=="Mutation"&&(v=v.replace(/Document$/,"").replace(/Query$|Mutation$/,"")||v),(v==="Query"||v==="Mutation"||v==="")&&v===""&&(v=S||"Unknown");let $=N?N==="mutation"?"useMutation":N==="subscription"?"useSubscription":d.includes("Lazy")?"useLazyQuery":"useQuery":d.includes("Mutation")?"useMutation":d.includes("Lazy")?"useLazyQuery":"useQuery";n.push({type:$,operationName:v,variables:[]});}}this.symbolTraceCache.set(c,n);}catch{}return n}analyzeCustomHook(e,t,s,i=new Set,o=0){if(o>10)return [];let n=[];try{let r=b.resolve(e,t),c=`hook:${r}:${s}`;if(i.has(c))return [];i.add(c);let l=this.symbolTraceCache.get(c);if(l!==void 0)return l;let g=[`${r}.tsx`,`${r}.ts`,`${r}/${s}.tsx`,`${r}/${s}.ts`,`${r}/index.tsx`,`${r}/index.ts`],u;for(let p of g)try{if(u=this.project.addSourceFileAtPath(p),u)break}catch{}if(!u)return n;let m=u.getImportDeclarations().some(p=>{let f=p.getModuleSpecifierValue();return f.includes("@apollo/client")||f.includes("apollo")||f.includes("graphql")||f.includes("__generated__")}),P=u.getImportDeclarations().filter(p=>{let f=p.getModuleSpecifierValue();return f.startsWith("./")||f.startsWith("../")});for(let p of P){let f=p.getModuleSpecifierValue(),d=p.getNamedImports().map(h=>h.getName()).filter(h=>/^use[A-Z]/.test(h));for(let h of d){let x=this.analyzeCustomHook(b.dirname(u.getFilePath()),f,h,i,o+1);n.push(...x);}}if(!m&&n.length===0)return n;let y=u.getDescendantsOfKind(SyntaxKind.CallExpression).filter(p=>{let f=p.getExpression().getText();return ["useQuery","useMutation","useLazyQuery","useSubscription"].includes(f)});for(let p of y){let f=p.getExpression().getText(),d=p.getArguments();if(d.length===0)continue;let h=d[0].getText(),x=h,S=null,v=this.resolveDocumentName(h);if(v)x=v.operationName,S=v.operationType;else if(h.endsWith("Document"))x=h.replace(/Document$/,"");else if(/^[A-Za-z]/.test(h)){let C=this.findOperationNameFromVariable(u,h);if(C&&(x=C),x===h&&h!=="Query"&&h!=="Mutation"){let $=h.match(/^(.+?)(Query|Mutation|Subscription)$/);$&&(x=$[1]);}}x!=="Query"&&x!=="Mutation"&&(x=x.replace(/Document$/,"").replace(/Query$|Mutation$/,"")||x),x===""&&(x=h||"Unknown");let N=S?S==="mutation"?"useMutation":S==="subscription"?"useSubscription":f.includes("Lazy")?"useLazyQuery":"useQuery":f.includes("Mutation")?"useMutation":f.includes("Lazy")?"useLazyQuery":"useQuery";n.push({type:N,operationName:`\u2192 ${x} (via ${s})`,variables:[]});}this.symbolTraceCache.set(c,n);}catch{}return n}globalContextQueries=[];async findPageFiles(){let e=this.getSetting("pagesDir","src/pages"),t=[],i=[...new Set([e,"pages","src/pages","app","src/app"])];for(let n of i){if(n==="app"||n==="src/app"){let c=["controllers","models","views","helpers"],l=this.resolvePath(n);if(c.some(u=>{try{return G.existsSync(b.join(l,u))}catch{return false}}))continue}let r=this.resolvePath(n);try{let c=await Q(["**/*.tsx","**/*.ts","**/*.jsx","**/*.js"],{cwd:r,ignore:["_app.tsx","_app.ts","_app.jsx","_app.js","_document.tsx","_document.ts","_document.jsx","_document.js","_error.tsx","_error.ts","_error.jsx","_error.js","api/**","**/*.test.*","**/*.spec.*","**/node_modules/**","**/components/pages/**"],absolute:!0});t.push(...c),c.length>0&&this.log(`Found ${c.length} pages in ${n}`);}catch{}}let o=["frontend/src/**/pages","app/javascript/**/pages"];for(let n of o)try{let r=await Q([`${n}/**/*.tsx`,`${n}/**/*.ts`,`${n}/**/*.jsx`,`${n}/**/*.js`],{cwd:this.basePath,ignore:["**/*.test.*","**/*.spec.*","**/node_modules/**","**/vendor/**","**/components/pages/**","**/stories/**"],absolute:!0});t.push(...r),r.length>0&&this.log(`Found ${r.length} React pages in ${n}`);}catch{}let a=["frontend/src/**/index.tsx","frontend/src/**/App.tsx","app/javascript/packs/*.tsx","app/javascript/packs/*.jsx"];for(let n of a)try{let r=await Q([n],{cwd:this.basePath,ignore:["**/node_modules/**","**/vendor/**"],absolute:!0});for(let c of r)t.includes(c)||t.push(c);}catch{}return [...new Set(t)]}async analyzeAppFile(){let e=this.getSetting("pagesDir","src/pages"),t=[this.resolvePath(`${e}/_app.tsx`),this.resolvePath(`${e}/_app.ts`)];for(let s of t)try{let i=this.project.addSourceFileAtPath(s);if(!i)continue;let o=i.getDescendantsOfKind(SyntaxKind.JsxElement),a=i.getDescendantsOfKind(SyntaxKind.JsxSelfClosingElement),n=new Set;for(let r of [...o,...a]){let c=r.getFirstDescendantByKind(SyntaxKind.Identifier)?.getText();c&&(c.includes("Provider")||c.includes("Context"))&&n.add(c);}for(let r of i.getImportDeclarations()){let c=r.getModuleSpecifierValue();if(!c.startsWith("./")&&!c.startsWith("../"))continue;let l=r.getNamedImports().map(u=>u.getName()),g=r.getDefaultImport()?.getText();for(let u of n)if(l.includes(u)||g===u){let m=this.analyzeImportedComponent(b.dirname(s),c,u,new Set,0);for(let P of m)this.globalContextQueries.push({...P,operationName:`[Global] ${P.operationName}`});}}this.globalContextQueries.length>0&&this.log(`Found ${this.globalContextQueries.length} global context queries from _app`);return}catch{}}async loadCodegenMapping(){let e=["__generated__","src/__generated__","src/__generated__/gql-graphql-gateway","generated","src/generated"];for(let t of e){let s=this.resolvePath(t);try{let i=await Q(["**/*.ts","**/*.tsx"],{cwd:s,absolute:!0,onlyFiles:!0});for(let o of i)try{let a=this.project.addSourceFileAtPath(o),n=a.getVariableDeclarations();for(let c of n){let l=c.getName();if(l.endsWith("Document")){let g=c.getInitializer()?.getText()??"",u=g.match(/(?:query|mutation|subscription)\s+(\w+)/),m=g.match(/(query|mutation|subscription)\s+/);u&&this.codegenMap.set(l,{operationName:u[1],operationType:m?m[1]:"query"});}}let r=a.getTypeAliases();for(let c of r){let l=c.getName();if((l.endsWith("Query")||l.endsWith("Mutation")||l.endsWith("Subscription"))&&!l.endsWith("Variables")){let g=l+"Document";if(!this.codegenMap.has(g)){let u=l.endsWith("Mutation")?"mutation":l.endsWith("Subscription")?"subscription":"query";this.codegenMap.set(g,{operationName:l,operationType:u});}}}}catch{}if(this.codegenMap.size>0){this.log(`Loaded ${this.codegenMap.size} codegen mappings from ${t}`);return}}catch{}}}resolveDocumentName(e){if(new Set(["Query","Mutation","Subscription"]).has(e))return null;let s=this.codegenMap.get(e);if(s!==void 0)return s;let i=e.endsWith("Document")?e:e+"Document",o=this.codegenMap.get(i);return o!==void 0?o:null}followReExport(e,t,s){try{let i=e.getExportDeclarations(),o=null;for(let a of i){let n=a.getNamedExports();for(let r of n){let c=a.getModuleSpecifierValue();if(!c)continue;let l=b.resolve(s,c),g=[`${l}.tsx`,`${l}.ts`,`${l}/index.tsx`,`${l}/index.ts`],u;for(let m of g)try{if(u=this.project.addSourceFileAtPath(m),u)break}catch{}if(u&&(o||(o=u),r.getName()===t||r.getAliasNode()?.getText()===t))return u}}if(o)return o;for(let a of e.getExportDeclarations())if(a.isNamespaceExport()){let n=a.getModuleSpecifierValue();if(n){let r=b.resolve(s,n),c=[`${r}.tsx`,`${r}.ts`];for(let l of c)try{let g=this.project.addSourceFileAtPath(l);if(g&&g.getExportedDeclarations().has(t))return g}catch{}}}}catch{}return null}isComponentName(e){return !/^[A-Z]/.test(e)||e.endsWith("Query")||e.endsWith("Mutation")||e.endsWith("Subscription")||e.endsWith("Fragment")||e.endsWith("Document")||e.endsWith("Variables")||e==="Query"||e==="Mutation"||e==="Subscription"||new Set(["NextPage","NextPageContext","NextApiRequest","NextApiResponse","GetServerSideProps","GetStaticProps","GetStaticPaths","InferGetServerSidePropsType","InferGetStaticPropsType","FC","FunctionComponent","VFC","Component","PureComponent","ReactNode","ReactElement","PropsWithChildren","ComponentProps","ComponentType","ElementType","RefObject","MutableRefObject","Dispatch","SetStateAction","ChangeEvent","MouseEvent","KeyboardEvent","FormEvent","SyntheticEvent"]).has(e)?false:!!(["Container","Page","Screen","View","Form","Modal","Dialog","Panel","Root","Provider","Wrapper"].some(i=>e.endsWith(i))||/Page[A-Z]?\w*$/.test(e)||/Container[A-Z]?\w*$/.test(e)||/^[A-Z][a-z]+[A-Z][a-z]+/.test(e))}extractNavigation(e){let t={visible:true,currentNavItem:null};try{let s=e.getDescendantsOfKind(SyntaxKind.PropertyAccessExpression).find(i=>{try{return i.getName()==="globalNavigationStyle"}catch{return !1}});if(s){let i=s.getParent();if(Node.isBinaryExpression(i)){let o=i.getRight(),a=o.getDescendantsOfKind(SyntaxKind.PropertyAssignment).find(c=>{try{return c.getName()==="visible"}catch{return !1}});a&&(t.visible=a.getInitializer()?.getText()==="true");let n=o.getDescendantsOfKind(SyntaxKind.PropertyAssignment).find(c=>{try{return c.getName()==="currentNavItem"}catch{return !1}});if(n){let c=n.getInitializer()?.getText();t.currentNavItem=c&&c!=="null"?c.replace(/['"]/g,""):null;}let r=o.getDescendantsOfKind(SyntaxKind.PropertyAssignment).find(c=>{try{return c.getName()==="mini"}catch{return !1}});r&&(t.mini=r.getInitializer()?.getText()==="true");}}}catch{}return t}extractSteps(e){let t=[],s=e.getDescendantsOfKind(SyntaxKind.CallExpression).filter(a=>a.getExpression().getText()==="useState");for(let a of s){let n=a.getParent();if(!n)continue;let c=n.getText().match(/\[\s*(step|currentStep|activeStep|page|currentPage|phase|stage)\s*,/i);if(c){let l=c[1],g=e.getDescendantsOfKind(SyntaxKind.SwitchStatement);for(let m of g)m.getExpression().getText().includes(l)&&m.getClauses().forEach((p,f)=>{if(p.isKind(SyntaxKind.CaseClause)){let d=p.getExpression()?.getText()||String(f),h=p.getDescendantsOfKind(SyntaxKind.JsxOpeningElement),x=h.length>0?h[0].getTagNameNode().getText():void 0;t.push({id:d.replace(/['"]/g,""),name:`Step ${d.replace(/['"]/g,"")}`,component:x});}});let u=e.getDescendantsOfKind(SyntaxKind.ArrayLiteralExpression);for(let m of u){let P=m.getParent();P&&P.getText().match(/steps|pages|screens|views|components/i)&&m.getElements().forEach((p,f)=>{let d=p.getText();if(d.startsWith("{")){let h=d.match(/(?:name|label|title)\s*:\s*['"]([^'"]+)['"]/),x=d.match(/(?:component|content)\s*:\s*<?\s*(\w+)/);t.push({id:f+1,name:h?h[1]:`Step ${f+1}`,component:x?x[1]:void 0});}else /^[A-Z]/.test(d)&&t.push({id:f+1,name:d,component:d});});}}}let i=e.getDescendantsOfKind(SyntaxKind.JsxOpeningElement);for(let a of i)if(a.getTagNameNode().getText().match(/Stepper|Wizard|Steps|TabPanel|FormStep/i)){let r=a.getParent();r&&r.isKind(SyntaxKind.JsxElement)&&r.getJsxChildren().forEach((l,g)=>{if(l.isKind(SyntaxKind.JsxElement)||l.isKind(SyntaxKind.JsxSelfClosingElement)){let u=l.isKind(SyntaxKind.JsxElement)?l.getOpeningElement().getTagNameNode().getText():l.getTagNameNode().getText(),m=l.isKind(SyntaxKind.JsxElement)?l.getOpeningElement().getAttributes():l.getAttributes(),P=u;for(let y of m)if(y.isKind(SyntaxKind.JsxAttribute)){let p=y.getNameNode().getText();if(p==="label"||p==="title"||p==="name"){let f=y.getInitializer()?.getText();if(f){P=f.replace(/['"{}]/g,"");break}}}t.push({id:g+1,name:P,component:u});}});}let o=e.getDescendantsOfKind(SyntaxKind.ConditionalExpression);for(let a of o){let n=a.getCondition().getText();if(n.match(/step\s*===?\s*\d+|currentStep|activeStep/i)){let r=a.getWhenTrue(),c=n.match(/===?\s*(\d+)/);if(c&&t.length===0){let l=r.getDescendantsOfKind(SyntaxKind.JsxOpeningElement);l.length>0&&t.push({id:parseInt(c[1]),component:l[0].getTagNameNode().getText()});}}}return t}extractLinkedPages(e){let t=[],s=e.getDescendantsOfKind(SyntaxKind.CallExpression).filter(o=>{let a=o.getExpression().getText();return a.includes("router.push")||a.includes("router.replace")||a.includes("Link")});for(let o of s){let a=o.getArguments();if(a.length>0){let r=a[0].getText().match(/['"`]([^'"`]+)['"`]/);r&&!t.includes(r[1])&&t.push(r[1]);}}let i=e.getDescendantsOfKind(SyntaxKind.JsxOpeningElement).filter(o=>o.getTagNameNode().getText()==="Link");for(let o of i)try{let a=o.getAttributes();for(let n of a)if(n.isKind(SyntaxKind.JsxAttribute)&&n.getNameNode().getText()==="href"){let l=n.getInitializer()?.getText();if(l){let g=l.match(/['"`]([^'"`]+)['"`]/);g&&!t.includes(g[1])&&t.push(g[1]);}}}catch{}return t}};var j=class extends w{project;constructor(e){super(e),this.project=new Project({tsConfigFilePath:this.resolvePath("tsconfig.json"),skipAddingFilesFromTsConfig:true});}getName(){return "GraphQLAnalyzer"}async analyze(){this.log("Starting GraphQL analysis...");let e=[];this.log("[GraphQLAnalyzer] Step 1: Analyzing .graphql files...");let t=await this.analyzeGraphQLFiles();e.push(...t),this.log(`[GraphQLAnalyzer] Step 1 done: ${t.length} from .graphql files`),this.log("[GraphQLAnalyzer] Step 2: Analyzing inline GraphQL...");let s=await this.analyzeInlineGraphQL();e.push(...s),this.log(`[GraphQLAnalyzer] Step 2 done: ${s.length} inline operations`),this.log("[GraphQLAnalyzer] Step 3: Analyzing codegen output...");let i=await this.analyzeCodegenGenerated();e.push(...i),this.log(`[GraphQLAnalyzer] Step 3 done: ${i.length} from codegen`);let o=this.deduplicateOperations(e);return this.log(`[GraphQLAnalyzer] Deduplicated: ${o.length} unique operations`),this.log("[GraphQLAnalyzer] Step 4: Finding operation usage..."),await this.findOperationUsage(o),this.log("[GraphQLAnalyzer] Step 4 done"),this.log(`Found ${o.length} GraphQL operations`),{graphqlOperations:o}}deduplicateOperations(e){let t=new Map;for(let s of e)if(!t.has(s.name))t.set(s.name,s);else {let i=t.get(s.name);if(i)for(let o of s.usedIn)i.usedIn.includes(o)||i.usedIn.push(o);}return Array.from(t.values())}async analyzeCodegenGenerated(){let e=[],t=await Q(["**/__generated__/graphql.ts","**/__generated__/gql.ts","**/generated/graphql.ts"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**"],absolute:true});for(let s of t)try{let i=await _.readFile(s,"utf-8"),o=b.relative(this.basePath,s),a=i.split(`
2
+ `);for(let n of a){if(!n.includes("Document =")||!n.includes("DocumentNode"))continue;let r=n.match(/export\s+const\s+(\w+Document)\s*=\s*(\{"kind":"Document".+\})\s*as\s+unknown\s+as\s+DocumentNode/);if(!r)continue;let c=r[1],l=r[2];try{let g=JSON.parse(l);if(g.kind==="Document"&&g.definitions){let u=g.definitions[0];if(u?.kind==="OperationDefinition"){let m=u.name?.value||c.replace(/Document$/,""),P=u.operation,y=(u.variableDefinitions||[]).map(p=>({name:p.variable?.name?.value||"unknown",type:this.extractTypeFromAst(p.type),required:p.type?.kind==="NonNullType"}));e.push({name:m,type:P,filePath:o,usedIn:[],variables:y,returnType:this.inferReturnTypeFromAst(u),fragments:this.extractFragmentReferencesFromAst(u),fields:this.extractFieldsFromAst(u.selectionSet)});}}}catch{}}this.log(`Found ${e.length} operations in codegen output: ${o}`);}catch(i){this.warn(`Failed to analyze codegen file ${s}: ${i.message}`);}return e}extractTypeFromAst(e){return e?e.kind==="NonNullType"?`${this.extractTypeFromAst(e.type)}!`:e.kind==="ListType"?`[${this.extractTypeFromAst(e.type)}]`:e.kind==="NamedType"&&e.name?.value||"unknown":"unknown"}extractFieldsFromAst(e,t=0){if(!e?.selections||t>5)return [];let s=[];for(let i of e.selections)if(i.kind==="Field"){let o={name:i.name?.value||"unknown"};if(i.arguments?.length>0){let a=i.arguments.map(n=>n.name?.value).join(", ");o.type=`(${a})`;}i.selectionSet&&(o.fields=this.extractFieldsFromAst(i.selectionSet,t+1)),s.push(o);}else if(i.kind==="FragmentSpread")s.push({name:`...${i.name?.value}`,type:"fragment"});else if(i.kind==="InlineFragment"){let o=i.typeCondition?.name?.value||"inline";s.push({name:`... on ${o}`,type:"inline-fragment",fields:this.extractFieldsFromAst(i.selectionSet,t+1)});}return s}extractFragmentReferencesFromAst(e){let t=[],s=i=>{if(i&&(i.kind==="FragmentSpread"&&t.push(i.name?.value),i.selectionSet?.selections))for(let o of i.selectionSet.selections)s(o);};return s(e),t.filter(Boolean)}inferReturnTypeFromAst(e){if(e.selectionSet?.selections?.length>0){let t=e.selectionSet.selections[0];if(t.kind==="Field")return t.name?.value||"unknown"}return "unknown"}async analyzeGraphQLFiles(){let e=await Q(["**/*.graphql"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**"],absolute:true});return (await E(e,async s=>{let i=await _.readFile(s,"utf-8"),o=parse(i);return this.extractOperationsFromDocument(o,b.relative(this.basePath,s))})).flat()}async analyzeInlineGraphQL(){let e=[],t=await Q(["**/*.ts","**/*.tsx"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**","**/__tests__/**","**/*.test.*","**/*.spec.*"],absolute:true});for(let s of t)try{let i=this.project.addSourceFileAtPath(s),o=b.relative(this.basePath,s),a=i.getImportDeclarations().some(c=>{let l=c.getModuleSpecifierValue(),g=c.getNamedImports().map(m=>m.getName()),u=c.getDefaultImport()?.getText();return (g.includes("gql")||g.includes("graphql")||u==="gql")&&(l.includes("graphql")||l.includes("apollo")||l.includes("gql")||l.includes("__generated__"))}),n=i.getDescendantsOfKind(SyntaxKind.TaggedTemplateExpression);for(let c of n){let l=c.getTag().getText();if(l==="gql"||l==="graphql")try{let g=c.getTemplate(),u="";if(g.isKind(SyntaxKind.NoSubstitutionTemplateLiteral)?u=g.getLiteralValue():g.isKind(SyntaxKind.TemplateExpression)&&(u=g.getText().slice(1,-1).replace(/\$\{[^}]*\}/g,"")),u&&u.trim())try{let m=parse(u),P=this.extractOperationsFromDocument(m,o);e.push(...P);}catch{}}catch{}}let r=i.getDescendantsOfKind(SyntaxKind.CallExpression);for(let c of r)try{let g=c.getExpression().getText();if(g==="gql"||g==="graphql"){let u=c.getArguments();if(u.length>0){let m=u[0],P="";if(m.isKind(SyntaxKind.NoSubstitutionTemplateLiteral))P=m.getLiteralValue();else if(m.isKind(SyntaxKind.TemplateExpression))P=m.getText().slice(1,-1).replace(/\$\{[^}]*\}/g,"");else {let y=m.getText();if(y.includes("`")){let p=y.match(/\/\*\s*GraphQL\s*\*\/\s*`([^`]*)`/);if(p)P=p[1];else {let f=y.match(/`([^`]*)`/);f&&(P=f[1]);}}}if(P&&P.trim())try{let y=parse(P),p=this.extractOperationsFromDocument(y,o),f=this.extractVariableNameFromCall(c);if(f)for(let d of p)d.variableNames=d.variableNames||[],d.variableNames.push(f),d.variableNames.push(`${d.name}Document`);e.push(...p);}catch{}}}}catch{}if(a){let c=i.getVariableDeclarations();for(let l of c){let g=l.getName();if(g.includes("QUERY")||g.includes("MUTATION")||g.includes("FRAGMENT")||g.includes("Query")||g.includes("Mutation")||g.includes("Subscription")||/^[A-Z_]+_(QUERY|MUTATION|FRAGMENT|SUBSCRIPTION)$/.test(g)||/Query$|Mutation$|Fragment$|Subscription$/.test(g)){let m=l.getInitializer();m&&m.isKind(SyntaxKind.CallExpression);}}}}catch(i){this.warn(`Failed to analyze ${s}: ${i.message}`);}return e}extractVariableNameFromCall(e){try{let t=e.getParent();for(;t;){if(t.isKind?.(SyntaxKind.VariableDeclaration))return t.getName?.()||null;t=t.getParent?.();}}catch{}return null}extractOperationsFromDocument(e,t){let s=[];for(let i of e.definitions){let o=this.extractOperation(i,t);o&&s.push(o);}return s}extractOperation(e,t){if(e.kind==="OperationDefinition"){let s=e.name?.value||"anonymous",i=e.operation,o=this.extractVariables(e),a=this.extractFragmentReferences(e),n=this.extractFields(e);return {name:s,type:i,filePath:t,usedIn:[],variables:o,returnType:this.inferReturnType(e),fragments:a,fields:n}}return e.kind==="FragmentDefinition"?{name:e.name.value,type:"fragment",filePath:t,usedIn:[],variables:[],returnType:e.typeCondition.name.value,fragments:this.extractFragmentReferences(e),fields:this.extractFields(e)}:null}extractFields(e){let t=[],s=(i,o=0)=>{if(!i||!i.selections||o>5)return [];let a=[];for(let n of i.selections)if(n.kind==="Field"){let r={name:n.name.value};if(n.arguments&&n.arguments.length>0){let c=n.arguments.map(l=>l.name.value).join(", ");r.type=`(${c})`;}n.selectionSet&&(r.fields=s(n.selectionSet,o+1)),a.push(r);}else if(n.kind==="FragmentSpread")a.push({name:`...${n.name.value}`,type:"fragment"});else if(n.kind==="InlineFragment"&&n.selectionSet){let r=n.typeCondition?.name?.value||"inline";a.push({name:`... on ${r}`,type:"inline-fragment",fields:s(n.selectionSet,o+1)});}return a};return e.selectionSet?s(e.selectionSet):t}extractVariables(e){let t=[];if(e.variableDefinitions)for(let s of e.variableDefinitions){let i=s.variable.name.value,o=this.typeNodeToString(s.type),a=s.type.kind==="NonNullType";t.push({name:i,type:o,required:a});}return t}typeNodeToString(e){return e.kind==="NonNullType"?`${this.typeNodeToString(e.type)}!`:e.kind==="ListType"?`[${this.typeNodeToString(e.type)}]`:e.kind==="NamedType"?e.name.value:"unknown"}extractFragmentReferences(e){let t=[],s=i=>{if(i&&(i.kind==="FragmentSpread"&&t.push(i.name.value),i.selectionSet))for(let o of i.selectionSet.selections)s(o);};return s(e),t}inferReturnType(e){if(e.selectionSet&&e.selectionSet.selections.length>0){let t=e.selectionSet.selections[0];if(t.kind==="Field")return t.name.value}return "unknown"}async findOperationUsage(e){if(e.length===0)return;let t=await Q(["**/*.ts","**/*.tsx"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**","**/__generated__/**"],absolute:true}),s=new Map,i=new Map,o=new Map;for(let l of e)if(s.set(l.name,l),i.set(`${l.name}Document`,l),l.variableNames)for(let g of l.variableNames)o.set(g,l);let a=new Set;for(let l of e)if(a.add(`${l.name}Document`),l.variableNames)for(let g of l.variableNames)a.add(g);let n=null,r=Array.from(a);if(r.length>0&&r.length<2e3){let l=r.sort((g,u)=>u.length-g.length).map(g=>g.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"));n=new RegExp(`\\b(${l.join("|")})\\b`,"g");}let c=50;for(let l=0;l<t.length;l+=c){let g=t.slice(l,l+c);await Promise.all(g.map(async u=>{try{let m=await _.readFile(u,"utf-8"),P=b.relative(this.basePath,u);if(!m.includes("Document")&&!m.includes("useQuery")&&!m.includes("useMutation")&&!m.includes("Query")&&!m.includes("Mutation")&&!m.includes("GET_")&&!m.includes("SEARCH_")&&!m.includes("CREATE_")&&!m.includes("UPDATE_")&&!m.includes("DELETE_"))return;if(n){let y=new Set,p;for(;(p=n.exec(m))!==null;)y.add(p[1]);n.lastIndex=0;for(let f of y){let d=i.get(f)||o.get(f);d&&P!==d.filePath&&(d.usedIn.includes(P)||d.usedIn.push(P));}}for(let[y,p]of s)P!==p.filePath&&(p.usedIn.includes(P)||(m.includes(`useQuery<${y}`)||m.includes(`useMutation<${y}`)||m.includes(`useLazyQuery<${y}`)||m.includes(`useSubscription<${y}`)||m.includes(`${y}Query`)||m.includes(`${y}Mutation`))&&p.usedIn.push(P));}catch{}}));}}};var W=class extends w{componentCache=new Map;constructor(e){super(e);}getName(){return "DataFlowAnalyzer"}async analyze(){this.log("Starting data flow analysis...");let e=await this.analyzeComponents(),t=await this.analyzeDataFlows(e);return this.log(`Analyzed ${e.length} components and ${t.length} data flows`),{components:e,dataFlows:t}}async analyzeComponents(){let e=[],t=[this.getSetting("featuresDir",""),this.getSetting("componentsDir",""),this.getSetting("pagesDir","")].filter(Boolean),s=["src/features","src/components","src/common/components","src/common","src/pages","src/app","src/modules","src/views","src/screens","components","pages","app"],o=[...new Set([...t,...s])].map(r=>`${r}/**/*.tsx`),a=await Q(o,{cwd:this.basePath,ignore:["**/*.test.*","**/*.spec.*","**/*.stories.*","**/node_modules/**","**/__generated__/**"],absolute:true,onlyFiles:true,unique:true});this.log(`[DataFlowAnalyzer] Found ${a.length} component files to analyze`);let n=100;for(let r=0;r<a.length;r+=n){let c=a.slice(r,r+n),l=await Promise.all(c.map(async g=>{try{let u=await _.readFile(g,"utf-8");return {filePath:g,content:u}}catch{return null}}));for(let g of l)if(g)try{let u=parseSync(g.content,{syntax:"typescript",tsx:!0,comments:!1}),m=b.relative(this.basePath,g.filePath),P=this.analyzeComponentFile(u,m,g.content);e.push(...P);}catch{}}return this.log(`[DataFlowAnalyzer] Extracted ${e.length} components`),this.buildDependencyGraph(e),e}analyzeComponentFile(e,t,s){let i=[],o=this.extractImports(e);for(let a of e.body){if(a.type==="ExportDeclaration"&&a.declaration?.type==="FunctionDeclaration"){let n=a.declaration.identifier?.value;if(n&&this.isComponentName(n)){let r=this.extractComponentInfo(n,t,s,o);i.push(r),this.componentCache.set(n,r);}}if(a.type==="FunctionDeclaration"){let n=a.identifier?.value;if(n&&this.isComponentName(n)){let r=this.extractComponentInfo(n,t,s,o);i.push(r),this.componentCache.set(n,r);}}if(a.type==="ExportDefaultDeclaration"&&a.decl?.type==="FunctionExpression"){let n=a.decl.identifier?.value;if(n&&this.isComponentName(n)){let r=this.extractComponentInfo(n,t,s,o);i.push(r),this.componentCache.set(n,r);}}if(a.type==="VariableDeclaration"){for(let n of a.declarations)if(n.id?.type==="Identifier"){let r=n.id.value;if(r&&(this.isComponentName(r)||r.startsWith("use"))&&n.init&&(n.init.type==="ArrowFunctionExpression"||n.init.type==="FunctionExpression")){let c=this.extractComponentInfo(r,t,s,o);i.push(c),this.componentCache.set(r,c);}}}if(a.type==="ExportDeclaration"&&a.declaration?.type==="VariableDeclaration"){for(let n of a.declaration.declarations)if(n.id?.type==="Identifier"){let r=n.id.value;if(r&&(this.isComponentName(r)||r.startsWith("use"))&&n.init&&(n.init.type==="ArrowFunctionExpression"||n.init.type==="FunctionExpression")){let c=this.extractComponentInfo(r,t,s,o);i.push(c),this.componentCache.set(r,c);}}}}return i}extractImports(e){let t=new Map;for(let s of e.body)if(s.type==="ImportDeclaration"){let i=s.source?.value||"";if(i.startsWith(".")||i.startsWith("@/"))for(let o of s.specifiers||[])o.type==="ImportSpecifier"&&o.local?.value&&t.set(o.local.value,i),o.type==="ImportDefaultSpecifier"&&o.local?.value&&t.set(o.local.value,i);}return t}isComponentName(e){return /^[A-Z][a-zA-Z0-9]*$/.test(e)}extractComponentInfo(e,t,s,i){let o="presentational";["/pages/","/app/","/routes/","/views/","/screens/"].some(l=>t.includes(l))?o="page":e.includes("Container")||e.includes("Provider")?o="container":e.includes("Layout")||e.includes("Shell")||e.includes("Wrapper")||e.includes("Frame")||e.includes("Scaffold")||t.includes("/layouts/")||t.includes("/layout/")?o="layout":e.startsWith("use")&&(o="hook");let n=this.extractHooksUsed(s),r=Array.from(i.keys()).filter(l=>this.isComponentName(l)||l.startsWith("use")),c=this.extractStateManagement(s);return {name:e,filePath:t,type:o,props:[],dependencies:r,dependents:[],hooks:n,stateManagement:c}}extractHooksUsed(e){let t=[],s=/\b(useQuery|useMutation|useLazyQuery)(?:<[^>]*>)?\s*\(\s*([A-Z_][A-Za-z0-9_]*)/g,i;for(;(i=s.exec(e))!==null;){let n=i[1],r=i[2];if(/^(Query|Mutation|QUERY|MUTATION)$/i.test(r))continue;let c=this.extractOperationName(r);if(n==="useQuery"||n==="useLazyQuery"){let l=c?`Query: ${c}`:`Query: ${r}`;t.includes(l)||t.push(l);}else if(n==="useMutation"){let l=c?`Mutation: ${c}`:`Mutation: ${r}`;t.includes(l)||t.push(l);}}let o=/\b(use[A-Z][a-zA-Z0-9]*)\s*\(/g,a;for(;(a=o.exec(e))!==null;){let n=a[1];if(!(n==="useQuery"||n==="useMutation"||n==="useLazyQuery"))if(n==="useContext"){let r=e.slice(a.index).match(/useContext\s*\(\s*([A-Z][A-Za-z0-9]*)/);if(r){let l=`\u{1F504} Context: ${r[1].replace(/Context$/,"")}`;t.includes(l)||t.push(l);}}else t.includes(n)||t.push(n);}return t}extractOperationName(e){if(!e)return null;let t=e.split(",")[0].trim();if(/^[{[\'"` ]/.test(t))return null;let s=t.replace(/^(GET_|FETCH_|CREATE_|UPDATE_|DELETE_)/,"").replace(/_QUERY$|_MUTATION$/,"").replace(/Document$/,"").replace(/Query$|Mutation$/,"");return !s||s.trim()===""||/^(QUERY|MUTATION)$/i.test(s.trim())?null:s}extractStateManagement(e){let t=[];return e.includes("useState")&&t.push("useState"),e.includes("useReducer")&&t.push("useReducer"),e.includes("useContext")&&t.push("useContext"),e.includes("useQuery")&&t.push("Apollo Query"),e.includes("useMutation")&&t.push("Apollo Mutation"),e.includes("useRecoil")&&t.push("Recoil"),(e.includes("useSelector")||e.includes("useDispatch"))&&t.push("Redux"),t}buildDependencyGraph(e){let t=new Map;for(let s of e)t.set(s.name,s);for(let s of e)for(let i of s.dependencies){let o=t.get(i);o&&!o.dependents.includes(s.name)&&o.dependents.push(s.name);}}async analyzeDataFlows(e){let t=[],s=1,i=this.analyzeContextFlows(e);t.push(...i.map(n=>({...n,id:`flow-${s++}`})));let o=this.analyzeApolloFlows(e);t.push(...o.map(n=>({...n,id:`flow-${s++}`})));let a=this.analyzePropDrilling(e);return t.push(...a.map(n=>({...n,id:`flow-${s++}`}))),t}analyzeContextFlows(e){let t=[],s=e.filter(o=>o.name.includes("Provider")||o.name.includes("Context")),i=e.filter(o=>o.hooks.some(a=>a.includes("Context")));for(let o of s){let a=o.name.replace("Provider","").replace("Context","");for(let n of i){let r=n.hooks.find(c=>c.includes("Context")&&c.includes(a));(r||n.hooks.some(c=>c.includes(a)))&&t.push({name:`\u{1F504} ${a} Context`,description:`Data flows from ${o.name} to ${n.name} via Context`,source:{type:"context",name:o.name},target:{type:"component",name:n.name},via:[],operations:[r||`useContext(${a})`]});}}return t}analyzeApolloFlows(e){let t=[];for(let s of e){let i=s.hooks.filter(a=>a.includes("Query:")||a==="useQuery"||a==="useLazyQuery");for(let a of i){let n=a.includes(":")?a.split(":")[1].trim():s.name;t.push({name:`Query: ${n}`,description:`${s.name} fetches ${n} via Apollo`,source:{type:"api",name:`GraphQL: ${n}`},target:{type:"component",name:s.name},via:[{type:"cache",name:"Apollo Cache"}],operations:[a]});}let o=s.hooks.filter(a=>a.includes("Mutation:")||a==="useMutation");for(let a of o){let n=a.includes(":")?a.split(":")[1].trim():s.name;t.push({name:`Mutation: ${n}`,description:`${s.name} mutates ${n} via Apollo`,source:{type:"component",name:s.name},target:{type:"api",name:`GraphQL: ${n}`},via:[],operations:[a]});}}return t}analyzePropDrilling(e){let t=[];for(let s of e)s.props.length>5&&s.dependents.length>0&&t.push({name:`Prop Drilling through ${s.name}`,description:`${s.name} passes ${s.props.length} props to children`,source:{type:"component",name:s.name},target:{type:"component",name:s.dependents[0]},via:[],operations:["props"]});return t}};var Z=class extends w{project;apiCallCounter=0;constructor(e){super(e),this.project=new Project({tsConfigFilePath:this.resolvePath("tsconfig.json"),skipAddingFilesFromTsConfig:true});}getName(){return "RestApiAnalyzer"}async analyze(){this.log("Starting REST API analysis...");let e=await Q(["**/*.ts","**/*.tsx"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**","**/__tests__/**","**/*.test.*","**/*.spec.*","**/*.stories.*","**/__generated__/**","**/dist/**","**/build/**"],absolute:true}),t=new Map;for(let o of e)try{t.set(o,this.project.addSourceFileAtPath(o));}catch{}let i=(await E(Array.from(t.entries()),async([o,a])=>{let n=b.relative(this.basePath,o),r=[];return r.push(...this.findFetchCalls(a,n)),r.push(...this.findAxiosCalls(a,n)),r.push(...this.findSwrCalls(a,n)),r},8)).flat();return this.log(`Found ${i.length} REST API calls`),{apiCalls:i}}findFetchCalls(e,t){let s=[],i=e.getDescendantsOfKind(SyntaxKind.CallExpression);for(let o of i)try{let n=o.getExpression().getText();if(n==="fetch"||n==="window.fetch"){let r=this.extractFetchCall(o,t);r&&s.push(r);}}catch{}return s}findAxiosCalls(e,t){let s=[],i=e.getDescendantsOfKind(SyntaxKind.CallExpression);for(let o of i)try{let n=o.getExpression().getText(),r=n.match(/^axios\.(get|post|put|delete|patch)$/i);if(r){let c=this.extractAxiosCall(o,t,r[1].toUpperCase());c&&s.push(c);}if(n==="axios"){let c=this.extractAxiosDirectCall(o,t);c&&s.push(c);}}catch{}return s}findSwrCalls(e,t){let s=[],i=e.getDescendantsOfKind(SyntaxKind.CallExpression);for(let o of i)try{let n=o.getExpression().getText();if(n==="useSWR"||n==="useSWRImmutable"){let r=this.extractSwrCall(o,t);r&&s.push(r);}}catch{}return s}extractFetchCall(e,t){let s=e.getArguments();if(s.length===0)return null;let i=s[0].getText(),o=this.extractUrlFromArg(i);if(!o.url||!o.isPlaceholder&&!this.isApiUrl(o.url))return null;let a="GET",n=false;if(s.length>1){let l=s[1].getText(),g=l.match(/method:\s*["'](\w+)["']/i);g&&(a=this.normalizeMethod(g[1])),n=l.includes("credentials")||l.includes("Authorization")||l.includes("withCredentials");}let r=this.getContainingFunctionName(e),c=e.getStartLineNumber();return {id:`api-${++this.apiCallCounter}`,method:a,url:o.url,callType:"fetch",filePath:t,line:c,containingFunction:r,usedIn:[],requiresAuth:n,category:this.categorizeApi(o.url)}}extractAxiosCall(e,t,s){let i=e.getArguments();if(i.length===0)return null;let o=i[0].getText(),a=this.extractUrlFromArg(o);if(!a.url)return null;let n=false;if(i.length>1){let l=i[i.length-1].getText();n=l.includes("withCredentials")||l.includes("Authorization");}let r=this.getContainingFunctionName(e),c=e.getStartLineNumber();return {id:`api-${++this.apiCallCounter}`,method:this.normalizeMethod(s),url:a.url,callType:"axios",filePath:t,line:c,containingFunction:r,usedIn:[],requiresAuth:n,category:this.categorizeApi(a.url)}}extractAxiosDirectCall(e,t){let s=e.getArguments();if(s.length===0)return null;let i=s[0].getText(),o=i.match(/url:\s*["'`]([^"'`]+)["'`]/),a=i.match(/method:\s*["'](\w+)["']/i);if(!o)return null;let n=o[1],r=a?this.normalizeMethod(a[1]):"GET",c=i.includes("withCredentials")||i.includes("Authorization"),l=this.getContainingFunctionName(e),g=e.getStartLineNumber();return {id:`api-${++this.apiCallCounter}`,method:r,url:n,callType:"axios",filePath:t,line:g,containingFunction:l,usedIn:[],requiresAuth:c,category:this.categorizeApi(n)}}extractSwrCall(e,t){let s=e.getArguments();if(s.length===0)return null;let i=s[0].getText(),o=null;if(i.startsWith('"')||i.startsWith("'")||i.startsWith("`"))o=this.cleanStringLiteral(i);else if(i.includes("?")&&i.includes(":")){let r=i.match(/\?\s*["'`]([^"'`]+)["'`]/);r?o=r[1]:(r=i.match(/:\s*["'`]([^"'`]+)["'`]/),r&&(o=r[1])),o||(r=i.match(/\?\s*`([^`]+)`/),r&&(o=r[1].replace(/\$\{[^}]+\}/g,":param")));}else {let r=this.extractUrlFromArg(i);r.url&&!i.includes("null")&&!i.includes("undefined")&&(o=r.url);}if(!o)return null;let a=this.getContainingFunctionName(e),n=e.getStartLineNumber();return {id:`api-${++this.apiCallCounter}`,method:"GET",url:o,callType:"useSWR",filePath:t,line:n,containingFunction:a,usedIn:[],requiresAuth:false,category:this.categorizeApi(o)}}getContainingFunctionName(e){let t=e;for(;t;){if(Node.isFunctionDeclaration(t))return t.getName()||"anonymous";if(Node.isVariableDeclaration(t)||Node.isMethodDeclaration(t))return t.getName();if(Node.isArrowFunction(t)){let s=t.getParent();if(s&&Node.isVariableDeclaration(s))return s.getName()}t=t.getParent();}return "unknown"}extractUrlFromArg(e){if(/^["'`]/.test(e))return {url:this.cleanStringLiteral(e),isPlaceholder:false};let t=e.match(/^(\w+)\s*\(\s*["'`]([^"'`]+)["'`]/);if(t)return {url:`[${t[1]}] ${t[2]}`,isPlaceholder:true};let s=e.match(/^(\w+)\s*\(\s*`([^`]+)`/);if(s){let i=s[2].replace(/\$\{[^}]+\}/g,":param");return {url:`[${s[1]}] ${i}`,isPlaceholder:true}}return /^\w+(\.\w+)*$/.test(e)?{url:`[${e}]`,isPlaceholder:true}:e.includes(".")?{url:`[${e}]`,isPlaceholder:true}:{url:null,isPlaceholder:false}}cleanStringLiteral(e){let t=e.replace(/^["'`]|["'`]$/g,"").trim();return t.includes("${")?t.replace(/\$\{[^}]+\}/g,":param"):t||null}isApiUrl(e){return e.startsWith("data:")||e.startsWith("blob:")||/\.(css|js|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot|html)$/i.test(e)?false:e.startsWith("/")||e.startsWith("http")||e.includes("/api/")||e.includes(".json")||e.includes("api.")||e.includes("github.io")||e.includes("hsforms.com")||e.includes("hubspot")||e.includes("amazonaws.com")||e.includes("s3.")||e.includes("googleapis.com")||e.includes("stripe.com")||e.includes("graph.facebook.com")||e.includes("api.twitter.com")||e.includes("slack.com")||e.includes("discord.com")||e.includes("sendgrid.com")||e.includes("twilio.com")||e.includes("firebase")||e.includes("supabase")||e.includes("auth0.com")||e.includes("okta.com")||e.includes("cloudflare.com")||e.includes("vercel.com")||e.includes("netlify.com")}categorizeApi(e){if(e.includes("hsforms.com")||e.includes("hubspot"))return "HubSpot";if(e.includes("amazonaws.com")||e.includes("s3."))return "AWS S3";if(e.includes("googleapis.com"))return "Google API";if(e.includes("stripe.com"))return "Stripe";if(e.includes("graph.facebook.com"))return "Facebook";if(e.includes("api.twitter.com"))return "Twitter";if(e.includes("slack.com"))return "Slack";if(e.includes("discord.com"))return "Discord";if(e.includes("sendgrid.com"))return "SendGrid";if(e.includes("twilio.com"))return "Twilio";if(e.includes("firebase"))return "Firebase";if(e.includes("supabase"))return "Supabase";if(e.includes("auth0.com"))return "Auth0";if(e.includes("okta.com"))return "Okta";if(e.includes("github.io"))return "GitHub Pages API";if(e.startsWith("/api/"))return "Internal API";if(e.startsWith("/"))return "Internal Route";if(e.startsWith("["))return "Dynamic URL"}normalizeMethod(e){let t=e.toUpperCase();return ["GET","POST","PUT","DELETE","PATCH"].includes(t)?t:"unknown"}};export{w as a,q as b,j as c,W as d,Z as e};
package/dist/cli.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import {a,b}from'./chunk-EYHNEFTO.js';import'./chunk-H4YGP3GL.js';import'./chunk-VV3A3UE3.js';import'./chunk-PSM6AV63.js';import'./chunk-XWZH2RDG.js';import'./chunk-MOEA75XK.js';import'./chunk-PTR5IROV.js';import {Command}from'commander';import n from'chalk';import*as p from'path';import*as s from'fs/promises';var d=new Command;d.name("repomap").description("Interactive documentation generator for code repositories").version("0.1.0");async function $(e){let o=p.basename(e),a=false,t=p.join(e,"Gemfile"),c=p.join(e,"config","routes.rb");try{await s.access(t),await s.access(c);let u=await s.readFile(t,"utf-8");a=u.includes("gem 'rails'")||u.includes('gem "rails"');}catch{}let r=p.join(e,"package.json"),i=false,l=false,m={};try{let u=JSON.parse(await s.readFile(r,"utf-8")),w={...u.dependencies,...u.devDependencies};i=!!w.react,l=!!w.next;let f=["src/pages","pages","app","src/app","frontend/src"];for(let g of f)try{await s.access(p.join(e,g)),m.pagesDir=g;break}catch{}let b=["src/features","features","src/modules","modules","frontend/src"];for(let g of b)try{await s.access(p.join(e,g)),m.featuresDir=g;break}catch{}let D=["src/components","components","src/common/components","frontend/src"];for(let g of D)try{await s.access(p.join(e,g)),m.componentsDir=g;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:o,displayName:o,description:a&&i?"Rails + React application":a?"Rails application":"",path:e,branch:"main",type:y,analyzers:h,settings:m}}async function x(e){let o=await $(e);if(!o)throw new Error("Could not detect project. Please create a repomap.config.ts file or run 'repomap init'.");return {outputDir:"./.repomap",site:{title:`${o.displayName} Documentation`,description:"Auto-generated documentation",baseUrl:"/docs"},repositories:[o],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 P(e,o){let a=e?[e]:["repomap.config.ts","repomap.config.js","repomap.config.mjs"];for(let t of a){let c=p.resolve(o,t);try{await s.access(c),console.log(n.gray(`Loading config from: ${c}`));let r=await import(c);return r.config||r.default}catch{}}return console.log(n.gray("No config file found, auto-detecting project...")),x(o)}d.command("generate").description("Generate documentation from source code").option("-c, --config <path>","Path to config file").option("-o, --output <path>","Output directory").option("--repo <name>","Analyze specific repository only").option("--watch","Watch for changes and regenerate").option("--no-cache","Disable caching (always analyze from scratch)").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 o=e.ci||process.env.CI==="true";o||console.log(n.blue.bold(`
2
+ import {a,b}from'./chunk-UR7HVBHH.js';import'./chunk-H4YGP3GL.js';import'./chunk-VV3A3UE3.js';import'./chunk-WJIBUCXB.js';import'./chunk-XWZH2RDG.js';import'./chunk-QZWPOG5B.js';import'./chunk-PTR5IROV.js';import {Command}from'commander';import n from'chalk';import*as p from'path';import*as s from'fs/promises';var d=new Command;d.name("repomap").description("Interactive documentation generator for code repositories").version("0.1.0");async function $(e){let o=p.basename(e),a=false,t=p.join(e,"Gemfile"),c=p.join(e,"config","routes.rb");try{await s.access(t),await s.access(c);let u=await s.readFile(t,"utf-8");a=u.includes("gem 'rails'")||u.includes('gem "rails"');}catch{}let r=p.join(e,"package.json"),i=false,l=false,m={};try{let u=JSON.parse(await s.readFile(r,"utf-8")),w={...u.dependencies,...u.devDependencies};i=!!w.react,l=!!w.next;let f=["src/pages","pages","app","src/app","frontend/src"];for(let g of f)try{await s.access(p.join(e,g)),m.pagesDir=g;break}catch{}let b=["src/features","features","src/modules","modules","frontend/src"];for(let g of b)try{await s.access(p.join(e,g)),m.featuresDir=g;break}catch{}let D=["src/components","components","src/common/components","frontend/src"];for(let g of D)try{await s.access(p.join(e,g)),m.componentsDir=g;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:o,displayName:o,description:a&&i?"Rails + React application":a?"Rails application":"",path:e,branch:"main",type:y,analyzers:h,settings:m}}async function x(e){let o=await $(e);if(!o)throw new Error("Could not detect project. Please create a repomap.config.ts file or run 'repomap init'.");return {outputDir:"./.repomap",site:{title:`${o.displayName} Documentation`,description:"Auto-generated documentation",baseUrl:"/docs"},repositories:[o],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 P(e,o){let a=e?[e]:["repomap.config.ts","repomap.config.js","repomap.config.mjs"];for(let t of a){let c=p.resolve(o,t);try{await s.access(c),console.log(n.gray(`Loading config from: ${c}`));let r=await import(c);return r.config||r.default}catch{}}return console.log(n.gray("No config file found, auto-detecting project...")),x(o)}d.command("generate").description("Generate documentation from source code").option("-c, --config <path>","Path to config file").option("-o, --output <path>","Output directory").option("--repo <name>","Analyze specific repository only").option("--watch","Watch for changes and regenerate").option("--no-cache","Disable caching (always analyze from scratch)").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 o=e.ci||process.env.CI==="true";o||console.log(n.blue.bold(`
3
3
  \u{1F4DA} Repomap - Documentation Generator
4
4
  `));try{let a$1=process.cwd(),t=await P(e.config,a$1);e.output&&(t.outputDir=e.output),e.repo&&(t.repositories=t.repositories.filter(r=>r.name===e.repo),t.repositories.length===0&&(console.error(n.red(`Repository "${e.repo}" not found in config`)),process.exit(1)));let c=new a(t,{noCache:!e.cache});if(e.watch)console.log(n.yellow(`
5
5
  \u{1F440} Watch mode enabled. Press Ctrl+C to stop.
6
6
  `)),await C(c,t);else {let r=await c.generate();if(e.format==="json"||e.static){let i=p.join(t.outputDir,"report.json");await s.mkdir(t.outputDir,{recursive:!0}),await s.writeFile(i,JSON.stringify(r,null,2)),o||console.log(n.green(`\u{1F4C4} JSON report: ${i}`));}if(e.static&&await G(t,r,o),!o)N(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(o?`Error: ${a.message}`:n.red(`
7
- \u274C Error:`),a.message),process.exit(1);}});async function G(e,o,a){let{PageMapGenerator:t}=await import('./page-map-generator-XNZ4TDJT.js'),{detectEnvironments:c}=await import('./env-detector-BIWJ7OYF.js'),r=e.outputDir;await s.mkdir(r,{recursive:true});let i=e.repositories[0]?.path||process.cwd(),l=await c(i),m=null;if(l.hasRails){let{analyzeRailsApp:f}=await import('./rails-FFISZ4AE.js');m=await f(i);}let y=new t().generatePageMapHtml(o,{envResult:l,railsAnalysis:m,staticMode:true});if(await s.writeFile(p.join(r,"index.html"),y),a||console.log(n.green(`\u{1F4C4} Static page map: ${p.join(r,"index.html")}`)),m){let{RailsMapGenerator:f}=await import('./rails-map-generator-UFLCMFAT.js'),D=new f().generateFromResult(m);await s.writeFile(p.join(r,"rails-map.html"),D),a||console.log(n.green(`\u{1F4C4} Static Rails map: ${p.join(r,"rails-map.html")}`));}let u=["common.css","page-map.css","docs.css","rails-map.css"],w=p.join(r,"assets");await s.mkdir(w,{recursive:true});for(let f of u)try{let b=new URL(`./generators/assets/${f}`,import.meta.url),D=await s.readFile(b,"utf-8");await s.writeFile(p.join(w,f),D);}catch{}a||(console.log(n.green(`
7
+ \u274C Error:`),a.message),process.exit(1);}});async function G(e,o,a){let{PageMapGenerator:t}=await import('./page-map-generator-HBKSOX2E.js'),{detectEnvironments:c}=await import('./env-detector-BIWJ7OYF.js'),r=e.outputDir;await s.mkdir(r,{recursive:true});let i=e.repositories[0]?.path||process.cwd(),l=await c(i),m=null;if(l.hasRails){let{analyzeRailsApp:f}=await import('./rails-FFISZ4AE.js');m=await f(i);}let y=new t().generatePageMapHtml(o,{envResult:l,railsAnalysis:m,staticMode:true});if(await s.writeFile(p.join(r,"index.html"),y),a||console.log(n.green(`\u{1F4C4} Static page map: ${p.join(r,"index.html")}`)),m){let{RailsMapGenerator:f}=await import('./rails-map-generator-UFLCMFAT.js'),D=new f().generateFromResult(m);await s.writeFile(p.join(r,"rails-map.html"),D),a||console.log(n.green(`\u{1F4C4} Static Rails map: ${p.join(r,"rails-map.html")}`));}let u=["common.css","page-map.css","docs.css","rails-map.css"],w=p.join(r,"assets");await s.mkdir(w,{recursive:true});for(let f of u)try{let b=new URL(`./generators/assets/${f}`,import.meta.url),D=await s.readFile(b,"utf-8");await s.writeFile(p.join(w,f),D);}catch{}a||(console.log(n.green(`
8
8
  \u2705 Static site generated in: ${r}`)),console.log(n.gray(" Deploy to GitHub Pages or any static hosting")));}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("-p, --port <number>","Server port","3030").option("--no-open","Don't open browser automatically").option("--no-cache","Disable caching (always analyze from scratch)").action(async e=>{console.log(n.blue.bold(`
9
9
  \u{1F310} Repomap - Documentation Server
10
10
  `));try{let o=e.path||process.cwd(),a=await P(e.config,o);await new b(a,parseInt(e.port),{noCache:!e.cache}).start(!e.open);}catch(o){console.error(n.red(`
@@ -164,6 +164,11 @@ declare class GraphQLAnalyzer extends BaseAnalyzer {
164
164
  private inferReturnTypeFromAst;
165
165
  private analyzeGraphQLFiles;
166
166
  private analyzeInlineGraphQL;
167
+ /**
168
+ * Extract variable name from parent declaration
169
+ * e.g., export const GET_USER = graphql(`...`) -> "GET_USER"
170
+ */
171
+ private extractVariableNameFromCall;
167
172
  private extractOperationsFromDocument;
168
173
  private extractOperation;
169
174
  private extractFields;
@@ -175,25 +180,21 @@ declare class GraphQLAnalyzer extends BaseAnalyzer {
175
180
  }
176
181
 
177
182
  /**
178
- * Analyzer for data flow patterns
179
- * データフローパターンの分析器
183
+ * Analyzer for data flow patterns using @swc/core for fast parsing
184
+ * データフローパターンの分析器 (@swc/core使用)
180
185
  */
181
186
  declare class DataFlowAnalyzer extends BaseAnalyzer {
182
- private project;
183
187
  private componentCache;
184
188
  constructor(config: RepositoryConfig);
185
189
  getName(): string;
186
190
  analyze(): Promise<Partial<AnalysisResult>>;
187
191
  private analyzeComponents;
188
192
  private analyzeComponentFile;
193
+ private extractImports;
189
194
  private isComponentName;
190
195
  private extractComponentInfo;
191
- private extractHookInfo;
192
- private extractProps;
193
196
  private extractHooksUsed;
194
197
  private extractOperationName;
195
- private extractContextName;
196
- private extractDependencies;
197
198
  private extractStateManagement;
198
199
  private buildDependencyGraph;
199
200
  private analyzeDataFlows;
@@ -186,6 +186,8 @@ body { background: var(--bg); color: var(--text); }
186
186
  .detail-item > span:not(.tag), .detail-item > code { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
187
187
  .detail-label { font-size: 9px; color: var(--text2); margin-bottom: 2px; }
188
188
  .detail-items { max-height: 300px; overflow-y: auto; }
189
+ .more-link { color: var(--accent); font-size: 11px; padding: 6px 4px; cursor: pointer; transition: all 0.15s; }
190
+ .more-link:hover { color: var(--accent-light); background: var(--bg3); border-radius: 4px; }
189
191
  .code-path { background: var(--bg3); padding: 10px; border-radius: 6px; font-family: monospace; font-size: 12px; word-break: break-all; }
190
192
  .usage-name { font-family: monospace; font-weight: 500; word-break: break-all; min-width: 0; }
191
193
  .line-num { margin-left: auto; font-size: 10px; color: var(--text2); flex-shrink: 0; }
@@ -1 +1 @@
1
- export{b as MarkdownGenerator,a as MermaidGenerator}from'../chunk-XWZH2RDG.js';export{a as PageMapGenerator}from'../chunk-MOEA75XK.js';
1
+ export{b as MarkdownGenerator,a as MermaidGenerator}from'../chunk-XWZH2RDG.js';export{a as PageMapGenerator}from'../chunk-QZWPOG5B.js';
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { DocGeneratorConfig, DocumentationReport } from './types.js';
2
2
  export { APICall, APIConnection, APIEndpoint, AnalysisConfig, AnalysisResult, AnalyzerType, AssociationInfo, AttributeInfo, AuthRequirement, ComponentInfo, CrossRepoAnalysis, CrossRepoLink, DataFetchingInfo, DataFlow, DataFlowNode, DiagramConfig, DiagramType, GraphQLField, GraphQLOperation, IntegrationsConfig, MermaidDiagram, ModelInfo, NavigationFlow, NavigationInfo, PageInfo, ParameterInfo, PropInfo, RepositoryConfig, RepositoryReport, RepositorySummary, ResponseInfo, SiteConfig, StepInfo, VariableInfo, WatchConfig } from './types.js';
3
- export { B as BaseAnalyzer, D as DataFlowAnalyzer, G as GraphQLAnalyzer, P as PagesAnalyzer } from './dataflow-analyzer-LeE44O3x.js';
3
+ export { B as BaseAnalyzer, D as DataFlowAnalyzer, G as GraphQLAnalyzer, P as PagesAnalyzer } from './dataflow-analyzer-mlxaq5qn.js';
4
4
  export { MarkdownGenerator, MermaidGenerator, PageMapGenerator, PageMapOptions } from './generators/index.js';
5
5
  export { DocServer, DocServerOptions } from './server/index.js';
6
6
 
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import'./chunk-6F4PWJZI.js';export{a as DocGeneratorEngine,b as DocServer}from'./chunk-EYHNEFTO.js';import'./chunk-H4YGP3GL.js';import'./chunk-VV3A3UE3.js';export{a as BaseAnalyzer,d as DataFlowAnalyzer,c as GraphQLAnalyzer,b as PagesAnalyzer}from'./chunk-PSM6AV63.js';export{b as MarkdownGenerator,a as MermaidGenerator}from'./chunk-XWZH2RDG.js';export{a as PageMapGenerator}from'./chunk-MOEA75XK.js';import'./chunk-PTR5IROV.js';
1
+ import'./chunk-6F4PWJZI.js';export{a as DocGeneratorEngine,b as DocServer}from'./chunk-UR7HVBHH.js';import'./chunk-H4YGP3GL.js';import'./chunk-VV3A3UE3.js';export{a as BaseAnalyzer,d as DataFlowAnalyzer,c as GraphQLAnalyzer,b as PagesAnalyzer}from'./chunk-WJIBUCXB.js';export{b as MarkdownGenerator,a as MermaidGenerator}from'./chunk-XWZH2RDG.js';export{a as PageMapGenerator}from'./chunk-QZWPOG5B.js';import'./chunk-PTR5IROV.js';
@@ -0,0 +1 @@
1
+ export{a as PageMapGenerator}from'./chunk-QZWPOG5B.js';
@@ -1 +1 @@
1
- export{b as DocServer}from'../chunk-EYHNEFTO.js';import'../chunk-H4YGP3GL.js';import'../chunk-VV3A3UE3.js';import'../chunk-PSM6AV63.js';import'../chunk-XWZH2RDG.js';import'../chunk-MOEA75XK.js';import'../chunk-PTR5IROV.js';
1
+ export{b as DocServer}from'../chunk-UR7HVBHH.js';import'../chunk-H4YGP3GL.js';import'../chunk-VV3A3UE3.js';import'../chunk-WJIBUCXB.js';import'../chunk-XWZH2RDG.js';import'../chunk-QZWPOG5B.js';import'../chunk-PTR5IROV.js';
package/dist/types.d.ts CHANGED
@@ -149,6 +149,8 @@ interface GraphQLOperation {
149
149
  returnType: string;
150
150
  fragments: string[];
151
151
  fields: GraphQLField[];
152
+ /** Variable names that reference this operation (e.g., GET_USER_QUERY, GetUserDocument) */
153
+ variableNames?: string[];
152
154
  }
153
155
  interface GraphQLField {
154
156
  name: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wtdlee/repomap",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "description": "Interactive documentation generator for code repositories - visualize pages, components, GraphQL operations, and data flows",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -77,6 +77,7 @@
77
77
  "dependencies": {
78
78
  "@babel/parser": "^7.23.0",
79
79
  "@babel/traverse": "^7.23.0",
80
+ "@swc/core": "^1.15.3",
80
81
  "chalk": "^5.3.0",
81
82
  "commander": "^14.0.2",
82
83
  "express": "^5.2.1",
@@ -1,2 +0,0 @@
1
- import {Project,Node,SyntaxKind}from'ts-morph';import z from'fast-glob';import*as F from'path';import*as W from'fs';import*as O from'fs/promises';import {parse}from'graphql';var D=class{config;basePath;constructor(e){this.config=e,this.basePath=e.path;}resolvePath(e){return `${this.basePath}/${e}`}getSetting(e,t=""){return this.config.settings[e]??t}log(e){console.log(`[${this.getName()}] ${e}`);}warn(e){console.warn(`[${this.getName()}] \u26A0\uFE0F ${e}`);}error(e,t){console.error(`[${this.getName()}] \u274C ${e}`,t?.message||"");}};async function E(T,e,t=8){let n=new Array(T.length).fill(null),s=0;async function i(){for(;s<T.length;){let o=s++;if(o<T.length)try{n[o]=await e(T[o],o);}catch{n[o]=null;}}}let a=Array(Math.min(t,T.length)).fill(null).map(()=>i());return await Promise.all(a),n.filter(o=>o!==null)}var q=class extends D{project;codegenMap=new Map;constructor(e){super(e),this.project=new Project({tsConfigFilePath:this.resolvePath("tsconfig.json"),skipAddingFilesFromTsConfig:true});}extractOperationNameFromGql(e){let t=e.match(/(?:query|mutation|subscription)\s+(\w+)/);if(t&&t[1])return t[1];let n=e.match(/`\s*(?:query|mutation|subscription)\s+(\w+)/);if(n&&n[1])return n[1];let s=e.match(/GraphQL[^`]*`\s*(?:\n\s*)?(?:query|mutation|subscription)\s+(\w+)/);return s&&s[1]?s[1]:null}findOperationNameFromVariable(e,t){let n=e.getVariableDeclaration(t);if(!n){let o=e.getExportedDeclarations().get(t);if(o&&o.length>0){let r=o[0];Node.isVariableDeclaration(r)&&(n=r);}}if(n||(n=e.getVariableDeclarations().find(o=>o.getName()===t)),!n){let a=e.getFullText(),o=[new RegExp(`(?:const|let|var)\\s+${t}\\s*=\\s*gql\\s*\\(\\s*/\\*[^*]*\\*/\\s*\`\\s*(?:query|mutation|subscription)\\s+(\\w+)`,"s"),new RegExp(`(?:const|let|var)\\s+${t}\\s*=\\s*gql\`\\s*(?:query|mutation|subscription)\\s+(\\w+)`,"s"),new RegExp(`(?:const|let|var)\\s+${t}\\s*=\\s*gql\\s*\\(\`\\s*(?:query|mutation|subscription)\\s+(\\w+)`,"s"),new RegExp(`(?:const|let|var)\\s+${t}\\s*=\\s*graphql\\s*\\(\`\\s*(?:query|mutation|subscription)\\s+(\\w+)`,"s")];for(let r of o){let c=a.match(r);if(c&&c[1])return c[1]}return null}let s=n.getInitializer();if(!s)return null;let i=s.getText();return this.extractOperationNameFromGql(i)}getName(){return "PagesAnalyzer"}async analyze(){this.log("Starting page analysis..."),await this.loadCodegenMapping(),await this.analyzeAppFile();let e=await this.findPageFiles();this.log(`Found ${e.length} page files`);for(let s of e)try{this.project.addSourceFileAtPath(s);}catch{}let n=(await E(e,async s=>{let i=this.detectPagesRoot(s);return this.analyzePageFile(s,i)},4)).filter(s=>s!==null);return this.log(`Analyzed ${n.length} pages successfully`),{pages:n}}async analyzePageFile(e,t){let n=this.project.getSourceFile(e);if(!n)return null;let s=F.relative(t,e),i=this.filePathToRoutePath(s),a=this.findPageComponent(n);if(!a)return null;let o=this.extractRouteParams(i),r=this.extractLayout(n),c=this.extractAuthRequirement(n),l=this.extractPermissions(n),g=this.extractDataFetching(n),u=this.extractNavigation(n),d=this.extractLinkedPages(n),S=this.extractSteps(n);return {path:i,filePath:s,component:a,params:o,layout:r,authentication:c,permissions:l,dataFetching:g,navigation:u,linkedPages:d,steps:S.length>0?S:void 0}}detectPagesRoot(e){let t=["/src/pages/","/pages/","/src/app/","/app/","/frontend/src/pages/","/app/javascript/pages/"];for(let n of t){let s=e.indexOf(n);if(s!==-1)return e.substring(0,s+n.length-1)}return this.basePath}filePathToRoutePath(e){return "/"+e.replace(/\.tsx?$/,"").replace(/\/index$/,"").replace(/\[\.\.\.(\w+)\]/g,"*").replace(/\[(\w+)\]/g,":$1")}extractRouteParams(e){let t=[],n=/:(\w+)/g,s;for(;(s=n.exec(e))!==null;)t.push(s[1]);return t}findPageComponent(e){let t=e.getDefaultExportSymbol();if(t){let o=t.getName();if(o!=="default")return o}let n=e.getExportAssignment(o=>!o.isExportEquals());if(n){let o=n.getExpression();if(o){let r=o.getText();if(/^[A-Z][a-zA-Z0-9]*$/.test(r))return r;if(Node.isFunctionExpression(o)||Node.isArrowFunction(o))return "default"}}let s=e.getFunctions();for(let o of s)if(o.isDefaultExport())return o.getName()||"default";if(e.getVariableDeclaration("Page"))return "Page";let a=e.getVariableDeclarations();for(let o of a){let r=o.getTypeNode();if(r){let c=r.getText();if(c.includes("NextPage")||c.includes("FC")||c.includes("React.FC"))return o.getName()}}for(let o of a){let r=o.getName();if(/^[A-Z][a-zA-Z0-9]*$/.test(r)){let c=o.getInitializer();if(c&&(Node.isArrowFunction(c)||Node.isFunctionExpression(c))){let l=c.getText();if(l.includes("return")&&(l.includes("<")||l.includes("jsx")))return r}}}return null}extractLayout(e){let t=e.getDescendantsOfKind(SyntaxKind.PropertyAccessExpression).find(n=>n.getName()==="getLayout");if(t){let n=t.getParent();if(Node.isBinaryExpression(n)){let i=n.getRight().getDescendantsOfKind(SyntaxKind.JsxOpeningElement);if(i.length>0)return i[0].getTagNameNode().getText()}}}extractAuthRequirement(e){let n=e.getFilePath().split("/").pop()||"",a={required:!["404.tsx","permission-denied.tsx","_app.tsx","_document.tsx","_error.tsx"].some(o=>n===o)};try{let o=["RequiredCondition","ProtectedRoute","AuthGuard","PrivateRoute","WithAuth","RequireAuth","Authenticated","Authorized"],r=e.getDescendantsOfKind(SyntaxKind.JsxOpeningElement).find(c=>{let l=c.getTagNameNode().getText();return o.some(g=>l.includes(g))});if(r){a.condition="Additional permissions required";let c=r.getAttributes();for(let l of c)if(l.isKind(SyntaxKind.JsxAttribute))try{let g=l.getNameNode().getText();if(["condition","roles","permissions","requiredRoles","allowedRoles"].includes(g)){let u=l.getInitializer();if(u){a.condition=u.getText();let d=this.extractRolesFromCondition(u.getText());d.length>0&&(a.roles=d);}}}catch{}}}catch{}return a}extractRolesFromCondition(e){let t=[],n=/(\w+Role|\w+Permission)\.(\w+)/g,s;for(;(s=n.exec(e))!==null;)t.push(s[2]);let i=/['"]([a-zA-Z_-]+)['"]/g;for(;(s=i.exec(e))!==null;){let o=s[1];/admin|user|owner|member|guest|manager|editor|viewer/i.test(o)&&t.push(o);}let a=/\b(ROLE_\w+|[A-Z]+_ROLE)\b/g;for(;(s=a.exec(e))!==null;)t.push(s[1]);return [...new Set(t)]}extractPermissions(e){let t=[],n=e.getDescendantsOfKind(SyntaxKind.PropertyAccessExpression).filter(s=>{let i=s.getText();return i.includes("Permission")||i.includes("Role")||i.includes("isAdmin")});for(let s of n){let i=s.getText();t.includes(i)||t.push(i);}return t}extractDataFetching(e){let t=[],n=new Map,s=["useQuery","useMutation","useLazyQuery","useSubscription"];for(let h of e.getImportDeclarations()){let p=h.getModuleSpecifierValue();if(p.includes("@apollo/client")||p.includes("apollo"))for(let f of h.getNamedImports()){let y=f.getName(),m=f.getAliasNode()?.getText()||y;s.includes(y)&&n.set(m,y);}}let i=n.size>0||e.getImportDeclarations().some(h=>{let p=h.getModuleSpecifierValue();return p.includes("@apollo/client")||p.includes("apollo")}),a=e.getDescendantsOfKind(SyntaxKind.CallExpression).filter(h=>{let p=h.getExpression().getText();return !!(n.has(p)||s.includes(p)||/^use[A-Z].*Query$/.test(p)&&!p.includes("Params")&&!p.includes("String")||/^use[A-Z].*Mutation$/.test(p))});for(let h of a){let p=h.getExpression().getText(),f;n.has(p)?f=n.get(p):p.includes("Mutation")?f="useMutation":p.includes("Lazy")?f="useLazyQuery":f="useQuery";let y=h.getArguments();if(y.length===0){if(/^use[A-Z]/.test(p)){let N=p.replace(/^use/,"").replace(/Query$|Mutation$/,"");t.push({type:f,operationName:N,variables:[]});}continue}let x=y[0].getText();if(x.startsWith("[")||x.startsWith("{")||x.startsWith("'")||x.startsWith('"')||x.startsWith("`")||!(i||x.endsWith("Document")||x.endsWith("Query")||x.endsWith("Mutation")||x.includes("gql")||/^[A-Z_]+$/.test(x)))continue;let P=x.replace(/Document$/,"").replace(/Query$|Mutation$/,""),C=[];if(y.length>1){let w=y[1].getDescendantsOfKind(SyntaxKind.PropertyAssignment).find(b=>{try{return b.getName()==="variables"}catch{return false}});if(w){let b=w.getInitializer();if(b){let k=b.getDescendantsOfKind(SyntaxKind.PropertyAssignment);for(let Z of k)try{C.push(Z.getName());}catch{}}}}t.push({type:f,operationName:P,variables:C});}let o=e.getVariableDeclaration("getServerSideProps"),r=e.getFunction("getServerSideProps"),c=o||r;if(c){let h=e.getImportDeclarations();for(let y of h){let m=y.getNamedImports();for(let x of m){let A=x.getName();if(A.endsWith("Document")&&e.getDescendantsOfKind(SyntaxKind.Identifier).filter(C=>C.getText()===A).length>0){let C=A.replace(/Document$/,"");t.push({type:"getServerSideProps",operationName:`\u2192 ${C}`});}}}let f=c.getText().match(/query:\s*(\w+)/g);if(f)for(let y of f){let m=y.replace(/query:\s*/,"");t.some(x=>x.operationName?.includes(m.replace(/Document$/,"")))||t.push({type:"getServerSideProps",operationName:`\u2192 ${m.replace(/Document$/,"")}`});}}let l=e.getVariableDeclaration("getStaticProps"),g=e.getFunction("getStaticProps");(l||g)&&t.push({type:"getStaticProps",operationName:"getStaticProps"});let u=e.getImportDeclarations(),d=e.getFilePath(),S=F.dirname(d);for(let h of u){let p=h.getModuleSpecifierValue(),f=p.startsWith(".")||p.startsWith("/"),y=!p.includes("node_modules")&&!p.startsWith("@types/")&&p.startsWith("@")===false;if(f||y){if(p.includes("__generated__")||p.includes("/generated/"))continue;let m=[],x=h.getNamedImports();for(let P of x){let C=P.getName();this.isComponentName(C)&&m.push(C);}let A=h.getDefaultImport();if(A){let P=A.getText();this.isComponentName(P)&&m.push(P);}for(let P of m){let C=this.analyzeImportedComponent(S,p,P);if(C.length>0)for(let N of C)t.push({type:N.type,operationName:N.operationName.startsWith("\u2192")?`\u2192 ${N.operationName} (${P})`:`\u2192 ${N.operationName} (${P})`,variables:N.variables});else t.push({type:"component",operationName:P,variables:[]});}}}return t}symbolTraceCache=new Map;analyzeImportedComponent(e,t,n,s=new Set,i=0){if(i>10)return [];let o=[];try{let r=F.resolve(e,t),c=`${r}:${n}`;if(s.has(c))return [];s.add(c);let l=this.symbolTraceCache.get(c);if(l!==void 0)return l;let g=[`${r}.tsx`,`${r}.ts`,`${r}/index.tsx`,`${r}/index.ts`,`${r}/${n}.tsx`,`${r}/${n}.ts`],u,d;for(let p of g)try{if(u=this.project.addSourceFileAtPath(p),u){d=p;break}}catch{}if(!u||!d)return o;if(d.endsWith("index.tsx")||d.endsWith("index.ts")){let p=this.followReExport(u,n,F.dirname(d));p&&(u=p);}let S=u.getImportDeclarations().some(p=>{let f=p.getModuleSpecifierValue();return f.includes("@apollo/client")||f.includes("apollo")||f.includes("gql")||f.includes("graphql")||f.includes("__generated__")}),h=u.getImportDeclarations().filter(p=>{let f=p.getModuleSpecifierValue();return f.startsWith("./")||f.startsWith("../")});for(let p of h){let f=p.getModuleSpecifierValue(),y=p.getNamedImports().map(m=>m.getName()).filter(m=>/^use[A-Z]/.test(m));for(let m of y){let x=this.analyzeCustomHook(F.dirname(u.getFilePath()),f,m,s,i+1);o.push(...x);}}for(let p of h){let f=p.getModuleSpecifierValue(),y=p.getNamedImports().map(A=>A.getName()),m=p.getDefaultImport()?.getText(),x=y.filter(A=>/^[A-Z]/.test(A)&&this.isComponentName(A));for(let A of x){let P=this.analyzeImportedComponent(F.dirname(u.getFilePath()),f,A,s,i+1);o.push(...P);}if(m&&/^[A-Z]/.test(m)&&this.isComponentName(m)){let A=this.analyzeImportedComponent(F.dirname(u.getFilePath()),f,m,s,i+1);o.push(...A);}}if(S){let p=u.getDescendantsOfKind(SyntaxKind.CallExpression).filter(f=>{let y=f.getExpression().getText();return ["useQuery","useMutation","useLazyQuery","useSubscription"].includes(y)});for(let f of p){let y=f.getExpression().getText(),m=f.getArguments();if(m.length===0)continue;let A=m[0].getText(),P=A,C=null,N=this.resolveDocumentName(A);if(N)P=N.operationName,C=N.operationType;else if(A.endsWith("Document"))P=A.replace(/Document$/,"");else if(/^[A-Za-z]/.test(A)){let b=this.findOperationNameFromVariable(u,A);if(b&&(P=b),P===A&&A!=="Query"&&A!=="Mutation"){let k=A.match(/^(.+?)(Query|Mutation|Subscription)$/);k&&(P=k[1]);}}P!=="Query"&&P!=="Mutation"&&(P=P.replace(/Document$/,"").replace(/Query$|Mutation$/,"")||P),(P==="Query"||P==="Mutation"||P==="")&&P===""&&(P=A||"Unknown");let w=C?C==="mutation"?"useMutation":C==="subscription"?"useSubscription":y.includes("Lazy")?"useLazyQuery":"useQuery":y.includes("Mutation")?"useMutation":y.includes("Lazy")?"useLazyQuery":"useQuery";o.push({type:w,operationName:P,variables:[]});}}this.symbolTraceCache.set(c,o);}catch{}return o}analyzeCustomHook(e,t,n,s=new Set,i=0){if(i>10)return [];let o=[];try{let r=F.resolve(e,t),c=`hook:${r}:${n}`;if(s.has(c))return [];s.add(c);let l=this.symbolTraceCache.get(c);if(l!==void 0)return l;let g=[`${r}.tsx`,`${r}.ts`,`${r}/${n}.tsx`,`${r}/${n}.ts`,`${r}/index.tsx`,`${r}/index.ts`],u;for(let p of g)try{if(u=this.project.addSourceFileAtPath(p),u)break}catch{}if(!u)return o;let d=u.getImportDeclarations().some(p=>{let f=p.getModuleSpecifierValue();return f.includes("@apollo/client")||f.includes("apollo")||f.includes("graphql")||f.includes("__generated__")}),S=u.getImportDeclarations().filter(p=>{let f=p.getModuleSpecifierValue();return f.startsWith("./")||f.startsWith("../")});for(let p of S){let f=p.getModuleSpecifierValue(),y=p.getNamedImports().map(m=>m.getName()).filter(m=>/^use[A-Z]/.test(m));for(let m of y){let x=this.analyzeCustomHook(F.dirname(u.getFilePath()),f,m,s,i+1);o.push(...x);}}if(!d&&o.length===0)return o;let h=u.getDescendantsOfKind(SyntaxKind.CallExpression).filter(p=>{let f=p.getExpression().getText();return ["useQuery","useMutation","useLazyQuery","useSubscription"].includes(f)});for(let p of h){let f=p.getExpression().getText(),y=p.getArguments();if(y.length===0)continue;let m=y[0].getText(),x=m,A=null,P=this.resolveDocumentName(m);if(P)x=P.operationName,A=P.operationType;else if(m.endsWith("Document"))x=m.replace(/Document$/,"");else if(/^[A-Za-z]/.test(m)){let N=this.findOperationNameFromVariable(u,m);if(N&&(x=N),x===m&&m!=="Query"&&m!=="Mutation"){let w=m.match(/^(.+?)(Query|Mutation|Subscription)$/);w&&(x=w[1]);}}x!=="Query"&&x!=="Mutation"&&(x=x.replace(/Document$/,"").replace(/Query$|Mutation$/,"")||x),x===""&&(x=m||"Unknown");let C=A?A==="mutation"?"useMutation":A==="subscription"?"useSubscription":f.includes("Lazy")?"useLazyQuery":"useQuery":f.includes("Mutation")?"useMutation":f.includes("Lazy")?"useLazyQuery":"useQuery";o.push({type:C,operationName:`\u2192 ${x} (via ${n})`,variables:[]});}this.symbolTraceCache.set(c,o);}catch{}return o}globalContextQueries=[];async findPageFiles(){let e=this.getSetting("pagesDir","src/pages"),t=[],s=[...new Set([e,"pages","src/pages","app","src/app"])];for(let o of s){if(o==="app"||o==="src/app"){let c=["controllers","models","views","helpers"],l=this.resolvePath(o);if(c.some(u=>{try{return W.existsSync(F.join(l,u))}catch{return false}}))continue}let r=this.resolvePath(o);try{let c=await z(["**/*.tsx","**/*.ts","**/*.jsx","**/*.js"],{cwd:r,ignore:["_app.tsx","_app.ts","_app.jsx","_app.js","_document.tsx","_document.ts","_document.jsx","_document.js","_error.tsx","_error.ts","_error.jsx","_error.js","api/**","**/*.test.*","**/*.spec.*","**/node_modules/**","**/components/pages/**"],absolute:!0});t.push(...c),c.length>0&&this.log(`Found ${c.length} pages in ${o}`);}catch{}}let i=["frontend/src/**/pages","app/javascript/**/pages"];for(let o of i)try{let r=await z([`${o}/**/*.tsx`,`${o}/**/*.ts`,`${o}/**/*.jsx`,`${o}/**/*.js`],{cwd:this.basePath,ignore:["**/*.test.*","**/*.spec.*","**/node_modules/**","**/vendor/**","**/components/pages/**","**/stories/**"],absolute:!0});t.push(...r),r.length>0&&this.log(`Found ${r.length} React pages in ${o}`);}catch{}let a=["frontend/src/**/index.tsx","frontend/src/**/App.tsx","app/javascript/packs/*.tsx","app/javascript/packs/*.jsx"];for(let o of a)try{let r=await z([o],{cwd:this.basePath,ignore:["**/node_modules/**","**/vendor/**"],absolute:!0});for(let c of r)t.includes(c)||t.push(c);}catch{}return [...new Set(t)]}async analyzeAppFile(){let e=this.getSetting("pagesDir","src/pages"),t=[this.resolvePath(`${e}/_app.tsx`),this.resolvePath(`${e}/_app.ts`)];for(let n of t)try{let s=this.project.addSourceFileAtPath(n);if(!s)continue;let i=s.getDescendantsOfKind(SyntaxKind.JsxElement),a=s.getDescendantsOfKind(SyntaxKind.JsxSelfClosingElement),o=new Set;for(let r of [...i,...a]){let c=r.getFirstDescendantByKind(SyntaxKind.Identifier)?.getText();c&&(c.includes("Provider")||c.includes("Context"))&&o.add(c);}for(let r of s.getImportDeclarations()){let c=r.getModuleSpecifierValue();if(!c.startsWith("./")&&!c.startsWith("../"))continue;let l=r.getNamedImports().map(u=>u.getName()),g=r.getDefaultImport()?.getText();for(let u of o)if(l.includes(u)||g===u){let d=this.analyzeImportedComponent(F.dirname(n),c,u,new Set,0);for(let S of d)this.globalContextQueries.push({...S,operationName:`[Global] ${S.operationName}`});}}this.globalContextQueries.length>0&&this.log(`Found ${this.globalContextQueries.length} global context queries from _app`);return}catch{}}async loadCodegenMapping(){let e=["__generated__","src/__generated__","src/__generated__/gql-graphql-gateway","generated","src/generated"];for(let t of e){let n=this.resolvePath(t);try{let s=await z(["**/*.ts","**/*.tsx"],{cwd:n,absolute:!0,onlyFiles:!0});for(let i of s)try{let a=this.project.addSourceFileAtPath(i),o=a.getVariableDeclarations();for(let c of o){let l=c.getName();if(l.endsWith("Document")){let g=c.getInitializer()?.getText()??"",u=g.match(/(?:query|mutation|subscription)\s+(\w+)/),d=g.match(/(query|mutation|subscription)\s+/);u&&this.codegenMap.set(l,{operationName:u[1],operationType:d?d[1]:"query"});}}let r=a.getTypeAliases();for(let c of r){let l=c.getName();if((l.endsWith("Query")||l.endsWith("Mutation")||l.endsWith("Subscription"))&&!l.endsWith("Variables")){let g=l+"Document";if(!this.codegenMap.has(g)){let u=l.endsWith("Mutation")?"mutation":l.endsWith("Subscription")?"subscription":"query";this.codegenMap.set(g,{operationName:l,operationType:u});}}}}catch{}if(this.codegenMap.size>0){this.log(`Loaded ${this.codegenMap.size} codegen mappings from ${t}`);return}}catch{}}}resolveDocumentName(e){if(new Set(["Query","Mutation","Subscription"]).has(e))return null;let n=this.codegenMap.get(e);if(n!==void 0)return n;let s=e.endsWith("Document")?e:e+"Document",i=this.codegenMap.get(s);return i!==void 0?i:null}followReExport(e,t,n){try{let s=e.getExportDeclarations(),i=null;for(let a of s){let o=a.getNamedExports();for(let r of o){let c=a.getModuleSpecifierValue();if(!c)continue;let l=F.resolve(n,c),g=[`${l}.tsx`,`${l}.ts`,`${l}/index.tsx`,`${l}/index.ts`],u;for(let d of g)try{if(u=this.project.addSourceFileAtPath(d),u)break}catch{}if(u&&(i||(i=u),r.getName()===t||r.getAliasNode()?.getText()===t))return u}}if(i)return i;for(let a of e.getExportDeclarations())if(a.isNamespaceExport()){let o=a.getModuleSpecifierValue();if(o){let r=F.resolve(n,o),c=[`${r}.tsx`,`${r}.ts`];for(let l of c)try{let g=this.project.addSourceFileAtPath(l);if(g&&g.getExportedDeclarations().has(t))return g}catch{}}}}catch{}return null}isComponentName(e){return !/^[A-Z]/.test(e)||e.endsWith("Query")||e.endsWith("Mutation")||e.endsWith("Subscription")||e.endsWith("Fragment")||e.endsWith("Document")||e.endsWith("Variables")||e==="Query"||e==="Mutation"||e==="Subscription"||new Set(["NextPage","NextPageContext","NextApiRequest","NextApiResponse","GetServerSideProps","GetStaticProps","GetStaticPaths","InferGetServerSidePropsType","InferGetStaticPropsType","FC","FunctionComponent","VFC","Component","PureComponent","ReactNode","ReactElement","PropsWithChildren","ComponentProps","ComponentType","ElementType","RefObject","MutableRefObject","Dispatch","SetStateAction","ChangeEvent","MouseEvent","KeyboardEvent","FormEvent","SyntheticEvent"]).has(e)?false:!!(["Container","Page","Screen","View","Form","Modal","Dialog","Panel","Root","Provider","Wrapper"].some(s=>e.endsWith(s))||/Page[A-Z]?\w*$/.test(e)||/Container[A-Z]?\w*$/.test(e)||/^[A-Z][a-z]+[A-Z][a-z]+/.test(e))}extractNavigation(e){let t={visible:true,currentNavItem:null};try{let n=e.getDescendantsOfKind(SyntaxKind.PropertyAccessExpression).find(s=>{try{return s.getName()==="globalNavigationStyle"}catch{return !1}});if(n){let s=n.getParent();if(Node.isBinaryExpression(s)){let i=s.getRight(),a=i.getDescendantsOfKind(SyntaxKind.PropertyAssignment).find(c=>{try{return c.getName()==="visible"}catch{return !1}});a&&(t.visible=a.getInitializer()?.getText()==="true");let o=i.getDescendantsOfKind(SyntaxKind.PropertyAssignment).find(c=>{try{return c.getName()==="currentNavItem"}catch{return !1}});if(o){let c=o.getInitializer()?.getText();t.currentNavItem=c&&c!=="null"?c.replace(/['"]/g,""):null;}let r=i.getDescendantsOfKind(SyntaxKind.PropertyAssignment).find(c=>{try{return c.getName()==="mini"}catch{return !1}});r&&(t.mini=r.getInitializer()?.getText()==="true");}}}catch{}return t}extractSteps(e){let t=[],n=e.getDescendantsOfKind(SyntaxKind.CallExpression).filter(a=>a.getExpression().getText()==="useState");for(let a of n){let o=a.getParent();if(!o)continue;let c=o.getText().match(/\[\s*(step|currentStep|activeStep|page|currentPage|phase|stage)\s*,/i);if(c){let l=c[1],g=e.getDescendantsOfKind(SyntaxKind.SwitchStatement);for(let d of g)d.getExpression().getText().includes(l)&&d.getClauses().forEach((p,f)=>{if(p.isKind(SyntaxKind.CaseClause)){let y=p.getExpression()?.getText()||String(f),m=p.getDescendantsOfKind(SyntaxKind.JsxOpeningElement),x=m.length>0?m[0].getTagNameNode().getText():void 0;t.push({id:y.replace(/['"]/g,""),name:`Step ${y.replace(/['"]/g,"")}`,component:x});}});let u=e.getDescendantsOfKind(SyntaxKind.ArrayLiteralExpression);for(let d of u){let S=d.getParent();S&&S.getText().match(/steps|pages|screens|views|components/i)&&d.getElements().forEach((p,f)=>{let y=p.getText();if(y.startsWith("{")){let m=y.match(/(?:name|label|title)\s*:\s*['"]([^'"]+)['"]/),x=y.match(/(?:component|content)\s*:\s*<?\s*(\w+)/);t.push({id:f+1,name:m?m[1]:`Step ${f+1}`,component:x?x[1]:void 0});}else /^[A-Z]/.test(y)&&t.push({id:f+1,name:y,component:y});});}}}let s=e.getDescendantsOfKind(SyntaxKind.JsxOpeningElement);for(let a of s)if(a.getTagNameNode().getText().match(/Stepper|Wizard|Steps|TabPanel|FormStep/i)){let r=a.getParent();r&&r.isKind(SyntaxKind.JsxElement)&&r.getJsxChildren().forEach((l,g)=>{if(l.isKind(SyntaxKind.JsxElement)||l.isKind(SyntaxKind.JsxSelfClosingElement)){let u=l.isKind(SyntaxKind.JsxElement)?l.getOpeningElement().getTagNameNode().getText():l.getTagNameNode().getText(),d=l.isKind(SyntaxKind.JsxElement)?l.getOpeningElement().getAttributes():l.getAttributes(),S=u;for(let h of d)if(h.isKind(SyntaxKind.JsxAttribute)){let p=h.getNameNode().getText();if(p==="label"||p==="title"||p==="name"){let f=h.getInitializer()?.getText();if(f){S=f.replace(/['"{}]/g,"");break}}}t.push({id:g+1,name:S,component:u});}});}let i=e.getDescendantsOfKind(SyntaxKind.ConditionalExpression);for(let a of i){let o=a.getCondition().getText();if(o.match(/step\s*===?\s*\d+|currentStep|activeStep/i)){let r=a.getWhenTrue(),c=o.match(/===?\s*(\d+)/);if(c&&t.length===0){let l=r.getDescendantsOfKind(SyntaxKind.JsxOpeningElement);l.length>0&&t.push({id:parseInt(c[1]),component:l[0].getTagNameNode().getText()});}}}return t}extractLinkedPages(e){let t=[],n=e.getDescendantsOfKind(SyntaxKind.CallExpression).filter(i=>{let a=i.getExpression().getText();return a.includes("router.push")||a.includes("router.replace")||a.includes("Link")});for(let i of n){let a=i.getArguments();if(a.length>0){let r=a[0].getText().match(/['"`]([^'"`]+)['"`]/);r&&!t.includes(r[1])&&t.push(r[1]);}}let s=e.getDescendantsOfKind(SyntaxKind.JsxOpeningElement).filter(i=>i.getTagNameNode().getText()==="Link");for(let i of s)try{let a=i.getAttributes();for(let o of a)if(o.isKind(SyntaxKind.JsxAttribute)&&o.getNameNode().getText()==="href"){let l=o.getInitializer()?.getText();if(l){let g=l.match(/['"`]([^'"`]+)['"`]/);g&&!t.includes(g[1])&&t.push(g[1]);}}}catch{}return t}};var G=class extends D{project;constructor(e){super(e),this.project=new Project({tsConfigFilePath:this.resolvePath("tsconfig.json"),skipAddingFilesFromTsConfig:true});}getName(){return "GraphQLAnalyzer"}async analyze(){this.log("Starting GraphQL analysis...");let e=[],t=await this.analyzeGraphQLFiles();e.push(...t);let n=await this.analyzeInlineGraphQL();e.push(...n);let s=await this.analyzeCodegenGenerated();e.push(...s);let i=this.deduplicateOperations(e);return await this.findOperationUsage(i),this.log(`Found ${i.length} GraphQL operations`),{graphqlOperations:i}}deduplicateOperations(e){let t=new Map;for(let n of e)if(!t.has(n.name))t.set(n.name,n);else {let s=t.get(n.name);if(s)for(let i of n.usedIn)s.usedIn.includes(i)||s.usedIn.push(i);}return Array.from(t.values())}async analyzeCodegenGenerated(){let e=[],t=await z(["**/__generated__/graphql.ts","**/__generated__/gql.ts","**/generated/graphql.ts"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**"],absolute:true});for(let n of t)try{let s=await O.readFile(n,"utf-8"),i=F.relative(this.basePath,n),a=s.split(`
2
- `);for(let o of a){if(!o.includes("Document =")||!o.includes("DocumentNode"))continue;let r=o.match(/export\s+const\s+(\w+Document)\s*=\s*(\{"kind":"Document".+\})\s*as\s+unknown\s+as\s+DocumentNode/);if(!r)continue;let c=r[1],l=r[2];try{let g=JSON.parse(l);if(g.kind==="Document"&&g.definitions){let u=g.definitions[0];if(u?.kind==="OperationDefinition"){let d=u.name?.value||c.replace(/Document$/,""),S=u.operation,h=(u.variableDefinitions||[]).map(p=>({name:p.variable?.name?.value||"unknown",type:this.extractTypeFromAst(p.type),required:p.type?.kind==="NonNullType"}));e.push({name:d,type:S,filePath:i,usedIn:[],variables:h,returnType:this.inferReturnTypeFromAst(u),fragments:[],fields:[]});}}}catch{}}this.log(`Found ${e.length} operations in codegen output: ${i}`);}catch(s){this.warn(`Failed to analyze codegen file ${n}: ${s.message}`);}return e}extractTypeFromAst(e){return e?e.kind==="NonNullType"?`${this.extractTypeFromAst(e.type)}!`:e.kind==="ListType"?`[${this.extractTypeFromAst(e.type)}]`:e.kind==="NamedType"&&e.name?.value||"unknown":"unknown"}extractFieldsFromAst(e,t=0){if(!e?.selections||t>5)return [];let n=[];for(let s of e.selections)if(s.kind==="Field"){let i={name:s.name?.value||"unknown"};if(s.arguments?.length>0){let a=s.arguments.map(o=>o.name?.value).join(", ");i.type=`(${a})`;}s.selectionSet&&(i.fields=this.extractFieldsFromAst(s.selectionSet,t+1)),n.push(i);}else if(s.kind==="FragmentSpread")n.push({name:`...${s.name?.value}`,type:"fragment"});else if(s.kind==="InlineFragment"){let i=s.typeCondition?.name?.value||"inline";n.push({name:`... on ${i}`,type:"inline-fragment",fields:this.extractFieldsFromAst(s.selectionSet,t+1)});}return n}extractFragmentReferencesFromAst(e){let t=[],n=s=>{if(s&&(s.kind==="FragmentSpread"&&t.push(s.name?.value),s.selectionSet?.selections))for(let i of s.selectionSet.selections)n(i);};return n(e),t.filter(Boolean)}inferReturnTypeFromAst(e){if(e.selectionSet?.selections?.length>0){let t=e.selectionSet.selections[0];if(t.kind==="Field")return t.name?.value||"unknown"}return "unknown"}async analyzeGraphQLFiles(){let e=await z(["**/*.graphql"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**"],absolute:true});return (await E(e,async n=>{let s=await O.readFile(n,"utf-8"),i=parse(s);return this.extractOperationsFromDocument(i,F.relative(this.basePath,n))})).flat()}async analyzeInlineGraphQL(){let e=[],t=await z(["**/*.ts","**/*.tsx"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**","**/__tests__/**","**/*.test.*","**/*.spec.*"],absolute:true});for(let n of t)try{let s=this.project.addSourceFileAtPath(n),i=F.relative(this.basePath,n),a=s.getImportDeclarations().some(c=>{let l=c.getModuleSpecifierValue(),g=c.getNamedImports().map(d=>d.getName()),u=c.getDefaultImport()?.getText();return (g.includes("gql")||g.includes("graphql")||u==="gql")&&(l.includes("graphql")||l.includes("apollo")||l.includes("gql")||l.includes("__generated__"))}),o=s.getDescendantsOfKind(SyntaxKind.TaggedTemplateExpression);for(let c of o){let l=c.getTag().getText();if(l==="gql"||l==="graphql")try{let g=c.getTemplate(),u="";if(g.isKind(SyntaxKind.NoSubstitutionTemplateLiteral)?u=g.getLiteralValue():g.isKind(SyntaxKind.TemplateExpression)&&(u=g.getText().slice(1,-1).replace(/\$\{[^}]*\}/g,"")),u&&u.trim())try{let d=parse(u),S=this.extractOperationsFromDocument(d,i);e.push(...S);}catch{}}catch{}}let r=s.getDescendantsOfKind(SyntaxKind.CallExpression);for(let c of r)try{let g=c.getExpression().getText();if(g==="gql"||g==="graphql"){let u=c.getArguments();if(u.length>0){let d=u[0],S="";if(d.isKind(SyntaxKind.NoSubstitutionTemplateLiteral))S=d.getLiteralValue();else if(d.isKind(SyntaxKind.TemplateExpression))S=d.getText().slice(1,-1).replace(/\$\{[^}]*\}/g,"");else {let h=d.getText();if(h.includes("`")){let p=h.match(/\/\*\s*GraphQL\s*\*\/\s*`([^`]*)`/);if(p)S=p[1];else {let f=h.match(/`([^`]*)`/);f&&(S=f[1]);}}}if(S&&S.trim())try{let h=parse(S),p=this.extractOperationsFromDocument(h,i);e.push(...p);}catch{}}}}catch{}if(a){let c=s.getVariableDeclarations();for(let l of c){let g=l.getName();if(g.includes("QUERY")||g.includes("MUTATION")||g.includes("FRAGMENT")||g.includes("Query")||g.includes("Mutation")||g.includes("Subscription")||/^[A-Z_]+_(QUERY|MUTATION|FRAGMENT|SUBSCRIPTION)$/.test(g)||/Query$|Mutation$|Fragment$|Subscription$/.test(g)){let d=l.getInitializer();d&&d.isKind(SyntaxKind.CallExpression);}}}}catch(s){this.warn(`Failed to analyze ${n}: ${s.message}`);}return e}extractOperationsFromDocument(e,t){let n=[];for(let s of e.definitions){let i=this.extractOperation(s,t);i&&n.push(i);}return n}extractOperation(e,t){if(e.kind==="OperationDefinition"){let n=e.name?.value||"anonymous",s=e.operation,i=this.extractVariables(e),a=this.extractFragmentReferences(e),o=this.extractFields(e);return {name:n,type:s,filePath:t,usedIn:[],variables:i,returnType:this.inferReturnType(e),fragments:a,fields:o}}return e.kind==="FragmentDefinition"?{name:e.name.value,type:"fragment",filePath:t,usedIn:[],variables:[],returnType:e.typeCondition.name.value,fragments:this.extractFragmentReferences(e),fields:this.extractFields(e)}:null}extractFields(e){let t=[],n=(s,i=0)=>{if(!s||!s.selections||i>5)return [];let a=[];for(let o of s.selections)if(o.kind==="Field"){let r={name:o.name.value};if(o.arguments&&o.arguments.length>0){let c=o.arguments.map(l=>l.name.value).join(", ");r.type=`(${c})`;}o.selectionSet&&(r.fields=n(o.selectionSet,i+1)),a.push(r);}else if(o.kind==="FragmentSpread")a.push({name:`...${o.name.value}`,type:"fragment"});else if(o.kind==="InlineFragment"&&o.selectionSet){let r=o.typeCondition?.name?.value||"inline";a.push({name:`... on ${r}`,type:"inline-fragment",fields:n(o.selectionSet,i+1)});}return a};return e.selectionSet?n(e.selectionSet):t}extractVariables(e){let t=[];if(e.variableDefinitions)for(let n of e.variableDefinitions){let s=n.variable.name.value,i=this.typeNodeToString(n.type),a=n.type.kind==="NonNullType";t.push({name:s,type:i,required:a});}return t}typeNodeToString(e){return e.kind==="NonNullType"?`${this.typeNodeToString(e.type)}!`:e.kind==="ListType"?`[${this.typeNodeToString(e.type)}]`:e.kind==="NamedType"?e.name.value:"unknown"}extractFragmentReferences(e){let t=[],n=s=>{if(s&&(s.kind==="FragmentSpread"&&t.push(s.name.value),s.selectionSet))for(let i of s.selectionSet.selections)n(i);};return n(e),t}inferReturnType(e){if(e.selectionSet&&e.selectionSet.selections.length>0){let t=e.selectionSet.selections[0];if(t.kind==="Field")return t.name.value}return "unknown"}async findOperationUsage(e){if(e.length===0)return;let t=await z(["**/*.ts","**/*.tsx"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**","**/__generated__/**"],absolute:true}),n=new Map,s=new Map;for(let r of e)n.set(r.name,r),s.set(`${r.name}Document`,r);let i=e.map(r=>`${r.name}Document`),a=new RegExp(`\\b(${i.join("|")})\\b`,"g"),o=50;for(let r=0;r<t.length;r+=o){let c=t.slice(r,r+o);await Promise.all(c.map(async l=>{try{let g=await O.readFile(l,"utf-8"),u=F.relative(this.basePath,l);if(!g.includes("Document")&&!g.includes("useQuery")&&!g.includes("useMutation")&&!g.includes("Query")&&!g.includes("Mutation"))return;let d=new Set,S;for(;(S=a.exec(g))!==null;)d.add(S[1]);a.lastIndex=0;for(let h of d){let p=s.get(h);p&&u!==p.filePath&&(p.usedIn.includes(u)||p.usedIn.push(u));}for(let[h,p]of n)u!==p.filePath&&(p.usedIn.includes(u)||(g.includes(`useQuery<${h}`)||g.includes(`useMutation<${h}`)||g.includes(`useLazyQuery<${h}`)||g.includes(`useSubscription<${h}`)||g.includes(`${h}Query`)||g.includes(`${h}Mutation`))&&p.usedIn.push(u));}catch{}}));}}};var K=class extends D{project;componentCache=new Map;constructor(e){super(e),this.project=new Project({tsConfigFilePath:this.resolvePath("tsconfig.json"),skipAddingFilesFromTsConfig:true});}getName(){return "DataFlowAnalyzer"}async analyze(){this.log("Starting data flow analysis...");let e=await this.analyzeComponents(),t=await this.analyzeDataFlows(e);return this.log(`Analyzed ${e.length} components and ${t.length} data flows`),{components:e,dataFlows:t}}async analyzeComponents(){let e=[],t=[this.getSetting("featuresDir",""),this.getSetting("componentsDir",""),this.getSetting("pagesDir","")].filter(Boolean),n=["src/features","src/components","src/common/components","src/common","src/pages","src/app","src/modules","src/views","src/screens","components","pages","app"],s=[...new Set([...t,...n])];for(let i of s){let a=await z(["**/*.tsx"],{cwd:this.resolvePath(i),ignore:["**/*.test.*","**/*.spec.*","**/*.stories.*"],absolute:true});for(let o of a)try{let r=this.project.addSourceFileAtPath(o),c=F.relative(this.basePath,o),l=this.analyzeComponentFile(r,c);e.push(...l);}catch(r){this.warn(`Failed to analyze ${o}: ${r.message}`);}}return this.buildDependencyGraph(e),e}analyzeComponentFile(e,t){let n=[],s=e.getFunctions();for(let o of s){let r=o.getName();if(r&&this.isComponentName(r)){let c=this.extractComponentInfo(o,r,t);n.push(c),this.componentCache.set(r,c);}}let i=e.getVariableDeclarations();for(let o of i){let r=o.getName();if(this.isComponentName(r)){let c=o.getInitializer();if(c&&(c.isKind(SyntaxKind.ArrowFunction)||c.isKind(SyntaxKind.FunctionExpression))){let l=this.extractComponentInfo(c,r,t);n.push(l),this.componentCache.set(r,l);}}}let a=e.getFunctions().filter(o=>{let r=o.getName();return r&&r.startsWith("use")});for(let o of a){let r=o.getName()??"",c=this.extractHookInfo(o,r,t);n.push(c),this.componentCache.set(r,c);}return n}isComponentName(e){return /^[A-Z][a-zA-Z0-9]*$/.test(e)}extractComponentInfo(e,t,n){let s=e.getSourceFile(),i="presentational";["/pages/","/app/","/routes/","/views/","/screens/"].some(g=>n.includes(g))?i="page":t.includes("Container")||t.includes("Provider")?i="container":(t.includes("Layout")||t.includes("Shell")||t.includes("Wrapper")||t.includes("Frame")||t.includes("Scaffold")||n.includes("/layouts/")||n.includes("/layout/"))&&(i="layout");let o=this.extractProps(e),r=this.extractHooksUsed(e),c=this.extractDependencies(s),l=this.extractStateManagement(e);return {name:t,filePath:n,type:i,props:o,dependencies:c,dependents:[],hooks:r,stateManagement:l}}extractHookInfo(e,t,n){let s=e.getSourceFile(),i=this.extractProps(e),a=this.extractHooksUsed(e),o=this.extractDependencies(s),r=this.extractStateManagement(e);return {name:t,filePath:n,type:"hook",props:i,dependencies:o,dependents:[],hooks:a,stateManagement:r}}extractProps(e){let t=[],n=e.getParameters?.()||[];if(n.length>0){let i=n[0].getTypeNode?.();if(i){let a=i.getDescendantsOfKind?.(SyntaxKind.PropertySignature)||[];for(let o of a)t.push({name:o.getName(),type:o.getType().getText(),required:!o.hasQuestionToken()});}}return t}extractHooksUsed(e){let t=[],n=e.getDescendantsOfKind?.(SyntaxKind.CallExpression)||[];for(let s of n)try{let i=s.getExpression().getText();if(i.startsWith("use"))if(i==="useQuery"||i==="useMutation"||i==="useLazyQuery"){let a=this.extractOperationName(s,i);t.includes(a)||t.push(a);}else if(i==="useContext"){let a=this.extractContextName(s);t.includes(a)||t.push(a);}else t.includes(i)||t.push(i);}catch{}return t}extractOperationName(e,t){try{let n=e.getArguments?.()||[];if(n.length>0){let i=n[0].getText().replace(/^(GET_|FETCH_|CREATE_|UPDATE_|DELETE_)/,"").replace(/_QUERY$|_MUTATION$/,"").replace(/Document$/,"").replace(/Query$|Mutation$/,"");return `${t==="useMutation"?"\u270F\uFE0F":"\u{1F4E1}"} ${t==="useMutation"?"Mutation":"Query"}: ${i}`}}catch{}return t}extractContextName(e){try{let t=e.getArguments?.()||[];if(t.length>0)return `\u{1F504} Context: ${t[0].getText().replace(/Context$/,"").replace(/^Session|^Token|^Apollo/,s=>s)}`}catch{}return "useContext"}extractDependencies(e){let t=[],n=e.getImportDeclarations();for(let s of n){let i=s.getModuleSpecifierValue();if(i.startsWith(".")||i.startsWith("@/")){let a=s.getNamedImports();for(let r of a){let c=r.getName();(this.isComponentName(c)||c.startsWith("use"))&&t.push(c);}let o=s.getDefaultImport();if(o){let r=o.getText();this.isComponentName(r)&&t.push(r);}}}return t}extractStateManagement(e){let t=[],n=e.getText?.()||"";return n.includes("useState")&&t.push("useState"),n.includes("useReducer")&&t.push("useReducer"),n.includes("useContext")&&t.push("useContext"),n.includes("useQuery")&&t.push("Apollo Query"),n.includes("useMutation")&&t.push("Apollo Mutation"),n.includes("useRecoil")&&t.push("Recoil"),(n.includes("useSelector")||n.includes("useDispatch"))&&t.push("Redux"),t}buildDependencyGraph(e){let t=new Map;for(let n of e)t.set(n.name,n);for(let n of e)for(let s of n.dependencies){let i=t.get(s);i&&!i.dependents.includes(n.name)&&i.dependents.push(n.name);}}async analyzeDataFlows(e){let t=[],n=1,s=this.analyzeContextFlows(e);t.push(...s.map(o=>({...o,id:`flow-${n++}`})));let i=this.analyzeApolloFlows(e);t.push(...i.map(o=>({...o,id:`flow-${n++}`})));let a=this.analyzePropDrilling(e);return t.push(...a.map(o=>({...o,id:`flow-${n++}`}))),t}analyzeContextFlows(e){let t=[],n=e.filter(i=>i.name.includes("Provider")||i.name.includes("Context")),s=e.filter(i=>i.hooks.some(a=>a.includes("Context")));for(let i of n){let a=i.name.replace("Provider","").replace("Context","");for(let o of s){let r=o.hooks.find(c=>c.includes("Context")&&c.includes(a));(r||o.hooks.some(c=>c.includes(a)))&&t.push({name:`\u{1F504} ${a} Context`,description:`Data flows from ${i.name} to ${o.name} via Context`,source:{type:"context",name:i.name},target:{type:"component",name:o.name},via:[],operations:[r||`useContext(${a})`]});}}return t}analyzeApolloFlows(e){let t=[];for(let n of e){let s=n.hooks.filter(a=>a.includes("Query:")||a==="useQuery"||a==="useLazyQuery");for(let a of s){let o=a.includes(":")?a.split(":")[1].trim():n.name;t.push({name:`\u{1F4E1} ${o}`,description:`${n.name} fetches ${o} via Apollo`,source:{type:"api",name:`GraphQL: ${o}`},target:{type:"component",name:n.name},via:[{type:"cache",name:"Apollo Cache"}],operations:[a]});}let i=n.hooks.filter(a=>a.includes("Mutation:")||a==="useMutation");for(let a of i){let o=a.includes(":")?a.split(":")[1].trim():n.name;t.push({name:`\u270F\uFE0F ${o}`,description:`${n.name} mutates ${o} via Apollo`,source:{type:"component",name:n.name},target:{type:"api",name:`GraphQL: ${o}`},via:[],operations:[a]});}}return t}analyzePropDrilling(e){let t=[];for(let n of e)n.props.length>5&&n.dependents.length>0&&t.push({name:`Prop Drilling through ${n.name}`,description:`${n.name} passes ${n.props.length} props to children`,source:{type:"component",name:n.name},target:{type:"component",name:n.dependents[0]},via:[],operations:["props"]});return t}};var H=class extends D{project;apiCallCounter=0;constructor(e){super(e),this.project=new Project({tsConfigFilePath:this.resolvePath("tsconfig.json"),skipAddingFilesFromTsConfig:true});}getName(){return "RestApiAnalyzer"}async analyze(){this.log("Starting REST API analysis...");let e=await z(["**/*.ts","**/*.tsx"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**","**/__tests__/**","**/*.test.*","**/*.spec.*","**/*.stories.*","**/__generated__/**","**/dist/**","**/build/**"],absolute:true}),t=new Map;for(let i of e)try{t.set(i,this.project.addSourceFileAtPath(i));}catch{}let s=(await E(Array.from(t.entries()),async([i,a])=>{let o=F.relative(this.basePath,i),r=[];return r.push(...this.findFetchCalls(a,o)),r.push(...this.findAxiosCalls(a,o)),r.push(...this.findSwrCalls(a,o)),r},8)).flat();return this.log(`Found ${s.length} REST API calls`),{apiCalls:s}}findFetchCalls(e,t){let n=[],s=e.getDescendantsOfKind(SyntaxKind.CallExpression);for(let i of s)try{let o=i.getExpression().getText();if(o==="fetch"||o==="window.fetch"){let r=this.extractFetchCall(i,t);r&&n.push(r);}}catch{}return n}findAxiosCalls(e,t){let n=[],s=e.getDescendantsOfKind(SyntaxKind.CallExpression);for(let i of s)try{let o=i.getExpression().getText(),r=o.match(/^axios\.(get|post|put|delete|patch)$/i);if(r){let c=this.extractAxiosCall(i,t,r[1].toUpperCase());c&&n.push(c);}if(o==="axios"){let c=this.extractAxiosDirectCall(i,t);c&&n.push(c);}}catch{}return n}findSwrCalls(e,t){let n=[],s=e.getDescendantsOfKind(SyntaxKind.CallExpression);for(let i of s)try{let o=i.getExpression().getText();if(o==="useSWR"||o==="useSWRImmutable"){let r=this.extractSwrCall(i,t);r&&n.push(r);}}catch{}return n}extractFetchCall(e,t){let n=e.getArguments();if(n.length===0)return null;let s=n[0].getText(),i=this.extractUrlFromArg(s);if(!i.url||!i.isPlaceholder&&!this.isApiUrl(i.url))return null;let a="GET",o=false;if(n.length>1){let l=n[1].getText(),g=l.match(/method:\s*["'](\w+)["']/i);g&&(a=this.normalizeMethod(g[1])),o=l.includes("credentials")||l.includes("Authorization")||l.includes("withCredentials");}let r=this.getContainingFunctionName(e),c=e.getStartLineNumber();return {id:`api-${++this.apiCallCounter}`,method:a,url:i.url,callType:"fetch",filePath:t,line:c,containingFunction:r,usedIn:[],requiresAuth:o,category:this.categorizeApi(i.url)}}extractAxiosCall(e,t,n){let s=e.getArguments();if(s.length===0)return null;let i=s[0].getText(),a=this.extractUrlFromArg(i);if(!a.url)return null;let o=false;if(s.length>1){let l=s[s.length-1].getText();o=l.includes("withCredentials")||l.includes("Authorization");}let r=this.getContainingFunctionName(e),c=e.getStartLineNumber();return {id:`api-${++this.apiCallCounter}`,method:this.normalizeMethod(n),url:a.url,callType:"axios",filePath:t,line:c,containingFunction:r,usedIn:[],requiresAuth:o,category:this.categorizeApi(a.url)}}extractAxiosDirectCall(e,t){let n=e.getArguments();if(n.length===0)return null;let s=n[0].getText(),i=s.match(/url:\s*["'`]([^"'`]+)["'`]/),a=s.match(/method:\s*["'](\w+)["']/i);if(!i)return null;let o=i[1],r=a?this.normalizeMethod(a[1]):"GET",c=s.includes("withCredentials")||s.includes("Authorization"),l=this.getContainingFunctionName(e),g=e.getStartLineNumber();return {id:`api-${++this.apiCallCounter}`,method:r,url:o,callType:"axios",filePath:t,line:g,containingFunction:l,usedIn:[],requiresAuth:c,category:this.categorizeApi(o)}}extractSwrCall(e,t){let n=e.getArguments();if(n.length===0)return null;let s=n[0].getText(),i=null;if(s.startsWith('"')||s.startsWith("'")||s.startsWith("`"))i=this.cleanStringLiteral(s);else if(s.includes("?")&&s.includes(":")){let r=s.match(/\?\s*["'`]([^"'`]+)["'`]/);r?i=r[1]:(r=s.match(/:\s*["'`]([^"'`]+)["'`]/),r&&(i=r[1])),i||(r=s.match(/\?\s*`([^`]+)`/),r&&(i=r[1].replace(/\$\{[^}]+\}/g,":param")));}else {let r=this.extractUrlFromArg(s);r.url&&!s.includes("null")&&!s.includes("undefined")&&(i=r.url);}if(!i)return null;let a=this.getContainingFunctionName(e),o=e.getStartLineNumber();return {id:`api-${++this.apiCallCounter}`,method:"GET",url:i,callType:"useSWR",filePath:t,line:o,containingFunction:a,usedIn:[],requiresAuth:false,category:this.categorizeApi(i)}}getContainingFunctionName(e){let t=e;for(;t;){if(Node.isFunctionDeclaration(t))return t.getName()||"anonymous";if(Node.isVariableDeclaration(t)||Node.isMethodDeclaration(t))return t.getName();if(Node.isArrowFunction(t)){let n=t.getParent();if(n&&Node.isVariableDeclaration(n))return n.getName()}t=t.getParent();}return "unknown"}extractUrlFromArg(e){if(/^["'`]/.test(e))return {url:this.cleanStringLiteral(e),isPlaceholder:false};let t=e.match(/^(\w+)\s*\(\s*["'`]([^"'`]+)["'`]/);if(t)return {url:`[${t[1]}] ${t[2]}`,isPlaceholder:true};let n=e.match(/^(\w+)\s*\(\s*`([^`]+)`/);if(n){let s=n[2].replace(/\$\{[^}]+\}/g,":param");return {url:`[${n[1]}] ${s}`,isPlaceholder:true}}return /^\w+(\.\w+)*$/.test(e)?{url:`[${e}]`,isPlaceholder:true}:e.includes(".")?{url:`[${e}]`,isPlaceholder:true}:{url:null,isPlaceholder:false}}cleanStringLiteral(e){let t=e.replace(/^["'`]|["'`]$/g,"").trim();return t.includes("${")?t.replace(/\$\{[^}]+\}/g,":param"):t||null}isApiUrl(e){return e.startsWith("data:")||e.startsWith("blob:")||/\.(css|js|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot|html)$/i.test(e)?false:e.startsWith("/")||e.startsWith("http")||e.includes("/api/")||e.includes(".json")||e.includes("api.")||e.includes("github.io")||e.includes("hsforms.com")||e.includes("hubspot")||e.includes("amazonaws.com")||e.includes("s3.")||e.includes("googleapis.com")||e.includes("stripe.com")||e.includes("graph.facebook.com")||e.includes("api.twitter.com")||e.includes("slack.com")||e.includes("discord.com")||e.includes("sendgrid.com")||e.includes("twilio.com")||e.includes("firebase")||e.includes("supabase")||e.includes("auth0.com")||e.includes("okta.com")||e.includes("cloudflare.com")||e.includes("vercel.com")||e.includes("netlify.com")}categorizeApi(e){if(e.includes("hsforms.com")||e.includes("hubspot"))return "HubSpot";if(e.includes("amazonaws.com")||e.includes("s3."))return "AWS S3";if(e.includes("googleapis.com"))return "Google API";if(e.includes("stripe.com"))return "Stripe";if(e.includes("graph.facebook.com"))return "Facebook";if(e.includes("api.twitter.com"))return "Twitter";if(e.includes("slack.com"))return "Slack";if(e.includes("discord.com"))return "Discord";if(e.includes("sendgrid.com"))return "SendGrid";if(e.includes("twilio.com"))return "Twilio";if(e.includes("firebase"))return "Firebase";if(e.includes("supabase"))return "Supabase";if(e.includes("auth0.com"))return "Auth0";if(e.includes("okta.com"))return "Okta";if(e.includes("github.io"))return "GitHub Pages API";if(e.startsWith("/api/"))return "Internal API";if(e.startsWith("/"))return "Internal Route";if(e.startsWith("["))return "Dynamic URL"}normalizeMethod(e){let t=e.toUpperCase();return ["GET","POST","PUT","DELETE","PATCH"].includes(t)?t:"unknown"}};export{D as a,q as b,G as c,K as d,H as e};
@@ -1 +0,0 @@
1
- export{a as PageMapGenerator}from'./chunk-MOEA75XK.js';