@wtdlee/repomap 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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,getLocation}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"],ve=["useSubscription","useFragment","useApolloClient"],z=[...X,...ee,...ve],Y={useQuery:"useQuery",useSuspenseQuery:"useQuery",useBackgroundQuery:"useQuery",useReadQuery:"useQuery",useLazyQuery:"useLazyQuery",useMutation:"useMutation",useSubscription:"useSubscription"},be=["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 Ce(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(Ce(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 be.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 Ae(p){try{return parseSync(p,{syntax:"typescript",tsx:!0,comments:!1})}catch{return null}}function v(p){return p?p.type==="Identifier"?p.value:p.type==="MemberExpression"&&p.property?.type==="Identifier"?p.property.value:null:null}function M(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)M(s,e);else r&&typeof r=="object"&&M(r,e);}}}function H(p,e,t){let r={documentImports:new Map,variableOperations:new Map,staticPropertyOperations:new Map,codegenMap:t||new Map};return M(p,s=>{s.type==="ImportDeclaration"&&we(s,r.documentImports),s.type==="VariableDeclarator"&&Fe(s,e,r.variableOperations),s.type==="AssignmentExpression"&&Ne(s,e,r.staticPropertyOperations);}),r}function we(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 Fe(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=v(s.callee);(n==="gql"||n==="graphql")&&(i=V(s,e));}if(s.type==="TaggedTemplateExpression"){let n=v(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 Ne(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=v(n.callee);(o==="gql"||o==="graphql")&&(a=V(n,e));}if(n.type==="TaggedTemplateExpression"){let o=v(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=v(s.tag);if(n==="gql"||n==="graphql")return true}if(s.type==="CallExpression"){let n=v(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=Me(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 Me(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=v(p.tag);if(r==="gql"||r==="graphql")return P(p.template)}if(p.type==="TemplateLiteral")return P(p);if(p.type==="CallExpression"){let r=v(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 je(p,e){let t=[],r=new Set;if(!W(p))return t;let s=Ae(p);if(!s)return t;let i=H(s,p,e);return M(s,n=>{if(n.type!=="CallExpression")return;let a=v(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 Ge(p){return `${{useQuery:"Query",useLazyQuery:"Query",useMutation:"Mutation",useSubscription:"Subscription"}[p.type]||"Query"}: ${p.operationName}`}async function S(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)&&Ie(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=Pe(n.initializer),l=Ee(o);if(!l)continue;let u=Re(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 Ie(p){return p?p.some(e=>e.kind===h.SyntaxKind.ExportKeyword):false}function Pe(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 Ee(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 Re(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=Qe(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 Qe(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:m=>F.existsSync(m),readFile:m=>{try{return F.readFileSync(m,"utf8")}catch{return}},directoryExists:m=>{try{return F.existsSync(m)&&F.statSync(m).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),g=c&&this.toRepoRelative(c)||void 0;return {file:f,evidence:{fromFile:this.normalizeRel(e),specifier:t,resolvedFile:f,configFile:g}}}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 S(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),g=this.extractPermissions(t),m=this.extractDataFetching(i,t,u),x=this.extractLinkedPages(i,t),C=this.extractNavigation(t),I=this.extractSteps(t);return {path:a,filePath:n,component:o,params:l,layout:f,authentication:c,permissions:g,dataFetching:m,navigation:C,linkedPages:x,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,g=c?a.get(c):void 0;if(g){let m=this.resolveImportPath(s,g);m&&F.existsSync(m)&&e.push(m);}}}}),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(M(e,l=>{if(l.type==="CallExpression"){let u=l,f=v(u.callee);if(!f)return;if($(f,o)&&ne(u,t,a)){let c=U(u,t,a),m={type:D(f,o),operationName:c||"unknown"},x=this.extractVariablesFromCall(u);Object.keys(x).length>0&&(m.variables=x);let C=`${m.type}:${m.operationName}`;i.has(C)||(i.add(C),s.push(m));}if(f==="query"||f==="mutate"){let c=this.analyzeClientDirectCall(u,t,a);if(c){let g=`${c.type}:${c.operationName}`;i.has(g)||(i.add(g),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:v(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 m=e.arguments[0],x=m?.expression||m,C=this.extractOperationFromArgument(x,r,s);C&&(f=C);}let g=this.extractVariablesFromCall(e);return {type:u,operationName:f,variables:g}}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){M(e,a=>{if(a.type!=="CallExpression")return;let o=v(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 le=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 S(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 S(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 g of c)g.variableNames=g.variableNames||[],g.variableNames.push(a),g.variableNames.push(`${g.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),g=this.extractOperationsFromDocument(c,r);if(a)for(let m of g)m.variableNames=m.variableNames||[],m.variableNames.push(a),m.variableNames.push(`${m.name}Document`);s.push(...g);}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),o=e.loc?getLocation(e.loc.source,e.loc.start):null;return {name:r,type:s,filePath:t,line:o?.line,column:o?.column,usedIn:[],variables:i,returnType:this.inferReturnType(e),fragments:n,fields:a}}if(e.kind==="FragmentDefinition"){let r=e.loc?getLocation(e.loc.source,e.loc.start):null;return {name:e.name.value,type:"fragment",filePath:t,line:r?.line,column:r?.column,usedIn:[],variables:[],returnType:e.typeCondition.name.value,fragments:this.extractFragmentReferences(e),fields:this.extractFields(e)}}return 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 g of c.variableNames)n.set(g,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 g of c.variableNames)o.add(g);let l=null,u=Array.from(o);if(u.length>0&&u.length<2e3){let c=u.sort((g,m)=>m.length-g.length).map(g=>g.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"));l=new RegExp(`\\b(${c.join("|")})\\b`,"g");}let f=50;for(let c=0;c<r.length;c+=f){let g=r.slice(c,c+f);await Promise.all(g.map(async m=>{try{let x=await T.readFile(m,"utf-8"),C=y.relative(this.basePath,m);if(!W(x))return;if(l){let I=new Set,J;for(;(J=l.exec(x))!==null;)I.add(J[1]);l.lastIndex=0;for(let ye of I){let q=i.get(ye);q&&C!==q.filePath&&(q.usedIn.includes(C)||q.usedIn.push(C));}}await this.findUsageWithAST(x,m,C,s,a,n,t);}catch{}}));}}async findUsageWithAST(e,t,r,s,i,n,a){try{let o=t.endsWith(".tsx")||t.endsWith(".jsx"),l=parseSync(e,{syntax:t.endsWith(".ts")||t.endsWith(".tsx")?"typescript":"ecmascript",tsx:o,jsx:o,comments:!1});this.traverseNodeForUsage(l,e,u=>{if(u.type==="CallExpression"){let f=this.getCalleeNameForUsage(u.callee);if(f&&$(f,a)){let c=this.extractTypeGenericFromCall(u,e);if(c){let m=i.get(c)||s.get(c.replace(/Query$|Mutation$|Variables$/,""));m&&r!==m.filePath&&(m.usedIn.includes(r)||m.usedIn.push(r));}let g=this.extractFirstArgName(u);if(g){let m=g.replace(/Document$/,""),x=n.get(g)||n.get(m)||s.get(m)||i.get(g);x&&r!==x.filePath&&(x.usedIn.includes(r)||x.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 ce=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}),g=y.relative(this.basePath,f.filePath),m=this.analyzeComponentFile(c,g,f.content);e.push(...m);}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),g=l?"Mutation":u?"Subscription":"Query",m=c?`${g}: ${c}`:`${g}: unknown`;n.has(m)||(n.add(m),i.push(m));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 ge=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 S(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{le as A,ce as B,ge as C,A as a,O as b,X as c,ee as d,ve as e,z as f,Y as g,be as h,R as i,Q as j,te as k,$ as l,D as m,W as n,d as o,Ae as p,v as q,M as r,H as s,V as t,P as u,ne as v,U as w,je as x,Ge 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-YKPXOHWZ.js';import'./chunk-LHP2OKKA.js';import'./chunk-VV3A3UE3.js';import'./chunk-IGRCLYVZ.js';import'./chunk-QBSB6BIU.js';import'./chunk-ATRSGO6O.js';import'./chunk-H7VVRHQZ.js';import'./chunk-ZWRDP37E.js';import {Command}from'commander';import s from'chalk';import*as c from'path';import*as $ from'fs';import*as n from'fs/promises';import*as P from'os';function x(){let e=P.tmpdir();return c.join(e,`repomap-${Date.now()}`)}function N(e){let t=async()=>{try{await n.rm(e,{recursive:!0,force:!0});}catch{}process.exit(0);};process.on("SIGINT",t),process.on("SIGTERM",t);}function S(){try{let e=new URL("../package.json",import.meta.url),t=$.readFileSync(e,"utf-8");return JSON.parse(t).version||"0.0.0"}catch{return "0.0.0"}}var d=new Command;d.name("repomap").description("Interactive documentation generator for code repositories").version(S());async function C(e){let t=c.basename(e),r=false,o=c.join(e,"Gemfile"),p=c.join(e,"config","routes.rb");try{await n.access(o),await n.access(p);let g=await n.readFile(o,"utf-8");r=g.includes("gem 'rails'")||g.includes('gem "rails"');}catch{}let a=c.join(e,"package.json"),i=false,l=false,m={};try{let g=JSON.parse(await n.readFile(a,"utf-8")),w={...g.dependencies,...g.devDependencies};i=!!w.react,l=!!w.next;let f=["src/pages","pages","app","src/app","frontend/src"];for(let u of f)try{await n.access(c.join(e,u)),m.pagesDir=u;break}catch{}let b=["src/features","features","src/modules","modules","frontend/src"];for(let u of b)try{await n.access(c.join(e,u)),m.featuresDir=u;break}catch{}let D=["src/components","components","src/common/components","frontend/src"];for(let u of D)try{await n.access(c.join(e,u)),m.componentsDir=u;break}catch{}}catch{}let h=[];(i||l)&&h.push("pages","graphql","dataflow","rest-api");let y="generic";return l?y="nextjs":r&&(y="rails"),!r&&!i&&!l?null:{name:t,displayName:t,description:r&&i?"Rails + React application":r?"Rails application":"",path:e,branch:"main",type:y,analyzers:h,settings:m}}async function E(e){let t=await C(e);if(!t)throw new Error("Could not detect project. Please create a repomap.config.ts file or run 'repomap init'.");return {outputDir:"./.repomap",site:{title:`${t.displayName} Documentation`,description:"Auto-generated documentation",baseUrl:"/docs"},repositories:[t],analysis:{include:["**/*.tsx","**/*.ts"],exclude:["**/node_modules/**","**/__tests__/**","**/*.test.*","**/*.spec.*","**/dist/**","**/.next/**"],maxDepth:5},diagrams:{enabled:true,types:["flowchart","sequence"],theme:"default"},watch:{enabled:false,debounce:1e3},integrations:{github:{enabled:false,organization:""},slack:{enabled:false}}}}async function v(e,t){let r=e?[e]:["repomap.config.ts","repomap.config.js","repomap.config.mjs"];for(let o of r){let p=c.resolve(t,o);try{await n.access(p);let a=await import(p);return a.config||a.default}catch{}}return E(t)}d.command("generate").description("Generate documentation from source code").option("-c, --config <path>","Path to config file").option("-o, --output <path>","Output directory").option("--temp","Use temporary directory (no files in repository)").option("--repo <name>","Analyze specific repository only").option("--watch","Watch for changes and regenerate").option("--format <type>","Output format: json, html, markdown (default: all)","all").option("--ci","CI mode: minimal output, exit codes for errors").option("--static","Generate standalone HTML files (for GitHub Pages)").action(async e=>{let t=e.ci||process.env.CI==="true";t||console.log(s.blue.bold(`
2
+ import {a,b}from'./chunk-54DEMJO2.js';import'./chunk-DSYVU23K.js';import'./chunk-VV3A3UE3.js';import'./chunk-O2SKKQVN.js';import'./chunk-QBSB6BIU.js';import'./chunk-JBPSEUZS.js';import'./chunk-H7VVRHQZ.js';import {Command}from'commander';import s from'chalk';import*as c from'path';import*as v 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 S(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 E(){try{let e=new URL("../package.json",import.meta.url),t=v.readFileSync(e,"utf-8");return JSON.parse(t).version||"0.0.0"}catch{return "0.0.0"}}var h=new Command;h.name("repomap").description("Interactive documentation generator for code repositories").version(E());async function C(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 d=await n.readFile(o,"utf-8");a=d.includes("gem 'rails'")||d.includes('gem "rails"');}catch{}let r=c.join(e,"package.json"),i=false,l=false,f={};try{let d=JSON.parse(await n.readFile(r,"utf-8")),w={...d.dependencies,...d.devDependencies};i=!!w.react,l=!!w.next;let m=["src/pages","pages","app","src/app","frontend/src"];for(let u of m)try{await n.access(c.join(e,u)),f.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)),f.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)),f.componentsDir=u;break}catch{}}catch{}let g=[];(i||l)&&g.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:g,settings:f}}async function N(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 $(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 N(t)}h.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 r=process.cwd(),o=await v(e.config,r);e.temp&&(o.outputDir=x(),t||console.log(s.cyan(`\u{1F4C1} Using temp directory: ${o.outputDir}
5
- `))),e.output&&(o.outputDir=e.output),e.repo&&(o.repositories=o.repositories.filter(a=>a.name===e.repo),o.repositories.length===0&&(console.error(s.red(`Repository "${e.repo}" not found in config`)),process.exit(1)));let p=new a(o);if(e.watch)console.log(s.yellow(`\u{1F440} Watch mode enabled. Press Ctrl+C to stop.
6
- `)),await k(p,o);else {let a=await p.generate();if(e.format==="json"||e.static){let i=c.join(o.outputDir,"report.json");await n.mkdir(o.outputDir,{recursive:!0}),await n.writeFile(i,JSON.stringify(a,null,2)),t||console.log(s.gray(` \u2192 ${i}`));}if(e.static&&await F(o,a,t),!t)O(a);else {let i=a.repositories.reduce((l,m)=>l+m.summary.totalPages,0);console.log(`\u2705 Generated: ${i} pages, ${a.repositories.length} repos`);}}}catch(r){console.error(t?`Error: ${r.message}`:s.red("Error:"),r.message),process.exit(1);}});async function F(e,t,r){let{PageMapGenerator:o}=await import('./page-map-generator-LTVRHSDC.js'),{detectEnvironments:p}=await import('./env-detector-RVGPBVNJ.js'),a=e.outputDir;await n.mkdir(a,{recursive:true});let i=e.repositories[0]?.path||process.cwd(),l=await p(i),m=null;if(l.hasRails){let{analyzeRailsApp:f}=await import('./rails-57MNOGHR.js');m=await f(i);}let y=new o().generatePageMapHtml(t,{envResult:l,railsAnalysis:m,staticMode:true});if(await n.writeFile(c.join(a,"index.html"),y),r||console.log(s.gray(` \u2192 ${c.join(a,"index.html")}`)),m){let{RailsMapGenerator:f}=await import('./rails-map-generator-JNU5QHX4.js'),D=new f().generateFromResult(m);await n.writeFile(c.join(a,"rails-map.html"),D),r||console.log(s.gray(` \u2192 ${c.join(a,"rails-map.html")}`));}let g=["common.css","page-map.css","docs.css","rails-map.css"],w=c.join(a,"assets");await n.mkdir(w,{recursive:true});for(let f of g)try{let b=new URL(`./generators/assets/${f}`,import.meta.url),D=await n.readFile(b,"utf-8");await n.writeFile(c.join(w,f),D);}catch{}r||console.log(s.green(`
7
- \u2705 Static site generated: ${a}`));}d.command("serve").description("Start local documentation server with live reload").option("-c, --config <path>","Path to config file").option("--path <path>","Path to repository to analyze (auto-detect if no config)").option("-o, --output <path>","Output directory (default: .repomap in target path)").option("-p, --port <number>","Server port","3030").option("--temp","Use temporary directory (no files in repository)").option("--no-open","Don't open browser automatically").action(async e=>{console.log(s.blue.bold(`
4
+ `));try{let a$1=process.cwd(),o=await $(e.config,a$1);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(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 k(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 F(o,r,t),!t)O(r);else {let i=r.repositories.reduce((l,f)=>l+f.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 F(e,t,a){let{PageMapGenerator:o}=await import('./page-map-generator-SL3H6CKF.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),f=null;if(l.hasRails){let{analyzeRailsApp:m}=await import('./rails-3HNUFTQV.js');f=await m(i);}let y=new o().generatePageMapHtml(t,{envResult:l,railsAnalysis:f,staticMode:true});if(await n.writeFile(c.join(r,"index.html"),y),a||console.log(s.gray(` \u2192 ${c.join(r,"index.html")}`)),f){let{RailsMapGenerator:m}=await import('./rails-map-generator-GV4ZIVJJ.js'),D=new m().generateFromResult(f);await n.writeFile(c.join(r,"rails-map.html"),D),a||console.log(s.gray(` \u2192 ${c.join(r,"rails-map.html")}`));}let d=["common.css","page-map.css","docs.css","rails-map.css"],w=c.join(r,"assets");await n.mkdir(w,{recursive:true});for(let m of d)try{let b=new URL(`./generators/assets/${m}`,import.meta.url),D=await n.readFile(b,"utf-8");await n.writeFile(c.join(w,m),D);}catch{}a||console.log(s.green(`
7
+ \u2705 Static site generated: ${r}`));}h.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(),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";
9
+ `));try{let t=e.path||process.cwd(),a=await $(e.config,t);e.temp&&(a.outputDir=x(),console.log(s.cyan(`\u{1F4C1} Using temp directory: ${a.outputDir}
10
+ `)),S(a.outputDir)),e.output&&(a.outputDir=c.resolve(e.output));let o=parseInt(e.port);if(e.open){let r=`http://localhost:${o}`;try{let i=new AbortController,l=setTimeout(()=>i.abort(),650),f=await fetch(`${r}/api/regenerate`,{method:"POST",signal:i.signal});if(clearTimeout(l),f.ok){console.log(s.cyan(`\u21BB Existing Repomap server detected. Regenerated and reloaded: ${r}`));let g=(await import('open')).default;await g(r,{wait:!1,newInstance:!1});return}}catch{}}await new b(a,o).start(e.open);}catch(t){console.error(s.red("Error:"),t.message),process.exit(1);}});h.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",r=o?.type||"nextjs",i=o?.settings.pagesDir||"src/pages",l=o?.settings.featuresDir||"src/features",f=o?.settings.componentsDir||"src/components",g=`import type { DocGeneratorConfig } from "repomap";
11
11
 
12
12
  export const config: DocGeneratorConfig = {
13
13
  outputDir: "./.repomap",
@@ -23,12 +23,12 @@ export const config: DocGeneratorConfig = {
23
23
  description: "Main repository",
24
24
  path: ".",
25
25
  branch: "main",
26
- type: "${a}",
26
+ type: "${r}",
27
27
  analyzers: ["pages", "graphql", "components", "dataflow"],
28
28
  settings: {
29
29
  pagesDir: "${i}",
30
30
  featuresDir: "${l}",
31
- componentsDir: "${m}",
31
+ componentsDir: "${f}",
32
32
  },
33
33
  },
34
34
  ],
@@ -53,13 +53,13 @@ export const config: DocGeneratorConfig = {
53
53
  };
54
54
 
55
55
  export default config;
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(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(`
56
+ `;await n.writeFile(t,g,"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);}});h.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:r}=await import('./rails-map-generator-JNU5QHX4.js'),o=e.output||c.join(t,"rails-map.html");await new r(t).generate({title:`${c.basename(t)} - Rails Map`,outputPath:o}),console.log(s.green(`\u2705 Rails map generated: ${o}`));let{exec:a}=await import('child_process');a(`open "${o}"`);}catch(t){console.error(s.red("Error:"),t.message),process.exit(1);}});d.command("diff").description("Show documentation changes since last generation").option("-c, --config <path>","Path to config file").action(async e=>{console.log(s.blue.bold(`
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-GV4ZIVJJ.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);}});h.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(),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(`
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();T(r,l);}catch(t){console.error(s.red("Failed to generate diff:"),t.message);}});async function k(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
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 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();
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 T(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}`));}}h.parse();
@@ -1 +1 @@
1
- export{a as detectEnvironments,b as getAnalyzersForEnvironments}from'./chunk-VV3A3UE3.js';import'./chunk-ZWRDP37E.js';
1
+ export{a as detectEnvironments,b as getAnalyzersForEnvironments}from'./chunk-VV3A3UE3.js';
@@ -483,7 +483,44 @@ body {
483
483
  z-index: 10;
484
484
  }
485
485
 
486
- .mermaid-controls button {
486
+ .mermaid-controls-spacer {
487
+ flex: 1;
488
+ }
489
+
490
+ .mermaid-iconbtn {
491
+ width: 34px;
492
+ height: 32px;
493
+ display: inline-flex;
494
+ align-items: center;
495
+ justify-content: center;
496
+ background: #ffffff;
497
+ border: 1px solid var(--docs-border);
498
+ border-radius: 6px;
499
+ cursor: pointer;
500
+ transition: all 0.15s;
501
+ color: #1a1a1a;
502
+ }
503
+ .mermaid-iconbtn:hover {
504
+ background: var(--accent);
505
+ border-color: var(--accent);
506
+ color: white;
507
+ }
508
+ .mermaid-iconbtn.is-ok {
509
+ background: #22c55e;
510
+ border-color: #22c55e;
511
+ color: white;
512
+ }
513
+ .mermaid-iconbtn.is-fail {
514
+ background: #ef4444;
515
+ border-color: #ef4444;
516
+ color: white;
517
+ }
518
+ .mermaid-iconbtn svg {
519
+ display: block;
520
+ }
521
+
522
+ /* Legacy button styles (kept for any non-icon controls) */
523
+ .mermaid-controls button:not(.mermaid-iconbtn) {
487
524
  background: #ffffff;
488
525
  border: 1px solid var(--docs-border);
489
526
  border-radius: 4px;
@@ -493,7 +530,7 @@ body {
493
530
  transition: all 0.2s;
494
531
  color: #1a1a1a;
495
532
  }
496
- .mermaid-controls button:hover {
533
+ .mermaid-controls button:not(.mermaid-iconbtn):hover {
497
534
  background: var(--accent);
498
535
  color: white;
499
536
  }
@@ -501,7 +538,7 @@ body {
501
538
  .mermaid-wrapper {
502
539
  overflow: hidden;
503
540
  padding: 24px;
504
- min-height: 200px;
541
+ min-height: 360px;
505
542
  cursor: grab;
506
543
  position: relative;
507
544
  }
@@ -281,6 +281,30 @@ body {
281
281
  top: 0;
282
282
  gap: 4px;
283
283
  }
284
+ .detail-actions {
285
+ display: flex;
286
+ align-items: center;
287
+ gap: 8px;
288
+ }
289
+ .detail-export {
290
+ background: var(--accent);
291
+ border: 1px solid var(--accent);
292
+ color: white;
293
+ font-size: 11px;
294
+ padding: 6px 10px;
295
+ border-radius: 8px;
296
+ cursor: pointer;
297
+ font-weight: 600;
298
+ line-height: 1;
299
+ }
300
+ .detail-export:hover {
301
+ filter: brightness(1.05);
302
+ }
303
+ .detail-export:disabled {
304
+ opacity: 0.5;
305
+ cursor: default;
306
+ filter: none;
307
+ }
284
308
  .detail-title {
285
309
  font-family: monospace;
286
310
  font-size: 13px;
@@ -257,6 +257,55 @@ header h1 {
257
257
  font-weight: 600;
258
258
  }
259
259
 
260
+ .diagram-action-btn {
261
+ padding: 6px 10px;
262
+ border: 1px solid var(--border);
263
+ border-radius: 6px;
264
+ background: var(--bg-secondary);
265
+ color: var(--text-primary);
266
+ cursor: pointer;
267
+ font-size: 12px;
268
+ line-height: 1;
269
+ }
270
+ .diagram-action-btn:hover {
271
+ background: var(--bg-tertiary);
272
+ }
273
+
274
+ .diagram-action-btn.icon {
275
+ width: 34px;
276
+ height: 32px;
277
+ padding: 0;
278
+ display: inline-flex;
279
+ align-items: center;
280
+ justify-content: center;
281
+ }
282
+ .diagram-action-btn.icon.subtle {
283
+ background: #666;
284
+ border-color: #666;
285
+ color: #fff;
286
+ }
287
+ .diagram-action-btn.icon.subtle:hover {
288
+ filter: brightness(1.05);
289
+ }
290
+ .diagram-action-btn.icon.primary {
291
+ background: #3b82f6;
292
+ border-color: #3b82f6;
293
+ color: #fff;
294
+ }
295
+ .diagram-action-btn.icon.primary:hover {
296
+ filter: brightness(1.05);
297
+ }
298
+ .diagram-action-btn.is-ok {
299
+ background: #22c55e;
300
+ border-color: #22c55e;
301
+ color: white;
302
+ }
303
+ .diagram-action-btn.is-fail {
304
+ background: #ef4444;
305
+ border-color: #ef4444;
306
+ color: white;
307
+ }
308
+
260
309
  /* View Toggle */
261
310
  .view-toggle {
262
311
  display: flex;
@@ -1 +1 @@
1
- export{b as MarkdownGenerator,a as MermaidGenerator}from'../chunk-QBSB6BIU.js';export{a as PageMapGenerator}from'../chunk-ATRSGO6O.js';import'../chunk-ZWRDP37E.js';
1
+ export{b as MarkdownGenerator,a as MermaidGenerator}from'../chunk-QBSB6BIU.js';export{a as PageMapGenerator}from'../chunk-JBPSEUZS.js';
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import'./chunk-6F4PWJZI.js';export{a as DocGeneratorEngine,b as DocServer}from'./chunk-YKPXOHWZ.js';import'./chunk-LHP2OKKA.js';import'./chunk-VV3A3UE3.js';export{a as BaseAnalyzer,B as DataFlowAnalyzer,A as GraphQLAnalyzer,z as PagesAnalyzer}from'./chunk-IGRCLYVZ.js';export{b as MarkdownGenerator,a as MermaidGenerator}from'./chunk-QBSB6BIU.js';export{a as PageMapGenerator}from'./chunk-ATRSGO6O.js';import'./chunk-H7VVRHQZ.js';import'./chunk-ZWRDP37E.js';
1
+ import'./chunk-6F4PWJZI.js';export{a as DocGeneratorEngine,b as DocServer}from'./chunk-54DEMJO2.js';import'./chunk-DSYVU23K.js';import'./chunk-VV3A3UE3.js';export{a as BaseAnalyzer,B as DataFlowAnalyzer,A as GraphQLAnalyzer,z as PagesAnalyzer}from'./chunk-O2SKKQVN.js';export{b as MarkdownGenerator,a as MermaidGenerator}from'./chunk-QBSB6BIU.js';export{a as PageMapGenerator}from'./chunk-JBPSEUZS.js';import'./chunk-H7VVRHQZ.js';
@@ -0,0 +1 @@
1
+ export{a as PageMapGenerator}from'./chunk-JBPSEUZS.js';
@@ -1 +1 @@
1
- export{f as RailsControllerAnalyzer,h as RailsGrpcAnalyzer,g as RailsModelAnalyzer,e as RailsRoutesAnalyzer,k as analyzeRailsApp,i as analyzeRailsViews,j as analyzeReactComponents,d as findNodes,a as initRubyParser,b as parseRuby,c as parseRubyFile}from'./chunk-H7VVRHQZ.js';import'./chunk-ZWRDP37E.js';
1
+ export{f as RailsControllerAnalyzer,h as RailsGrpcAnalyzer,g as RailsModelAnalyzer,e as RailsRoutesAnalyzer,k as analyzeRailsApp,i as analyzeRailsViews,j as analyzeReactComponents,d as findNodes,a as initRubyParser,b as parseRuby,c as parseRubyFile}from'./chunk-H7VVRHQZ.js';
@@ -0,0 +1 @@
1
+ export{b as RailsMapGenerator}from'./chunk-DSYVU23K.js';import'./chunk-H7VVRHQZ.js';
@@ -1 +1 @@
1
- export{b as DocServer}from'../chunk-YKPXOHWZ.js';import'../chunk-LHP2OKKA.js';import'../chunk-VV3A3UE3.js';import'../chunk-IGRCLYVZ.js';import'../chunk-QBSB6BIU.js';import'../chunk-ATRSGO6O.js';import'../chunk-H7VVRHQZ.js';import'../chunk-ZWRDP37E.js';
1
+ export{b as DocServer}from'../chunk-54DEMJO2.js';import'../chunk-DSYVU23K.js';import'../chunk-VV3A3UE3.js';import'../chunk-O2SKKQVN.js';import'../chunk-QBSB6BIU.js';import'../chunk-JBPSEUZS.js';import'../chunk-H7VVRHQZ.js';
package/dist/types.d.ts CHANGED
@@ -175,6 +175,10 @@ interface GraphQLOperation {
175
175
  name: string;
176
176
  type: 'query' | 'mutation' | 'subscription' | 'fragment';
177
177
  filePath: string;
178
+ /** 1-based line number where the operation starts (best-effort) */
179
+ line?: number;
180
+ /** 1-based column number where the operation starts (best-effort) */
181
+ column?: number;
178
182
  usedIn: string[];
179
183
  variables: VariableInfo[];
180
184
  returnType: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wtdlee/repomap",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "Interactive documentation generator for code repositories - visualize pages, components, GraphQL operations, and data flows",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -42,6 +42,14 @@
42
42
  "src/**/*.ts": [
43
43
  "eslint --fix",
44
44
  "prettier --write"
45
+ ],
46
+ "vscode/src/**/*.ts": [
47
+ "eslint --fix",
48
+ "prettier --write"
49
+ ],
50
+ "*.ts": [
51
+ "eslint --fix",
52
+ "prettier --write"
45
53
  ]
46
54
  },
47
55
  "keywords": [
@@ -86,6 +94,7 @@
86
94
  "open": "^11.0.0",
87
95
  "simple-git": "^3.21.0",
88
96
  "socket.io": "^4.7.2",
97
+ "typescript": "^5.3.2",
89
98
  "tree-sitter-wasms": "^0.1.13",
90
99
  "web-tree-sitter": "^0.25.10",
91
100
  "yaml": "^2.3.4"
@@ -104,23 +113,23 @@
104
113
  "prettier": "^3.7.4",
105
114
  "tsup": "^8.5.1",
106
115
  "tsx": "^4.6.2",
107
- "typescript": "^5.3.2",
108
116
  "typescript-eslint": "^8.49.0",
109
117
  "vitest": "^4.0.15"
110
118
  },
111
119
  "scripts": {
112
120
  "build": "tsup",
113
121
  "build:tsc": "tsc && npm run copy-assets",
122
+ "build:vscode": "pnpm -C vscode install && pnpm -C vscode build",
114
123
  "copy-assets": "mkdir -p dist/generators/assets && cp src/generators/assets/*.css dist/generators/assets/",
115
124
  "dev": "tsx watch src/cli.ts",
116
125
  "dev:serve": "tsx watch --clear-screen=false src/cli.ts serve --no-cache",
117
126
  "generate": "tsx src/cli.ts generate",
118
127
  "serve": "tsx src/cli.ts serve",
119
- "test": "vitest",
120
- "lint": "eslint src",
121
- "lint:fix": "eslint src --fix",
122
- "format": "prettier --write \"src/**/*.ts\"",
123
- "format:check": "prettier --check \"src/**/*.ts\"",
128
+ "test": "vitest --pool=threads",
129
+ "lint": "eslint \"src/**/*.ts\" \"vscode/src/**/*.ts\" \"*.ts\"",
130
+ "lint:fix": "eslint \"src/**/*.ts\" \"vscode/src/**/*.ts\" \"*.ts\" --fix",
131
+ "format": "prettier --write \"src/**/*.ts\" \"vscode/src/**/*.ts\" \"*.ts\"",
132
+ "format:check": "prettier --check \"src/**/*.ts\" \"vscode/src/**/*.ts\" \"*.ts\"",
124
133
  "typecheck": "tsc --noEmit",
125
134
  "changeset": "changeset",
126
135
  "release": "changeset publish"