@wtdlee/repomap 0.6.0 → 0.7.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.
- package/README.md +44 -12
- package/dist/analyzers/index.d.ts +175 -25
- package/dist/analyzers/index.js +1 -1
- package/dist/{chunk-QZWPOG5B.js → chunk-GCIRJGW3.js} +78 -45
- package/dist/chunk-H7VVRHQZ.js +34 -0
- package/dist/chunk-HPBPEGHS.js +19 -0
- package/dist/{chunk-WQANJ7IA.js → chunk-JDM7Y7PX.js} +34 -28
- package/dist/{chunk-H4YGP3GL.js → chunk-OQAXO3X2.js} +346 -22
- package/dist/chunk-TNUKDIO7.js +5 -0
- package/dist/cli.js +17 -33
- package/dist/dataflow-analyzer-CJ2T0cGS.d.ts +345 -0
- package/dist/generators/assets/docs.css +176 -46
- package/dist/generators/assets/favicon/apple-touch-icon.png +0 -0
- package/dist/generators/assets/favicon/favicon-96x96.png +0 -0
- package/dist/generators/assets/favicon/favicon.ico +0 -0
- package/dist/generators/assets/favicon/favicon.svg +3 -0
- package/dist/generators/assets/favicon/site.webmanifest +21 -0
- package/dist/generators/assets/favicon/web-app-manifest-192x192.png +0 -0
- package/dist/generators/assets/favicon/web-app-manifest-512x512.png +0 -0
- package/dist/generators/assets/page-map.css +392 -87
- package/dist/generators/assets/rails-map.css +221 -48
- package/dist/generators/index.d.ts +0 -8
- package/dist/generators/index.js +1 -1
- package/dist/index.d.ts +18 -9
- package/dist/index.js +1 -1
- package/dist/page-map-generator-3GO6GL2P.js +1 -0
- package/dist/{rails-FFISZ4AE.js → rails-3HNUFTQV.js} +1 -1
- package/dist/rails-map-generator-CAQZUBI6.js +1 -0
- package/dist/server/index.d.ts +2 -6
- package/dist/server/index.js +1 -1
- package/dist/types.d.ts +12 -3
- package/package.json +1 -1
- package/dist/chunk-BPV4UZSW.js +0 -2
- package/dist/chunk-PTR5IROV.js +0 -36
- package/dist/chunk-XWZH2RDG.js +0 -19
- package/dist/dataflow-analyzer-s6ufFkKC.d.ts +0 -215
- package/dist/page-map-generator-HBKSOX2E.js +0 -1
- package/dist/rails-map-generator-UFLCMFAT.js +0 -1
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import {parseSync}from'@swc/core';import q from'fast-glob';import*as x from'path';import*as b from'fs';import*as Q from'fs/promises';import {parse}from'graphql';var v=class{config;basePath;constructor(e){this.config=e,this.basePath=e.path;}resolvePath(e){return `${this.basePath}/${e}`}getSetting(e,t=""){return this.config.settings[e]??t}log(e){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 W=["useQuery","useLazyQuery","useSuspenseQuery","useBackgroundQuery","useReadQuery"],V=["useMutation"],le=["useSubscription","useFragment","useApolloClient"],R=[...W,...V,...le],z={useQuery:"useQuery",useSuspenseQuery:"useQuery",useBackgroundQuery:"useQuery",useReadQuery:"useQuery",useLazyQuery:"useLazyQuery",useMutation:"useMutation",useSubscription:"useSubscription"},ue=["Document","useQuery","useMutation","useLazyQuery","useSuspenseQuery","useBackgroundQuery","useSubscription","Query","Mutation","gql","graphql","GET_","FETCH_","SEARCH_","CREATE_","UPDATE_","DELETE_","SUBSCRIBE_","@apollo","ApolloClient"];function M(l){return W.includes(l)||/^use[A-Z].*Query$/.test(l)}function S(l){return V.includes(l)||/^use[A-Z].*Mutation$/.test(l)}function U(l){return l==="useSubscription"}function F(l){return R.includes(l)||M(l)||S(l)}function T(l){return z[l]?z[l]:l.includes("Mutation")?"useMutation":l.includes("Lazy")?"useLazyQuery":l.includes("Subscription")?"useSubscription":"useQuery"}function L(l){return ue.some(e=>l.includes(e))}function h(l){return l.replace(/^(GET_|FETCH_|CREATE_|UPDATE_|DELETE_)/,"").replace(/_QUERY$|_MUTATION$/,"").replace(/Document$/,"").replace(/Query$|Mutation$|Variables$|Subscription$/,"")}function ce(l){try{return parseSync(l,{syntax:"typescript",tsx:!0,comments:!1})}catch{return null}}function d(l){return l?l.type==="Identifier"?l.value:l.type==="MemberExpression"&&l.property?.type==="Identifier"?l.property.value:null:null}function A(l,e){if(!(!l||typeof l!="object")){e(l);for(let t of Object.keys(l)){let r=l[t];if(Array.isArray(r))for(let s of r)A(s,e);else r&&typeof r=="object"&&A(r,e);}}}function O(l,e,t){let r={documentImports:new Map,variableOperations:new Map,staticPropertyOperations:new Map,codegenMap:t||new Map};return A(l,s=>{s.type==="ImportDeclaration"&&fe(s,r.documentImports),s.type==="VariableDeclarator"&&me(s,e,r.variableOperations),s.type==="AssignmentExpression"&&ge(s,e,r.staticPropertyOperations);}),r}function fe(l,e){let t=l.source?.value||"",r=t.includes("__generated__")||t.includes("generated")||t.includes("graphql")||t.includes(".generated")||t.endsWith(".graphql");for(let s of l.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 me(l,e,t){if(l.id?.type!=="Identifier")return;let r=l.id.value,s=l.init;if(!s)return;let i=null;if(s.type==="CallExpression"){let n=d(s.callee);(n==="gql"||n==="graphql")&&(i=k(s,e));}if(s.type==="TaggedTemplateExpression"){let n=d(s.tag);(n==="gql"||n==="graphql")&&(i=I(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 ge(l,e,t){if(l.left?.type!=="MemberExpression")return;let r=l.left.object,s=l.left.property;if(r?.type!=="Identifier"||s?.type!=="Identifier")return;let i=`${r.value}.${s.value}`,n=l.right;if(!n)return;let a=null;if(n.type==="CallExpression"){let o=d(n.callee);(o==="gql"||o==="graphql")&&(a=k(n,e));}if(n.type==="TaggedTemplateExpression"){let o=d(n.tag);(o==="gql"||o==="graphql")&&(a=I(n.template));}a&&t.set(i,a);}function k(l,e){if(!l.arguments?.length)return null;let t=l.arguments[0],r=t?.expression||t;if(r?.type==="TemplateLiteral")return I(r);if(l.span){let i=e.slice(l.span.start,l.span.end).match(/(?:query|mutation|subscription)\s+(\w+)/i);if(i)return i[1]}return null}function I(l,e){if(!l?.quasis?.[0])return null;let r=(l.quasis[0].raw||l.quasis[0].cooked||"").match(/(?:query|mutation|subscription)\s+(\w+)/i);return r?r[1]:null}function H(l,e,t){if(!l.arguments?.length)return false;let r=l.arguments[0],s=r?.expression||r;if(!s)return false;if(l.typeArguments?.params?.length>0){let n=l.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=d(s.tag);if(n==="gql"||n==="graphql")return true}if(s.type==="CallExpression"){let n=d(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}}let i=l.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 _(l,e,t){let r=he(l,e);if(r)return r;if(l.arguments?.length>0){let s=l.arguments[0],i=s?.expression||s;if(i){let n=Z(i,e,t);if(n)return n}}return null}function he(l,e){if(l.typeArguments?.params?.length>0){let t=l.typeArguments.params[0];if(t?.type==="TsTypeReference"&&t.typeName?.type==="Identifier")return h(t.typeName.value)}if(l.callee?.span&&l.span){let t=l.callee.span.end,r=Math.min(t+150,l.span.end),i=e.slice(t,r).match(/^<\s*(\w+)(?:Query|Mutation|Variables|Subscription)?[\s,>]/);if(i)return h(i[1])}return null}function Z(l,e,t){if(l.type==="Identifier")return B(l.value,t);if(l.type==="MemberExpression")return ye(l,t);if(l.type==="TaggedTemplateExpression"){let r=d(l.tag);if(r==="gql"||r==="graphql")return I(l.template)}if(l.type==="TemplateLiteral")return I(l);if(l.type==="CallExpression"){let r=d(l.callee);if(r==="gql"||r==="graphql")return k(l,e)}return l.type==="ObjectExpression"?J(l,e,t):null}function B(l,e){let t=e.variableOperations.get(l);if(t)return e.variableOperations.has(t)?B(t,e):t.endsWith("Document")||t.endsWith("Query")||t.endsWith("Mutation")?e.documentImports.get(t)||h(t):t;let r=e.documentImports.get(l);if(r)return r;let s=e.codegenMap.get(l);return s?s.operationName:/^(Query|Mutation|QUERY|MUTATION|Document)$/i.test(l)?null:h(l)}function ye(l,e){let t=l.object?.type==="Identifier"?l.object.value:null,r=l.property?.type==="Identifier"?l.property.value:null;if(!r)return null;if(t){let s=`${t}.${r}`,i=e.staticPropertyOperations.get(s);if(i)return i}return h(r)}function J(l,e,t){for(let r of l.properties||[])if(r.type==="KeyValueProperty"&&r.key?.type==="Identifier"&&r.key.value==="query")return Z(r.value,e,t);return null}function we(l,e){let t=[],r=new Set;if(!L(l))return t;let s=ce(l);if(!s)return t;let i=O(s,l,e);return A(s,n=>{if(n.type!=="CallExpression")return;let a=d(n.callee);if(a){if(F(a)){let o=_(n,l,i),p=T(a),c=`${p}:${o||"unknown"}`;r.has(c)||(r.add(c),t.push({operationName:o||"unknown",hookName:a,type:p}));}if((a==="query"||a==="mutate")&&n.arguments?.length>0){let o=n.arguments[0],p=o?.expression||o;if(p?.type==="ObjectExpression"){let c=J(p,l,i),u=a==="mutate"?"useMutation":"useQuery",f=`${u}:${c||"unknown"}`;c&&!r.has(f)&&(r.add(f),t.push({operationName:c,hookName:`client.${a}`,type:u}));}}}}),t}function Ie(l){return `${{useQuery:"Query",useLazyQuery:"Query",useMutation:"Mutation",useSubscription:"Subscription"}[l.type]||"Query"}: ${l.operationName}`}async function N(l,e,t=8){let r=new Array(l.length).fill(null),s=0;async function i(){for(;s<l.length;){let a=s++;if(a<l.length)try{r[a]=await e(l[a],a);}catch{r[a]=null;}}}let n=Array(Math.min(t,l.length)).fill(null).map(()=>i());return await Promise.all(n),r.filter(a=>a!==null)}var Y=class extends v{codegenMap=new Map;constructor(e){super(e);}getName(){return "PagesAnalyzer"}async analyze(){this.log("Starting page analysis..."),await this.loadCodegenMapping();let e=await this.findPageFiles();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 p=>{try{let c=await Q.readFile(p,"utf-8");return {filePath:p,content:c}}catch{return null}}));for(let p of o)p&&r.set(p.filePath,p.content);}let i=(await N(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}}async loadCodegenMapping(){let e=await q(["**/__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 Q.readFile(t,"utf-8"),s=x.relative(this.basePath,t);if(!r.includes("DocumentNode"))continue;let i=r.split(`
|
|
2
|
+
`);for(let n of i){if(!n.includes("Document")||!n.includes("="))continue;let a=[/export\s+const\s+(\w+Document)\s*=/,/export\s+const\s+(\w+):\s*DocumentNode\s*=/,/const\s+(\w+Document)\s*=.*DocumentNode/];for(let o of a){let p=n.match(o);if(!p)continue;let c=p[1],u=c.replace(/Document$/,""),f="query";n.includes('"mutation"')||c.toLowerCase().includes("mutation")?f="mutation":(n.includes('"subscription"')||c.toLowerCase().includes("subscription"))&&(f="subscription"),this.codegenMap.set(c,{operationName:u,operationType:f});break}}this.codegenMap.size>0&&this.log(`Loaded ${this.codegenMap.size} 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=x.relative(r,e),a=this.filePathToRoutePath(n),o=this.findPageComponent(i,t);if(!o)return null;let p=this.extractRouteParams(a),c=this.extractImports(i),u=this.extractLayout(i,t),f=this.extractAuthRequirement(i,t,e),m=this.extractPermissions(t),g=this.extractDataFetching(i,t,c),y=this.extractLinkedPages(i,t),C=this.extractNavigation(t),w=this.extractSteps(t);return {path:a,filePath:n,component:o,params:p,layout:u,authentication:f,permissions:m,dataFetching:g,navigation:C,linkedPages:y,steps:w.length>0?w:void 0}}catch{return 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"],p=this.resolvePath(n);if(o.some(u=>{try{return b.existsSync(x.join(p,u))}catch{return false}}))continue}let a=this.resolvePath(n);try{let o=await q(["**/*.tsx","**/*.ts","**/*.jsx","**/*.js"],{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(...o),o.length>0&&this.log(`Found ${o.length} pages in ${n}`);}catch{}}let i=["frontend/src/**/pages","app/javascript/**/pages"];for(let n of i)try{let a=await q([`${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=[],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(b.existsSync(s))try{let i=await Q.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 p=this.getJsxTagName(o);if(p==="Route"||p==="PrivateRoute"){let c=this.getJsxAttribute(o,"component"),u=this.getJsxAttribute(o,"element"),f=c||u,m=f?a.get(f):void 0;if(m){let g=this.resolveImportPath(x.dirname(s),m);g&&b.existsSync(g)&&e.push(g);}}}}),e.length>0&&e.push(s);}catch{}}return e}resolveImportPath(e,t){if(!t.startsWith("."))return null;let r=[".tsx",".ts",".jsx",".js","/index.tsx","/index.ts","/index.jsx","/index.js"],s=x.resolve(e,t);for(let i of r){let n=s+i;if(b.existsSync(n))return n}if(b.existsSync(s)&&b.statSync(s).isDirectory())for(let i of ["/index.tsx","/index.ts","/index.jsx","/index.js"]){let n=s+i;if(b.existsSync(n))return n}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){return "/"+e.replace(/\.tsx?$/,"").replace(/\.jsx?$/,"").replace(/\/index$/,"").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"),p;for(;(p=o.exec(t))!==null;)i.push({name:a,index:p.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=x.basename(r),a={required:!["404.tsx","permission-denied.tsx","_app.tsx","_document.tsx","_error.tsx"].some(p=>s===p)},o=["RequiredCondition","ProtectedRoute","AuthGuard","PrivateRoute","WithAuth","RequireAuth","Authenticated","Authorized"];for(let p of o)if(t.includes(`<${p}`)){a.condition="Additional permissions required";let c=this.extractRolesFromContent(t);c.length>0&&(a.roles=c);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[o,p]of this.codegenMap)n.set(o,{operationName:p.operationName,type:p.operationType});let a=O(e,t,n);if(A(e,o=>{if(o.type==="CallExpression"){let p=o,c=d(p.callee);if(!c)return;if(F(c)&&H(p,t,a)){let u=_(p,t,a),m={type:T(c),operationName:u||"unknown"},g=this.extractVariablesFromCall(p);Object.keys(g).length>0&&(m.variables=g);let y=`${m.type}:${m.operationName}`;i.has(y)||(i.add(y),s.push(m));}if(c==="query"||c==="mutate"){let u=this.analyzeClientDirectCall(p,t,a);if(u){let f=`${u.type}:${u.operationName}`;i.has(f)||(i.add(f),s.push(u));}}}}),this.extractSSRDataFetching(e,t,s,i),t.includes("getStaticProps")){let o="getStaticProps:getStaticProps";i.has(o)||(i.add(o),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 p=a.value;o=r.variableOperations.get(p)||r.documentImports.get(p)||h(p);}if(a?.type==="MemberExpression"){let p=a.object?.type==="Identifier"?a.object.value:null,c=a.property?.type==="Identifier"?a.property.value:null;if(p&&c){let u=`${p}.${c}`;o=r.staticPropertyOperations.get(u)||h(c);}}if(o)return {type:d(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 c=o.quasis[0].raw.match(/(?:query|mutation|subscription)\s+(\w+)/i);c&&r.set(i,c[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=R.includes(i),a=M(i)&&!i.includes("Params"),o=S(i);if(!n&&!a&&!o)return null;let p=T(i),c=i.replace(/^use/,"").replace(/Query$|Mutation$/,""),u=this.extractTypeGeneric(e,t);if(u&&(c=u.replace(/Query$|Mutation$|Variables$/,"")),e.arguments&&e.arguments.length>0){let m=e.arguments[0],g=m?.expression||m,y=this.extractOperationFromArgument(g,r,s);y&&(c=y);}let f=this.extractVariablesFromCall(e);return {type:p,operationName:c,variables:f}}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 p of o.declarations)p.id?.type==="Identifier"&&p.id.value==="getServerSideProps"&&this.extractSSRQueriesFromNode(p,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){A(e,a=>{if(a.type!=="CallExpression")return;let o=d(a.callee);if(o==="query"||o==="mutate"){let p=this.extractQueryFromClientCall(a,t,r,s);if(p){let c=`getServerSideProps:\u2192 ${p}`;n.has(c)||(n.add(c),i.push({type:"getServerSideProps",operationName:`\u2192 ${p}`}));}}});}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 p=o.value;if(s.has(p))return s.get(p);let c=this.codegenMap.get(p);return c?c.operationName:r.get(p)?h(p):h(p)}if(o?.type==="MemberExpression"){let p=o.object?.type==="Identifier"?o.object.value:null,c=o.property?.type==="Identifier"?o.property.value:null;if(p&&c)return `${p}.${c}`}}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 ee=class extends v{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}}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 q(["**/__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 Q.readFile(r,"utf-8"),i=x.relative(this.basePath,r),n=s.split(`
|
|
3
|
+
`);for(let a of n){if(!a.includes("Document =")||!a.includes("DocumentNode"))continue;let o=a.match(/export\s+const\s+(\w+Document)\s*=\s*(\{"kind":"Document".+\})\s*as\s+unknown\s+as\s+DocumentNode/);if(!o)continue;let p=o[1],c=o[2];try{let u=JSON.parse(c);if(u.kind==="Document"&&u.definitions){let f=u.definitions[0];if(f?.kind==="OperationDefinition"){let m=f.name?.value||p.replace(/Document$/,""),g=f.operation,y=(f.variableDefinitions||[]).map(C=>({name:C.variable?.name?.value||"unknown",type:this.extractTypeFromAst(C.type),required:C.type?.kind==="NonNullType"}));e.push({name:m,type:g,filePath:i,usedIn:[],variables:y,returnType:this.inferReturnTypeFromAst(f),fragments:this.extractFragmentReferencesFromAst(f),fields:this.extractFieldsFromAst(f.selectionSet)});}}}catch{}}this.log(`Found ${e.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 q(["**/*.graphql"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**"],absolute:true});return (await N(e,async r=>{let s=await Q.readFile(r,"utf-8"),i=parse(s);return this.extractOperationsFromDocument(i,x.relative(this.basePath,r))})).flat()}async analyzeInlineGraphQL(){let e=[],t=await q(["**/*.ts","**/*.tsx","**/*.js","**/*.jsx"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**","**/__tests__/**","**/*.test.*","**/*.spec.*","**/__generated__/**"],absolute:true}),r=50;for(let s=0;s<t.length;s+=r){let i=t.slice(s,s+r),n=await N(i,async a=>{try{let o=await Q.readFile(a,"utf-8");if(!o.includes("gql")&&!o.includes("graphql"))return [];let p=x.relative(this.basePath,a),c=a.endsWith(".tsx")||a.endsWith(".jsx"),u=parseSync(o,{syntax:a.endsWith(".ts")||a.endsWith(".tsx")?"typescript":"ecmascript",tsx:c,jsx:c});return this.analyzeModuleForGraphQL(u,o,p)}catch{return []}},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,p=this.getTagName(o.tag);if(p==="gql"||p==="graphql"){let c=this.extractTemplateContent(o.template,t);if(c)try{let u=parse(c),f=this.extractOperationsFromDocument(u,r);if(a)for(let m of f)m.variableNames=m.variableNames||[],m.variableNames.push(a),m.variableNames.push(`${m.name}Document`);s.push(...f);}catch{}}}if(n.type==="CallExpression"){let o=n,p=this.getCalleeName(o.callee);if((p==="gql"||p==="graphql")&&o.arguments.length>0){let c=o.arguments[0].expression,u=this.extractGraphQLFromExpression(c,t);if(u)try{let f=parse(u),m=this.extractOperationsFromDocument(f,r);if(a)for(let g of m)g.variableNames=g.variableNames||[],g.variableNames.push(a),g.variableNames.push(`${g.name}Document`);s.push(...m);}catch{}}}}),s}traverseNodeWithContext(e,t,r){if(!e||typeof e!="object")return;let s=false;e.type==="VariableDeclarator"&&e.id?.type==="Identifier"&&(t.push(e.id.value),s=true),r(e,t.length>0?t[t.length-1]:null);for(let i of Object.keys(e)){let n=e[i];if(Array.isArray(n))for(let a of n)this.traverseNodeWithContext(a,t,r);else n&&typeof n=="object"&&this.traverseNodeWithContext(n,t,r);}s&&t.pop();}getTagName(e){return e.type==="Identifier"?e.value:null}getCalleeName(e){return e.type==="Identifier"?e.value:null}extractTemplateContent(e,t){if(e.type==="TemplateLiteral"){if(e.quasis.length===1&&e.expressions.length===0)return e.quasis[0].raw;let r=e.span.start,s=e.span.end;return t.slice(r,s).slice(1,-1).replace(/\$\{[^}]*\}/g,"")}return null}extractGraphQLFromExpression(e,t){return e.type==="TemplateLiteral"?this.extractTemplateContent(e,t):e.type==="StringLiteral"?e.value:null}extractOperationsFromDocument(e,t){let r=[];for(let s of e.definitions){let i=this.extractOperation(s,t);i&&r.push(i);}return r}extractOperation(e,t){if(e.kind==="OperationDefinition"){let r=e.name?.value||"anonymous",s=e.operation,i=this.extractVariables(e),n=this.extractFragmentReferences(e),a=this.extractFields(e);return {name:r,type:s,filePath:t,usedIn:[],variables:i,returnType:this.inferReturnType(e),fragments:n,fields:a}}return e.kind==="FragmentDefinition"?{name:e.name.value,type:"fragment",filePath:t,usedIn:[],variables:[],returnType:e.typeCondition.name.value,fragments:this.extractFragmentReferences(e),fields:this.extractFields(e)}:null}extractFields(e){let t=[],r=(s,i=0)=>{if(!s||!s.selections||i>5)return [];let n=[];for(let a of s.selections)if(a.kind==="Field"){let o={name:a.name.value};if(a.arguments&&a.arguments.length>0){let p=a.arguments.map(c=>c.name.value).join(", ");o.type=`(${p})`;}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=await q(["**/*.ts","**/*.tsx"],{cwd:this.basePath,ignore:["**/node_modules/**","**/.next/**","**/__generated__/**","**/dist/**","**/build/**"],absolute:true}),r=new Map,s=new Map,i=new Map,n=new Map;for(let u of e)if(r.set(u.name,u),s.set(`${u.name}Document`,u),n.set(`${u.name}Query`,u),n.set(`${u.name}Mutation`,u),n.set(`${u.name}Subscription`,u),n.set(`${u.name}QueryVariables`,u),n.set(`${u.name}MutationVariables`,u),u.variableNames)for(let f of u.variableNames)i.set(f,u);let a=new Set;for(let u of e)if(a.add(u.name),a.add(`${u.name}Document`),a.add(`${u.name}Query`),a.add(`${u.name}Mutation`),a.add(`${u.name}Subscription`),u.variableNames)for(let f of u.variableNames)a.add(f);let o=null,p=Array.from(a);if(p.length>0&&p.length<2e3){let u=p.sort((f,m)=>m.length-f.length).map(f=>f.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"));o=new RegExp(`\\b(${u.join("|")})\\b`,"g");}let c=50;for(let u=0;u<t.length;u+=c){let f=t.slice(u,u+c);await Promise.all(f.map(async m=>{try{let g=await Q.readFile(m,"utf-8"),y=x.relative(this.basePath,m);if(!L(g))return;if(o){let C=new Set,w;for(;(w=o.exec(g))!==null;)C.add(w[1]);o.lastIndex=0;for(let P of C){let E=s.get(P)||i.get(P)||n.get(P)||r.get(P);E&&y!==E.filePath&&(E.usedIn.includes(y)||E.usedIn.push(y));}}await this.findUsageWithAST(g,m,y,r,n);}catch{}}));}}async findUsageWithAST(e,t,r,s,i){try{let n=t.endsWith(".tsx")||t.endsWith(".jsx"),a=parseSync(e,{syntax:t.endsWith(".ts")||t.endsWith(".tsx")?"typescript":"ecmascript",tsx:n,jsx:n,comments:!1});this.traverseNodeForUsage(a,e,o=>{if(o.type==="CallExpression"){let p=this.getCalleeNameForUsage(o.callee);if(p&&F(p)){let c=this.extractTypeGenericFromCall(o,e);if(c){let f=i.get(c)||s.get(c.replace(/Query$|Mutation$|Variables$/,""));f&&r!==f.filePath&&(f.usedIn.includes(r)||f.usedIn.push(r));}let u=this.extractFirstArgName(o);if(u){let f=u.replace(/Document$/,""),m=s.get(f)||i.get(u);m&&r!==m.filePath&&(m.usedIn.includes(r)||m.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 ne=class extends v{componentCache=new Map;constructor(e){super(e);}getName(){return "DataFlowAnalyzer"}async analyze(){this.log("Starting data flow analysis...");let e=await this.analyzeComponents(),t=await this.analyzeDataFlows(e);return this.log(`Analyzed ${e.length} components and ${t.length} data flows`),{components:e,dataFlows:t}}async analyzeComponents(){let e=[],t=[this.getSetting("featuresDir",""),this.getSetting("componentsDir",""),this.getSetting("pagesDir","")].filter(Boolean),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 q(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`);let a=50;for(let o=0;o<n.length;o+=a){let p=n.slice(o,o+a),c=await Promise.all(p.map(async u=>{try{let f=await Q.readFile(u,"utf-8");return {filePath:u,content:f}}catch{return null}}));for(let u of c)if(u)try{let f=parseSync(u.content,{syntax:"typescript",tsx:!0,comments:!1}),m=x.relative(this.basePath,u.filePath),g=this.analyzeComponentFile(f,m,u.content);e.push(...g);}catch{}}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 p=this.extractComponentInfo(o,t,r,i);s.push(p),this.componentCache.set(o,p);}}}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 p=this.extractComponentInfo(o,t,r,i);s.push(p),this.componentCache.set(o,p);}}}}return s}extractImports(e){let t=new Map;for(let r of e.body)if(r.type==="ImportDeclaration"){let s=r.source?.value||"";if(s.startsWith(".")||s.startsWith("@/"))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}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(u=>t.includes(u))?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(u=>this.isComponentName(u)||u.startsWith("use")),p=[];for(let[u,f]of s)p.push({name:u,path:f});let c=this.extractStateManagement(r);return {name:e,filePath:t,type:i,props:[],dependencies:o,dependents:[],hooks:a,stateManagement:c,imports:p}}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 p=this.getCalleeNameFromNode(o.callee);if(p==="gql"||p==="graphql"){let c=this.extractOperationNameFromGqlCall(o,t);c&&r.set(a,c);}}if(o.type==="TaggedTemplateExpression"){let p=this.getCalleeNameFromNode(o.tag);if((p==="gql"||p==="graphql")&&o.template?.quasis?.[0]?.raw){let u=o.template.quasis[0].raw.match(/(?:query|mutation|subscription)\s+(\w+)/i);u&&r.set(a,u[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 p of o)i(p);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 p of o)this.traverseForHooks(p,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=M(a),p=S(a),c=U(a);if((o||p||c)&&this.hasGraphQLArgument(e,t,r,s)){let f=this.extractOperationNameFromCall(e,t,r,s),m=p?"Mutation":c?"Subscription":"Query",g=f?`${m}: ${f}`:`${m}: unknown`;n.has(g)||(n.add(g),i.push(g));return}if(a==="useContext"){let u=this.extractContextName(e);if(u){let f=`\u{1F504} Context: ${u}`;n.has(f)||(n.add(f),i.push(f));}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 h(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 h(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 p=r.get(a);return p||(/^(Query|Mutation|QUERY|MUTATION)$/i.test(a)?null:h(a))}if(n.type==="MemberExpression"&&n.property?.type==="Identifier")return h(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],p=o?.expression||o;if(p?.type==="TemplateLiteral"&&p.quasis?.[0]?.raw){let u=p.quasis[0].raw.match(/(?:query|mutation|subscription)\s+(\w+)/i);if(u)return u[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 h(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],p=i[2];if(p&&/^(Query|Mutation|QUERY|MUTATION)$/i.test(p))continue;let c=p?h(p):"unknown",f=`${o.includes("Mutation")?"Mutation":o.includes("Subscription")?"Subscription":"Query"}: ${c}`;r.has(f)||(r.add(f),t.push(f));}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 p=e.slice(a.index).match(/useContext\s*\(\s*([A-Z][A-Za-z0-9]*)/);if(p){let u=`\u{1F504} Context: ${p[1].replace(/Context$/,"")}`;r.has(u)||(r.add(u),t.push(u));}}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(p=>p.includes("Context")&&p.includes(n));(o||a.hooks.some(p=>p.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 ie=class l extends v{apiCallCounter=0;constructor(e){super(e);}getName(){return "RestApiAnalyzer"}async analyze(){this.log("Starting REST API analysis...");let e=await q(["**/*.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 N(i,async a=>{try{let o=await Q.readFile(a,"utf-8"),p=x.relative(this.basePath,a),c=a.endsWith(".tsx")||a.endsWith(".jsx"),u=parseSync(o,{syntax:a.endsWith(".ts")||a.endsWith(".tsx")?"typescript":"ecmascript",tsx:c,jsx:c});return this.analyzeModule(u,o,p)}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(`
|
|
4
|
+
`);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 p=e.arguments[1].expression;if(p.type==="ObjectExpression")for(let c of p.properties)c.type==="KeyValueProperty"&&c.key.type==="Identifier"&&(c.key.value==="method"&&c.value.type==="StringLiteral"&&(n=this.normalizeMethod(c.value.value)),(c.key.value==="credentials"||c.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 l.NON_API_SCHEMES.test(e)||l.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 l.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"}};
|
|
5
|
+
export{ne as A,ie as B,v as a,W as b,V as c,le as d,R as e,z as f,ue as g,M as h,S as i,U as j,F as k,T as l,L as m,h as n,ce as o,d as p,A as q,O as r,k as s,I as t,H as u,_ as v,we as w,Ie as x,Y as y,ee as z};
|
package/dist/cli.js
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {a,b}from'./chunk-
|
|
3
|
-
\u{1F4DA} Repomap
|
|
4
|
-
`));try{let a$1=process.cwd(),
|
|
5
|
-
\
|
|
6
|
-
|
|
7
|
-
\
|
|
8
|
-
|
|
9
|
-
\u{1F310} Repomap - Documentation Server
|
|
10
|
-
`));try{let o=e.path||process.cwd(),a=await P(e.config,o);await new b(a,parseInt(e.port),{noCache:!e.cache}).start(!e.open);}catch(o){console.error(n.red(`
|
|
11
|
-
\u274C Error:`),o.message),process.exit(1);}});d.command("init").description("Initialize repomap configuration").option("-f, --force","Overwrite existing config").action(async e=>{let o="./repomap.config.ts";try{if(await s.access(o).then(()=>!0).catch(()=>!1)&&!e.force){console.log(n.yellow("Config file already exists. Use --force to overwrite."));return}let t=await $(process.cwd()),c=t?.name||"my-project",r=t?.type||"nextjs",i=t?.settings.pagesDir||"src/pages",l=t?.settings.featuresDir||"src/features",m=t?.settings.componentsDir||"src/components",h=`import type { DocGeneratorConfig } from "repomap";
|
|
2
|
+
import {a,b}from'./chunk-JDM7Y7PX.js';import'./chunk-OQAXO3X2.js';import'./chunk-VV3A3UE3.js';import'./chunk-TNUKDIO7.js';import'./chunk-HPBPEGHS.js';import'./chunk-GCIRJGW3.js';import'./chunk-H7VVRHQZ.js';import {Command}from'commander';import s from'chalk';import*as p from'path';import*as n from'fs/promises';var d=new Command;d.name("repomap").description("Interactive documentation generator for code repositories").version("0.6.0");async function $(e){let t=p.basename(e),a=false,o=p.join(e,"Gemfile"),c=p.join(e,"config","routes.rb");try{await n.access(o),await n.access(c);let u=await n.readFile(o,"utf-8");a=u.includes("gem 'rails'")||u.includes('gem "rails"');}catch{}let r=p.join(e,"package.json"),i=false,l=false,f={};try{let u=JSON.parse(await n.readFile(r,"utf-8")),y={...u.dependencies,...u.devDependencies};i=!!y.react,l=!!y.next;let m=["src/pages","pages","app","src/app","frontend/src"];for(let g of m)try{await n.access(p.join(e,g)),f.pagesDir=g;break}catch{}let b=["src/features","features","src/modules","modules","frontend/src"];for(let g of b)try{await n.access(p.join(e,g)),f.featuresDir=g;break}catch{}let D=["src/components","components","src/common/components","frontend/src"];for(let g of D)try{await n.access(p.join(e,g)),f.componentsDir=g;break}catch{}}catch{}let h=[];(i||l)&&h.push("pages","graphql","dataflow","rest-api");let w="generic";return l?w="nextjs":a&&(w="rails"),!a&&!i&&!l?null:{name:t,displayName:t,description:a&&i?"Rails + React application":a?"Rails application":"",path:e,branch:"main",type:w,analyzers:h,settings:f}}async function x(e){let t=await $(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 P(e,t){let a=e?[e]:["repomap.config.ts","repomap.config.js","repomap.config.mjs"];for(let o of a){let c=p.resolve(t,o);try{await n.access(c);let r=await import(c);return r.config||r.default}catch{}}return x(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("--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
|
+
\u{1F4DA} Repomap
|
|
4
|
+
`));try{let a$1=process.cwd(),o=await P(e.config,a$1);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 c=new a(o);if(e.watch)console.log(s.yellow(`\u{1F440} Watch mode enabled. Press Ctrl+C to stop.
|
|
5
|
+
`)),await G(c,o);else {let r=await c.generate();if(e.format==="json"||e.static){let i=p.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 C(o,r,t),!t)E(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 C(e,t,a){let{PageMapGenerator:o}=await import('./page-map-generator-3GO6GL2P.js'),{detectEnvironments:c}=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 c(i),f=null;if(l.hasRails){let{analyzeRailsApp:m}=await import('./rails-3HNUFTQV.js');f=await m(i);}let w=new o().generatePageMapHtml(t,{envResult:l,railsAnalysis:f,staticMode:true});if(await n.writeFile(p.join(r,"index.html"),w),a||console.log(s.gray(` \u2192 ${p.join(r,"index.html")}`)),f){let{RailsMapGenerator:m}=await import('./rails-map-generator-CAQZUBI6.js'),D=new m().generateFromResult(f);await n.writeFile(p.join(r,"rails-map.html"),D),a||console.log(s.gray(` \u2192 ${p.join(r,"rails-map.html")}`));}let u=["common.css","page-map.css","docs.css","rails-map.css"],y=p.join(r,"assets");await n.mkdir(y,{recursive:true});for(let m of u)try{let b=new URL(`./generators/assets/${m}`,import.meta.url),D=await n.readFile(b,"utf-8");await n.writeFile(p.join(y,m),D);}catch{}a||console.log(s.green(`
|
|
6
|
+
\u2705 Static site generated: ${r}`));}d.command("serve").description("Start local documentation server with live reload").option("-c, --config <path>","Path to config file").option("--path <path>","Path to repository to analyze (auto-detect if no config)").option("-p, --port <number>","Server port","3030").option("--no-open","Don't open browser automatically").action(async e=>{console.log(s.blue.bold(`
|
|
7
|
+
\u{1F310} Repomap
|
|
8
|
+
`));try{let t=e.path||process.cwd(),a=await P(e.config,t);await new b(a,parseInt(e.port)).start(!e.open);}catch(t){console.error(s.red("Error:"),t.message),process.exit(1);}});d.command("init").description("Initialize repomap configuration").option("-f, --force","Overwrite existing config").action(async e=>{let t="./repomap.config.ts";try{if(await n.access(t).then(()=>!0).catch(()=>!1)&&!e.force){console.log(s.yellow("Config file already exists. Use --force to overwrite."));return}let o=await $(process.cwd()),c=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",h=`import type { DocGeneratorConfig } from "repomap";
|
|
12
9
|
|
|
13
10
|
export const config: DocGeneratorConfig = {
|
|
14
11
|
outputDir: "./.repomap",
|
|
@@ -29,20 +26,9 @@ export const config: DocGeneratorConfig = {
|
|
|
29
26
|
settings: {
|
|
30
27
|
pagesDir: "${i}",
|
|
31
28
|
featuresDir: "${l}",
|
|
32
|
-
componentsDir: "${
|
|
29
|
+
componentsDir: "${f}",
|
|
33
30
|
},
|
|
34
31
|
},
|
|
35
|
-
// Add more repositories for cross-repo analysis:
|
|
36
|
-
// {
|
|
37
|
-
// name: "other-repo",
|
|
38
|
-
// displayName: "Other Repository",
|
|
39
|
-
// description: "Another repository",
|
|
40
|
-
// path: "../other-repo",
|
|
41
|
-
// branch: "main",
|
|
42
|
-
// type: "nextjs",
|
|
43
|
-
// analyzers: ["pages", "graphql", "components", "dataflow"],
|
|
44
|
-
// settings: {},
|
|
45
|
-
// },
|
|
46
32
|
],
|
|
47
33
|
analysis: {
|
|
48
34
|
include: ["**/*.tsx", "**/*.ts"],
|
|
@@ -65,15 +51,13 @@ export const config: DocGeneratorConfig = {
|
|
|
65
51
|
};
|
|
66
52
|
|
|
67
53
|
export default config;
|
|
68
|
-
`;await
|
|
69
|
-
Run 'npx repomap serve' to start the documentation server.`));}catch(a){console.error(
|
|
70
|
-
\u{1F6E4}\uFE0F Repomap
|
|
71
|
-
`));try{let
|
|
72
|
-
\u2705 Rails map generated: ${t}`));let{exec:r}=await import('child_process');r(`open "${t}"`);}catch(o){console.error(n.red(`
|
|
73
|
-
\u274C Error:`),o.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(n.blue.bold(`
|
|
54
|
+
`;await n.writeFile(t,h,"utf-8"),console.log(s.green(`\u2705 Created ${t}`)),console.log(s.gray(`
|
|
55
|
+
Run 'npx repomap serve' to start the documentation server.`));}catch(a){console.error(s.red("Failed to create config:"),a.message);}});d.command("rails").description("Analyze a Rails application and generate interactive map").option("--path <path>","Path to Rails application").option("-o, --output <path>","Output HTML file path").action(async e=>{console.log(s.blue.bold(`
|
|
56
|
+
\u{1F6E4}\uFE0F Repomap Rails
|
|
57
|
+
`));try{let t=e.path||process.cwd();try{await n.access(p.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-CAQZUBI6.js'),o=e.output||p.join(t,"rails-map.html");await new a(t).generate({title:`${p.basename(t)} - Rails Map`,outputPath:o}),console.log(s.green(`\u2705 Rails map generated: ${o}`));let{exec:r}=await import('child_process');r(`open "${o}"`);}catch(t){console.error(s.red("Error:"),t.message),process.exit(1);}});d.command("diff").description("Show documentation changes since last generation").option("-c, --config <path>","Path to config file").action(async e=>{console.log(s.blue.bold(`
|
|
74
58
|
\u{1F4CA} Documentation Diff
|
|
75
|
-
`));try{let
|
|
76
|
-
\u{1F504} Change detected: ${i.filename}`)),await e.generate();},
|
|
77
|
-
\
|
|
78
|
-
`));for(let
|
|
79
|
-
`));for(let a of
|
|
59
|
+
`));try{let t=process.cwd(),a$1=await P(e.config,t),o=p.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();F(r,l);}catch(t){console.error(s.red("Failed to generate diff:"),t.message);}});async function G(e,t){await e.generate();let a=t.repositories.map(o=>o.path);for(let o of a){let c=n.watch(o,{recursive:true}),r=null;for await(let i of c)i.filename&&(i.filename.endsWith(".ts")||i.filename.endsWith(".tsx"))&&(r&&clearTimeout(r),r=setTimeout(async()=>{console.log(s.yellow(`
|
|
60
|
+
\u{1F504} Change detected: ${i.filename}`)),await e.generate();},t.watch.debounce));}}function E(e){console.log(s.green.bold(`
|
|
61
|
+
\u2705 Complete
|
|
62
|
+
`));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 F(e,t){console.log(s.cyan(`Changes detected:
|
|
63
|
+
`));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 c=a.summary.totalPages-o.summary.totalPages,r=a.summary.totalComponents-o.summary.totalComponents,i=a.summary.totalGraphQLOperations-o.summary.totalGraphQLOperations;(c!==0||r!==0||i!==0)&&(console.log(s.yellow(` ~ ${a.displayName}:`)),c!==0&&console.log(` Pages: ${c>0?"+":""}${c}`),r!==0&&console.log(` Components: ${r>0?"+":""}${r}`),i!==0&&console.log(` GraphQL Ops: ${i>0?"+":""}${i}`));}}d.parse();
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import { RepositoryConfig, AnalysisResult } from './types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Base class for all analyzers
|
|
5
|
+
*/
|
|
6
|
+
declare abstract class BaseAnalyzer {
|
|
7
|
+
protected config: RepositoryConfig;
|
|
8
|
+
protected basePath: string;
|
|
9
|
+
constructor(config: RepositoryConfig);
|
|
10
|
+
/**
|
|
11
|
+
* Run the analysis
|
|
12
|
+
*/
|
|
13
|
+
abstract analyze(): Promise<Partial<AnalysisResult>>;
|
|
14
|
+
/**
|
|
15
|
+
* Get the analyzer name
|
|
16
|
+
*/
|
|
17
|
+
abstract getName(): string;
|
|
18
|
+
/**
|
|
19
|
+
* Resolve path relative to repository root
|
|
20
|
+
*/
|
|
21
|
+
protected resolvePath(relativePath: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Get setting value with fallback
|
|
24
|
+
*/
|
|
25
|
+
protected getSetting(key: string, defaultValue?: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Log analysis progress (silent by default, set REPOMAP_VERBOSE=1 to enable)
|
|
28
|
+
*/
|
|
29
|
+
protected log(_message: string): void;
|
|
30
|
+
/**
|
|
31
|
+
* Log warning (always shown)
|
|
32
|
+
*/
|
|
33
|
+
protected warn(message: string): void;
|
|
34
|
+
/**
|
|
35
|
+
* Log error (always shown)
|
|
36
|
+
*/
|
|
37
|
+
protected error(message: string, error?: Error): void;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Analyzer for Next.js/React pages using @swc/core for fast parsing
|
|
42
|
+
*/
|
|
43
|
+
declare class PagesAnalyzer extends BaseAnalyzer {
|
|
44
|
+
private codegenMap;
|
|
45
|
+
constructor(config: RepositoryConfig);
|
|
46
|
+
getName(): string;
|
|
47
|
+
analyze(): Promise<Partial<AnalysisResult>>;
|
|
48
|
+
/**
|
|
49
|
+
* Load GraphQL Code Generator mapping from __generated__ files
|
|
50
|
+
* Dynamically searches for codegen output files
|
|
51
|
+
*/
|
|
52
|
+
private loadCodegenMapping;
|
|
53
|
+
/**
|
|
54
|
+
* Analyze a single page file using SWC
|
|
55
|
+
*/
|
|
56
|
+
private analyzePageFile;
|
|
57
|
+
/**
|
|
58
|
+
* Find page files from multiple possible locations
|
|
59
|
+
*/
|
|
60
|
+
private findPageFiles;
|
|
61
|
+
/**
|
|
62
|
+
* Find routes from SPA (react-router-dom) based projects
|
|
63
|
+
*/
|
|
64
|
+
private findSPARoutes;
|
|
65
|
+
/**
|
|
66
|
+
* Resolve import path to absolute file path
|
|
67
|
+
*/
|
|
68
|
+
private resolveImportPath;
|
|
69
|
+
/**
|
|
70
|
+
* Detect the pages root directory from a file path
|
|
71
|
+
*/
|
|
72
|
+
private detectPagesRoot;
|
|
73
|
+
private filePathToRoutePath;
|
|
74
|
+
private extractRouteParams;
|
|
75
|
+
/**
|
|
76
|
+
* Find page component name from AST
|
|
77
|
+
*/
|
|
78
|
+
private findPageComponent;
|
|
79
|
+
/**
|
|
80
|
+
* Find the main component used in the page's JSX
|
|
81
|
+
* This is more accurate than using the default export name like "Page"
|
|
82
|
+
*/
|
|
83
|
+
private findMainJsxComponent;
|
|
84
|
+
/**
|
|
85
|
+
* Extract imports from AST
|
|
86
|
+
*/
|
|
87
|
+
private extractImports;
|
|
88
|
+
/**
|
|
89
|
+
* Extract layout from page
|
|
90
|
+
*/
|
|
91
|
+
private extractLayout;
|
|
92
|
+
/**
|
|
93
|
+
* Extract authentication requirements
|
|
94
|
+
*/
|
|
95
|
+
private extractAuthRequirement;
|
|
96
|
+
/**
|
|
97
|
+
* Extract roles from content
|
|
98
|
+
*/
|
|
99
|
+
private extractRolesFromContent;
|
|
100
|
+
/**
|
|
101
|
+
* Extract permissions from content
|
|
102
|
+
*/
|
|
103
|
+
private extractPermissions;
|
|
104
|
+
/**
|
|
105
|
+
* Extract data fetching operations using unified GraphQL context extraction
|
|
106
|
+
* Uses shared utilities for consistent operation name resolution
|
|
107
|
+
*/
|
|
108
|
+
private extractDataFetching;
|
|
109
|
+
/**
|
|
110
|
+
* Analyze Apollo client direct calls: client.query({ query: MyQuery })
|
|
111
|
+
*/
|
|
112
|
+
private analyzeClientDirectCall;
|
|
113
|
+
/**
|
|
114
|
+
* Extract Document imports from AST
|
|
115
|
+
* Tracks imports like: import { GetUserDocument } from '__generated__/graphql'
|
|
116
|
+
*/
|
|
117
|
+
private extractDocumentImports;
|
|
118
|
+
/**
|
|
119
|
+
* Extract variable assignments that reference Documents or gql() calls
|
|
120
|
+
* Tracks: const doc = GetUserDocument
|
|
121
|
+
* Tracks: const Query = gql(`query GetFollowPage { ... }`)
|
|
122
|
+
*/
|
|
123
|
+
private extractVariableAssignments;
|
|
124
|
+
/**
|
|
125
|
+
* Extract operation name from gql() function call
|
|
126
|
+
*/
|
|
127
|
+
private extractOperationNameFromGqlCall;
|
|
128
|
+
/**
|
|
129
|
+
* Analyze a GraphQL hook call expression
|
|
130
|
+
* Supports: useQuery, useMutation, useLazyQuery, useSuspenseQuery, etc.
|
|
131
|
+
*/
|
|
132
|
+
private analyzeGraphQLHookCall;
|
|
133
|
+
/**
|
|
134
|
+
* Extract type generic from hook call - useQuery<GetUserQuery>
|
|
135
|
+
*/
|
|
136
|
+
private extractTypeGeneric;
|
|
137
|
+
/**
|
|
138
|
+
* Extract operation name from function argument
|
|
139
|
+
* Supports: Identifier, MemberExpression, variable references, graphql() calls
|
|
140
|
+
*/
|
|
141
|
+
private extractOperationFromArgument;
|
|
142
|
+
/**
|
|
143
|
+
* Extract variables from hook call options
|
|
144
|
+
*/
|
|
145
|
+
private extractVariablesFromCall;
|
|
146
|
+
/**
|
|
147
|
+
* Extract SSR data fetching (getServerSideProps)
|
|
148
|
+
*/
|
|
149
|
+
private extractSSRDataFetching;
|
|
150
|
+
/**
|
|
151
|
+
* Extract SSR queries from a node (getServerSideProps body)
|
|
152
|
+
*/
|
|
153
|
+
private extractSSRQueriesFromNode;
|
|
154
|
+
/**
|
|
155
|
+
* Extract operation name from client.query({ query: ... }) call
|
|
156
|
+
*/
|
|
157
|
+
private extractQueryFromClientCall;
|
|
158
|
+
/**
|
|
159
|
+
* Extract navigation info
|
|
160
|
+
*/
|
|
161
|
+
private extractNavigation;
|
|
162
|
+
/**
|
|
163
|
+
* Extract linked pages from Link components
|
|
164
|
+
*/
|
|
165
|
+
private extractLinkedPages;
|
|
166
|
+
/**
|
|
167
|
+
* Extract steps from wizard/stepper patterns
|
|
168
|
+
*/
|
|
169
|
+
private extractSteps;
|
|
170
|
+
/**
|
|
171
|
+
* Traverse AST nodes recursively
|
|
172
|
+
*/
|
|
173
|
+
private traverseNode;
|
|
174
|
+
/**
|
|
175
|
+
* Get callee name from call expression
|
|
176
|
+
*/
|
|
177
|
+
private getCalleeName;
|
|
178
|
+
/**
|
|
179
|
+
* Get JSX tag name
|
|
180
|
+
*/
|
|
181
|
+
private getJsxTagName;
|
|
182
|
+
/**
|
|
183
|
+
* Get JSX attribute value
|
|
184
|
+
*/
|
|
185
|
+
private getJsxAttribute;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Analyzer for GraphQL operations
|
|
190
|
+
* Uses @swc/core for fast parsing
|
|
191
|
+
*/
|
|
192
|
+
declare class GraphQLAnalyzer extends BaseAnalyzer {
|
|
193
|
+
constructor(config: RepositoryConfig);
|
|
194
|
+
getName(): string;
|
|
195
|
+
analyze(): Promise<Partial<AnalysisResult>>;
|
|
196
|
+
/**
|
|
197
|
+
* Deduplicate operations by name, keeping the first occurrence
|
|
198
|
+
*/
|
|
199
|
+
private deduplicateOperations;
|
|
200
|
+
/**
|
|
201
|
+
* Analyze GraphQL Code Generator output files
|
|
202
|
+
* Supports multiple codegen patterns: client preset, near-operation-file, etc.
|
|
203
|
+
*/
|
|
204
|
+
private analyzeCodegenGenerated;
|
|
205
|
+
/**
|
|
206
|
+
* Extract type string from AST type node
|
|
207
|
+
*/
|
|
208
|
+
private extractTypeFromAst;
|
|
209
|
+
/**
|
|
210
|
+
* Extract fields from AST selection set
|
|
211
|
+
*/
|
|
212
|
+
private extractFieldsFromAst;
|
|
213
|
+
/**
|
|
214
|
+
* Extract fragment references from AST
|
|
215
|
+
*/
|
|
216
|
+
private extractFragmentReferencesFromAst;
|
|
217
|
+
/**
|
|
218
|
+
* Infer return type from AST definition
|
|
219
|
+
*/
|
|
220
|
+
private inferReturnTypeFromAst;
|
|
221
|
+
private analyzeGraphQLFiles;
|
|
222
|
+
private analyzeInlineGraphQL;
|
|
223
|
+
/**
|
|
224
|
+
* Analyze a parsed module for GraphQL operations
|
|
225
|
+
*/
|
|
226
|
+
private analyzeModuleForGraphQL;
|
|
227
|
+
/**
|
|
228
|
+
* Traverse AST nodes with variable context tracking
|
|
229
|
+
*/
|
|
230
|
+
private traverseNodeWithContext;
|
|
231
|
+
/**
|
|
232
|
+
* Get tag name from tagged template expression
|
|
233
|
+
*/
|
|
234
|
+
private getTagName;
|
|
235
|
+
/**
|
|
236
|
+
* Get callee name from call expression
|
|
237
|
+
*/
|
|
238
|
+
private getCalleeName;
|
|
239
|
+
/**
|
|
240
|
+
* Extract content from template literal
|
|
241
|
+
*/
|
|
242
|
+
private extractTemplateContent;
|
|
243
|
+
/**
|
|
244
|
+
* Extract GraphQL content from expression (handles various patterns)
|
|
245
|
+
*/
|
|
246
|
+
private extractGraphQLFromExpression;
|
|
247
|
+
private extractOperationsFromDocument;
|
|
248
|
+
private extractOperation;
|
|
249
|
+
private extractFields;
|
|
250
|
+
private extractVariables;
|
|
251
|
+
private typeNodeToString;
|
|
252
|
+
private extractFragmentReferences;
|
|
253
|
+
private inferReturnType;
|
|
254
|
+
private findOperationUsage;
|
|
255
|
+
/**
|
|
256
|
+
* Find operation usage using AST analysis for accurate type generic extraction
|
|
257
|
+
*/
|
|
258
|
+
private findUsageWithAST;
|
|
259
|
+
/**
|
|
260
|
+
* Traverse AST nodes for usage analysis
|
|
261
|
+
*/
|
|
262
|
+
private traverseNodeForUsage;
|
|
263
|
+
/**
|
|
264
|
+
* Get callee name for usage tracking
|
|
265
|
+
*/
|
|
266
|
+
private getCalleeNameForUsage;
|
|
267
|
+
/**
|
|
268
|
+
* Extract type generic from hook call
|
|
269
|
+
*/
|
|
270
|
+
private extractTypeGenericFromCall;
|
|
271
|
+
/**
|
|
272
|
+
* Extract first argument name from call
|
|
273
|
+
*/
|
|
274
|
+
private extractFirstArgName;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Analyzer for data flow patterns using @swc/core for fast parsing
|
|
279
|
+
*/
|
|
280
|
+
declare class DataFlowAnalyzer extends BaseAnalyzer {
|
|
281
|
+
private componentCache;
|
|
282
|
+
constructor(config: RepositoryConfig);
|
|
283
|
+
getName(): string;
|
|
284
|
+
analyze(): Promise<Partial<AnalysisResult>>;
|
|
285
|
+
private analyzeComponents;
|
|
286
|
+
private analyzeComponentFile;
|
|
287
|
+
private extractImports;
|
|
288
|
+
private isComponentName;
|
|
289
|
+
private extractComponentInfo;
|
|
290
|
+
/**
|
|
291
|
+
* Extract hooks used in component using AST-based analysis
|
|
292
|
+
* Uses parseSync for accurate detection instead of regex
|
|
293
|
+
*/
|
|
294
|
+
private extractHooksUsed;
|
|
295
|
+
/**
|
|
296
|
+
* Extract Document imports from AST for operation name resolution
|
|
297
|
+
*/
|
|
298
|
+
private extractDocumentImportsFromAst;
|
|
299
|
+
/**
|
|
300
|
+
* Extract variable -> operation name mapping from gql() calls
|
|
301
|
+
* e.g., const Query = gql(`query GetFollowPage { ... }`) -> { Query: "GetFollowPage" }
|
|
302
|
+
*/
|
|
303
|
+
private extractVariableOperationMap;
|
|
304
|
+
/**
|
|
305
|
+
* Extract operation name from gql() function call
|
|
306
|
+
*/
|
|
307
|
+
private extractOperationNameFromGqlCall;
|
|
308
|
+
/**
|
|
309
|
+
* Traverse AST to find hook calls
|
|
310
|
+
*/
|
|
311
|
+
private traverseForHooks;
|
|
312
|
+
/**
|
|
313
|
+
* Analyze a hook call expression
|
|
314
|
+
*/
|
|
315
|
+
private analyzeHookCall;
|
|
316
|
+
/**
|
|
317
|
+
* Check if a hook call has GraphQL-related arguments
|
|
318
|
+
* This verifies the hook is actually used for GraphQL, not just has a similar name
|
|
319
|
+
*/
|
|
320
|
+
private hasGraphQLArgument;
|
|
321
|
+
/**
|
|
322
|
+
* Get callee name from call expression node
|
|
323
|
+
*/
|
|
324
|
+
private getCalleeNameFromNode;
|
|
325
|
+
/**
|
|
326
|
+
* Extract operation name from hook call arguments and type generics
|
|
327
|
+
*/
|
|
328
|
+
private extractOperationNameFromCall;
|
|
329
|
+
/**
|
|
330
|
+
* Extract context name from useContext call
|
|
331
|
+
*/
|
|
332
|
+
private extractContextName;
|
|
333
|
+
/**
|
|
334
|
+
* Fallback regex-based hook extraction
|
|
335
|
+
*/
|
|
336
|
+
private extractHooksWithRegex;
|
|
337
|
+
private extractStateManagement;
|
|
338
|
+
private buildDependencyGraph;
|
|
339
|
+
private analyzeDataFlows;
|
|
340
|
+
private analyzeContextFlows;
|
|
341
|
+
private analyzeApolloFlows;
|
|
342
|
+
private analyzePropDrilling;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export { BaseAnalyzer as B, DataFlowAnalyzer as D, GraphQLAnalyzer as G, PagesAnalyzer as P };
|