@wtdlee/repomap 0.9.1 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ import {parseSync}from'@swc/core';import j from'fast-glob';import*as y from'path';import*as F from'fs';import*as T from'fs/promises';import h from'typescript';import {parse}from'graphql';var A=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}getListSetting(e,t=[]){let r=this.getSetting(e,"");return r?r.split(/[,\n]/g).map(s=>s.trim()).filter(Boolean):t}getGraphQLHookPatterns(){let e=(this.getSetting("graphqlHookPreset","auto")||"auto").trim().toLowerCase(),t=this.getListSetting("graphqlHookPatterns",[]),r=["useLazyLoadQuery","usePreloadedQuery","useQueryLoader","useMutation","useSubscription","useFragment","usePaginationFragment","useRefetchableFragment","useRelayEnvironment"],s=["useUrql*"],i=["useGql*","useGraphQL*","useGraphql*","useApiQuery*","useApiMutation*"],n=[];return e==="none"||e==="off"||e==="false"?n=[]:e==="apollo"?n=[]:e==="urql"?n=s:e==="relay"?n=r:n=[...r,...s,...i],Array.from(new Set([...n,...t]))}log(e){process.env.REPOMAP_VERBOSE==="1"&&console.log(`[${this.getName()}] ${e}`);}warn(e){console.warn(`\u26A0\uFE0F ${e}`);}error(e,t){console.error(`\u274C ${e}`,t?.message||"");}};var X=["useQuery","useLazyQuery","useSuspenseQuery","useBackgroundQuery","useReadQuery"],ee=["useMutation"],xe=["useSubscription","useFragment","useApolloClient"],z=[...X,...ee,...xe],Y={useQuery:"useQuery",useSuspenseQuery:"useQuery",useBackgroundQuery:"useQuery",useReadQuery:"useQuery",useLazyQuery:"useLazyQuery",useMutation:"useMutation",useSubscription:"useSubscription"},ve=["Document","useQuery","useMutation","useLazyQuery","useSuspenseQuery","useBackgroundQuery","useSubscription","Query","Mutation","gql","graphql","GET_","FETCH_","SEARCH_","CREATE_","UPDATE_","DELETE_","SUBSCRIBE_","@apollo","ApolloClient","@urql","urql","react-relay","Relay"];function be(p,e){if(!e)return false;if(e===p)return true;if(!e.includes("*"))return false;let t=e.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${t}$`).test(p)}function E(p,e){for(let t of e)if(be(p,t))return true;return false}function R(p,e=[]){return E(p,e)?/Query$/.test(p)||!/(Mutation|Subscription)$/.test(p):X.includes(p)||/^use[A-Z].*Query$/.test(p)}function Q(p,e=[]){return E(p,e)?/Mutation$/.test(p)||p.toLowerCase().includes("mutation"):ee.includes(p)||/^use[A-Z].*Mutation$/.test(p)}function te(p,e=[]){return E(p,e)?/Subscription$/.test(p)||p.toLowerCase().includes("subscription"):p==="useSubscription"}function $(p,e=[]){return E(p,e)?true:z.includes(p)||R(p,e)||Q(p,e)}function D(p,e=[]){return Y[p]?Y[p]:p.includes("Mutation")||E(p,e)?"useMutation":p.includes("Lazy")?"useLazyQuery":p.includes("Subscription")?"useSubscription":"useQuery"}function W(p){return ve.some(e=>p.includes(e))}function d(p){return p.replace(/^(GET_|FETCH_|CREATE_|UPDATE_|DELETE_)/,"").replace(/_QUERY$|_MUTATION$/,"").replace(/Document$/,"").replace(/Query$|Mutation$|Variables$|Subscription$/,"")}function Ce(p){try{return parseSync(p,{syntax:"typescript",tsx:!0,comments:!1})}catch{return null}}function x(p){return p?p.type==="Identifier"?p.value:p.type==="MemberExpression"&&p.property?.type==="Identifier"?p.property.value:null:null}function S(p,e){if(!(!p||typeof p!="object")){e(p);for(let t of Object.keys(p)){let r=p[t];if(Array.isArray(r))for(let s of r)S(s,e);else r&&typeof r=="object"&&S(r,e);}}}function H(p,e,t){let r={documentImports:new Map,variableOperations:new Map,staticPropertyOperations:new Map,codegenMap:t||new Map};return S(p,s=>{s.type==="ImportDeclaration"&&Ae(s,r.documentImports),s.type==="VariableDeclarator"&&we(s,e,r.variableOperations),s.type==="AssignmentExpression"&&Fe(s,e,r.staticPropertyOperations);}),r}function Ae(p,e){let t=p.source?.value||"",r=t.includes("__generated__")||t.includes("generated")||t.includes("graphql")||t.includes(".generated")||t.endsWith(".graphql");for(let s of p.specifiers||[]){let i;(s.type==="ImportSpecifier"||s.type==="ImportDefaultSpecifier")&&(i=s.local?.value),i&&((i.endsWith("Document")||r)&&e.set(i,i.replace(/Document$/,"")),(i.endsWith("Query")||i.endsWith("Mutation"))&&e.set(i,i.replace(/Query$|Mutation$/,"")));}}function we(p,e,t){if(p.id?.type!=="Identifier")return;let r=p.id.value,s=p.init;if(!s)return;let i=null;if(s.type==="CallExpression"){let n=x(s.callee);(n==="gql"||n==="graphql")&&(i=V(s,e));}if(s.type==="TaggedTemplateExpression"){let n=x(s.tag);(n==="gql"||n==="graphql")&&(i=P(s.template));}if(s.type==="Identifier"){let n=s.value;if(n.endsWith("Document")||n.endsWith("Query")||n.endsWith("Mutation")){t.set(r,n);return}}i&&t.set(r,i);}function Fe(p,e,t){if(p.left?.type!=="MemberExpression")return;let r=p.left.object,s=p.left.property;if(r?.type!=="Identifier"||s?.type!=="Identifier")return;let i=`${r.value}.${s.value}`,n=p.right;if(!n)return;let a=null;if(n.type==="CallExpression"){let o=x(n.callee);(o==="gql"||o==="graphql")&&(a=V(n,e));}if(n.type==="TaggedTemplateExpression"){let o=x(n.tag);(o==="gql"||o==="graphql")&&(a=P(n.template));}a&&t.set(i,a);}function V(p,e){if(!p.arguments?.length)return null;let t=p.arguments[0],r=t?.expression||t;if(r?.type==="TemplateLiteral")return P(r);if(p.span){let i=e.slice(p.span.start,p.span.end).match(/(?:query|mutation|subscription)\s+(\w+)/i);if(i)return i[1]}return null}function P(p,e){if(!p?.quasis?.[0])return null;let r=(p.quasis[0].raw||p.quasis[0].cooked||"").match(/(?:query|mutation|subscription)\s+(\w+)/i);return r?r[1]:null}function ne(p,e,t){if(!p.arguments?.length)return false;let r=p.arguments[0],s=r?.expression||r;if(!s)return false;if(p.typeArguments?.params?.length>0){let n=p.typeArguments.params[0];if(n?.type==="TsTypeReference"&&n.typeName?.type==="Identifier"){let a=n.typeName.value;if(/Query$|Mutation$|Subscription$|Document$/.test(a))return true}}if(s.type==="Identifier"){let n=s.value;if(t.documentImports.has(n)||t.variableOperations.has(n)||n.endsWith("Document")||/^[A-Z][a-zA-Z0-9]*Query$/.test(n)||/^[A-Z][a-zA-Z0-9]*Mutation$/.test(n)||/^[A-Z][A-Z0-9_]*_QUERY$/.test(n)||/^[A-Z][A-Z0-9_]*_MUTATION$/.test(n))return true}if(s.type==="TaggedTemplateExpression"){let n=x(s.tag);if(n==="gql"||n==="graphql")return true}if(s.type==="CallExpression"){let n=x(s.callee);if(n==="gql"||n==="graphql")return true}if(s.type==="TemplateLiteral"&&s.quasis?.[0]?.raw){let n=s.quasis[0].raw;if(/(?:query|mutation|subscription)\s+\w+/i.test(n))return true}if(s.type==="MemberExpression"){let n=s.property?.value;if(n&&/Query$|Mutation$|Document$/.test(n))return true;let a=s.object?.type==="Identifier"?s.object.value:null;if(a&&n){let o=`${a}.${n}`;if(t.staticPropertyOperations.has(o))return true}}if(s.type==="ObjectExpression")for(let n of s.properties||[]){if(n.type!=="KeyValueProperty")continue;let a=n.key?.type==="Identifier"||n.key?.type==="StringLiteral"?n.key.value:null;if(!a||!["query","mutation","document","subscription"].includes(a))continue;let o=n.value;if(o&&Z(o,e,t))return true}let i=p.span;if(i){let n=e.slice(i.start,Math.min(i.end,i.start+500));if(/\bDocument\b/.test(n)||/\bgql\s*[`(]/.test(n)||/\bgraphql\s*[`(]/.test(n)||/query\s+[A-Z]\w+\s*[({]/.test(n)||/mutation\s+[A-Z]\w+\s*[({]/.test(n))return true}return false}function U(p,e,t){let r=Ne(p,e);if(r)return r;if(p.arguments?.length>0){let s=p.arguments[0],i=s?.expression||s;if(i){let n=Z(i,e,t);if(n)return n}}return null}function Ne(p,e){if(p.typeArguments?.params?.length>0){let t=p.typeArguments.params[0];if(t?.type==="TsTypeReference"&&t.typeName?.type==="Identifier")return d(t.typeName.value)}if(p.callee?.span&&p.span){let t=p.callee.span.end,r=Math.min(t+150,p.span.end),i=e.slice(t,r).match(/^<\s*(\w+)(?:Query|Mutation|Variables|Subscription)?[\s,>]/);if(i)return d(i[1])}return null}function Z(p,e,t){if(p.type==="Identifier")return re(p.value,t);if(p.type==="MemberExpression")return Se(p,t);if(p.type==="TaggedTemplateExpression"){let r=x(p.tag);if(r==="gql"||r==="graphql")return P(p.template)}if(p.type==="TemplateLiteral")return P(p);if(p.type==="CallExpression"){let r=x(p.callee);if(r==="gql"||r==="graphql")return V(p,e)}return p.type==="ObjectExpression"?se(p,e,t):null}function re(p,e){let t=e.variableOperations.get(p);if(t)return e.variableOperations.has(t)?re(t,e):t.endsWith("Document")||t.endsWith("Query")||t.endsWith("Mutation")?e.documentImports.get(t)||d(t):t;let r=e.documentImports.get(p);if(r)return r;let s=e.codegenMap.get(p);return s?s.operationName:/^(Query|Mutation|QUERY|MUTATION|Document)$/i.test(p)?null:d(p)}function Se(p,e){let t=p.object?.type==="Identifier"?p.object.value:null,r=p.property?.type==="Identifier"?p.property.value:null;if(!r)return null;if(t){let s=`${t}.${r}`,i=e.staticPropertyOperations.get(s);if(i)return i}return d(r)}function se(p,e,t){for(let r of p.properties||[])if(r.type==="KeyValueProperty"&&r.key?.type==="Identifier"&&r.key.value==="query")return Z(r.value,e,t);return null}function Oe(p,e){let t=[],r=new Set;if(!W(p))return t;let s=Ce(p);if(!s)return t;let i=H(s,p,e);return S(s,n=>{if(n.type!=="CallExpression")return;let a=x(n.callee);if(a){if($(a)){let o=U(n,p,i),l=D(a),u=`${l}:${o||"unknown"}`;r.has(u)||(r.add(u),t.push({operationName:o||"unknown",hookName:a,type:l}));}if((a==="query"||a==="mutate")&&n.arguments?.length>0){let o=n.arguments[0],l=o?.expression||o;if(l?.type==="ObjectExpression"){let u=se(l,p,i),f=a==="mutate"?"useMutation":"useQuery",c=`${f}:${u||"unknown"}`;u&&!r.has(c)&&(r.add(c),t.push({operationName:u,hookName:`client.${a}`,type:f}));}}}}),t}function je(p){return `${{useQuery:"Query",useLazyQuery:"Query",useMutation:"Mutation",useSubscription:"Subscription"}[p.type]||"Query"}: ${p.operationName}`}async function M(p,e,t=8){let r=new Array(p.length).fill(null),s=0;async function i(){for(;s<p.length;){let a=s++;if(a<p.length)try{r[a]=await e(p[a],a);}catch{r[a]=null;}}}let n=Array(Math.min(t,p.length)).fill(null).map(()=>i());return await Promise.all(n),r.filter(a=>a!==null)}function k(p,e){let t=h.createSourceFile(e,p,h.ScriptTarget.Latest,true,h.ScriptKind.TS),r=[],s=i=>{if(h.isVariableStatement(i)&&Me(i.modifiers))for(let n of i.declarationList.declarations){if(!h.isIdentifier(n.name))continue;let a=n.name.text;if(!a.endsWith("Document")||!n.initializer)continue;let o=Ie(n.initializer),l=Pe(o);if(!l)continue;let u=Ee(l);if(!u)continue;let c=h.getLineAndCharacterOfPosition(t,n.name.getStart(t)).line+1;r.push({documentName:a,operationName:u.operationName,operationType:u.operationType,document:l,line:c});}h.forEachChild(i,s);};return s(t),r}function Me(p){return p?p.some(e=>e.kind===h.SyntaxKind.ExportKeyword):false}function Ie(p){let e=p;for(;;){if(h.isParenthesizedExpression(e)){e=e.expression;continue}if(h.isAsExpression(e)){e=e.expression;continue}if(h.isTypeAssertionExpression(e)){e=e.expression;continue}if(h.isNonNullExpression(e)){e=e.expression;continue}break}return e}function Pe(p){if(!h.isObjectLiteralExpression(p))return null;let e=K(p);if(!e||typeof e!="object")return null;let t=e.kind,r=e.definitions;return t!=="Document"||!Array.isArray(r)?null:e}function Ee(p){let e=p.definitions;if(!Array.isArray(e)||e.length===0)return null;let t=e[0];if(!t||typeof t!="object"||t.kind!=="OperationDefinition")return null;let s=t.operation,i=t.name,n=s==="mutation"||s==="subscription"?s:"query",a="";if(i&&typeof i=="object"){let o=i.value;typeof o=="string"&&(a=o);}return a?{operationName:a,operationType:n}:null}function K(p){if(h.isObjectLiteralExpression(p)){let e={};for(let t of p.properties){if(h.isPropertyAssignment(t)){let r=Re(t.name);if(!r)continue;e[r]=K(t.initializer);continue}h.isShorthandPropertyAssignment(t);}return e}return h.isArrayLiteralExpression(p)?p.elements.map(e=>h.isExpression(e)?K(e):null):h.isStringLiteral(p)||h.isNoSubstitutionTemplateLiteral(p)?p.text:h.isNumericLiteral(p)?Number(p.text):p.kind===h.SyntaxKind.TrueKeyword?true:p.kind===h.SyntaxKind.FalseKeyword?false:(p.kind===h.SyntaxKind.NullKeyword,null)}function Re(p){return h.isIdentifier(p)||h.isStringLiteral(p)||h.isNumericLiteral(p)?p.text:(h.isComputedPropertyName(p),null)}var O=class{repoRootAbs;knownFiles;configCache=new Map;configPathCache=new Map;constructor(e,t){this.repoRootAbs=y.resolve(e),this.knownFiles=t;}resolve(e,t){if(!t||!t.startsWith(".")&&!t.startsWith("/")&&!t.startsWith("@")&&!t.includes("/"))return null;let r=y.join(this.repoRootAbs,e),s=this.getParsedConfigForFile(r),i={fileExists:g=>F.existsSync(g),readFile:g=>{try{return F.readFileSync(g,"utf8")}catch{return}},directoryExists:g=>{try{return F.existsSync(g)&&F.statSync(g).isDirectory()}catch{return false}},getCurrentDirectory:()=>this.repoRootAbs,realpath:h.sys.realpath},n=s?.options||{moduleResolution:h.ModuleResolutionKind.NodeNext,jsx:h.JsxEmit.ReactJSX,allowJs:true},o=h.resolveModuleName(t,r,n,i).resolvedModule?.resolvedFileName;if(!o)return null;let l=this.toRepoRelative(o);if(!l)return null;let u=this.normalizeRel(l),f=this.pickKnownFile(u);if(!f)return null;let c=this.getConfigPathForFile(r),m=c&&this.toRepoRelative(c)||void 0;return {file:f,evidence:{fromFile:this.normalizeRel(e),specifier:t,resolvedFile:f,configFile:m}}}getConfigPathForFile(e){let t=y.dirname(e),r=this.configPathCache.get(t);if(r!==void 0)return r;let s=this.findNearestConfig(t);return this.configPathCache.set(t,s),s}getParsedConfigForFile(e){let t=this.getConfigPathForFile(e);if(!t)return null;let r=this.configCache.get(t);if(r!==void 0)return r;try{let s=h.readConfigFile(t,h.sys.readFile);if(s.error)return this.configCache.set(t,null),null;let i=h.parseJsonConfigFileContent(s.config,h.sys,y.dirname(t),void 0,t);return this.configCache.set(t,i),i}catch{return this.configCache.set(t,null),null}}findNearestConfig(e){let t=y.resolve(e),r=this.repoRootAbs;for(;;){let s=y.join(t,"tsconfig.json"),i=y.join(t,"jsconfig.json");if(F.existsSync(s))return s;if(F.existsSync(i))return i;if(t===r)break;let n=y.dirname(t);if(n===t||(t=n,!t.startsWith(r)))break}return null}toRepoRelative(e){let t=y.resolve(e);if(!t.startsWith(this.repoRootAbs))return null;let r=y.relative(this.repoRootAbs,t);return this.normalizeRel(r)}normalizeRel(e){return y.normalize(e).replace(/\\/g,"/")}pickKnownFile(e){if(this.knownFiles.has(e))return e;let t=e.replace(/\.(ts|tsx|js|jsx|mts|cts|mjs|cjs|d\.ts)$/,""),r=this.firstKnownByStem(t);if(r)return r;let s=this.firstKnownByStem(`${t}/index`);return s||null}firstKnownByStem(e){let t=[".ts",".tsx",".js",".jsx",".mts",".cts",".mjs",".cjs"];for(let r of t){let s=`${e}${r}`;if(this.knownFiles.has(s))return s}return null}};var ae=class extends A{codegenMap=new Map;tsResolver=null;coverage={tsFilesScanned:0,tsParseFailures:0,graphqlParseFailures:0,codegenFilesDetected:0,codegenFilesParsed:0,codegenExportsFound:0};constructor(e){super(e);}getName(){return "PagesAnalyzer"}async analyze(){this.log("Starting page analysis..."),await this.loadCodegenMapping();let e=await this.findPageFiles();this.coverage.tsFilesScanned+=e.length,this.log(`Found ${e.length} page files`);let t=50,r=new Map;for(let n=0;n<e.length;n+=t){let a=e.slice(n,n+t),o=await Promise.all(a.map(async l=>{try{let u=await T.readFile(l,"utf-8");return {filePath:l,content:u}}catch{return null}}));for(let l of o)l&&r.set(l.filePath,l.content);}let i=(await M(e,async n=>{let a=r.get(n);if(!a)return null;let o=this.detectPagesRoot(n);return this.analyzePageFile(n,a,o)},8)).filter(n=>n!==null);return this.log(`Analyzed ${i.length} pages successfully`),{pages:i,coverage:this.coverage}}async loadCodegenMapping(){let e=await j(["**/__generated__/graphql.ts","**/__generated__/gql.ts","**/generated/graphql.ts","**/generated/gql.ts","**/*.generated.ts","**/graphql.ts"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**","**/dist/**","**/build/**"],absolute:true});for(let t of e)try{let r=await T.readFile(t,"utf-8"),s=y.relative(this.basePath,t);if(!r.includes("Document")||!r.includes("definitions"))continue;this.coverage.codegenFilesDetected+=1;let i=k(r,s);this.coverage.codegenFilesParsed+=1,this.coverage.codegenExportsFound+=i.length;for(let n of i)this.codegenMap.set(n.documentName,{operationName:n.operationName,operationType:n.operationType});i.length>0&&this.log(`Loaded ${i.length} codegen mappings from ${s}`);}catch{}}analyzePageFile(e,t,r){try{let s=e.endsWith(".tsx")||e.endsWith(".jsx"),i=parseSync(t,{syntax:e.endsWith(".ts")||e.endsWith(".tsx")?"typescript":"ecmascript",tsx:s,jsx:s,comments:!1}),n=y.relative(r,e),a=this.filePathToRoutePath(n),o=this.findPageComponent(i,t);if(!o)return null;let l=this.extractRouteParams(a),u=this.extractImports(i),f=this.extractLayout(i,t),c=this.extractAuthRequirement(i,t,e),m=this.extractPermissions(t),g=this.extractDataFetching(i,t,u),C=this.extractLinkedPages(i,t),b=this.extractNavigation(t),I=this.extractSteps(t);return {path:a,filePath:n,component:o,params:l,layout:f,authentication:c,permissions:m,dataFetching:g,navigation:b,linkedPages:C,steps:I.length>0?I:void 0}}catch{return this.coverage.tsParseFailures+=1,null}}async findPageFiles(){let e=this.getSetting("pagesDir","src/pages"),t=[],s=[...new Set([e,"pages","src/pages","app","src/app"])];for(let n of s){if(n==="app"||n==="src/app"){let o=["controllers","models","views","helpers"],l=this.resolvePath(n);if(o.some(f=>{try{return F.existsSync(y.join(l,f))}catch{return false}}))continue}let a=this.resolvePath(n);try{let l=n==="app"||n==="src/app"||n.endsWith("/app")?["**/page.{tsx,ts,jsx,js}"]:["**/*.tsx","**/*.ts","**/*.jsx","**/*.js"],u=await j(l,{cwd:a,ignore:["_app.tsx","_app.ts","_app.jsx","_app.js","_document.tsx","_document.ts","_error.tsx","api/**","**/*.test.*","**/*.spec.*","**/node_modules/**","**/components/pages/**"],absolute:!0});t.push(...u),u.length>0&&this.log(`Found ${u.length} pages in ${n}`);}catch{}}let i=["frontend/src/**/pages","app/javascript/**/pages"];for(let n of i)try{let a=await j([`${n}/**/*.tsx`,`${n}/**/*.ts`,`${n}/**/*.jsx`,`${n}/**/*.js`],{cwd:this.basePath,ignore:["**/*.test.*","**/*.spec.*","**/node_modules/**","**/components/pages/**"],absolute:!0});t.push(...a);}catch{}if(t.length===0){let n=await this.findSPARoutes();n.length>0&&(this.log(`Found ${n.length} SPA routes from App.tsx`),t.push(...n));}return [...new Set(t)]}async findSPARoutes(){let e=[];if(!this.tsResolver)try{let r=await j(["**/*.{ts,tsx,js,jsx}"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**","**/dist/**","**/build/**"],absolute:!1,onlyFiles:!0,unique:!0,dot:!1});this.tsResolver=new O(this.basePath,new Set(r.map(s=>s.replace(/\\/g,"/"))));}catch{this.tsResolver=null;}let t=["src/App.tsx","src/App.jsx","src/App.js","App.tsx","App.jsx","App.js"];for(let r of t){let s=this.resolvePath(r);if(F.existsSync(s))try{let i=await T.readFile(s,"utf-8");if(!i.includes("react-router")&&!i.includes("Route"))continue;let n=parseSync(i,{syntax:"typescript",tsx:!0}),a=this.extractImports(n);this.traverseNode(n,o=>{if(o.type==="JSXOpeningElement"){let l=this.getJsxTagName(o);if(l==="Route"||l==="PrivateRoute"){let u=this.getJsxAttribute(o,"component"),f=this.getJsxAttribute(o,"element"),c=u||f,m=c?a.get(c):void 0;if(m){let g=this.resolveImportPath(s,m);g&&F.existsSync(g)&&e.push(g);}}}}),e.length>0&&e.push(s);}catch{}}return e}resolveImportPath(e,t){if(!t.startsWith(".")){let n=y.relative(this.basePath,e).replace(/\\/g,"/");if(this.tsResolver){let a=this.tsResolver.resolve(n,t);if(a)return y.join(this.basePath,a.file)}return null}let r=[".tsx",".ts",".jsx",".js","/index.tsx","/index.ts","/index.jsx","/index.js"],s=y.dirname(e),i=y.resolve(s,t);for(let n of r){let a=i+n;if(F.existsSync(a))return a}if(F.existsSync(i)&&F.statSync(i).isDirectory())for(let n of ["/index.tsx","/index.ts","/index.jsx","/index.js"]){let a=i+n;if(F.existsSync(a))return a}return null}detectPagesRoot(e){let t=["/src/pages/","/pages/","/src/app/","/app/","/frontend/src/pages/","/app/javascript/pages/"];for(let r of t){let s=e.indexOf(r);if(s!==-1)return e.substring(0,s+r.length-1)}return this.basePath}filePathToRoutePath(e){let t=e.replace(/\\/g,"/").replace(/\.(tsx?|jsx?)$/,"");return t=t.replace(/\/page$/,""),t=t.replace(/\/route$/,""),"/"+t.split("/").filter(Boolean).map(n=>n.replace(/^\(\.\.\.\)|^\(\.\.\)|^\(\.\)/,"")).filter(n=>!(n.startsWith("(")&&n.endsWith(")")||n.startsWith("@"))).join("/").replace(/\/index$/,"").replace(/\[\[\.\.\.(\w+)\]\]/g,"*").replace(/\[\.\.\.(\w+)\]/g,"*").replace(/\[(\w+)\]/g,":$1")}extractRouteParams(e){let t=[],r=e.match(/:(\w+)/g);if(r)for(let s of r)t.push(s.slice(1));return t}findPageComponent(e,t){let r=this.findMainJsxComponent(e,t);if(r&&r!=="Page"&&r!=="default")return r;for(let s of e.body){if(s.type==="ExportDefaultDeclaration"){let i=s.decl;if(i?.type==="FunctionExpression"&&i.identifier?.value){let n=i.identifier.value;if(n!=="Page")return n}if(i?.type==="Identifier"){let n=i.value;if(n!=="Page")return n}if(i?.type==="ArrowFunctionExpression")return r||"default"}if(s.type==="ExportDefaultExpression"){let i=s.expression;if(i?.type==="Identifier"){let n=i.value;if(n!=="Page")return n}}}if(r)return r;for(let s of e.body)if(s.type==="VariableDeclaration"){for(let i of s.declarations)if(i.id?.type==="Identifier"&&i.id.value==="Page")return "Page"}for(let s of e.body)if(s.type==="ExportDeclaration"&&s.declaration?.type==="FunctionDeclaration"){let i=s.declaration.identifier?.value;if(i&&/^[A-Z]/.test(i))return i}for(let s of e.body){if(s.type==="FunctionDeclaration"){let i=s.identifier?.value;if(i&&/^[A-Z]/.test(i))return i}if(s.type==="VariableDeclaration"){for(let i of s.declarations)if(i.id?.type==="Identifier"){let n=i.id.value;if(n&&/^[A-Z]/.test(n)&&t.includes("return")&&t.includes("<"))return n}}}return null}findMainJsxComponent(e,t){let r=this.extractImports(e),s=new Set;for(let[a,o]of r)/^[A-Z]/.test(a)&&(o.includes("features")||o.includes("components")||o.includes("containers"))&&s.add(a);let i=[];for(let a of s){let o=new RegExp(`<${a}[\\s/>]`,"g"),l;for(;(l=o.exec(t))!==null;)i.push({name:a,index:l.index});}let n=i.find(a=>a.name.includes("Container")||a.name.includes("Page")||a.name.includes("View")||a.name.includes("Screen"));return n?n.name:i.length>0?(i.sort((a,o)=>a.index-o.index),i[0].name):null}extractImports(e){let t=new Map;for(let r of e.body)if(r.type==="ImportDeclaration"){let s=r.source?.value||"";for(let i of r.specifiers||[])i.type==="ImportSpecifier"&&i.local?.value&&t.set(i.local.value,s),i.type==="ImportDefaultSpecifier"&&i.local?.value&&t.set(i.local.value,s);}return t}extractLayout(e,t){if(t.includes("getLayout")){let r=t.match(/getLayout\s*=.*?<(\w+Layout|\w+Shell)/);if(r)return r[1]}}extractAuthRequirement(e,t,r){let s=y.basename(r),a={required:!["404.tsx","permission-denied.tsx","_app.tsx","_document.tsx","_error.tsx"].some(l=>s===l)},o=["RequiredCondition","ProtectedRoute","AuthGuard","PrivateRoute","WithAuth","RequireAuth","Authenticated","Authorized"];for(let l of o)if(t.includes(`<${l}`)){a.condition="Additional permissions required";let u=this.extractRolesFromContent(t);u.length>0&&(a.roles=u);break}return a}extractRolesFromContent(e){let t=[];this.traverseNode({content:e},()=>{});let r=e.matchAll(/(\w+Role|\w+Permission)\.(\w+)/g);for(let s of r)t.push(s[2]);return [...new Set(t)]}extractPermissions(e){let t=[],r=e.matchAll(/(?:Permission|Role|isAdmin)\.\w+/g);for(let s of r)t.includes(s[0])||t.push(s[0]);return t}extractDataFetching(e,t,r){let s=[],i=new Set,n=new Map;for(let[l,u]of this.codegenMap)n.set(l,{operationName:u.operationName,type:u.operationType});let a=H(e,t,n),o=this.getGraphQLHookPatterns();if(S(e,l=>{if(l.type==="CallExpression"){let u=l,f=x(u.callee);if(!f)return;if($(f,o)&&ne(u,t,a)){let c=U(u,t,a),g={type:D(f,o),operationName:c||"unknown"},C=this.extractVariablesFromCall(u);Object.keys(C).length>0&&(g.variables=C);let b=`${g.type}:${g.operationName}`;i.has(b)||(i.add(b),s.push(g));}if(f==="query"||f==="mutate"){let c=this.analyzeClientDirectCall(u,t,a);if(c){let m=`${c.type}:${c.operationName}`;i.has(m)||(i.add(m),s.push(c));}}}}),this.extractSSRDataFetching(e,t,s,i),t.includes("getStaticProps")){let l="getStaticProps:getStaticProps";i.has(l)||(i.add(l),s.push({type:"getStaticProps",operationName:"getStaticProps"}));}return s}analyzeClientDirectCall(e,t,r){if(!e.arguments?.length)return null;let s=e.arguments[0],i=s?.expression||s;if(i?.type!=="ObjectExpression")return null;for(let n of i.properties||[])if(n.type==="KeyValueProperty"&&n.key?.type==="Identifier"&&n.key.value==="query"){let a=n.value,o=null;if(a?.type==="Identifier"){let l=a.value;o=r.variableOperations.get(l)||r.documentImports.get(l)||d(l);}if(a?.type==="MemberExpression"){let l=a.object?.type==="Identifier"?a.object.value:null,u=a.property?.type==="Identifier"?a.property.value:null;if(l&&u){let f=`${l}.${u}`;o=r.staticPropertyOperations.get(f)||d(u);}}if(o)return {type:x(e.callee)==="mutate"?"useMutation":"useQuery",operationName:o}}return null}extractDocumentImports(e){let t=new Map;for(let r of e.body)if(r.type==="ImportDeclaration"){let s=r.source?.value||"",i=s.includes("__generated__")||s.includes("generated")||s.includes("graphql")||s.includes(".generated");for(let n of r.specifiers||[]){let a=n.type==="ImportSpecifier"||n.type==="ImportDefaultSpecifier"?n.local?.value:null;if(a){if(a.endsWith("Document")||i){let o=a.replace(/Document$/,"");t.set(a,o);}(a.endsWith("Query")||a.endsWith("Mutation"))&&t.set(a,a.replace(/Query$|Mutation$/,""));}}}return t}extractVariableAssignments(e,t){let r=new Map;return this.traverseNode(e,s=>{if(s.type==="VariableDeclarator"&&s.id?.type==="Identifier"){let i=s.id.value,n=s.init;if(!n)return;if(n.type==="Identifier"){let a=n.value;(a.endsWith("Document")||a.endsWith("Query"))&&r.set(i,a);}if(n.type==="CallExpression"){let a=this.getCalleeName(n.callee);if(a==="gql"||a==="graphql"){let o=this.extractOperationNameFromGqlCall(n,t);o&&r.set(i,o);}}if(n.type==="TaggedTemplateExpression"){let a=this.getCalleeName(n.tag);if(a==="gql"||a==="graphql"){let o=n.template;if(o?.quasis?.[0]?.raw){let u=o.quasis[0].raw.match(/(?:query|mutation|subscription)\s+(\w+)/i);u&&r.set(i,u[1]);}}}}}),r}extractOperationNameFromGqlCall(e,t){if(!e.arguments?.length)return null;let r=e.arguments[0],s=r?.expression||r;if(s?.type==="TemplateLiteral"&&s.quasis?.[0]?.raw){let n=s.quasis[0].raw.match(/(?:query|mutation|subscription)\s+(\w+)/i);if(n)return n[1]}if(e.span){let n=t.slice(e.span.start,e.span.end).match(/(?:query|mutation|subscription)\s+(\w+)/i);if(n)return n[1]}return null}analyzeGraphQLHookCall(e,t,r,s){let i=this.getCalleeName(e.callee);if(!i)return null;let n=this.getGraphQLHookPatterns(),a=z.includes(i),o=R(i,n)&&!i.includes("Params"),l=Q(i,n);if(!a&&!o&&!l)return null;let u=D(i,n),f=i.replace(/^use/,"").replace(/Query$|Mutation$/,""),c=this.extractTypeGeneric(e,t);if(c&&(f=c.replace(/Query$|Mutation$|Variables$/,"")),e.arguments&&e.arguments.length>0){let g=e.arguments[0],C=g?.expression||g,b=this.extractOperationFromArgument(C,r,s);b&&(f=b);}let m=this.extractVariablesFromCall(e);return {type:u,operationName:f,variables:m}}extractTypeGeneric(e,t){if(e.typeArguments?.params?.length>0){let r=e.typeArguments.params[0];if(r?.type==="TsTypeReference"&&r.typeName?.type==="Identifier")return r.typeName.value}if(e.callee?.span){let r=e.callee.span.end,i=t.slice(r,r+100).match(/^<(\w+)(?:Query|Mutation|Variables)?[,>]/);if(i)return i[1]}return null}extractOperationFromArgument(e,t,r){if(!e)return null;if(e.type==="Identifier"){let s=e.value;if(["[","{","'",'"',"`"].some(o=>s.startsWith(o)))return null;let i=r.get(s);if(i)return !i.endsWith("Document")&&!i.endsWith("Query")?i:t.get(i)||i.replace(/Document$/,"");let n=t.get(s);if(n)return n;let a=this.codegenMap.get(s);return a?a.operationName:/^(Query|Mutation|QUERY|MUTATION)$/i.test(s)?null:s.replace(/Document$/,"").replace(/Query$|Mutation$/,"")}if(e.type==="MemberExpression"&&e.property?.type==="Identifier")return e.property.value.replace(/Document$/,"").replace(/Query$|Mutation$/,"");if(e.type==="TaggedTemplateExpression"&&e.template?.quasis?.[0]?.raw){let i=e.template.quasis[0].raw.match(/(?:query|mutation|subscription)\s+(\w+)/i);if(i)return i[1]}if(e.type==="CallExpression"){let s=this.getCalleeName(e.callee);if((s==="graphql"||s==="gql")&&e.arguments?.length>0){let i=e.arguments[0],n=i?.expression||i;if(n?.type==="TemplateLiteral"&&n.quasis?.[0]?.raw){let o=n.quasis[0].raw.match(/(?:query|mutation|subscription)\s+(\w+)/i);if(o)return o[1]}}}if(e.type==="TemplateLiteral"&&e.quasis?.[0]?.raw){let i=e.quasis[0].raw.match(/(?:query|mutation|subscription)\s+(\w+)/i);if(i)return i[1]}return null}extractVariablesFromCall(e){let t=[];if(e.arguments&&e.arguments.length>1){let r=e.arguments[1],s=r?.expression||r;if(s?.type==="ObjectExpression"){for(let i of s.properties||[])if(i.type==="KeyValueProperty"&&i.key?.type==="Identifier"&&i.key.value==="variables"&&i.value?.type==="ObjectExpression")for(let n of i.value.properties||[])n.type==="KeyValueProperty"&&n.key?.type==="Identifier"?t.push(n.key.value):n.type==="Identifier"&&t.push(n.value);}}return t}extractSSRDataFetching(e,t,r,s){let i=this.extractImports(e),n=this.extractDocumentImports(e);for(let a of e.body)if(a.type==="ExportDeclaration"){let o=a.declaration;if(o?.type==="VariableDeclaration")for(let l of o.declarations)l.id?.type==="Identifier"&&l.id.value==="getServerSideProps"&&this.extractSSRQueriesFromNode(l,t,i,n,r,s);o?.type==="FunctionDeclaration"&&o.identifier?.value==="getServerSideProps"&&this.extractSSRQueriesFromNode(o,t,i,n,r,s);}}extractSSRQueriesFromNode(e,t,r,s,i,n){S(e,a=>{if(a.type!=="CallExpression")return;let o=x(a.callee);if(o==="query"||o==="mutate"){let l=this.extractQueryFromClientCall(a,t,r,s);if(l){let u=`getServerSideProps:\u2192 ${l}`;n.has(u)||(n.add(u),i.push({type:"getServerSideProps",operationName:`\u2192 ${l}`}));}}});}extractQueryFromClientCall(e,t,r,s){if(!e.arguments?.length)return null;let i=e.arguments[0],n=i?.expression||i;if(n?.type!=="ObjectExpression")return null;for(let a of n.properties||[])if(a.type==="KeyValueProperty"&&a.key?.type==="Identifier"&&a.key.value==="query"){let o=a.value;if(o?.type==="Identifier"){let l=o.value;if(s.has(l))return s.get(l)||null;let u=this.codegenMap.get(l);return u?u.operationName:r.get(l)?d(l):d(l)}if(o?.type==="MemberExpression"){let l=o.object?.type==="Identifier"?o.object.value:null,u=o.property?.type==="Identifier"?o.property.value:null;if(l&&u)return `${l}.${u}`}}return null}extractNavigation(e){let t={visible:true,currentNavItem:null};(e.includes("hideNavigation")||e.includes("noNav"))&&(t.visible=false),(e.includes("miniNav")||e.includes("collapsedNav"))&&(t.mini=true);let r=e.match(/currentNav(?:Item)?[:\s=]+['"`]([^'"`]+)['"`]/);return r&&(t.currentNavItem=r[1]),t}extractLinkedPages(e,t){let r=[];return this.traverseNode(e,s=>{if(s.type==="JSXOpeningElement"&&this.getJsxTagName(s)==="Link"){let n=this.getJsxAttribute(s,"href");if(n&&n.startsWith("/")&&!n.includes("http")){let a=n.split("?")[0].split("#")[0];r.includes(a)||r.push(a);}}}),r}extractSteps(e){let t=[],r=e.matchAll(/(?:step|Step)\s*[:=]\s*['"`]([^'"`]+)['"`]/g),s=0;for(let i of r)t.push({id:s++,name:i[1]});return t}traverseNode(e,t){if(!(!e||typeof e!="object")){t(e);for(let r of Object.keys(e)){let s=e[r];if(Array.isArray(s))for(let i of s)this.traverseNode(i,t);else s&&typeof s=="object"&&this.traverseNode(s,t);}}}getCalleeName(e){if(e.type==="Identifier")return e.value;if(e.type==="MemberExpression"){let t=e.object,r=e.property;if(t.type==="Identifier"&&r.type==="Identifier")return `${t.value}.${r.value}`}return null}getJsxTagName(e){return e.name?.type==="Identifier"?e.name.value:null}getJsxAttribute(e,t){if(!e.attributes)return null;for(let r of e.attributes)if(r.type==="JSXAttribute"&&r.name?.value===t){if(r.value?.type==="StringLiteral")return r.value.value;if(r.value?.type==="JSXExpressionContainer"&&(r.value.expression?.type==="Identifier"||r.value.expression?.type==="StringLiteral"))return r.value.expression.value}return null}};var pe=class extends A{coverage={tsFilesScanned:0,tsParseFailures:0,graphqlParseFailures:0,codegenFilesDetected:0,codegenFilesParsed:0,codegenExportsFound:0};constructor(e){super(e);}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 r=await this.analyzeInlineGraphQL();e.push(...r),this.log(`[GraphQLAnalyzer] Step 2 done: ${r.length} inline operations`),this.log("[GraphQLAnalyzer] Step 3: Analyzing codegen output...");let s=await this.analyzeCodegenGenerated();e.push(...s),this.log(`[GraphQLAnalyzer] Step 3 done: ${s.length} from codegen`);let i=this.deduplicateOperations(e);return this.log(`[GraphQLAnalyzer] Deduplicated: ${i.length} unique operations`),this.log("[GraphQLAnalyzer] Step 4: Finding operation usage..."),await this.findOperationUsage(i),this.log("[GraphQLAnalyzer] Step 4 done"),this.log(`Found ${i.length} GraphQL operations`),{graphqlOperations:i,coverage:this.coverage}}deduplicateOperations(e){let t=new Map;for(let r of e)if(!t.has(r.name))t.set(r.name,r);else {let s=t.get(r.name);if(s)for(let i of r.usedIn)s.usedIn.includes(i)||s.usedIn.push(i);}return Array.from(t.values())}async analyzeCodegenGenerated(){let e=[],t=await j(["**/__generated__/graphql.ts","**/__generated__/gql.ts","**/generated/graphql.ts","**/generated/gql.ts","**/*.generated.ts","**/*.generated.tsx","**/graphql/generated.ts","**/gql/generated.ts"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**","**/dist/**","**/build/**"],absolute:true});for(let r of t)try{let s=await T.readFile(r,"utf-8"),i=y.relative(this.basePath,r);if(!s.includes("Document")||!s.includes("definitions"))continue;this.coverage.codegenFilesDetected+=1;let n=k(s,i);this.coverage.codegenFilesParsed+=1,this.coverage.codegenExportsFound+=n.length;for(let a of n){let l=a.document?.definitions?.[0];if(!l||l.kind!=="OperationDefinition")continue;let u=(l.variableDefinitions||[]).map(f=>({name:f.variable?.name?.value||"unknown",type:this.extractTypeFromAst(f.type),required:f.type?.kind==="NonNullType"}));e.push({name:a.operationName,type:a.operationType,filePath:i,usedIn:[],variables:u,returnType:this.inferReturnTypeFromAst(l),fragments:this.extractFragmentReferencesFromAst(l),fields:this.extractFieldsFromAst(l.selectionSet),variableNames:[a.documentName]});}n.length>0&&this.log(`Found ${n.length} operations in codegen output: ${i}`);}catch(s){this.warn(`Failed to analyze codegen file ${r}: ${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 r=[];for(let s of e.selections)if(s.kind==="Field"){let i={name:s.name?.value||"unknown"};if(s.arguments?.length>0){let n=s.arguments.map(a=>a.name?.value).join(", ");i.type=`(${n})`;}s.selectionSet&&(i.fields=this.extractFieldsFromAst(s.selectionSet,t+1)),r.push(i);}else if(s.kind==="FragmentSpread")r.push({name:`...${s.name?.value}`,type:"fragment"});else if(s.kind==="InlineFragment"){let i=s.typeCondition?.name?.value||"inline";r.push({name:`... on ${i}`,type:"inline-fragment",fields:this.extractFieldsFromAst(s.selectionSet,t+1)});}return r}extractFragmentReferencesFromAst(e){let t=[],r=s=>{if(s&&(s.kind==="FragmentSpread"&&t.push(s.name?.value),s.selectionSet?.selections))for(let i of s.selectionSet.selections)r(i);};return r(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 j(["**/*.graphql"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**"],absolute:true});return (await M(e,async r=>{let s=await T.readFile(r,"utf-8");try{let i=parse(s);return this.extractOperationsFromDocument(i,y.relative(this.basePath,r))}catch{return this.coverage.graphqlParseFailures+=1,[]}})).flat()}async analyzeInlineGraphQL(){let e=[],t=await j(["**/*.ts","**/*.tsx","**/*.js","**/*.jsx"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**","**/__tests__/**","**/*.test.*","**/*.spec.*","**/__generated__/**"],absolute:true});this.coverage.tsFilesScanned+=t.length;let r=50;for(let s=0;s<t.length;s+=r){let i=t.slice(s,s+r),n=await M(i,async a=>{try{let o=await T.readFile(a,"utf-8");if(!o.includes("gql")&&!o.includes("graphql"))return [];let l=y.relative(this.basePath,a),u=a.endsWith(".tsx")||a.endsWith(".jsx"),f=parseSync(o,{syntax:a.endsWith(".ts")||a.endsWith(".tsx")?"typescript":"ecmascript",tsx:u,jsx:u});return this.analyzeModuleForGraphQL(f,o,l)}catch{return this.coverage.tsParseFailures+=1,[]}},10);e.push(...n.flat());}return e}analyzeModuleForGraphQL(e,t,r){let s=[],i=[];return this.traverseNodeWithContext(e,i,(n,a)=>{if(n.type==="TaggedTemplateExpression"){let o=n,l=this.getTagName(o.tag);if(l==="gql"||l==="graphql"){let u=this.extractTemplateContent(o.template,t);if(u)try{let f=parse(u),c=this.extractOperationsFromDocument(f,r);if(a)for(let m of c)m.variableNames=m.variableNames||[],m.variableNames.push(a),m.variableNames.push(`${m.name}Document`);s.push(...c);}catch{this.coverage.graphqlParseFailures+=1;}}}if(n.type==="CallExpression"){let o=n,l=this.getCalleeName(o.callee);if((l==="gql"||l==="graphql")&&o.arguments.length>0){let u=o.arguments[0].expression,f=this.extractGraphQLFromExpression(u,t);if(f)try{let c=parse(f),m=this.extractOperationsFromDocument(c,r);if(a)for(let g of m)g.variableNames=g.variableNames||[],g.variableNames.push(a),g.variableNames.push(`${g.name}Document`);s.push(...m);}catch{this.coverage.graphqlParseFailures+=1;}}}}),s}traverseNodeWithContext(e,t,r){if(!e||typeof e!="object")return;let s=false;e.type==="VariableDeclarator"&&e.id?.type==="Identifier"&&(t.push(e.id.value),s=true),r(e,t.length>0?t[t.length-1]:null);for(let i of Object.keys(e)){let n=e[i];if(Array.isArray(n))for(let a of n)this.traverseNodeWithContext(a,t,r);else n&&typeof n=="object"&&this.traverseNodeWithContext(n,t,r);}s&&t.pop();}getTagName(e){return e.type==="Identifier"?e.value:null}getCalleeName(e){return e.type==="Identifier"?e.value:null}extractTemplateContent(e,t){if(e.type==="TemplateLiteral"){if(e.quasis.length===1&&e.expressions.length===0)return e.quasis[0].raw;let r=e.span.start,s=e.span.end;return t.slice(r,s).slice(1,-1).replace(/\$\{[^}]*\}/g,"")}return null}extractGraphQLFromExpression(e,t){return e.type==="TemplateLiteral"?this.extractTemplateContent(e,t):e.type==="StringLiteral"?e.value:null}extractOperationsFromDocument(e,t){let r=[];for(let s of e.definitions){let i=this.extractOperation(s,t);i&&r.push(i);}return r}extractOperation(e,t){if(e.kind==="OperationDefinition"){let r=e.name?.value||"anonymous",s=e.operation,i=this.extractVariables(e),n=this.extractFragmentReferences(e),a=this.extractFields(e);return {name:r,type:s,filePath:t,usedIn:[],variables:i,returnType:this.inferReturnType(e),fragments:n,fields:a}}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=[],r=(s,i=0)=>{if(!s||!s.selections||i>5)return [];let n=[];for(let a of s.selections)if(a.kind==="Field"){let o={name:a.name.value};if(a.arguments&&a.arguments.length>0){let l=a.arguments.map(u=>u.name.value).join(", ");o.type=`(${l})`;}a.selectionSet&&(o.fields=r(a.selectionSet,i+1)),n.push(o);}else if(a.kind==="FragmentSpread")n.push({name:`...${a.name.value}`,type:"fragment"});else if(a.kind==="InlineFragment"&&a.selectionSet){let o=a.typeCondition?.name?.value||"inline";n.push({name:`... on ${o}`,type:"inline-fragment",fields:r(a.selectionSet,i+1)});}return n};return e.selectionSet?r(e.selectionSet):t}extractVariables(e){let t=[];if(e.variableDefinitions)for(let r of e.variableDefinitions){let s=r.variable.name.value,i=this.typeNodeToString(r.type),n=r.type.kind==="NonNullType";t.push({name:s,type:i,required:n});}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=[],r=s=>{if(s&&(s.kind==="FragmentSpread"&&t.push(s.name.value),s.selectionSet))for(let i of s.selectionSet.selections)r(i);};return r(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=this.getGraphQLHookPatterns(),r=await j(["**/*.ts","**/*.tsx"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**","**/__generated__/**","**/dist/**","**/build/**"],absolute:true}),s=new Map,i=new Map,n=new Map,a=new Map;for(let c of e)if(s.set(c.name,c),i.set(`${c.name}Document`,c),a.set(`${c.name}Query`,c),a.set(`${c.name}Mutation`,c),a.set(`${c.name}Subscription`,c),a.set(`${c.name}QueryVariables`,c),a.set(`${c.name}MutationVariables`,c),c.variableNames)for(let m of c.variableNames)n.set(m,c);let o=new Set;for(let c of e)if(o.add(c.name),o.add(`${c.name}Document`),o.add(`${c.name}Query`),o.add(`${c.name}Mutation`),o.add(`${c.name}Subscription`),c.variableNames)for(let m of c.variableNames)o.add(m);let l=null,u=Array.from(o);if(u.length>0&&u.length<2e3){let c=u.sort((m,g)=>g.length-m.length).map(m=>m.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"));l=new RegExp(`\\b(${c.join("|")})\\b`,"g");}let f=50;for(let c=0;c<r.length;c+=f){let m=r.slice(c,c+f);await Promise.all(m.map(async g=>{try{let C=await T.readFile(g,"utf-8"),b=y.relative(this.basePath,g);if(!W(C))return;if(l){let I=new Set,J;for(;(J=l.exec(C))!==null;)I.add(J[1]);l.lastIndex=0;for(let de of I){let q=i.get(de);q&&b!==q.filePath&&(q.usedIn.includes(b)||q.usedIn.push(b));}}await this.findUsageWithAST(C,g,b,s,a,t);}catch{}}));}}async findUsageWithAST(e,t,r,s,i,n){try{let a=t.endsWith(".tsx")||t.endsWith(".jsx"),o=parseSync(e,{syntax:t.endsWith(".ts")||t.endsWith(".tsx")?"typescript":"ecmascript",tsx:a,jsx:a,comments:!1});this.traverseNodeForUsage(o,e,l=>{if(l.type==="CallExpression"){let u=this.getCalleeNameForUsage(l.callee);if(u&&$(u,n)){let f=this.extractTypeGenericFromCall(l,e);if(f){let m=i.get(f)||s.get(f.replace(/Query$|Mutation$|Variables$/,""));m&&r!==m.filePath&&(m.usedIn.includes(r)||m.usedIn.push(r));}let c=this.extractFirstArgName(l);if(c){let m=c.replace(/Document$/,""),g=s.get(m)||i.get(c);g&&r!==g.filePath&&(g.usedIn.includes(r)||g.usedIn.push(r));}}}});}catch{}}traverseNodeForUsage(e,t,r){if(!(!e||typeof e!="object")){r(e);for(let s of Object.keys(e)){let i=e[s];if(Array.isArray(i))for(let n of i)this.traverseNodeForUsage(n,t,r);else i&&typeof i=="object"&&this.traverseNodeForUsage(i,t,r);}}}getCalleeNameForUsage(e){return e?e.type==="Identifier"?e.value:e.type==="MemberExpression"&&e.property?.type==="Identifier"?e.property.value:null:null}extractTypeGenericFromCall(e,t){if(e.typeArguments?.params?.length>0){let r=e.typeArguments.params[0];if(r?.type==="TsTypeReference"&&r.typeName?.type==="Identifier")return r.typeName.value}if(e.callee?.span){let r=e.callee.span.end,i=t.slice(r,r+150).match(/^<\s*(\w+)(?:Query|Mutation|Variables|Subscription)?(?:\s*,|\s*>)/);if(i)return i[1]}return null}extractFirstArgName(e){if(e.arguments?.length>0){let t=e.arguments[0].expression;if(t?.type==="Identifier")return t.value;if(t?.type==="MemberExpression"&&t.property?.type==="Identifier")return t.property.value}return null}};var ue=class extends A{componentCache=new Map;coverage={tsFilesScanned:0,tsParseFailures:0,graphqlParseFailures:0,codegenFilesDetected:0,codegenFilesParsed:0,codegenExportsFound:0};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,coverage:this.coverage}}async analyzeComponents(){let e=[],t=[this.getSetting("featuresDir",""),this.getSetting("componentsDir",""),this.getSetting("pagesDir","")].filter(Boolean),r=["src/features","src/components","src/common/components","src/common","src/pages","src/app","src/modules","src/views","src/screens","components","pages","app"],i=[...new Set([...t,...r])].flatMap(o=>[`${o}/**/*.tsx`,`${o}/**/*.ts`]),n=await j(i,{cwd:this.basePath,ignore:["**/*.test.*","**/*.spec.*","**/*.stories.*","**/node_modules/**","**/__generated__/**"],absolute:true,onlyFiles:true,unique:true});this.log(`[DataFlowAnalyzer] Found ${n.length} component files to analyze`),this.coverage.tsFilesScanned+=n.length;let a=50;for(let o=0;o<n.length;o+=a){let l=n.slice(o,o+a),u=await Promise.all(l.map(async f=>{try{let c=await T.readFile(f,"utf-8");return {filePath:f,content:c}}catch{return null}}));for(let f of u)if(f)try{let c=parseSync(f.content,{syntax:"typescript",tsx:!0,comments:!1}),m=y.relative(this.basePath,f.filePath),g=this.analyzeComponentFile(c,m,f.content);e.push(...g);}catch{this.coverage.tsParseFailures+=1;}}return this.log(`[DataFlowAnalyzer] Extracted ${e.length} components`),this.buildDependencyGraph(e),e}analyzeComponentFile(e,t,r){let s=[],i=this.extractImports(e);for(let n of e.body){if(n.type==="ExportDeclaration"&&n.declaration?.type==="FunctionDeclaration"){let a=n.declaration.identifier?.value;if(a&&this.isComponentName(a)){let o=this.extractComponentInfo(a,t,r,i);s.push(o),this.componentCache.set(a,o);}}if(n.type==="FunctionDeclaration"){let a=n.identifier?.value;if(a&&this.isComponentName(a)){let o=this.extractComponentInfo(a,t,r,i);s.push(o),this.componentCache.set(a,o);}}if(n.type==="ExportDefaultDeclaration"&&n.decl?.type==="FunctionExpression"){let a=n.decl.identifier?.value;if(a&&this.isComponentName(a)){let o=this.extractComponentInfo(a,t,r,i);s.push(o),this.componentCache.set(a,o);}}if(n.type==="VariableDeclaration"){for(let a of n.declarations)if(a.id?.type==="Identifier"){let o=a.id.value;if(o&&(this.isComponentName(o)||o.startsWith("use"))&&a.init&&(a.init.type==="ArrowFunctionExpression"||a.init.type==="FunctionExpression")){let l=this.extractComponentInfo(o,t,r,i);s.push(l),this.componentCache.set(o,l);}}}if(n.type==="ExportDeclaration"&&n.declaration?.type==="VariableDeclaration"){for(let a of n.declaration.declarations)if(a.id?.type==="Identifier"){let o=a.id.value;if(o&&(this.isComponentName(o)||o.startsWith("use"))&&a.init&&(a.init.type==="ArrowFunctionExpression"||a.init.type==="FunctionExpression")){let l=this.extractComponentInfo(o,t,r,i);s.push(l),this.componentCache.set(o,l);}}}}return s}extractImports(e){let t=new Map,r=this.getListSetting("aliasPrefixes",["@/","~/","#/"]);for(let s of e.body)if(s.type==="ImportDeclaration"){let i=s.source?.value||"",n=r.some(a=>i.startsWith(a));if(i.startsWith(".")||n)for(let a of s.specifiers||[])a.type==="ImportSpecifier"&&a.local?.value&&t.set(a.local.value,i),a.type==="ImportDefaultSpecifier"&&a.local?.value&&t.set(a.local.value,i);}return t}isComponentName(e){return /^[A-Z][a-zA-Z0-9]*$/.test(e)}extractComponentInfo(e,t,r,s){let i="presentational";["/pages/","/app/","/routes/","/views/","/screens/"].some(f=>t.includes(f))?i="page":e.includes("Container")||e.includes("Provider")?i="container":e.includes("Layout")||e.includes("Shell")||e.includes("Wrapper")||e.includes("Frame")||e.includes("Scaffold")||t.includes("/layouts/")||t.includes("/layout/")?i="layout":e.startsWith("use")&&(i="hook");let a=this.extractHooksUsed(r),o=Array.from(s.keys()).filter(f=>this.isComponentName(f)||f.startsWith("use")),l=[];for(let[f,c]of s)l.push({name:f,path:c});let u=this.extractStateManagement(r);return {name:e,filePath:t,type:i,props:[],dependencies:o,dependents:[],hooks:a,stateManagement:u,imports:l}}extractHooksUsed(e){let t=[],r=new Set;if(!e.includes("use"))return t;try{let s=parseSync(e,{syntax:"typescript",tsx:!0,comments:!1}),i=this.extractDocumentImportsFromAst(s),n=this.extractVariableOperationMap(s,e);this.traverseForHooks(s,e,i,n,t,r);}catch{this.extractHooksWithRegex(e,t,r);}return t}extractDocumentImportsFromAst(e){let t=new Map;for(let r of e.body)if(r.type==="ImportDeclaration"){let s=r.source?.value||"",i=s.includes("__generated__")||s.includes("generated")||s.includes("graphql")||s.includes(".generated");for(let n of r.specifiers||[]){let a;(n.type==="ImportSpecifier"||n.type==="ImportDefaultSpecifier")&&(a=n.local?.value),a&&((a.endsWith("Document")||i)&&t.set(a,a.replace(/Document$/,"")),(a.endsWith("Query")||a.endsWith("Mutation"))&&t.set(a,a.replace(/Query$|Mutation$/,"")));}}return t}extractVariableOperationMap(e,t){let r=new Map,s=n=>{if(n.type!=="VariableDeclarator"||n.id?.type!=="Identifier")return;let a=n.id.value,o=n.init;if(o){if(o.type==="CallExpression"){let l=this.getCalleeNameFromNode(o.callee);if(l==="gql"||l==="graphql"){let u=this.extractOperationNameFromGqlCall(o,t);u&&r.set(a,u);}}if(o.type==="TaggedTemplateExpression"){let l=this.getCalleeNameFromNode(o.tag);if((l==="gql"||l==="graphql")&&o.template?.quasis?.[0]?.raw){let f=o.template.quasis[0].raw.match(/(?:query|mutation|subscription)\s+(\w+)/i);f&&r.set(a,f[1]);}}}},i=n=>{if(!(!n||typeof n!="object")){s(n);for(let a of Object.keys(n)){let o=n[a];if(Array.isArray(o))for(let l of o)i(l);else o&&typeof o=="object"&&i(o);}}};return i(e),r}extractOperationNameFromGqlCall(e,t){if(!e.arguments?.length)return null;let r=e.arguments[0],s=r?.expression||r;if(s?.type==="TemplateLiteral"&&s.quasis?.[0]?.raw){let n=s.quasis[0].raw.match(/(?:query|mutation|subscription)\s+(\w+)/i);if(n)return n[1]}if(e.span){let n=t.slice(e.span.start,e.span.end).match(/(?:query|mutation|subscription)\s+(\w+)/i);if(n)return n[1]}return null}traverseForHooks(e,t,r,s,i,n){if(!(!e||typeof e!="object")){e.type==="CallExpression"&&this.analyzeHookCall(e,t,r,s,i,n);for(let a of Object.keys(e)){let o=e[a];if(Array.isArray(o))for(let l of o)this.traverseForHooks(l,t,r,s,i,n);else o&&typeof o=="object"&&this.traverseForHooks(o,t,r,s,i,n);}}}analyzeHookCall(e,t,r,s,i,n){let a=this.getCalleeNameFromNode(e.callee);if(!a||!a.startsWith("use"))return;let o=R(a),l=Q(a),u=te(a);if((o||l||u)&&this.hasGraphQLArgument(e,t,r,s)){let c=this.extractOperationNameFromCall(e,t,r,s),m=l?"Mutation":u?"Subscription":"Query",g=c?`${m}: ${c}`:`${m}: unknown`;n.has(g)||(n.add(g),i.push(g));return}if(a==="useContext"){let f=this.extractContextName(e);if(f){let c=`\u{1F504} Context: ${f}`;n.has(c)||(n.add(c),i.push(c));}return}n.has(a)||(n.add(a),i.push(a));}hasGraphQLArgument(e,t,r,s){if(!e.arguments?.length)return false;let i=e.arguments[0],n=i?.expression||i;if(!n)return false;if(n.type==="Identifier"){let a=n.value;if(r.has(a)||s.has(a)||a.endsWith("Document")||/[A-Z][a-z]*Query$/.test(a)||/[A-Z][a-z]*Mutation$/.test(a)||/^[A-Z][A-Z0-9_]*_QUERY$/.test(a)||/^[A-Z][A-Z0-9_]*_MUTATION$/.test(a))return true}if(n.type==="TaggedTemplateExpression"){let a=this.getCalleeNameFromNode(n.tag);if(a==="gql"||a==="graphql")return true}if(n.type==="CallExpression"){let a=this.getCalleeNameFromNode(n.callee);if(a==="gql"||a==="graphql")return true}if(n.type==="TemplateLiteral"&&n.quasis?.[0]?.raw){let a=n.quasis[0].raw;if(/(?:query|mutation|subscription)\s+\w+/i.test(a))return true}if(n.type==="MemberExpression"){let a=n.property?.value;if(a&&/Query$|Mutation$|Document$/.test(a))return true}if(e.span){let a=t.slice(e.span.start,Math.min(e.span.end,e.span.start+500));if(a.includes("Document")||/\bgql\s*[`(]/.test(a)||/\bgraphql\s*[`(]/.test(a)||/query\s+\w+\s*[({]/.test(a)||/mutation\s+\w+\s*[({]/.test(a))return true}return false}getCalleeNameFromNode(e){return e?e.type==="Identifier"?e.value:e.type==="MemberExpression"&&e.property?.type==="Identifier"?e.property.value:null:null}extractOperationNameFromCall(e,t,r,s){if(e.typeArguments?.params?.length>0){let i=e.typeArguments.params[0];if(i?.type==="TsTypeReference"&&i.typeName?.type==="Identifier"){let n=i.typeName.value;return d(n)}}if(e.callee?.span&&e.span){let i=e.callee.span.end,n=Math.min(i+150,e.span.end),o=t.slice(i,n).match(/^<\s*(\w+)(?:Query|Mutation|Variables|Subscription)?[\s,>]/);if(o)return d(o[1])}if(e.arguments?.length>0){let i=e.arguments[0],n=i?.expression||i;if(!n)return null;if(n.type==="Identifier"){let a=n.value,o=s.get(a);if(o)return o;let l=r.get(a);return l||(/^(Query|Mutation|QUERY|MUTATION)$/i.test(a)?null:d(a))}if(n.type==="MemberExpression"&&n.property?.type==="Identifier")return d(n.property.value);if(n.type==="TaggedTemplateExpression"&&n.template?.quasis?.[0]?.raw){let o=n.template.quasis[0].raw.match(/(?:query|mutation|subscription)\s+(\w+)/i);if(o)return o[1]}if(n.type==="CallExpression"){let a=this.getCalleeNameFromNode(n.callee);if((a==="graphql"||a==="gql")&&n.arguments?.length>0){let o=n.arguments[0],l=o?.expression||o;if(l?.type==="TemplateLiteral"&&l.quasis?.[0]?.raw){let f=l.quasis[0].raw.match(/(?:query|mutation|subscription)\s+(\w+)/i);if(f)return f[1]}}}if(n.type==="TemplateLiteral"&&n.quasis?.[0]?.raw){let o=n.quasis[0].raw.match(/(?:query|mutation|subscription)\s+(\w+)/i);if(o)return o[1]}}if(e.span){let i=t.slice(e.span.start,e.span.end),n=i.match(/\b([A-Z][a-zA-Z0-9]*Document)\b/);if(n)return d(n[1]);let a=i.match(/(?:query|mutation|subscription)\s+(\w+)/i);if(a)return a[1]}return null}extractContextName(e){if(e.arguments?.length>0){let t=e.arguments[0].expression;if(t?.type==="Identifier")return t.value.replace(/Context$/,"")}return null}extractHooksWithRegex(e,t,r){let s=/\b(useQuery|useMutation|useLazyQuery|useSuspenseQuery|useBackgroundQuery|useSubscription)(?:<[^>]*>)?\s*\(\s*([A-Z_][A-Za-z0-9_]*)?/gs,i;for(;(i=s.exec(e))!==null;){let o=i[1],l=i[2];if(l&&/^(Query|Mutation|QUERY|MUTATION)$/i.test(l))continue;let u=l?d(l):"unknown",c=`${o.includes("Mutation")?"Mutation":o.includes("Subscription")?"Subscription":"Query"}: ${u}`;r.has(c)||(r.add(c),t.push(c));}let n=/\b(use[A-Z][a-zA-Z0-9]*)\s*\(/g,a;for(;(a=n.exec(e))!==null;){let o=a[1];if(!["useQuery","useMutation","useLazyQuery","useSuspenseQuery","useBackgroundQuery","useSubscription"].includes(o))if(o==="useContext"){let l=e.slice(a.index).match(/useContext\s*\(\s*([A-Z][A-Za-z0-9]*)/);if(l){let f=`\u{1F504} Context: ${l[1].replace(/Context$/,"")}`;r.has(f)||(r.add(f),t.push(f));}}else r.has(o)||(r.add(o),t.push(o));}}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 r of e)t.set(r.name,r);for(let r of e)for(let s of r.dependencies){let i=t.get(s);i&&!i.dependents.includes(r.name)&&i.dependents.push(r.name);}}async analyzeDataFlows(e){let t=[],r=1,s=this.analyzeContextFlows(e);t.push(...s.map(a=>({...a,id:`flow-${r++}`})));let i=this.analyzeApolloFlows(e);t.push(...i.map(a=>({...a,id:`flow-${r++}`})));let n=this.analyzePropDrilling(e);return t.push(...n.map(a=>({...a,id:`flow-${r++}`}))),t}analyzeContextFlows(e){let t=[],r=e.filter(i=>i.name.includes("Provider")||i.name.includes("Context")),s=e.filter(i=>i.hooks.some(n=>n.includes("Context")));for(let i of r){let n=i.name.replace("Provider","").replace("Context","");for(let a of s){let o=a.hooks.find(l=>l.includes("Context")&&l.includes(n));(o||a.hooks.some(l=>l.includes(n)))&&t.push({name:`\u{1F504} ${n} Context`,description:`Data flows from ${i.name} to ${a.name} via Context`,source:{type:"context",name:i.name},target:{type:"component",name:a.name},via:[],operations:[o||`useContext(${n})`]});}}return t}analyzeApolloFlows(e){let t=[];for(let r of e){let s=r.hooks.filter(n=>n.includes("Query:")||n==="useQuery"||n==="useLazyQuery");for(let n of s){let a=n.includes(":")?n.split(":")[1].trim():r.name;t.push({name:`Query: ${a}`,description:`${r.name} fetches ${a} via Apollo`,source:{type:"api",name:`GraphQL: ${a}`},target:{type:"component",name:r.name},via:[{type:"cache",name:"Apollo Cache"}],operations:[n]});}let i=r.hooks.filter(n=>n.includes("Mutation:")||n==="useMutation");for(let n of i){let a=n.includes(":")?n.split(":")[1].trim():r.name;t.push({name:`Mutation: ${a}`,description:`${r.name} mutates ${a} via Apollo`,source:{type:"component",name:r.name},target:{type:"api",name:`GraphQL: ${a}`},via:[],operations:[n]});}}return t}analyzePropDrilling(e){let t=[];for(let r of e)r.props.length>5&&r.dependents.length>0&&t.push({name:`Prop Drilling through ${r.name}`,description:`${r.name} passes ${r.props.length} props to children`,source:{type:"component",name:r.name},target:{type:"component",name:r.dependents[0]},via:[],operations:["props"]});return t}};var me=class p extends A{apiCallCounter=0;constructor(e){super(e);}getName(){return "RestApiAnalyzer"}async analyze(){this.log("Starting REST API analysis...");let e=await j(["**/*.ts","**/*.tsx","**/*.js","**/*.jsx"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**","**/__tests__/**","**/*.test.*","**/*.spec.*","**/*.stories.*","**/__generated__/**","**/dist/**","**/build/**"],absolute:true}),t=50,r=[];for(let s=0;s<e.length;s+=t){let i=e.slice(s,s+t),n=await M(i,async a=>{try{let o=await T.readFile(a,"utf-8"),l=y.relative(this.basePath,a),u=a.endsWith(".tsx")||a.endsWith(".jsx"),f=parseSync(o,{syntax:a.endsWith(".ts")||a.endsWith(".tsx")?"typescript":"ecmascript",tsx:u,jsx:u});return this.analyzeModule(f,o,l)}catch{return []}},10);r.push(...n.flat());}return this.log(`Found ${r.length} REST API calls`),{apiCalls:r}}analyzeModule(e,t,r){let s=[],i=t.split(`
2
+ `);return this.traverseNode(e,n=>{if(n.type==="CallExpression"){let a=n,o=this.analyzeCallExpression(a,r,i);o&&s.push(o);}}),s}traverseNode(e,t){if(!(!e||typeof e!="object")){t(e);for(let r of Object.keys(e)){let s=e[r];if(Array.isArray(s))for(let i of s)this.traverseNode(i,t);else s&&typeof s=="object"&&this.traverseNode(s,t);}}}analyzeCallExpression(e,t,r){let s=e.callee;if(s.type==="Super"||s.type==="Import")return null;let i=this.getCalleeName(s);if(!i)return null;if(i==="fetch"||i==="window.fetch")return this.extractFetchCall(e,t,r);let n=i.match(/^axios\.(get|post|put|delete|patch)$/i);return n?this.extractAxiosMethodCall(e,t,r,n[1].toUpperCase()):i==="axios"?this.extractAxiosDirectCall(e,t,r):i==="useSWR"||i==="useSWRImmutable"?this.extractSwrCall(e,t,r):null}getCalleeName(e){if(e.type==="Identifier")return e.value;if(e.type==="MemberExpression"){let t=e.object,r=e.property;if(t.type==="Identifier"&&r.type==="Identifier")return `${t.value}.${r.value}`}return null}extractFetchCall(e,t,r){if(e.arguments.length===0)return null;let s=e.arguments[0],i=this.extractUrlFromExpression(s.expression);if(!i.url||!i.isPlaceholder&&!this.isApiUrl(i.url))return null;let n="GET",a=false;if(e.arguments.length>1){let l=e.arguments[1].expression;if(l.type==="ObjectExpression")for(let u of l.properties)u.type==="KeyValueProperty"&&u.key.type==="Identifier"&&(u.key.value==="method"&&u.value.type==="StringLiteral"&&(n=this.normalizeMethod(u.value.value)),(u.key.value==="credentials"||u.key.value==="headers")&&(a=true));}let o=this.getLineNumber(e.span.start,r);return {id:`api-${++this.apiCallCounter}`,method:n,url:i.url,callType:"fetch",filePath:t,line:o,containingFunction:"unknown",usedIn:[],requiresAuth:a,category:this.categorizeApi(i.url)}}extractAxiosMethodCall(e,t,r,s){if(e.arguments.length===0)return null;let i=e.arguments[0],n=this.extractUrlFromExpression(i.expression);if(!n.url)return null;let a=this.getLineNumber(e.span.start,r);return {id:`api-${++this.apiCallCounter}`,method:this.normalizeMethod(s),url:n.url,callType:"axios",filePath:t,line:a,containingFunction:"unknown",usedIn:[],requiresAuth:false,category:this.categorizeApi(n.url)}}extractAxiosDirectCall(e,t,r){if(e.arguments.length===0)return null;let s=e.arguments[0].expression;if(s.type!=="ObjectExpression")return null;let i=null,n="GET";for(let o of s.properties)o.type==="KeyValueProperty"&&o.key.type==="Identifier"&&(o.key.value==="url"&&o.value.type==="StringLiteral"&&(i=o.value.value),o.key.value==="method"&&o.value.type==="StringLiteral"&&(n=this.normalizeMethod(o.value.value)));if(!i)return null;let a=this.getLineNumber(e.span.start,r);return {id:`api-${++this.apiCallCounter}`,method:n,url:i,callType:"axios",filePath:t,line:a,containingFunction:"unknown",usedIn:[],requiresAuth:false,category:this.categorizeApi(i)}}extractSwrCall(e,t,r){if(e.arguments.length===0)return null;let s=e.arguments[0].expression,i=this.extractUrlFromExpression(s);if(!i.url)return null;let n=this.getLineNumber(e.span.start,r);return {id:`api-${++this.apiCallCounter}`,method:"GET",url:i.url,callType:"useSWR",filePath:t,line:n,containingFunction:"unknown",usedIn:[],requiresAuth:false,category:this.categorizeApi(i.url)}}extractUrlFromExpression(e){if(e.type==="StringLiteral")return {url:e.value,isPlaceholder:false};if(e.type==="TemplateLiteral")return e.quasis.length===1&&e.expressions.length===0?{url:e.quasis[0].raw,isPlaceholder:false}:{url:e.quasis.map(s=>s.raw).join(":param"),isPlaceholder:true};if(e.type==="Identifier")return {url:`[${e.value}]`,isPlaceholder:true};if(e.type==="MemberExpression"){let t=e.object.type==="Identifier"?e.object.value:"?",r=e.property.type==="Identifier"?e.property.value:"?";return {url:`[${t}.${r}]`,isPlaceholder:true}}if(e.type==="ConditionalExpression"){let t=this.extractUrlFromExpression(e.consequent);return t.url?t:this.extractUrlFromExpression(e.alternate)}return {url:null,isPlaceholder:false}}getLineNumber(e,t){let r=0;for(let s=0;s<t.length;s++)if(r+=t[s].length+1,r>e)return s+1;return t.length}static STATIC_FILE_EXTENSIONS=/\.(css|js|mjs|cjs|ts|tsx|jsx|png|jpg|jpeg|gif|webp|svg|ico|woff|woff2|ttf|eot|otf|mp3|mp4|webm|ogg|wav|pdf|doc|docx|xls|xlsx|ppt|pptx|zip|tar|gz|rar|html|htm|xml|txt|md|map|wasm)$/i;static NON_API_SCHEMES=/^(data:|blob:|javascript:|mailto:|tel:|file:)/;isApiUrl(e){return p.NON_API_SCHEMES.test(e)||p.STATIC_FILE_EXTENSIONS.test(e)||!e.trim()?false:!!(e.startsWith("/")||e.startsWith("http://")||e.startsWith("https://")||e.startsWith("[")||e.includes("/api/")||e.includes("/v1/")||e.includes("/v2/")||e.includes("/graphql"))}static SERVICE_PATTERNS=[{pattern:/amazonaws\.com|\.s3\./i,name:"AWS"},{pattern:/googleapis\.com|google\.com\/api/i,name:"Google API"},{pattern:/graph\.facebook\.com|facebook\.com\/v\d+/i,name:"Facebook"},{pattern:/api\.twitter\.com|twitter\.com\/\d+/i,name:"Twitter/X"},{pattern:/api\.github\.com|github\.com\/api/i,name:"GitHub API"},{pattern:/stripe\.com/i,name:"Stripe"},{pattern:/paypal\.com/i,name:"PayPal"},{pattern:/slack\.com/i,name:"Slack"},{pattern:/discord\.com|discordapp\.com/i,name:"Discord"},{pattern:/twilio\.com/i,name:"Twilio"},{pattern:/sendgrid\.(com|net)/i,name:"SendGrid"},{pattern:/mailchimp\.com/i,name:"Mailchimp"},{pattern:/hubspot\.com|hsforms\.com/i,name:"HubSpot"},{pattern:/salesforce\.com/i,name:"Salesforce"},{pattern:/zendesk\.com/i,name:"Zendesk"},{pattern:/intercom\.io/i,name:"Intercom"},{pattern:/firebase(io)?\.com|firestore\.googleapis/i,name:"Firebase"},{pattern:/supabase\.(co|com|io)/i,name:"Supabase"},{pattern:/auth0\.com/i,name:"Auth0"},{pattern:/okta\.com/i,name:"Okta"},{pattern:/clerk\.(dev|com)/i,name:"Clerk"},{pattern:/cloudflare\.com|workers\.dev/i,name:"Cloudflare"},{pattern:/vercel\.com|vercel\.app/i,name:"Vercel"},{pattern:/netlify\.com|netlify\.app/i,name:"Netlify"},{pattern:/heroku\.com|herokuapp\.com/i,name:"Heroku"},{pattern:/railway\.app/i,name:"Railway"},{pattern:/render\.com/i,name:"Render"},{pattern:/digitalocean\.com/i,name:"DigitalOcean"},{pattern:/algolia\.(com|net|io)/i,name:"Algolia"},{pattern:/elastic\.co|elasticsearch/i,name:"Elasticsearch"},{pattern:/mongodb\.com|mongodb\.net/i,name:"MongoDB"},{pattern:/planetscale\.com/i,name:"PlanetScale"},{pattern:/sentry\.io/i,name:"Sentry"},{pattern:/datadog\.com/i,name:"Datadog"},{pattern:/segment\.(com|io)/i,name:"Segment"},{pattern:/mixpanel\.com/i,name:"Mixpanel"},{pattern:/amplitude\.com/i,name:"Amplitude"},{pattern:/openai\.com/i,name:"OpenAI"},{pattern:/anthropic\.com/i,name:"Anthropic"},{pattern:/cohere\.(ai|com)/i,name:"Cohere"}];categorizeApi(e){if(e.startsWith("["))return "Dynamic URL";if(e.startsWith("/"))return e.startsWith("/api/")?"Internal API":e.includes("/graphql")?"GraphQL":"Internal Route";for(let{pattern:t,name:r}of p.SERVICE_PATTERNS)if(t.test(e))return r;try{let s=new URL(e).hostname.replace(/^(api\.|www\.)/,"").split(".");if(s.length>=2){let i=s[s.length-2];return i.charAt(0).toUpperCase()+i.slice(1)+" API"}}catch{}return "External API"}normalizeMethod(e){let t=e.toUpperCase();return ["GET","POST","PUT","DELETE","PATCH"].includes(t)?t:"unknown"}};
3
+ export{pe as A,ue as B,me as C,A as a,O as b,X as c,ee as d,xe as e,z as f,Y as g,ve as h,R as i,Q as j,te as k,$ as l,D as m,W as n,d as o,Ce as p,x as q,S as r,H as s,V as t,P as u,ne as v,U as w,Oe as x,je as y,ae as z};
package/dist/cli.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import {a,b}from'./chunk-6AZNHUOB.js';import'./chunk-NQMJ3QRX.js';import'./chunk-VV3A3UE3.js';import'./chunk-QDVE7MT3.js';import'./chunk-2XZSFAJF.js';import'./chunk-WZAAA7DS.js';import'./chunk-H7VVRHQZ.js';import {Command}from'commander';import s from'chalk';import*as c from'path';import*as n from'fs/promises';import*as v from'os';function P(){let e=v.tmpdir();return c.join(e,`repomap-${Date.now()}`)}function C(e){let t=async()=>{try{await n.rm(e,{recursive:!0,force:!0});}catch{}process.exit(0);};process.on("SIGINT",t),process.on("SIGTERM",t);}var d=new Command;d.name("repomap").description("Interactive documentation generator for code repositories").version("0.6.0");async function x(e){let t=c.basename(e),a=false,o=c.join(e,"Gemfile"),p=c.join(e,"config","routes.rb");try{await n.access(o),await n.access(p);let g=await n.readFile(o,"utf-8");a=g.includes("gem 'rails'")||g.includes('gem "rails"');}catch{}let r=c.join(e,"package.json"),i=false,l=false,m={};try{let g=JSON.parse(await n.readFile(r,"utf-8")),w={...g.dependencies,...g.devDependencies};i=!!w.react,l=!!w.next;let f=["src/pages","pages","app","src/app","frontend/src"];for(let u of f)try{await n.access(c.join(e,u)),m.pagesDir=u;break}catch{}let b=["src/features","features","src/modules","modules","frontend/src"];for(let u of b)try{await n.access(c.join(e,u)),m.featuresDir=u;break}catch{}let D=["src/components","components","src/common/components","frontend/src"];for(let u of D)try{await n.access(c.join(e,u)),m.componentsDir=u;break}catch{}}catch{}let h=[];(i||l)&&h.push("pages","graphql","dataflow","rest-api");let y="generic";return l?y="nextjs":a&&(y="rails"),!a&&!i&&!l?null:{name:t,displayName:t,description:a&&i?"Rails + React application":a?"Rails application":"",path:e,branch:"main",type:y,analyzers:h,settings:m}}async function E(e){let t=await x(e);if(!t)throw new Error("Could not detect project. Please create a repomap.config.ts file or run 'repomap init'.");return {outputDir:"./.repomap",site:{title:`${t.displayName} Documentation`,description:"Auto-generated documentation",baseUrl:"/docs"},repositories:[t],analysis:{include:["**/*.tsx","**/*.ts"],exclude:["**/node_modules/**","**/__tests__/**","**/*.test.*","**/*.spec.*","**/dist/**","**/.next/**"],maxDepth:5},diagrams:{enabled:true,types:["flowchart","sequence"],theme:"default"},watch:{enabled:false,debounce:1e3},integrations:{github:{enabled:false,organization:""},slack:{enabled:false}}}}async function $(e,t){let a=e?[e]:["repomap.config.ts","repomap.config.js","repomap.config.mjs"];for(let o of a){let p=c.resolve(t,o);try{await n.access(p);let r=await import(p);return r.config||r.default}catch{}}return E(t)}d.command("generate").description("Generate documentation from source code").option("-c, --config <path>","Path to config file").option("-o, --output <path>","Output directory").option("--temp","Use temporary directory (no files in repository)").option("--repo <name>","Analyze specific repository only").option("--watch","Watch for changes and regenerate").option("--format <type>","Output format: json, html, markdown (default: all)","all").option("--ci","CI mode: minimal output, exit codes for errors").option("--static","Generate standalone HTML files (for GitHub Pages)").action(async e=>{let t=e.ci||process.env.CI==="true";t||console.log(s.blue.bold(`
2
+ import {a,b}from'./chunk-7BQRBJUG.js';import'./chunk-LHP2OKKA.js';import'./chunk-VV3A3UE3.js';import'./chunk-YO6EB4OI.js';import'./chunk-QBSB6BIU.js';import'./chunk-ATRSGO6O.js';import'./chunk-H7VVRHQZ.js';import {Command}from'commander';import s from'chalk';import*as c from'path';import*as $ from'fs';import*as n from'fs/promises';import*as P from'os';function x(){let e=P.tmpdir();return c.join(e,`repomap-${Date.now()}`)}function N(e){let t=async()=>{try{await n.rm(e,{recursive:!0,force:!0});}catch{}process.exit(0);};process.on("SIGINT",t),process.on("SIGTERM",t);}function S(){try{let e=new URL("../package.json",import.meta.url),t=$.readFileSync(e,"utf-8");return JSON.parse(t).version||"0.0.0"}catch{return "0.0.0"}}var d=new Command;d.name("repomap").description("Interactive documentation generator for code repositories").version(S());async function C(e){let t=c.basename(e),r=false,o=c.join(e,"Gemfile"),p=c.join(e,"config","routes.rb");try{await n.access(o),await n.access(p);let g=await n.readFile(o,"utf-8");r=g.includes("gem 'rails'")||g.includes('gem "rails"');}catch{}let a=c.join(e,"package.json"),i=false,l=false,m={};try{let g=JSON.parse(await n.readFile(a,"utf-8")),w={...g.dependencies,...g.devDependencies};i=!!w.react,l=!!w.next;let f=["src/pages","pages","app","src/app","frontend/src"];for(let u of f)try{await n.access(c.join(e,u)),m.pagesDir=u;break}catch{}let b=["src/features","features","src/modules","modules","frontend/src"];for(let u of b)try{await n.access(c.join(e,u)),m.featuresDir=u;break}catch{}let D=["src/components","components","src/common/components","frontend/src"];for(let u of D)try{await n.access(c.join(e,u)),m.componentsDir=u;break}catch{}}catch{}let h=[];(i||l)&&h.push("pages","graphql","dataflow","rest-api");let y="generic";return l?y="nextjs":r&&(y="rails"),!r&&!i&&!l?null:{name:t,displayName:t,description:r&&i?"Rails + React application":r?"Rails application":"",path:e,branch:"main",type:y,analyzers:h,settings:m}}async function E(e){let t=await C(e);if(!t)throw new Error("Could not detect project. Please create a repomap.config.ts file or run 'repomap init'.");return {outputDir:"./.repomap",site:{title:`${t.displayName} Documentation`,description:"Auto-generated documentation",baseUrl:"/docs"},repositories:[t],analysis:{include:["**/*.tsx","**/*.ts"],exclude:["**/node_modules/**","**/__tests__/**","**/*.test.*","**/*.spec.*","**/dist/**","**/.next/**"],maxDepth:5},diagrams:{enabled:true,types:["flowchart","sequence"],theme:"default"},watch:{enabled:false,debounce:1e3},integrations:{github:{enabled:false,organization:""},slack:{enabled:false}}}}async function v(e,t){let r=e?[e]:["repomap.config.ts","repomap.config.js","repomap.config.mjs"];for(let o of r){let p=c.resolve(t,o);try{await n.access(p);let a=await import(p);return a.config||a.default}catch{}}return E(t)}d.command("generate").description("Generate documentation from source code").option("-c, --config <path>","Path to config file").option("-o, --output <path>","Output directory").option("--temp","Use temporary directory (no files in repository)").option("--repo <name>","Analyze specific repository only").option("--watch","Watch for changes and regenerate").option("--format <type>","Output format: json, html, markdown (default: all)","all").option("--ci","CI mode: minimal output, exit codes for errors").option("--static","Generate standalone HTML files (for GitHub Pages)").action(async e=>{let t=e.ci||process.env.CI==="true";t||console.log(s.blue.bold(`
3
3
  \u{1F4DA} Repomap
4
- `));try{let a$1=process.cwd(),o=await $(e.config,a$1);e.temp&&(o.outputDir=P(),t||console.log(s.cyan(`\u{1F4C1} Using temp directory: ${o.outputDir}
5
- `))),e.output&&(o.outputDir=e.output),e.repo&&(o.repositories=o.repositories.filter(r=>r.name===e.repo),o.repositories.length===0&&(console.error(s.red(`Repository "${e.repo}" not found in config`)),process.exit(1)));let p=new a(o);if(e.watch)console.log(s.yellow(`\u{1F440} Watch mode enabled. Press Ctrl+C to stop.
6
- `)),await F(p,o);else {let r=await p.generate();if(e.format==="json"||e.static){let i=c.join(o.outputDir,"report.json");await n.mkdir(o.outputDir,{recursive:!0}),await n.writeFile(i,JSON.stringify(r,null,2)),t||console.log(s.gray(` \u2192 ${i}`));}if(e.static&&await N(o,r,t),!t)S(r);else {let i=r.repositories.reduce((l,m)=>l+m.summary.totalPages,0);console.log(`\u2705 Generated: ${i} pages, ${r.repositories.length} repos`);}}}catch(a){console.error(t?`Error: ${a.message}`:s.red("Error:"),a.message),process.exit(1);}});async function N(e,t,a){let{PageMapGenerator:o}=await import('./page-map-generator-HROGGVAQ.js'),{detectEnvironments:p}=await import('./env-detector-BIWJ7OYF.js'),r=e.outputDir;await n.mkdir(r,{recursive:true});let i=e.repositories[0]?.path||process.cwd(),l=await p(i),m=null;if(l.hasRails){let{analyzeRailsApp:f}=await import('./rails-3HNUFTQV.js');m=await f(i);}let y=new o().generatePageMapHtml(t,{envResult:l,railsAnalysis:m,staticMode:true});if(await n.writeFile(c.join(r,"index.html"),y),a||console.log(s.gray(` \u2192 ${c.join(r,"index.html")}`)),m){let{RailsMapGenerator:f}=await import('./rails-map-generator-DF2YAXW4.js'),D=new f().generateFromResult(m);await n.writeFile(c.join(r,"rails-map.html"),D),a||console.log(s.gray(` \u2192 ${c.join(r,"rails-map.html")}`));}let g=["common.css","page-map.css","docs.css","rails-map.css"],w=c.join(r,"assets");await n.mkdir(w,{recursive:true});for(let f of g)try{let b=new URL(`./generators/assets/${f}`,import.meta.url),D=await n.readFile(b,"utf-8");await n.writeFile(c.join(w,f),D);}catch{}a||console.log(s.green(`
7
- \u2705 Static site generated: ${r}`));}d.command("serve").description("Start local documentation server with live reload").option("-c, --config <path>","Path to config file").option("--path <path>","Path to repository to analyze (auto-detect if no config)").option("-o, --output <path>","Output directory (default: .repomap in target path)").option("-p, --port <number>","Server port","3030").option("--temp","Use temporary directory (no files in repository)").option("--no-open","Don't open browser automatically").action(async e=>{console.log(s.blue.bold(`
4
+ `));try{let r=process.cwd(),o=await v(e.config,r);e.temp&&(o.outputDir=x(),t||console.log(s.cyan(`\u{1F4C1} Using temp directory: ${o.outputDir}
5
+ `))),e.output&&(o.outputDir=e.output),e.repo&&(o.repositories=o.repositories.filter(a=>a.name===e.repo),o.repositories.length===0&&(console.error(s.red(`Repository "${e.repo}" not found in config`)),process.exit(1)));let p=new a(o);if(e.watch)console.log(s.yellow(`\u{1F440} Watch mode enabled. Press Ctrl+C to stop.
6
+ `)),await k(p,o);else {let a=await p.generate();if(e.format==="json"||e.static){let i=c.join(o.outputDir,"report.json");await n.mkdir(o.outputDir,{recursive:!0}),await n.writeFile(i,JSON.stringify(a,null,2)),t||console.log(s.gray(` \u2192 ${i}`));}if(e.static&&await F(o,a,t),!t)O(a);else {let i=a.repositories.reduce((l,m)=>l+m.summary.totalPages,0);console.log(`\u2705 Generated: ${i} pages, ${a.repositories.length} repos`);}}}catch(r){console.error(t?`Error: ${r.message}`:s.red("Error:"),r.message),process.exit(1);}});async function F(e,t,r){let{PageMapGenerator:o}=await import('./page-map-generator-BQ3SSOJG.js'),{detectEnvironments:p}=await import('./env-detector-BIWJ7OYF.js'),a=e.outputDir;await n.mkdir(a,{recursive:true});let i=e.repositories[0]?.path||process.cwd(),l=await p(i),m=null;if(l.hasRails){let{analyzeRailsApp:f}=await import('./rails-3HNUFTQV.js');m=await f(i);}let y=new o().generatePageMapHtml(t,{envResult:l,railsAnalysis:m,staticMode:true});if(await n.writeFile(c.join(a,"index.html"),y),r||console.log(s.gray(` \u2192 ${c.join(a,"index.html")}`)),m){let{RailsMapGenerator:f}=await import('./rails-map-generator-RY6KXIBU.js'),D=new f().generateFromResult(m);await n.writeFile(c.join(a,"rails-map.html"),D),r||console.log(s.gray(` \u2192 ${c.join(a,"rails-map.html")}`));}let g=["common.css","page-map.css","docs.css","rails-map.css"],w=c.join(a,"assets");await n.mkdir(w,{recursive:true});for(let f of g)try{let b=new URL(`./generators/assets/${f}`,import.meta.url),D=await n.readFile(b,"utf-8");await n.writeFile(c.join(w,f),D);}catch{}r||console.log(s.green(`
7
+ \u2705 Static site generated: ${a}`));}d.command("serve").description("Start local documentation server with live reload").option("-c, --config <path>","Path to config file").option("--path <path>","Path to repository to analyze (auto-detect if no config)").option("-o, --output <path>","Output directory (default: .repomap in target path)").option("-p, --port <number>","Server port","3030").option("--temp","Use temporary directory (no files in repository)").option("--no-open","Don't open browser automatically").action(async e=>{console.log(s.blue.bold(`
8
8
  \u{1F310} Repomap
9
- `));try{let t=e.path||process.cwd(),a=await $(e.config,t);e.temp&&(a.outputDir=P(),console.log(s.cyan(`\u{1F4C1} Using temp directory: ${a.outputDir}
10
- `)),C(a.outputDir)),e.output&&(a.outputDir=c.resolve(e.output)),await new b(a,parseInt(e.port)).start(!e.open);}catch(t){console.error(s.red("Error:"),t.message),process.exit(1);}});d.command("init").description("Initialize repomap configuration").option("-f, --force","Overwrite existing config").action(async e=>{let t="./repomap.config.ts";try{if(await n.access(t).then(()=>!0).catch(()=>!1)&&!e.force){console.log(s.yellow("Config file already exists. Use --force to overwrite."));return}let o=await x(process.cwd()),p=o?.name||"my-project",r=o?.type||"nextjs",i=o?.settings.pagesDir||"src/pages",l=o?.settings.featuresDir||"src/features",m=o?.settings.componentsDir||"src/components",h=`import type { DocGeneratorConfig } from "repomap";
9
+ `));try{let t=e.path||process.cwd(),r=await v(e.config,t);e.temp&&(r.outputDir=x(),console.log(s.cyan(`\u{1F4C1} Using temp directory: ${r.outputDir}
10
+ `)),N(r.outputDir)),e.output&&(r.outputDir=c.resolve(e.output)),await new b(r,parseInt(e.port)).start(!e.open);}catch(t){console.error(s.red("Error:"),t.message),process.exit(1);}});d.command("init").description("Initialize repomap configuration").option("-f, --force","Overwrite existing config").action(async e=>{let t="./repomap.config.ts";try{if(await n.access(t).then(()=>!0).catch(()=>!1)&&!e.force){console.log(s.yellow("Config file already exists. Use --force to overwrite."));return}let o=await C(process.cwd()),p=o?.name||"my-project",a=o?.type||"nextjs",i=o?.settings.pagesDir||"src/pages",l=o?.settings.featuresDir||"src/features",m=o?.settings.componentsDir||"src/components",h=`import type { DocGeneratorConfig } from "repomap";
11
11
 
12
12
  export const config: DocGeneratorConfig = {
13
13
  outputDir: "./.repomap",
@@ -23,7 +23,7 @@ export const config: DocGeneratorConfig = {
23
23
  description: "Main repository",
24
24
  path: ".",
25
25
  branch: "main",
26
- type: "${r}",
26
+ type: "${a}",
27
27
  analyzers: ["pages", "graphql", "components", "dataflow"],
28
28
  settings: {
29
29
  pagesDir: "${i}",
@@ -54,12 +54,12 @@ export const config: DocGeneratorConfig = {
54
54
 
55
55
  export default config;
56
56
  `;await n.writeFile(t,h,"utf-8"),console.log(s.green(`\u2705 Created ${t}`)),console.log(s.gray(`
57
- Run 'npx repomap serve' to start the documentation server.`));}catch(a){console.error(s.red("Failed to create config:"),a.message);}});d.command("rails").description("Analyze a Rails application and generate interactive map").option("--path <path>","Path to Rails application").option("-o, --output <path>","Output HTML file path").action(async e=>{console.log(s.blue.bold(`
57
+ Run 'npx repomap serve' to start the documentation server.`));}catch(r){console.error(s.red("Failed to create config:"),r.message);}});d.command("rails").description("Analyze a Rails application and generate interactive map").option("--path <path>","Path to Rails application").option("-o, --output <path>","Output HTML file path").action(async e=>{console.log(s.blue.bold(`
58
58
  \u{1F6E4}\uFE0F Repomap Rails
59
- `));try{let t=e.path||process.cwd();try{await n.access(c.join(t,"config","routes.rb"));}catch{console.error(s.red("Not a Rails project (config/routes.rb not found)")),process.exit(1);}let{RailsMapGenerator:a}=await import('./rails-map-generator-DF2YAXW4.js'),o=e.output||c.join(t,"rails-map.html");await new a(t).generate({title:`${c.basename(t)} - Rails Map`,outputPath:o}),console.log(s.green(`\u2705 Rails map generated: ${o}`));let{exec:r}=await import('child_process');r(`open "${o}"`);}catch(t){console.error(s.red("Error:"),t.message),process.exit(1);}});d.command("diff").description("Show documentation changes since last generation").option("-c, --config <path>","Path to config file").action(async e=>{console.log(s.blue.bold(`
59
+ `));try{let t=e.path||process.cwd();try{await n.access(c.join(t,"config","routes.rb"));}catch{console.error(s.red("Not a Rails project (config/routes.rb not found)")),process.exit(1);}let{RailsMapGenerator:r}=await import('./rails-map-generator-RY6KXIBU.js'),o=e.output||c.join(t,"rails-map.html");await new r(t).generate({title:`${c.basename(t)} - Rails Map`,outputPath:o}),console.log(s.green(`\u2705 Rails map generated: ${o}`));let{exec:a}=await import('child_process');a(`open "${o}"`);}catch(t){console.error(s.red("Error:"),t.message),process.exit(1);}});d.command("diff").description("Show documentation changes since last generation").option("-c, --config <path>","Path to config file").action(async e=>{console.log(s.blue.bold(`
60
60
  \u{1F4CA} Documentation Diff
61
- `));try{let t=process.cwd(),a$1=await $(e.config,t),o=c.join(a$1.outputDir,"report.json");if(!await n.access(o).then(()=>!0).catch(()=>!1)){console.log(s.yellow("No previous report found. Run 'generate' first."));return}let r=JSON.parse(await n.readFile(o,"utf-8")),l=await new a(a$1).generate();k(r,l);}catch(t){console.error(s.red("Failed to generate diff:"),t.message);}});async function F(e,t){await e.generate();let a=t.repositories.map(o=>o.path);for(let o of a){let p=n.watch(o,{recursive:true}),r=null;for await(let i of p)i.filename&&(i.filename.endsWith(".ts")||i.filename.endsWith(".tsx"))&&(r&&clearTimeout(r),r=setTimeout(async()=>{console.log(s.yellow(`
62
- \u{1F504} Change detected: ${i.filename}`)),await e.generate();},t.watch.debounce));}}function S(e){console.log(s.green.bold(`
61
+ `));try{let t=process.cwd(),r=await v(e.config,t),o=c.join(r.outputDir,"report.json");if(!await n.access(o).then(()=>!0).catch(()=>!1)){console.log(s.yellow("No previous report found. Run 'generate' first."));return}let a$1=JSON.parse(await n.readFile(o,"utf-8")),l=await new a(r).generate();M(a$1,l);}catch(t){console.error(s.red("Failed to generate diff:"),t.message);}});async function k(e,t){await e.generate();let r=t.repositories.map(o=>o.path);for(let o of r){let p=n.watch(o,{recursive:true}),a=null;for await(let i of p)i.filename&&(i.filename.endsWith(".ts")||i.filename.endsWith(".tsx"))&&(a&&clearTimeout(a),a=setTimeout(async()=>{console.log(s.yellow(`
62
+ \u{1F504} Change detected: ${i.filename}`)),await e.generate();},t.watch.debounce));}}function O(e){console.log(s.green.bold(`
63
63
  \u2705 Complete
64
- `));for(let t of e.repositories)console.log(s.white(` ${t.displayName}`)),console.log(s.gray(` ${t.summary.totalPages} pages \xB7 ${t.summary.totalComponents} components \xB7 ${t.summary.totalGraphQLOperations} GraphQL ops`));console.log();}function k(e,t){console.log(s.cyan(`Changes detected:
65
- `));for(let a of t.repositories){let o=e.repositories.find(l=>l.name===a.name);if(!o){console.log(s.green(` + New repository: ${a.displayName}`));continue}let p=a.summary.totalPages-o.summary.totalPages,r=a.summary.totalComponents-o.summary.totalComponents,i=a.summary.totalGraphQLOperations-o.summary.totalGraphQLOperations;(p!==0||r!==0||i!==0)&&(console.log(s.yellow(` ~ ${a.displayName}:`)),p!==0&&console.log(` Pages: ${p>0?"+":""}${p}`),r!==0&&console.log(` Components: ${r>0?"+":""}${r}`),i!==0&&console.log(` GraphQL Ops: ${i>0?"+":""}${i}`));}}d.parse();
64
+ `));for(let t of e.repositories)console.log(s.white(` ${t.displayName}`)),console.log(s.gray(` ${t.summary.totalPages} pages \xB7 ${t.summary.totalComponents} components \xB7 ${t.summary.totalGraphQLOperations} GraphQL ops`));console.log();}function M(e,t){console.log(s.cyan(`Changes detected:
65
+ `));for(let r of t.repositories){let o=e.repositories.find(l=>l.name===r.name);if(!o){console.log(s.green(` + New repository: ${r.displayName}`));continue}let p=r.summary.totalPages-o.summary.totalPages,a=r.summary.totalComponents-o.summary.totalComponents,i=r.summary.totalGraphQLOperations-o.summary.totalGraphQLOperations;(p!==0||a!==0||i!==0)&&(console.log(s.yellow(` ~ ${r.displayName}:`)),p!==0&&console.log(` Pages: ${p>0?"+":""}${p}`),a!==0&&console.log(` Components: ${a>0?"+":""}${a}`),i!==0&&console.log(` GraphQL Ops: ${i>0?"+":""}${i}`));}}d.parse();
@@ -23,6 +23,20 @@ declare abstract class BaseAnalyzer {
23
23
  * Get setting value with fallback
24
24
  */
25
25
  protected getSetting(key: string, defaultValue?: string): string;
26
+ /**
27
+ * Get list-like setting value (comma/newline separated).
28
+ * Example: "useMyQuery, useMyMutation" -> ["useMyQuery", "useMyMutation"]
29
+ */
30
+ protected getListSetting(key: string, defaultValue?: string[]): string[];
31
+ /**
32
+ * Resolve effective GraphQL hook patterns by combining:
33
+ * - a preset selected by `settings.graphqlHookPreset` (default: "auto")
34
+ * - user-defined patterns from `settings.graphqlHookPatterns`
35
+ *
36
+ * Presets are meant to improve out-of-the-box support for common "production variants"
37
+ * (Relay/urql/custom wrappers) while keeping false positives low.
38
+ */
39
+ protected getGraphQLHookPatterns(): string[];
26
40
  /**
27
41
  * Log analysis progress (silent by default, set REPOMAP_VERBOSE=1 to enable)
28
42
  */
@@ -42,6 +56,8 @@ declare abstract class BaseAnalyzer {
42
56
  */
43
57
  declare class PagesAnalyzer extends BaseAnalyzer {
44
58
  private codegenMap;
59
+ private tsResolver;
60
+ private coverage;
45
61
  constructor(config: RepositoryConfig);
46
62
  getName(): string;
47
63
  analyze(): Promise<Partial<AnalysisResult>>;
@@ -190,6 +206,7 @@ declare class PagesAnalyzer extends BaseAnalyzer {
190
206
  * Uses @swc/core for fast parsing
191
207
  */
192
208
  declare class GraphQLAnalyzer extends BaseAnalyzer {
209
+ private coverage;
193
210
  constructor(config: RepositoryConfig);
194
211
  getName(): string;
195
212
  analyze(): Promise<Partial<AnalysisResult>>;
@@ -279,6 +296,7 @@ declare class GraphQLAnalyzer extends BaseAnalyzer {
279
296
  */
280
297
  declare class DataFlowAnalyzer extends BaseAnalyzer {
281
298
  private componentCache;
299
+ private coverage;
282
300
  constructor(config: RepositoryConfig);
283
301
  getName(): string;
284
302
  analyze(): Promise<Partial<AnalysisResult>>;
@@ -597,6 +597,16 @@ body {
597
597
  font-size: 13px;
598
598
  }
599
599
 
600
+ .detail-badges {
601
+ padding: 8px 12px;
602
+ background: var(--docs-bg3);
603
+ border-radius: 4px;
604
+ display: flex;
605
+ flex-wrap: wrap;
606
+ gap: 6px;
607
+ align-items: center;
608
+ }
609
+
600
610
  .detail-badge {
601
611
  display: inline-block;
602
612
  padding: 4px 10px;
@@ -605,6 +615,10 @@ body {
605
615
  font-weight: 500;
606
616
  margin-right: 6px;
607
617
  }
618
+
619
+ .detail-badges .detail-badge {
620
+ margin-right: 0;
621
+ }
608
622
  .detail-badge.query {
609
623
  background: #dbeafe;
610
624
  color: #1d4ed8;
@@ -630,6 +644,14 @@ body {
630
644
  color: #475569;
631
645
  }
632
646
 
647
+ .detail-badge.confidence {
648
+ cursor: help;
649
+ color: #fff;
650
+ }
651
+ .detail-badge.confidence.likely {
652
+ background: #f59e0b;
653
+ }
654
+
633
655
  /* Regenerate Button */
634
656
  .regenerate-btn {
635
657
  background: var(--accent);
@@ -475,6 +475,15 @@ header h1 {
475
475
  }
476
476
 
477
477
  /* Model Card */
478
+ .model-card-grid {
479
+ display: grid;
480
+ gap: 12px;
481
+ }
482
+
483
+ .model-card-grid .model-card {
484
+ margin-bottom: 0;
485
+ }
486
+
478
487
  .model-card {
479
488
  background: var(--bg-secondary);
480
489
  border: 1px solid var(--border-color);
@@ -522,6 +531,10 @@ header h1 {
522
531
  justify-content: space-between;
523
532
  }
524
533
 
534
+ .controller-card:not(.expanded) .controller-header {
535
+ border-bottom: none;
536
+ }
537
+
525
538
  .controller-header:hover {
526
539
  background: var(--bg-tertiary);
527
540
  }
@@ -1 +1 @@
1
- export{b as MarkdownGenerator,a as MermaidGenerator}from'../chunk-2XZSFAJF.js';export{a as PageMapGenerator}from'../chunk-WZAAA7DS.js';
1
+ export{b as MarkdownGenerator,a as MermaidGenerator}from'../chunk-QBSB6BIU.js';export{a as PageMapGenerator}from'../chunk-ATRSGO6O.js';
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { DocGeneratorConfig, DocumentationReport } from './types.js';
2
- export { APICall, APIConnection, APIEndpoint, AnalysisConfig, AnalysisResult, AnalyzerType, AssociationInfo, AttributeInfo, AuthRequirement, ComponentInfo, CrossRepoAnalysis, CrossRepoLink, DataFetchingInfo, DataFlow, DataFlowNode, DiagramConfig, DiagramType, GraphQLField, GraphQLOperation, ImportInfo, 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-CJ2T0cGS.js';
2
+ export { APICall, APIConnection, APIEndpoint, AnalysisConfig, AnalysisResult, AnalyzerType, AssociationInfo, AttributeInfo, AuthRequirement, ComponentInfo, CoverageMetrics, CrossRepoAnalysis, CrossRepoLink, DataFetchingInfo, DataFlow, DataFlowNode, DiagramConfig, DiagramType, GraphQLField, GraphQLOperation, ImportInfo, 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-DIUsRpvv.js';
4
4
  export { MarkdownGenerator, MermaidGenerator, PageMapGenerator, PageMapOptions } from './generators/index.js';
5
5
  export { DocServer } 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-6AZNHUOB.js';import'./chunk-NQMJ3QRX.js';import'./chunk-VV3A3UE3.js';export{a as BaseAnalyzer,A as DataFlowAnalyzer,z as GraphQLAnalyzer,y as PagesAnalyzer}from'./chunk-QDVE7MT3.js';export{b as MarkdownGenerator,a as MermaidGenerator}from'./chunk-2XZSFAJF.js';export{a as PageMapGenerator}from'./chunk-WZAAA7DS.js';import'./chunk-H7VVRHQZ.js';
1
+ import'./chunk-6F4PWJZI.js';export{a as DocGeneratorEngine,b as DocServer}from'./chunk-7BQRBJUG.js';import'./chunk-LHP2OKKA.js';import'./chunk-VV3A3UE3.js';export{a as BaseAnalyzer,B as DataFlowAnalyzer,A as GraphQLAnalyzer,z as PagesAnalyzer}from'./chunk-YO6EB4OI.js';export{b as MarkdownGenerator,a as MermaidGenerator}from'./chunk-QBSB6BIU.js';export{a as PageMapGenerator}from'./chunk-ATRSGO6O.js';import'./chunk-H7VVRHQZ.js';
@@ -0,0 +1 @@
1
+ export{a as PageMapGenerator}from'./chunk-ATRSGO6O.js';
@@ -0,0 +1 @@
1
+ export{a as RailsMapGenerator}from'./chunk-LHP2OKKA.js';import'./chunk-H7VVRHQZ.js';
@@ -1 +1 @@
1
- export{b as DocServer}from'../chunk-6AZNHUOB.js';import'../chunk-NQMJ3QRX.js';import'../chunk-VV3A3UE3.js';import'../chunk-QDVE7MT3.js';import'../chunk-2XZSFAJF.js';import'../chunk-WZAAA7DS.js';import'../chunk-H7VVRHQZ.js';
1
+ export{b as DocServer}from'../chunk-7BQRBJUG.js';import'../chunk-LHP2OKKA.js';import'../chunk-VV3A3UE3.js';import'../chunk-YO6EB4OI.js';import'../chunk-QBSB6BIU.js';import'../chunk-ATRSGO6O.js';import'../chunk-H7VVRHQZ.js';
package/dist/types.d.ts CHANGED
@@ -57,6 +57,8 @@ interface AnalysisResult {
57
57
  timestamp: string;
58
58
  version: string;
59
59
  commitHash: string;
60
+ /** Coverage / observability metrics to prevent silent omissions */
61
+ coverage?: CoverageMetrics;
60
62
  pages: PageInfo[];
61
63
  graphqlOperations: GraphQLOperation[];
62
64
  apiCalls: APICall[];
@@ -66,6 +68,20 @@ interface AnalysisResult {
66
68
  models: ModelInfo[];
67
69
  crossRepoLinks: CrossRepoLink[];
68
70
  }
71
+ interface CoverageMetrics {
72
+ /** Number of TS/TSX/JS/JSX files scanned by analyzers (best-effort) */
73
+ tsFilesScanned: number;
74
+ /** Number of source files that failed to parse (SWC/TS parser failures) */
75
+ tsParseFailures: number;
76
+ /** Number of GraphQL parse failures (graphql parse errors) */
77
+ graphqlParseFailures: number;
78
+ /** Number of codegen files detected (best-effort) */
79
+ codegenFilesDetected: number;
80
+ /** Number of codegen files successfully parsed by AST */
81
+ codegenFilesParsed: number;
82
+ /** Number of Document exports extracted from codegen outputs */
83
+ codegenExportsFound: number;
84
+ }
69
85
  /**
70
86
  * Frontend API call information
71
87
  */
@@ -131,6 +147,23 @@ interface DataFetchingInfo {
131
147
  operationName: string;
132
148
  variables?: string[];
133
149
  source?: string;
150
+ /**
151
+ * Confidence for the mapping between page <-> hook <-> operation.
152
+ * - 'certain': direct/close evidence
153
+ * - 'likely': reachable but indirect evidence
154
+ * - 'unknown': reachable via widely-shared/common modules (UI may display this as "Common" or omit it)
155
+ */
156
+ confidence?: 'certain' | 'likely' | 'unknown';
157
+ /**
158
+ * Evidence for why this operation is linked.
159
+ * This is primarily for debugging missing/incorrect links.
160
+ */
161
+ evidence?: Array<{
162
+ kind: 'import-edge' | 'operation-reference';
163
+ file: string;
164
+ line?: number;
165
+ detail?: string;
166
+ }>;
134
167
  }
135
168
  interface NavigationInfo {
136
169
  visible: boolean;
@@ -303,4 +336,4 @@ interface NavigationFlow {
303
336
  trigger: string;
304
337
  }
305
338
 
306
- export type { APICall, APIConnection, APIEndpoint, AnalysisConfig, AnalysisResult, AnalyzerType, AssociationInfo, AttributeInfo, AuthRequirement, ComponentInfo, CrossRepoAnalysis, CrossRepoLink, DataFetchingInfo, DataFlow, DataFlowNode, DiagramConfig, DiagramType, DocGeneratorConfig, DocumentationReport, GraphQLField, GraphQLOperation, ImportInfo, IntegrationsConfig, MermaidDiagram, ModelInfo, NavigationFlow, NavigationInfo, PageInfo, ParameterInfo, PropInfo, RepositoryConfig, RepositoryReport, RepositorySummary, ResponseInfo, SiteConfig, StepInfo, VariableInfo, WatchConfig };
339
+ export type { APICall, APIConnection, APIEndpoint, AnalysisConfig, AnalysisResult, AnalyzerType, AssociationInfo, AttributeInfo, AuthRequirement, ComponentInfo, CoverageMetrics, CrossRepoAnalysis, CrossRepoLink, DataFetchingInfo, DataFlow, DataFlowNode, DiagramConfig, DiagramType, DocGeneratorConfig, DocumentationReport, GraphQLField, GraphQLOperation, ImportInfo, IntegrationsConfig, MermaidDiagram, ModelInfo, NavigationFlow, NavigationInfo, PageInfo, ParameterInfo, PropInfo, RepositoryConfig, RepositoryReport, RepositorySummary, ResponseInfo, SiteConfig, StepInfo, VariableInfo, WatchConfig };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wtdlee/repomap",
3
- "version": "0.9.1",
3
+ "version": "0.10.1",
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",
@@ -86,6 +86,7 @@
86
86
  "open": "^11.0.0",
87
87
  "simple-git": "^3.21.0",
88
88
  "socket.io": "^4.7.2",
89
+ "typescript": "^5.3.2",
89
90
  "tree-sitter-wasms": "^0.1.13",
90
91
  "web-tree-sitter": "^0.25.10",
91
92
  "yaml": "^2.3.4"
@@ -104,7 +105,6 @@
104
105
  "prettier": "^3.7.4",
105
106
  "tsup": "^8.5.1",
106
107
  "tsx": "^4.6.2",
107
- "typescript": "^5.3.2",
108
108
  "typescript-eslint": "^8.49.0",
109
109
  "vitest": "^4.0.15"
110
110
  },
@@ -116,7 +116,7 @@
116
116
  "dev:serve": "tsx watch --clear-screen=false src/cli.ts serve --no-cache",
117
117
  "generate": "tsx src/cli.ts generate",
118
118
  "serve": "tsx src/cli.ts serve",
119
- "test": "vitest",
119
+ "test": "vitest --pool=threads",
120
120
  "lint": "eslint src",
121
121
  "lint:fix": "eslint src --fix",
122
122
  "format": "prettier --write \"src/**/*.ts\"",