@didnhdj/fnmap 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +62 -31
- package/dist/main.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
3
|
-
`)}let xe=!0,ve=null;const x={error:e=>{xe||console.error(`${y.red}✗${y.reset} ${e}`)},success:e=>{xe||console.log(`${y.green}✓${y.reset} ${e}`)},info:e=>{xe||console.log(e)},warn:e=>{xe||console.warn(`${y.yellow}!${y.reset} ${e}`)},title:e=>{xe||console.log(`${y.bold}${e}${y.reset}`)},stats:e=>{console.log(e)}};function Se(e){xe=e}function Fe(){return xe}function
|
|
2
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const b=require("fs"),E=require("path"),ut=require("commander"),_e=require("child_process"),gt=require("@babel/parser"),je=require("@babel/traverse"),yt=require("node:readline"),ht=require("os");function $t(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const n in e)if(n!=="default"){const s=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,s.get?s:{enumerable:!0,get:()=>e[n]})}}return t.default=e,Object.freeze(t)}const Ze=$t(yt),U={FILE_NOT_FOUND:"FILE_NOT_FOUND",FILE_READ_ERROR:"FILE_READ_ERROR",PARSE_ERROR:"PARSE_ERROR",CONFIG_ERROR:"CONFIG_ERROR",VALIDATION_ERROR:"VALIDATION_ERROR",PERMISSION_ERROR:"PERMISSION_ERROR",FILE_TOO_LARGE:"FILE_TOO_LARGE"};function Ke(e){return"parseError"in e}function Et(e){return e.success===!0}function St(e){return e.success===!1}function Rt(e){return e.valid===!0}function xt(e){return e.valid===!1}const y={reset:"\x1B[0m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",gray:"\x1B[90m",bold:"\x1B[1m"},Me=10*1024*1024,Ue=50,Le=[".js",".ts",".jsx",".tsx",".mjs",".vue",".svelte"],Ve=["node_modules",".git","dist","build",".next","coverage","__pycache__",".cache"],Ge={enable:!0,include:["**/*.js","**/*.ts","**/*.jsx","**/*.tsx","**/*.mjs","**/*.vue","**/*.svelte"],exclude:[]};function Ae(e){if(!e)return e;const t=e.replace(/\\/g,"/");return E.normalize(t)}function Ct(e){return e.map(Ae)}function et(e){if(!e||typeof e!="string")return{valid:!1,error:"File path is required and must be a string / 文件路径必须是字符串",errorType:U.VALIDATION_ERROR};if(!b.existsSync(e))return{valid:!1,error:`File not found: ${e} / 文件不存在: ${e}`,errorType:U.FILE_NOT_FOUND};try{const t=b.statSync(e);if(!t.isFile())return{valid:!1,error:`Path is not a file: ${e} / 路径不是文件: ${e}`,errorType:U.VALIDATION_ERROR};if(t.size>Me)return{valid:!1,error:`File too large (${(t.size/1024/1024).toFixed(2)}MB > ${Me/1024/1024}MB): ${e} / 文件过大`,errorType:U.FILE_TOO_LARGE}}catch(t){return{valid:!1,error:`Cannot access file: ${e}. Reason: ${t.message} / 无法访问文件`,errorType:U.PERMISSION_ERROR}}return{valid:!0}}function qe(e){if(!e||typeof e!="object")return{valid:!1,error:"Config must be an object / 配置必须是对象"};const t=e;return t.enable!==void 0&&typeof t.enable!="boolean"?{valid:!1,error:"Config.enable must be a boolean / enable 字段必须是布尔值"}:t.include!==void 0&&!Array.isArray(t.include)?{valid:!1,error:"Config.include must be an array / include 字段必须是数组"}:t.exclude!==void 0&&!Array.isArray(t.exclude)?{valid:!1,error:"Config.exclude must be an array / exclude 字段必须是数组"}:{valid:!0}}function be(e,t,n={}){const s=[t];return n.file&&s.push(`File: ${n.file}`),n.line!==void 0&&n.column!==void 0&&s.push(`Location: Line ${n.line}, Column ${n.column}`),n.suggestion&&s.push(`Suggestion: ${n.suggestion}`),s.join(`
|
|
3
|
+
`)}let xe=!0,ve=null;const x={error:e=>{xe||console.error(`${y.red}✗${y.reset} ${e}`)},success:e=>{xe||console.log(`${y.green}✓${y.reset} ${e}`)},info:e=>{xe||console.log(e)},warn:e=>{xe||console.warn(`${y.yellow}!${y.reset} ${e}`)},title:e=>{xe||console.log(`${y.bold}${e}${y.reset}`)},stats:e=>{console.log(e)}};function Se(e){xe=e}function Fe(){return xe}function tt(){try{let e;try{e=require("../../package.json")}catch{e=require("../package.json")}return e.version}catch{return"0.1.0"}}function He(){return ve=new ut.Command,ve.name("fnmap").description("AI code indexing tool - Analyzes JS/TS code structure and generates structured code maps").version(tt(),"-v, --version","Show version number").option("-f, --files <files>","Process specified files (comma-separated)",e=>e.split(",").map(t=>Ae(t.trim())).filter(Boolean)).option("-d, --dir <dir>","Process all code files in directory",e=>Ae(e)).option("-p, --project <dir>","Specify project root directory (default: current directory)",e=>Ae(e),process.env.CLAUDE_PROJECT_DIR??process.cwd()).option("-c, --changed","Process only git changed files (staged + modified + untracked)").option("-s, --staged","Process only git staged files (for pre-commit hook)").option("--merge","Merge all files in same directory into one .fnmap (default: per-file)").option("-m, --mermaid [mode]","Generate Mermaid call graph (file=file-level, project=project-level)").option("-l, --log","Show detailed processing logs").option("--init","Create default config file and setup project (interactive)").option("--clear","Clear generated files (.fnmap, *.fnmap, *.mermaid)").option("--hooks","Setup Claude Code hooks for auto quality checks").argument("[files...]","Directly specify file paths").allowUnknownOption(!1).addHelpText("after",`
|
|
4
4
|
Configuration files (by priority):
|
|
5
5
|
.fnmaprc JSON config file
|
|
6
6
|
.fnmaprc.json JSON config file
|
|
@@ -25,16 +25,16 @@ Examples:
|
|
|
25
25
|
$ fnmap --merge --dir src Merge into one .fnmap per directory
|
|
26
26
|
$ fnmap --clear --dir src Clear generated files in src directory
|
|
27
27
|
$ fnmap --hooks Setup Claude Code hooks
|
|
28
|
-
`),ve}function Te(){return ve||
|
|
28
|
+
`),ve}function Te(){return ve||He()}const At={get opts(){return Te().opts.bind(Te())},get args(){return Te().args},get parse(){return Te().parse.bind(Te())}};function nt(e){const t=[".fnmaprc",".fnmaprc.json"];for(const s of t){const i=E.join(e,s);if(b.existsSync(i))try{const f=b.readFileSync(i,"utf-8");if(!f.trim()){x.warn(`Config file is empty: ${s}. Using default config / 配置文件为空,使用默认配置`);continue}let $;try{$=JSON.parse(f)}catch(m){const g=m,o=be(U.CONFIG_ERROR,`Failed to parse config file: ${s} / 配置文件解析失败`,{file:i,line:g.lineNumber,column:g.columnNumber,suggestion:"Check JSON syntax, ensure proper quotes and commas / 检查 JSON 语法,确保引号和逗号正确"});x.warn(o);continue}const c=qe($);if(!c.valid){x.warn(`Invalid config in ${s}: ${c.error}`);continue}return{config:$,source:s}}catch(f){const $=f,c=be(U.FILE_READ_ERROR,`Failed to read config file: ${s} / 配置文件读取失败`,{file:i,suggestion:$.message});x.warn(c)}}const n=E.join(e,"package.json");if(b.existsSync(n))try{const s=JSON.parse(b.readFileSync(n,"utf-8"));if(s.fnmap){const i=qe(s.fnmap);if(!i.valid)x.warn(`Invalid fnmap config in package.json: ${i.error}`);else return{config:s.fnmap,source:"package.json#fnmap"}}}catch{}return{config:null,source:null}}function st(e){return e?{...Ge,...e,exclude:[...e.exclude??[]]}:Ge}function Je(e){return e.endsWith(".d.ts")||e.endsWith(".d.tsx")||e.endsWith(".d.mts")}function bt(e){try{return _e.execSync("git rev-parse --show-toplevel",{cwd:e,encoding:"utf-8"}).trim()}catch{return null}}function ot(e,t=!1){const n=[];try{const s=bt(e);if(!s)return[];let i;if(t)i=_e.execSync("git diff --cached --name-only --diff-filter=ACMR",{cwd:e,encoding:"utf-8"});else{const c=_e.execSync("git diff --cached --name-only --diff-filter=ACMR",{cwd:e,encoding:"utf-8"}),m=_e.execSync("git diff --name-only --diff-filter=ACMR",{cwd:e,encoding:"utf-8"}),g=_e.execSync("git ls-files --others --exclude-standard",{cwd:e,encoding:"utf-8"});i=`${c}
|
|
29
29
|
${m}
|
|
30
30
|
${g}`}const f=i.split(`
|
|
31
|
-
`).map(c=>c.trim()).filter(Boolean).filter(c=>{const m
|
|
32
|
-
`).map(s=>s.replace(/^\s*\*\s?/,"").trim());for(const s of n)if(s.startsWith("@description "))return s.slice(13).trim().slice(0,60);for(const s of n)if(s&&!s.startsWith("@")&&!s.startsWith("/"))return s.slice(0,60);return""}function Ce(e,t){if(e.leadingComments&&e.leadingComments.length>0)return e.leadingComments[e.leadingComments.length-1]??null;if(t&&(t.type==="ExportNamedDeclaration"||t.type==="ExportDefaultDeclaration")){const n=t;if(n.leadingComments&&n.leadingComments.length>0)return n.leadingComments[n.leadingComments.length-1]??null}return null}let we=null;function
|
|
33
|
-
`).map(a=>a.replace(/^\s*\*\s?/,"").trim()).filter(a=>a&&!a.startsWith("/")&&!a.startsWith("@ai"));for(const a of r)if(a.startsWith("@description ")){n.description=a.slice(13).trim();break}if(!n.description&&r.length>0){const a=r.find(u=>!u.startsWith("@"));a&&(n.description=a)}}const i=t==null?void 0:t.endsWith(".vue"),f=t==null?void 0:t.endsWith(".svelte");let E=e,c="";if(i||f){const d=i?It(E):Tt(E);if(!d)return{parseError:Ae(U.PARSE_ERROR,`Failed to extract script from ${i?"Vue":"Svelte"} SFC / 无法从 SFC 提取 script`,{file:t??void 0}),errorType:U.PARSE_ERROR};E=d.code,c=d.lang}let m;try{const d=t&&(t.endsWith(".ts")||t.endsWith(".tsx")||c==="ts");m=mt.parse(E,{sourceType:"unambiguous",plugins:["jsx","classPrivateProperties","classPrivateMethods",...d?["typescript"]:[]]})}catch(d){const r=d;return{parseError:Ae(U.PARSE_ERROR,`Syntax error: ${r.message} / 语法错误`,{file:t??void 0,line:(G=r.loc)==null?void 0:G.line,column:(H=r.loc)==null?void 0:H.column,suggestion:"Check syntax errors in the file / 检查文件中的语法错误"}),loc:r.loc,errorType:U.PARSE_ERROR}}const g=new Map,o=new Map,p=new Map;function l(d){if(!d)return null;if(d.type==="Identifier")return d.name;if(d.type==="MemberExpression"){const r=d.object,a=d.property;if(r.type==="Identifier"&&a.type==="Identifier")return r.name}return null}function b(d){var a,u,C;let r=d;for(;r;){if(r.node.type==="FunctionDeclaration"){const S=r.node;if(S.id)return S.id.name}if(r.node.type==="ClassMethod"){const S=r.node,h=(a=r.parentPath)==null?void 0:a.parentPath,I=h==null?void 0:h.node,F=((u=I==null?void 0:I.id)==null?void 0:u.name)??"",w=((C=S.key)==null?void 0:C.name)??"";return F?`${F}.${w}`:w}if(r.node.type==="ArrowFunctionExpression"||r.node.type==="FunctionExpression"){const S=r.parent;if((S==null?void 0:S.type)==="VariableDeclarator"){const I=S.id;if(I!=null&&I.name)return I.name}}r=r.parentPath}return null}ke(m,{VariableDeclarator(d){var a,u,C,S;const r=d.node;if(((a=r.init)==null?void 0:a.type)==="CallExpression"&&((u=r.init.callee)==null?void 0:u.type)==="Identifier"&&r.init.callee.name==="require"&&((S=(C=r.init.arguments)==null?void 0:C[0])==null?void 0:S.type)==="StringLiteral"){const h=r.init.arguments[0].value;if(g.has(h)||g.set(h,new Set),r.id.type==="Identifier"){const I=r.id.name;g.get(h).add(I),o.set(I,h),p.set(I,new Set)}else if(r.id.type==="ObjectPattern"){for(const I of r.id.properties)if(I.type==="ObjectProperty"&&I.key.type==="Identifier"){const F=I.value.type==="Identifier"?I.value.name:I.key.name;g.get(h).add(I.key.name),o.set(F,h),p.set(F,new Set)}}}},CallExpression(d){var a,u,C,S,h,I;const r=d.node;if(((a=r.callee)==null?void 0:a.type)==="Identifier"&&r.callee.name==="require"&&((C=(u=r.arguments)==null?void 0:u[0])==null?void 0:C.type)==="StringLiteral"){const F=d.parent;if((F==null?void 0:F.type)==="MemberExpression"&&((S=F.property)==null?void 0:S.type)==="Identifier"){const w=r.arguments[0].value;g.has(w)||g.set(w,new Set),g.get(w).add(F.property.name);const q=(h=d.parentPath)==null?void 0:h.parent;if((q==null?void 0:q.type)==="VariableDeclarator"){const B=q;((I=B.id)==null?void 0:I.type)==="Identifier"&&(o.set(B.id.name,w),p.set(B.id.name,new Set))}}}},ImportDeclaration(d){const r=d.node,a=r.source.value;g.has(a)||g.set(a,new Set);for(const u of r.specifiers){let C,S;if(u.type==="ImportDefaultSpecifier")C="default",S=u.local.name;else if(u.type==="ImportNamespaceSpecifier")C="*",S=u.local.name;else if(u.type==="ImportSpecifier"){const h=u.imported;C=h.type==="Identifier"?h.name:h.value,S=u.local.name}C&&S&&(g.get(a).add(C),o.set(S,a),p.set(S,new Set))}}}),ke(m,{Identifier(d){const r=d.node.name;if(p.has(r)){const a=d.parent;if((a==null?void 0:a.type)==="VariableDeclarator"&&a.id===d.node||(a==null?void 0:a.type)==="ImportSpecifier"||(a==null?void 0:a.type)==="ImportDefaultSpecifier")return;const u=b(d);u&&p.get(r).add(u)}},FunctionDeclaration(d){var I,F,w,q,B;if(d.parent.type==="ExportDefaultDeclaration")return;const r=d.node,a=((I=r.id)==null?void 0:I.name)??"[anonymous]",u=r.params.map(M=>{var Y,Z;return M.type==="Identifier"?M.name:M.type==="AssignmentPattern"&&((Y=M.left)==null?void 0:Y.type)==="Identifier"?M.left.name+"?":M.type==="RestElement"&&((Z=M.argument)==null?void 0:Z.type)==="Identifier"?"..."+M.argument.name:"?"}),C=((w=(F=r.loc)==null?void 0:F.start)==null?void 0:w.line)??0,S=((B=(q=r.loc)==null?void 0:q.end)==null?void 0:B.line)??0,h=oe(Ce(r,d.parent));n.functions.push({name:a,params:u.join(","),startLine:C,endLine:S,description:h})},ClassDeclaration(d){var F,w,q,B,M,Y,Z,re,ie;if(d.parent.type==="ExportDefaultDeclaration")return;const r=d.node,a=((F=r.id)==null?void 0:F.name)??"[anonymous]",u=((q=(w=r.loc)==null?void 0:w.start)==null?void 0:q.line)??0,C=((M=(B=r.loc)==null?void 0:B.end)==null?void 0:M.line)??0,S=l(r.superClass),h=oe(Ce(r,d.parent)),I=[];if((Y=r.body)!=null&&Y.body){for(const V of r.body.body)if(V.type==="ClassMethod"){const le=((Z=V.key)==null?void 0:Z.type)==="Identifier"?V.key.name:"[computed]",fe=V.params.map(ee=>{var ce;return ee.type==="Identifier"?ee.name:ee.type==="AssignmentPattern"&&((ce=ee.left)==null?void 0:ce.type)==="Identifier"?ee.left.name+"?":"?"}),de=((ie=(re=V.loc)==null?void 0:re.start)==null?void 0:ie.line)??0;let ae="";const te=V.leadingComments;te&&te.length>0&&(ae=oe(te[te.length-1])),I.push({name:le,params:fe.join(","),line:de,static:V.static,kind:V.kind,description:ae})}}n.classes.push({name:a,superClass:S,startLine:u,endLine:C,methods:I,description:h})},VariableDeclaration(d){var C,S,h,I,F,w,q,B,M,Y,Z,re,ie,V,le,fe,de,ae,te,ee,ce,me,ue,ge,ye,he,$e,pe,J,L,X,z,Q;const r=d.parent.type;if(r!=="Program"&&r!=="ExportNamedDeclaration")return;const a=d.node,u=oe(Ce(a,d.parent));for(const k of a.declarations){const R=((C=k.id)==null?void 0:C.type)==="Identifier"?k.id.name:void 0;if(R){if(((S=k.init)==null?void 0:S.type)==="ArrowFunctionExpression"||((h=k.init)==null?void 0:h.type)==="FunctionExpression"){const T=k.init.params.map(D=>{var j,P;return D.type==="Identifier"?D.name:D.type==="AssignmentPattern"&&((j=D.left)==null?void 0:j.type)==="Identifier"?D.left.name+"?":D.type==="RestElement"&&((P=D.argument)==null?void 0:P.type)==="Identifier"?"..."+D.argument.name:"?"}),ne=((F=(I=a.loc)==null?void 0:I.start)==null?void 0:F.line)??0,K=((q=(w=a.loc)==null?void 0:w.end)==null?void 0:q.line)??0;n.functions.push({name:R,params:T.join(","),startLine:ne,endLine:K,description:u});continue}if(((B=k.init)==null?void 0:B.type)==="ClassExpression"){const O=k.init,T=((Y=(M=a.loc)==null?void 0:M.start)==null?void 0:Y.line)??0,ne=((re=(Z=a.loc)==null?void 0:Z.end)==null?void 0:re.line)??0,K=l(O.superClass),D=[];if((ie=O.body)!=null&&ie.body){for(const j of O.body.body)if(j.type==="ClassMethod"){const P=((V=j.key)==null?void 0:V.type)==="Identifier"?j.key.name:"[computed]",W=j.params.map(Ie=>{var ze;return Ie.type==="Identifier"?Ie.name:Ie.type==="AssignmentPattern"&&((ze=Ie.left)==null?void 0:ze.type)==="Identifier"?Ie.left.name+"?":"?"}),se=((fe=(le=j.loc)==null?void 0:le.start)==null?void 0:fe.line)??0;let Ee="";const Re=j.leadingComments;Re&&Re.length>0&&(Ee=oe(Re[Re.length-1])),D.push({name:P,params:W.join(","),line:se,static:j.static,kind:j.kind,description:Ee})}}n.classes.push({name:R,superClass:K,startLine:T,endLine:ne,methods:D,description:u});continue}if(((de=k.init)==null?void 0:de.type)==="ObjectExpression"){const O=k.init;for(const T of O.properties)if(T.type==="ObjectMethod"){const ne=((ae=T.key)==null?void 0:ae.type)==="Identifier"?`${R}.${T.key.name}`:`${R}.[computed]`,K=T.params.map(W=>{var se,Ee;return W.type==="Identifier"?W.name:W.type==="AssignmentPattern"&&((se=W.left)==null?void 0:se.type)==="Identifier"?W.left.name+"?":W.type==="RestElement"&&((Ee=W.argument)==null?void 0:Ee.type)==="Identifier"?"..."+W.argument.name:"?"}),D=((ee=(te=T.loc)==null?void 0:te.start)==null?void 0:ee.line)??0,j=((me=(ce=T.loc)==null?void 0:ce.end)==null?void 0:me.line)??0;let P="";T.leadingComments&&T.leadingComments.length>0&&(P=oe(T.leadingComments[T.leadingComments.length-1])),n.functions.push({name:ne,params:K.join(","),startLine:D,endLine:j,description:P})}else if(T.type==="ObjectProperty"&&((ue=T.key)==null?void 0:ue.type)==="Identifier"&&(((ge=T.value)==null?void 0:ge.type)==="ArrowFunctionExpression"||((ye=T.value)==null?void 0:ye.type)==="FunctionExpression")){const ne=T.value,K=`${R}.${T.key.name}`,D=ne.params.map(se=>{var Ee,Re;return se.type==="Identifier"?se.name:se.type==="AssignmentPattern"&&((Ee=se.left)==null?void 0:Ee.type)==="Identifier"?se.left.name+"?":se.type==="RestElement"&&((Re=se.argument)==null?void 0:Re.type)==="Identifier"?"..."+se.argument.name:"?"}),j=(($e=(he=T.loc)==null?void 0:he.start)==null?void 0:$e.line)??0,P=((J=(pe=T.loc)==null?void 0:pe.end)==null?void 0:J.line)??0;let W="";T.leadingComments&&T.leadingComments.length>0&&(W=oe(T.leadingComments[T.leadingComments.length-1])),n.functions.push({name:K,params:D.join(","),startLine:j,endLine:P,description:W})}}if(a.kind==="const"&&!(((L=k.init)==null?void 0:L.type)==="CallExpression"&&((X=k.init.callee)==null?void 0:X.type)==="Identifier"&&k.init.callee.name==="require")){const T=((Q=(z=a.loc)==null?void 0:z.start)==null?void 0:Q.line)??0;n.constants.push({name:R,line:T,description:u})}}}},ExportDefaultDeclaration(d){var C,S,h,I,F,w,q,B,M,Y,Z,re,ie,V,le,fe,de,ae,te,ee,ce,me,ue,ge,ye,he,$e,pe,J;const r=d.node,a=r.declaration,u=oe(Ce(r,d.parent));if(a.type==="FunctionDeclaration"){const L=a,X=((C=L.id)==null?void 0:C.name)??"[default]",z=L.params.map(R=>{var O,T;return R.type==="Identifier"?R.name:R.type==="AssignmentPattern"&&((O=R.left)==null?void 0:O.type)==="Identifier"?R.left.name+"?":R.type==="RestElement"&&((T=R.argument)==null?void 0:T.type)==="Identifier"?"..."+R.argument.name:"?"}),Q=((h=(S=r.loc)==null?void 0:S.start)==null?void 0:h.line)??0,k=((F=(I=r.loc)==null?void 0:I.end)==null?void 0:F.line)??0;n.functions.push({name:X,params:z.join(","),startLine:Q,endLine:k,description:u});return}if(a.type==="ClassDeclaration"){const L=a,X=((w=L.id)==null?void 0:w.name)??"[default]",z=((B=(q=r.loc)==null?void 0:q.start)==null?void 0:B.line)??0,Q=((Y=(M=r.loc)==null?void 0:M.end)==null?void 0:Y.line)??0,k=l(L.superClass),R=[];if((Z=L.body)!=null&&Z.body){for(const O of L.body.body)if(O.type==="ClassMethod"){const T=((re=O.key)==null?void 0:re.type)==="Identifier"?O.key.name:"[computed]",ne=O.params.map(P=>{var W;return P.type==="Identifier"?P.name:P.type==="AssignmentPattern"&&((W=P.left)==null?void 0:W.type)==="Identifier"?P.left.name+"?":"?"}),K=((V=(ie=O.loc)==null?void 0:ie.start)==null?void 0:V.line)??0;let D="";const j=O.leadingComments;j&&j.length>0&&(D=oe(j[j.length-1])),R.push({name:T,params:ne.join(","),line:K,static:O.static,kind:O.kind,description:D})}}n.classes.push({name:X,superClass:k,startLine:z,endLine:Q,methods:R,description:u});return}if(a.type==="ArrowFunctionExpression"||a.type==="FunctionExpression"){const L=a,X=L.type==="FunctionExpression"&&((le=L.id)!=null&&le.name)?L.id.name:"[default]",z=L.params.map(R=>{var O,T;return R.type==="Identifier"?R.name:R.type==="AssignmentPattern"&&((O=R.left)==null?void 0:O.type)==="Identifier"?R.left.name+"?":R.type==="RestElement"&&((T=R.argument)==null?void 0:T.type)==="Identifier"?"..."+R.argument.name:"?"}),Q=((de=(fe=r.loc)==null?void 0:fe.start)==null?void 0:de.line)??0,k=((te=(ae=r.loc)==null?void 0:ae.end)==null?void 0:te.line)??0;n.functions.push({name:X,params:z.join(","),startLine:Q,endLine:k,description:u});return}if(a.type==="ClassExpression"){const L=a,X=((ee=L.id)==null?void 0:ee.name)??"[default]",z=((me=(ce=r.loc)==null?void 0:ce.start)==null?void 0:me.line)??0,Q=((ge=(ue=r.loc)==null?void 0:ue.end)==null?void 0:ge.line)??0,k=((ye=L.superClass)==null?void 0:ye.type)==="Identifier"?L.superClass.name:null,R=[];if((he=L.body)!=null&&he.body){for(const O of L.body.body)if(O.type==="ClassMethod"){const T=(($e=O.key)==null?void 0:$e.type)==="Identifier"?O.key.name:"[computed]",ne=O.params.map(P=>{var W;return P.type==="Identifier"?P.name:P.type==="AssignmentPattern"&&((W=P.left)==null?void 0:W.type)==="Identifier"?P.left.name+"?":"?"}),K=((J=(pe=O.loc)==null?void 0:pe.start)==null?void 0:J.line)??0;let D="";const j=O.leadingComments;j&&j.length>0&&(D=oe(j[j.length-1])),R.push({name:T,params:ne.join(","),line:K,static:O.static,kind:O.kind,description:D})}}n.classes.push({name:X,superClass:k,startLine:z,endLine:Q,methods:R,description:u})}},AssignmentExpression(d){var S,h,I,F,w,q,B,M,Y,Z,re,ie,V,le,fe,de,ae,te,ee,ce,me,ue,ge,ye,he,$e;const r=d.node;if(d.parent.type!=="ExpressionStatement")return;const a=(S=d.parentPath)==null?void 0:S.parent;if((a==null?void 0:a.type)!=="Program")return;const u=r.left,C=r.right;if(u.type==="MemberExpression"&&((h=u.object)==null?void 0:h.type)==="Identifier"&&u.object.name==="module"&&((I=u.property)==null?void 0:I.type)==="Identifier"&&u.property.name==="exports"){const pe=oe(Ce(d.parent,a));if(C.type==="FunctionExpression"||C.type==="ArrowFunctionExpression"){const J=C,L=C.type==="FunctionExpression"&&((F=C.id)!=null&&F.name)?C.id.name:"[exports]",X=J.params.map(k=>{var R,O;return k.type==="Identifier"?k.name:k.type==="AssignmentPattern"&&((R=k.left)==null?void 0:R.type)==="Identifier"?k.left.name+"?":k.type==="RestElement"&&((O=k.argument)==null?void 0:O.type)==="Identifier"?"..."+k.argument.name:"?"}),z=((q=(w=r.loc)==null?void 0:w.start)==null?void 0:q.line)??0,Q=((M=(B=r.loc)==null?void 0:B.end)==null?void 0:M.line)??0;n.functions.push({name:L,params:X.join(","),startLine:z,endLine:Q,description:pe});return}if(C.type==="ClassExpression"){const J=C,L=((Y=J.id)==null?void 0:Y.name)??"[exports]",X=((re=(Z=r.loc)==null?void 0:Z.start)==null?void 0:re.line)??0,z=((V=(ie=r.loc)==null?void 0:ie.end)==null?void 0:V.line)??0,Q=l(J.superClass),k=[];if((le=J.body)!=null&&le.body){for(const R of J.body.body)if(R.type==="ClassMethod"){const O=((fe=R.key)==null?void 0:fe.type)==="Identifier"?R.key.name:"[computed]",T=R.params.map(K=>{var D;return K.type==="Identifier"?K.name:K.type==="AssignmentPattern"&&((D=K.left)==null?void 0:D.type)==="Identifier"?K.left.name+"?":"?"}),ne=((ae=(de=R.loc)==null?void 0:de.start)==null?void 0:ae.line)??0;k.push({name:O,params:T.join(","),line:ne,static:R.static,kind:R.kind,description:""})}}n.classes.push({name:L,superClass:Q,startLine:X,endLine:z,methods:k,description:pe});return}}if(u.type==="MemberExpression"&&((te=u.property)==null?void 0:te.type)==="Identifier"){const pe=u.property.name;let J=!1;if(((ee=u.object)==null?void 0:ee.type)==="Identifier"&&u.object.name==="exports"&&(J=!0),((ce=u.object)==null?void 0:ce.type)==="MemberExpression"&&((me=u.object.object)==null?void 0:me.type)==="Identifier"&&u.object.object.name==="module"&&((ue=u.object.property)==null?void 0:ue.type)==="Identifier"&&u.object.property.name==="exports"&&(J=!0),J){const L=oe(Ce(d.parent,a));if(C.type==="FunctionExpression"||C.type==="ArrowFunctionExpression"){const z=C.params.map(R=>{var O,T;return R.type==="Identifier"?R.name:R.type==="AssignmentPattern"&&((O=R.left)==null?void 0:O.type)==="Identifier"?R.left.name+"?":R.type==="RestElement"&&((T=R.argument)==null?void 0:T.type)==="Identifier"?"..."+R.argument.name:"?"}),Q=((ye=(ge=r.loc)==null?void 0:ge.start)==null?void 0:ye.line)??0,k=(($e=(he=r.loc)==null?void 0:he.end)==null?void 0:$e.line)??0;n.functions.push({name:pe,params:z.join(","),startLine:Q,endLine:k,description:L})}}}}});for(const[d,r]of g){const a=new Set;for(const u of o.keys())if(o.get(u)===d&&p.has(u))for(const C of p.get(u))a.add(C);n.imports.push({module:d,members:Array.from(r),usedIn:Array.from(a)})}const _=new Set;for(const d of n.functions)_.add(d.name);for(const d of n.classes)for(const r of d.methods)_.add(r.name),_.add(`${d.name}.${r.name}`);const v=new Set(o.keys()),N=new Map;ke(m,{CallExpression(d){var u,C;const r=d.node;let a=null;if(r.callee.type==="Identifier")a=r.callee.name;else if(r.callee.type==="MemberExpression"&&((u=r.callee.property)==null?void 0:u.type)==="Identifier"){const S=((C=r.callee.object)==null?void 0:C.type)==="Identifier"?r.callee.object.name:void 0,h=r.callee.property.name;S&&v.has(S)?a=`${S}.${h}`:a=h}if(a){const S=b(d);if(S&&S!==a){const h=_.has(a),I=v.has(a)||a.includes(".")&&v.has(a.split(".")[0]);(h||I)&&(N.has(S)||N.set(S,new Set),N.get(S).add(a))}}}}),n.callGraph={};for(const[d,r]of N)n.callGraph[d]=Array.from(r);return ke(m,{ExportNamedDeclaration(d){var C,S;const r=d.node,a=((S=(C=r.loc)==null?void 0:C.start)==null?void 0:S.line)??0,u=r.exportKind==="type";if(r.specifiers&&r.specifiers.length>0){for(const h of r.specifiers)if(h.type==="ExportSpecifier"){const I=h.exported.type==="Identifier"?h.exported.name:h.exported.value,F=h.local.name,w=u||h.exportKind==="type";n.exports.push({name:I,localName:F!==I?F:void 0,line:a,kind:w?"type":"value"})}return}if(r.declaration){const h=r.declaration;if(h.type==="FunctionDeclaration"&&h.id)n.exports.push({name:h.id.name,line:a,kind:"value"});else if(h.type==="ClassDeclaration"&&h.id)n.exports.push({name:h.id.name,line:a,kind:"value"});else if(h.type==="VariableDeclaration")for(const I of h.declarations)I.id.type==="Identifier"&&n.exports.push({name:I.id.name,line:a,kind:"value"});else(h.type==="TSTypeAliasDeclaration"||h.type==="TSInterfaceDeclaration")&&h.id&&n.exports.push({name:h.id.name,line:a,kind:"type"})}},ExportDefaultDeclaration(d){var S,h;const r=d.node,a=((h=(S=r.loc)==null?void 0:S.start)==null?void 0:h.line)??0,u=r.declaration;let C;u.type==="FunctionDeclaration"&&u.id||u.type==="ClassDeclaration"&&u.id?C=u.id.name:u.type==="Identifier"&&(C=u.name),n.exports.push({name:"default",localName:C,line:a,kind:"default"})}}),n.isPureType=Ot(m),n}function Ot(e){let t=!1;for(const n of e.program.body){switch(n.type){case"TSTypeAliasDeclaration":case"TSInterfaceDeclaration":case"TSEnumDeclaration":break;case"ImportDeclaration":n.importKind!=="type"&&n.specifiers.some(i=>i.type==="ImportSpecifier"?i.importKind!=="type":!0)&&n.specifiers.length>0&&(t=!0);break;case"ExportNamedDeclaration":if(n.exportKind==="type")break;if(n.declaration){const s=n.declaration.type;s!=="TSTypeAliasDeclaration"&&s!=="TSInterfaceDeclaration"&&(t=!0)}else n.specifiers&&n.specifiers.length>0&&n.specifiers.some(i=>i.type==="ExportSpecifier"?i.exportKind!=="type":!0)&&(t=!0);break;case"ExportDefaultDeclaration":t=!0;break;case"ExportAllDeclaration":n.exportKind!=="type"&&(t=!0);break;default:t=!0;break}if(t)break}return!t}function _t(e,t){const n=[];let s=`/*@AI ${t}`;e.description&&(s+=` - ${e.description.slice(0,50)}`),n.push(s);for(const i of e.imports){const f=Array.isArray(i.members)?i.members.join(","):"";let E=`<${i.module}:${f}`;Array.isArray(i.usedIn)&&i.usedIn.length>0&&(E+=` ->${i.usedIn.join(",")}`),n.push(E)}for(const i of e.classes){let f=i.name;i.superClass&&(f+=`:${i.superClass}`),f+=` ${i.startLine}-${i.endLine}`,i.description&&(f+=` ${i.description}`),n.push(f);for(const E of i.methods){const c=E.static?" +":" .",m=E.kind==="get"?"get:":E.kind==="set"?"set:":"";let g=`${c}${m}${E.name}(${E.params}) ${E.line}`;E.description&&(g+=` ${E.description}`),n.push(g)}}for(const i of e.functions){let f=`${i.name}(${i.params}) ${i.startLine}-${i.endLine}`;i.description&&(f+=` ${i.description}`),n.push(f)}for(const i of e.constants){let f=`${i.name} ${i.line}`;i.description&&(f+=` ${i.description}`),n.push(f)}return n.push("@AI*/"),n.join(`
|
|
34
|
-
`)}function
|
|
35
|
-
`)}function
|
|
36
|
-
`)}function
|
|
37
|
-
`)}function
|
|
31
|
+
`).map(c=>c.trim()).filter(Boolean).filter(c=>{const m=E.extname(c);return Le.includes(m)&&!Je(c)}),$=[...new Set(f)];for(const c of $){const m=E.resolve(s,c);b.existsSync(m)&&m.startsWith(E.resolve(e))&&n.push(m)}}catch{return[]}return n}function It(e){const t=[];if(!b.existsSync(e))return t;try{const n=b.readdirSync(e,{withFileTypes:!0});for(const s of n)if(s.isFile()){const i=E.extname(s.name);Le.includes(i)&&!Je(s.name)&&t.push(E.join(e,s.name))}}catch{return t}return t}function Ne(e,t=e,n=Ve,s=0,i=new Set){const f=[];if(!b.existsSync(e))return x.warn(`Directory does not exist: ${e} / 目录不存在`),f;if(s>Ue)return x.warn(`Max directory depth (${Ue}) exceeded: ${e} / 超过最大目录深度`),f;let $;try{$=b.realpathSync(e)}catch(m){const g=m;return x.warn(`Cannot resolve real path: ${e}. Reason: ${g.message} / 无法解析真实路径`),f}if(i.has($))return x.warn(`Circular reference detected, skipping: ${e} / 检测到循环引用`),f;i.add($);let c;try{c=b.readdirSync(e,{withFileTypes:!0})}catch(m){const g=m;return g.code==="EACCES"||g.code==="EPERM"?x.warn(`Permission denied: ${e} / 权限不足`):x.warn(`Failed to read directory: ${e}. Reason: ${g.message} / 读取目录失败`),f}for(const m of c)try{const g=E.join(e,m.name);if(m.isDirectory())n.includes(m.name)||f.push(...Ne(g,t,n,s+1,i));else if(m.isFile()){const o=E.extname(m.name);Le.includes(o)&&!Je(m.name)&&f.push(E.relative(t,g))}}catch(g){const o=g;x.warn(`Error processing entry: ${m.name}. Reason: ${o.message} / 处理条目出错`)}return f}function oe(e){if(!e)return"";const n=e.value.split(`
|
|
32
|
+
`).map(s=>s.replace(/^\s*\*\s?/,"").trim());for(const s of n)if(s.startsWith("@description "))return s.slice(13).trim().slice(0,60);for(const s of n)if(s&&!s.startsWith("@")&&!s.startsWith("/"))return s.slice(0,60);return""}function Ce(e,t){if(e.leadingComments&&e.leadingComments.length>0)return e.leadingComments[e.leadingComments.length-1]??null;if(t&&(t.type==="ExportNamedDeclaration"||t.type==="ExportDefaultDeclaration")){const n=t;if(n.leadingComments&&n.leadingComments.length>0)return n.leadingComments[n.leadingComments.length-1]??null}return null}let we=null;function Tt(){return we||(we=require("@vue/compiler-sfc")),we}const ke=typeof je=="function"?je:je.default;function Ot(e){const{descriptor:t,errors:n}=Tt().parse(e,{pad:"line"});if(n.length>0)return null;const s=t.scriptSetup??t.script;return s?{code:s.content,lang:s.lang??"js"}:null}function _t(e){const t=/<script(?:\s+[^>]*)?>(\s*[\s\S]*?)<\/script>/gi;let n=null,s;for(;(s=t.exec(e))!==null;){const i=s[0],f=s[1]??"",$=/context\s*=\s*["']module["']/.test(i)||/\bmodule\b/.test(i),m=i.match(/lang\s*=\s*["'](ts|typescript)["']/i)?"ts":"js";if(!$)return{code:f,lang:m};n||(n={code:f,lang:m})}return n}function ze(e,t){var G,H;if(e==null)return{parseError:"Code content is null or undefined / 代码内容为空",errorType:U.VALIDATION_ERROR};if(typeof e!="string")return{parseError:"Code must be a string / 代码必须是字符串类型",errorType:U.VALIDATION_ERROR};if(!e.trim())return{description:"",imports:[],functions:[],classes:[],constants:[],exports:[],callGraph:{}};const n={description:"",imports:[],functions:[],classes:[],constants:[],exports:[],callGraph:{}},s=e.match(/^\/\*\*[\s\S]*?\*\//);if(s){const r=s[0].split(`
|
|
33
|
+
`).map(a=>a.replace(/^\s*\*\s?/,"").trim()).filter(a=>a&&!a.startsWith("/")&&!a.startsWith("@ai"));for(const a of r)if(a.startsWith("@description ")){n.description=a.slice(13).trim();break}if(!n.description&&r.length>0){const a=r.find(u=>!u.startsWith("@"));a&&(n.description=a)}}const i=t==null?void 0:t.endsWith(".vue"),f=t==null?void 0:t.endsWith(".svelte");let $=e,c="";if(i||f){const d=i?Ot($):_t($);if(!d)return{parseError:be(U.PARSE_ERROR,`Failed to extract script from ${i?"Vue":"Svelte"} SFC / 无法从 SFC 提取 script`,{file:t??void 0}),errorType:U.PARSE_ERROR};$=d.code,c=d.lang}let m;try{const d=t&&(t.endsWith(".ts")||t.endsWith(".tsx")||c==="ts");m=gt.parse($,{sourceType:"unambiguous",plugins:["jsx","decorators-legacy","classPrivateProperties","classPrivateMethods",...d?["typescript"]:[]]})}catch(d){const r=d;return{parseError:be(U.PARSE_ERROR,`Syntax error: ${r.message} / 语法错误`,{file:t??void 0,line:(G=r.loc)==null?void 0:G.line,column:(H=r.loc)==null?void 0:H.column,suggestion:"Check syntax errors in the file / 检查文件中的语法错误"}),loc:r.loc,errorType:U.PARSE_ERROR}}const g=new Map,o=new Map,p=new Map;function l(d){if(!d)return null;if(d.type==="Identifier")return d.name;if(d.type==="MemberExpression"){const r=d.object,a=d.property;if(r.type==="Identifier"&&a.type==="Identifier")return r.name}return null}function A(d){var a,u,C;let r=d;for(;r;){if(r.node.type==="FunctionDeclaration"){const S=r.node;if(S.id)return S.id.name}if(r.node.type==="ClassMethod"){const S=r.node,h=(a=r.parentPath)==null?void 0:a.parentPath,I=h==null?void 0:h.node,F=((u=I==null?void 0:I.id)==null?void 0:u.name)??"",w=((C=S.key)==null?void 0:C.name)??"";return F?`${F}.${w}`:w}if(r.node.type==="ArrowFunctionExpression"||r.node.type==="FunctionExpression"){const S=r.parent;if((S==null?void 0:S.type)==="VariableDeclarator"){const I=S.id;if(I!=null&&I.name)return I.name}}r=r.parentPath}return null}ke(m,{VariableDeclarator(d){var a,u,C,S;const r=d.node;if(((a=r.init)==null?void 0:a.type)==="CallExpression"&&((u=r.init.callee)==null?void 0:u.type)==="Identifier"&&r.init.callee.name==="require"&&((S=(C=r.init.arguments)==null?void 0:C[0])==null?void 0:S.type)==="StringLiteral"){const h=r.init.arguments[0].value;if(g.has(h)||g.set(h,new Set),r.id.type==="Identifier"){const I=r.id.name;g.get(h).add(I),o.set(I,h),p.set(I,new Set)}else if(r.id.type==="ObjectPattern"){for(const I of r.id.properties)if(I.type==="ObjectProperty"&&I.key.type==="Identifier"){const F=I.value.type==="Identifier"?I.value.name:I.key.name;g.get(h).add(I.key.name),o.set(F,h),p.set(F,new Set)}}}},CallExpression(d){var a,u,C,S,h,I;const r=d.node;if(((a=r.callee)==null?void 0:a.type)==="Identifier"&&r.callee.name==="require"&&((C=(u=r.arguments)==null?void 0:u[0])==null?void 0:C.type)==="StringLiteral"){const F=d.parent;if((F==null?void 0:F.type)==="MemberExpression"&&((S=F.property)==null?void 0:S.type)==="Identifier"){const w=r.arguments[0].value;g.has(w)||g.set(w,new Set),g.get(w).add(F.property.name);const q=(h=d.parentPath)==null?void 0:h.parent;if((q==null?void 0:q.type)==="VariableDeclarator"){const B=q;((I=B.id)==null?void 0:I.type)==="Identifier"&&(o.set(B.id.name,w),p.set(B.id.name,new Set))}}}},ImportDeclaration(d){const r=d.node,a=r.source.value;g.has(a)||g.set(a,new Set);for(const u of r.specifiers){let C,S;if(u.type==="ImportDefaultSpecifier")C="default",S=u.local.name;else if(u.type==="ImportNamespaceSpecifier")C="*",S=u.local.name;else if(u.type==="ImportSpecifier"){const h=u.imported;C=h.type==="Identifier"?h.name:h.value,S=u.local.name}C&&S&&(g.get(a).add(C),o.set(S,a),p.set(S,new Set))}}}),ke(m,{Identifier(d){const r=d.node.name;if(p.has(r)){const a=d.parent;if((a==null?void 0:a.type)==="VariableDeclarator"&&a.id===d.node||(a==null?void 0:a.type)==="ImportSpecifier"||(a==null?void 0:a.type)==="ImportDefaultSpecifier")return;const u=A(d);u&&p.get(r).add(u)}},FunctionDeclaration(d){var I,F,w,q,B;if(d.parent.type==="ExportDefaultDeclaration")return;const r=d.node,a=((I=r.id)==null?void 0:I.name)??"[anonymous]",u=r.params.map(M=>{var Y,Z;return M.type==="Identifier"?M.name:M.type==="AssignmentPattern"&&((Y=M.left)==null?void 0:Y.type)==="Identifier"?M.left.name+"?":M.type==="RestElement"&&((Z=M.argument)==null?void 0:Z.type)==="Identifier"?"..."+M.argument.name:"?"}),C=((w=(F=r.loc)==null?void 0:F.start)==null?void 0:w.line)??0,S=((B=(q=r.loc)==null?void 0:q.end)==null?void 0:B.line)??0,h=oe(Ce(r,d.parent));n.functions.push({name:a,params:u.join(","),startLine:C,endLine:S,description:h})},ClassDeclaration(d){var F,w,q,B,M,Y,Z,re,ie;if(d.parent.type==="ExportDefaultDeclaration")return;const r=d.node,a=((F=r.id)==null?void 0:F.name)??"[anonymous]",u=((q=(w=r.loc)==null?void 0:w.start)==null?void 0:q.line)??0,C=((M=(B=r.loc)==null?void 0:B.end)==null?void 0:M.line)??0,S=l(r.superClass),h=oe(Ce(r,d.parent)),I=[];if((Y=r.body)!=null&&Y.body){for(const K of r.body.body)if(K.type==="ClassMethod"){const le=((Z=K.key)==null?void 0:Z.type)==="Identifier"?K.key.name:"[computed]",fe=K.params.map(ee=>{var ce;return ee.type==="Identifier"?ee.name:ee.type==="AssignmentPattern"&&((ce=ee.left)==null?void 0:ce.type)==="Identifier"?ee.left.name+"?":"?"}),de=((ie=(re=K.loc)==null?void 0:re.start)==null?void 0:ie.line)??0;let ae="";const te=K.leadingComments;te&&te.length>0&&(ae=oe(te[te.length-1])),I.push({name:le,params:fe.join(","),line:de,static:K.static,kind:K.kind,description:ae})}}n.classes.push({name:a,superClass:S,startLine:u,endLine:C,methods:I,description:h})},VariableDeclaration(d){var C,S,h,I,F,w,q,B,M,Y,Z,re,ie,K,le,fe,de,ae,te,ee,ce,me,ue,ge,ye,he,$e,pe,J,L,X,z,Q;const r=d.parent.type;if(r!=="Program"&&r!=="ExportNamedDeclaration")return;const a=d.node,u=oe(Ce(a,d.parent));for(const k of a.declarations){const R=((C=k.id)==null?void 0:C.type)==="Identifier"?k.id.name:void 0;if(R){if(((S=k.init)==null?void 0:S.type)==="ArrowFunctionExpression"||((h=k.init)==null?void 0:h.type)==="FunctionExpression"){const T=k.init.params.map(D=>{var j,P;return D.type==="Identifier"?D.name:D.type==="AssignmentPattern"&&((j=D.left)==null?void 0:j.type)==="Identifier"?D.left.name+"?":D.type==="RestElement"&&((P=D.argument)==null?void 0:P.type)==="Identifier"?"..."+D.argument.name:"?"}),ne=((F=(I=a.loc)==null?void 0:I.start)==null?void 0:F.line)??0,V=((q=(w=a.loc)==null?void 0:w.end)==null?void 0:q.line)??0;n.functions.push({name:R,params:T.join(","),startLine:ne,endLine:V,description:u});continue}if(((B=k.init)==null?void 0:B.type)==="ClassExpression"){const O=k.init,T=((Y=(M=a.loc)==null?void 0:M.start)==null?void 0:Y.line)??0,ne=((re=(Z=a.loc)==null?void 0:Z.end)==null?void 0:re.line)??0,V=l(O.superClass),D=[];if((ie=O.body)!=null&&ie.body){for(const j of O.body.body)if(j.type==="ClassMethod"){const P=((K=j.key)==null?void 0:K.type)==="Identifier"?j.key.name:"[computed]",W=j.params.map(Ie=>{var Xe;return Ie.type==="Identifier"?Ie.name:Ie.type==="AssignmentPattern"&&((Xe=Ie.left)==null?void 0:Xe.type)==="Identifier"?Ie.left.name+"?":"?"}),se=((fe=(le=j.loc)==null?void 0:le.start)==null?void 0:fe.line)??0;let Ee="";const Re=j.leadingComments;Re&&Re.length>0&&(Ee=oe(Re[Re.length-1])),D.push({name:P,params:W.join(","),line:se,static:j.static,kind:j.kind,description:Ee})}}n.classes.push({name:R,superClass:V,startLine:T,endLine:ne,methods:D,description:u});continue}if(((de=k.init)==null?void 0:de.type)==="ObjectExpression"){const O=k.init;for(const T of O.properties)if(T.type==="ObjectMethod"){const ne=((ae=T.key)==null?void 0:ae.type)==="Identifier"?`${R}.${T.key.name}`:`${R}.[computed]`,V=T.params.map(W=>{var se,Ee;return W.type==="Identifier"?W.name:W.type==="AssignmentPattern"&&((se=W.left)==null?void 0:se.type)==="Identifier"?W.left.name+"?":W.type==="RestElement"&&((Ee=W.argument)==null?void 0:Ee.type)==="Identifier"?"..."+W.argument.name:"?"}),D=((ee=(te=T.loc)==null?void 0:te.start)==null?void 0:ee.line)??0,j=((me=(ce=T.loc)==null?void 0:ce.end)==null?void 0:me.line)??0;let P="";T.leadingComments&&T.leadingComments.length>0&&(P=oe(T.leadingComments[T.leadingComments.length-1])),n.functions.push({name:ne,params:V.join(","),startLine:D,endLine:j,description:P})}else if(T.type==="ObjectProperty"&&((ue=T.key)==null?void 0:ue.type)==="Identifier"&&(((ge=T.value)==null?void 0:ge.type)==="ArrowFunctionExpression"||((ye=T.value)==null?void 0:ye.type)==="FunctionExpression")){const ne=T.value,V=`${R}.${T.key.name}`,D=ne.params.map(se=>{var Ee,Re;return se.type==="Identifier"?se.name:se.type==="AssignmentPattern"&&((Ee=se.left)==null?void 0:Ee.type)==="Identifier"?se.left.name+"?":se.type==="RestElement"&&((Re=se.argument)==null?void 0:Re.type)==="Identifier"?"..."+se.argument.name:"?"}),j=(($e=(he=T.loc)==null?void 0:he.start)==null?void 0:$e.line)??0,P=((J=(pe=T.loc)==null?void 0:pe.end)==null?void 0:J.line)??0;let W="";T.leadingComments&&T.leadingComments.length>0&&(W=oe(T.leadingComments[T.leadingComments.length-1])),n.functions.push({name:V,params:D.join(","),startLine:j,endLine:P,description:W})}}if(a.kind==="const"&&!(((L=k.init)==null?void 0:L.type)==="CallExpression"&&((X=k.init.callee)==null?void 0:X.type)==="Identifier"&&k.init.callee.name==="require")){const T=((Q=(z=a.loc)==null?void 0:z.start)==null?void 0:Q.line)??0;n.constants.push({name:R,line:T,description:u})}}}},ExportDefaultDeclaration(d){var C,S,h,I,F,w,q,B,M,Y,Z,re,ie,K,le,fe,de,ae,te,ee,ce,me,ue,ge,ye,he,$e,pe,J;const r=d.node,a=r.declaration,u=oe(Ce(r,d.parent));if(a.type==="FunctionDeclaration"){const L=a,X=((C=L.id)==null?void 0:C.name)??"[default]",z=L.params.map(R=>{var O,T;return R.type==="Identifier"?R.name:R.type==="AssignmentPattern"&&((O=R.left)==null?void 0:O.type)==="Identifier"?R.left.name+"?":R.type==="RestElement"&&((T=R.argument)==null?void 0:T.type)==="Identifier"?"..."+R.argument.name:"?"}),Q=((h=(S=r.loc)==null?void 0:S.start)==null?void 0:h.line)??0,k=((F=(I=r.loc)==null?void 0:I.end)==null?void 0:F.line)??0;n.functions.push({name:X,params:z.join(","),startLine:Q,endLine:k,description:u});return}if(a.type==="ClassDeclaration"){const L=a,X=((w=L.id)==null?void 0:w.name)??"[default]",z=((B=(q=r.loc)==null?void 0:q.start)==null?void 0:B.line)??0,Q=((Y=(M=r.loc)==null?void 0:M.end)==null?void 0:Y.line)??0,k=l(L.superClass),R=[];if((Z=L.body)!=null&&Z.body){for(const O of L.body.body)if(O.type==="ClassMethod"){const T=((re=O.key)==null?void 0:re.type)==="Identifier"?O.key.name:"[computed]",ne=O.params.map(P=>{var W;return P.type==="Identifier"?P.name:P.type==="AssignmentPattern"&&((W=P.left)==null?void 0:W.type)==="Identifier"?P.left.name+"?":"?"}),V=((K=(ie=O.loc)==null?void 0:ie.start)==null?void 0:K.line)??0;let D="";const j=O.leadingComments;j&&j.length>0&&(D=oe(j[j.length-1])),R.push({name:T,params:ne.join(","),line:V,static:O.static,kind:O.kind,description:D})}}n.classes.push({name:X,superClass:k,startLine:z,endLine:Q,methods:R,description:u});return}if(a.type==="ArrowFunctionExpression"||a.type==="FunctionExpression"){const L=a,X=L.type==="FunctionExpression"&&((le=L.id)!=null&&le.name)?L.id.name:"[default]",z=L.params.map(R=>{var O,T;return R.type==="Identifier"?R.name:R.type==="AssignmentPattern"&&((O=R.left)==null?void 0:O.type)==="Identifier"?R.left.name+"?":R.type==="RestElement"&&((T=R.argument)==null?void 0:T.type)==="Identifier"?"..."+R.argument.name:"?"}),Q=((de=(fe=r.loc)==null?void 0:fe.start)==null?void 0:de.line)??0,k=((te=(ae=r.loc)==null?void 0:ae.end)==null?void 0:te.line)??0;n.functions.push({name:X,params:z.join(","),startLine:Q,endLine:k,description:u});return}if(a.type==="ClassExpression"){const L=a,X=((ee=L.id)==null?void 0:ee.name)??"[default]",z=((me=(ce=r.loc)==null?void 0:ce.start)==null?void 0:me.line)??0,Q=((ge=(ue=r.loc)==null?void 0:ue.end)==null?void 0:ge.line)??0,k=((ye=L.superClass)==null?void 0:ye.type)==="Identifier"?L.superClass.name:null,R=[];if((he=L.body)!=null&&he.body){for(const O of L.body.body)if(O.type==="ClassMethod"){const T=(($e=O.key)==null?void 0:$e.type)==="Identifier"?O.key.name:"[computed]",ne=O.params.map(P=>{var W;return P.type==="Identifier"?P.name:P.type==="AssignmentPattern"&&((W=P.left)==null?void 0:W.type)==="Identifier"?P.left.name+"?":"?"}),V=((J=(pe=O.loc)==null?void 0:pe.start)==null?void 0:J.line)??0;let D="";const j=O.leadingComments;j&&j.length>0&&(D=oe(j[j.length-1])),R.push({name:T,params:ne.join(","),line:V,static:O.static,kind:O.kind,description:D})}}n.classes.push({name:X,superClass:k,startLine:z,endLine:Q,methods:R,description:u})}},AssignmentExpression(d){var S,h,I,F,w,q,B,M,Y,Z,re,ie,K,le,fe,de,ae,te,ee,ce,me,ue,ge,ye,he,$e;const r=d.node;if(d.parent.type!=="ExpressionStatement")return;const a=(S=d.parentPath)==null?void 0:S.parent;if((a==null?void 0:a.type)!=="Program")return;const u=r.left,C=r.right;if(u.type==="MemberExpression"&&((h=u.object)==null?void 0:h.type)==="Identifier"&&u.object.name==="module"&&((I=u.property)==null?void 0:I.type)==="Identifier"&&u.property.name==="exports"){const pe=oe(Ce(d.parent,a));if(C.type==="FunctionExpression"||C.type==="ArrowFunctionExpression"){const J=C,L=C.type==="FunctionExpression"&&((F=C.id)!=null&&F.name)?C.id.name:"[exports]",X=J.params.map(k=>{var R,O;return k.type==="Identifier"?k.name:k.type==="AssignmentPattern"&&((R=k.left)==null?void 0:R.type)==="Identifier"?k.left.name+"?":k.type==="RestElement"&&((O=k.argument)==null?void 0:O.type)==="Identifier"?"..."+k.argument.name:"?"}),z=((q=(w=r.loc)==null?void 0:w.start)==null?void 0:q.line)??0,Q=((M=(B=r.loc)==null?void 0:B.end)==null?void 0:M.line)??0;n.functions.push({name:L,params:X.join(","),startLine:z,endLine:Q,description:pe});return}if(C.type==="ClassExpression"){const J=C,L=((Y=J.id)==null?void 0:Y.name)??"[exports]",X=((re=(Z=r.loc)==null?void 0:Z.start)==null?void 0:re.line)??0,z=((K=(ie=r.loc)==null?void 0:ie.end)==null?void 0:K.line)??0,Q=l(J.superClass),k=[];if((le=J.body)!=null&&le.body){for(const R of J.body.body)if(R.type==="ClassMethod"){const O=((fe=R.key)==null?void 0:fe.type)==="Identifier"?R.key.name:"[computed]",T=R.params.map(V=>{var D;return V.type==="Identifier"?V.name:V.type==="AssignmentPattern"&&((D=V.left)==null?void 0:D.type)==="Identifier"?V.left.name+"?":"?"}),ne=((ae=(de=R.loc)==null?void 0:de.start)==null?void 0:ae.line)??0;k.push({name:O,params:T.join(","),line:ne,static:R.static,kind:R.kind,description:""})}}n.classes.push({name:L,superClass:Q,startLine:X,endLine:z,methods:k,description:pe});return}}if(u.type==="MemberExpression"&&((te=u.property)==null?void 0:te.type)==="Identifier"){const pe=u.property.name;let J=!1;if(((ee=u.object)==null?void 0:ee.type)==="Identifier"&&u.object.name==="exports"&&(J=!0),((ce=u.object)==null?void 0:ce.type)==="MemberExpression"&&((me=u.object.object)==null?void 0:me.type)==="Identifier"&&u.object.object.name==="module"&&((ue=u.object.property)==null?void 0:ue.type)==="Identifier"&&u.object.property.name==="exports"&&(J=!0),J){const L=oe(Ce(d.parent,a));if(C.type==="FunctionExpression"||C.type==="ArrowFunctionExpression"){const z=C.params.map(R=>{var O,T;return R.type==="Identifier"?R.name:R.type==="AssignmentPattern"&&((O=R.left)==null?void 0:O.type)==="Identifier"?R.left.name+"?":R.type==="RestElement"&&((T=R.argument)==null?void 0:T.type)==="Identifier"?"..."+R.argument.name:"?"}),Q=((ye=(ge=r.loc)==null?void 0:ge.start)==null?void 0:ye.line)??0,k=(($e=(he=r.loc)==null?void 0:he.end)==null?void 0:$e.line)??0;n.functions.push({name:pe,params:z.join(","),startLine:Q,endLine:k,description:L})}}}}});for(const[d,r]of g){const a=new Set;for(const u of o.keys())if(o.get(u)===d&&p.has(u))for(const C of p.get(u))a.add(C);n.imports.push({module:d,members:Array.from(r),usedIn:Array.from(a)})}const _=new Set;for(const d of n.functions)_.add(d.name);for(const d of n.classes)for(const r of d.methods)_.add(r.name),_.add(`${d.name}.${r.name}`);const v=new Set(o.keys()),N=new Map;ke(m,{CallExpression(d){var u,C;const r=d.node;let a=null;if(r.callee.type==="Identifier")a=r.callee.name;else if(r.callee.type==="MemberExpression"&&((u=r.callee.property)==null?void 0:u.type)==="Identifier"){const S=((C=r.callee.object)==null?void 0:C.type)==="Identifier"?r.callee.object.name:void 0,h=r.callee.property.name;S&&v.has(S)?a=`${S}.${h}`:a=h}if(a){const S=A(d);if(S&&S!==a){const h=_.has(a),I=v.has(a)||a.includes(".")&&v.has(a.split(".")[0]);(h||I)&&(N.has(S)||N.set(S,new Set),N.get(S).add(a))}}}}),n.callGraph={};for(const[d,r]of N)n.callGraph[d]=Array.from(r);return ke(m,{ExportNamedDeclaration(d){var C,S;const r=d.node,a=((S=(C=r.loc)==null?void 0:C.start)==null?void 0:S.line)??0,u=r.exportKind==="type";if(r.specifiers&&r.specifiers.length>0){for(const h of r.specifiers)if(h.type==="ExportSpecifier"){const I=h.exported.type==="Identifier"?h.exported.name:h.exported.value,F=h.local.name,w=u||h.exportKind==="type";n.exports.push({name:I,localName:F!==I?F:void 0,line:a,kind:w?"type":"value"})}return}if(r.declaration){const h=r.declaration;if(h.type==="FunctionDeclaration"&&h.id)n.exports.push({name:h.id.name,line:a,kind:"value"});else if(h.type==="ClassDeclaration"&&h.id)n.exports.push({name:h.id.name,line:a,kind:"value"});else if(h.type==="VariableDeclaration")for(const I of h.declarations)I.id.type==="Identifier"&&n.exports.push({name:I.id.name,line:a,kind:"value"});else(h.type==="TSTypeAliasDeclaration"||h.type==="TSInterfaceDeclaration")&&h.id&&n.exports.push({name:h.id.name,line:a,kind:"type"})}},ExportDefaultDeclaration(d){var S,h;const r=d.node,a=((h=(S=r.loc)==null?void 0:S.start)==null?void 0:h.line)??0,u=r.declaration;let C;u.type==="FunctionDeclaration"&&u.id||u.type==="ClassDeclaration"&&u.id?C=u.id.name:u.type==="Identifier"&&(C=u.name),n.exports.push({name:"default",localName:C,line:a,kind:"default"})}}),n.isPureType=vt(m),n}function vt(e){let t=!1;for(const n of e.program.body){switch(n.type){case"TSTypeAliasDeclaration":case"TSInterfaceDeclaration":case"TSEnumDeclaration":break;case"ImportDeclaration":n.importKind!=="type"&&n.specifiers.some(i=>i.type==="ImportSpecifier"?i.importKind!=="type":!0)&&n.specifiers.length>0&&(t=!0);break;case"ExportNamedDeclaration":if(n.exportKind==="type")break;if(n.declaration){const s=n.declaration.type;s!=="TSTypeAliasDeclaration"&&s!=="TSInterfaceDeclaration"&&(t=!0)}else n.specifiers&&n.specifiers.length>0&&n.specifiers.some(i=>i.type==="ExportSpecifier"?i.exportKind!=="type":!0)&&(t=!0);break;case"ExportDefaultDeclaration":t=!0;break;case"ExportAllDeclaration":n.exportKind!=="type"&&(t=!0);break;default:t=!0;break}if(t)break}return!t}function kt(e,t){const n=[];let s=`/*@AI ${t}`;e.description&&(s+=` - ${e.description.slice(0,50)}`),n.push(s);for(const i of e.imports){const f=Array.isArray(i.members)?i.members.join(","):"";let $=`<${i.module}:${f}`;Array.isArray(i.usedIn)&&i.usedIn.length>0&&($+=` ->${i.usedIn.join(",")}`),n.push($)}for(const i of e.classes){let f=i.name;i.superClass&&(f+=`:${i.superClass}`),f+=` ${i.startLine}-${i.endLine}`,i.description&&(f+=` ${i.description}`),n.push(f);for(const $ of i.methods){const c=$.static?" +":" .",m=$.kind==="get"?"get:":$.kind==="set"?"set:":"";let g=`${c}${m}${$.name}(${$.params}) ${$.line}`;$.description&&(g+=` ${$.description}`),n.push(g)}}for(const i of e.functions){let f=`${i.name}(${i.params}) ${i.startLine}-${i.endLine}`;i.description&&(f+=` ${i.description}`),n.push(f)}for(const i of e.constants){let f=`${i.name} ${i.line}`;i.description&&(f+=` ${i.description}`),n.push(f)}return n.push("@AI*/"),n.join(`
|
|
34
|
+
`)}function Ft(e){let t=e;return t=t.replace(/\/\*@AI[\s\S]*?@AI\*\/\s*/g,""),t=t.replace(/\/\*\*[\s\S]*?@ai-context-end[\s\S]*?\*\/\s*/g,""),t=t.replace(/^\/\*\*[\s\S]*?\*\/\s*\n?/,""),t}function We(e,t){var s,i,f;const n=[`@FNMAP ${E.basename(e)}/`];for(const{relativePath:$,info:c}of t){let g=`#${E.basename($)}`;c.description&&(g+=` ${c.description.slice(0,50)}`),n.push(g);for(const o of c.imports){const p=Array.isArray(o.members)?o.members.join(","):"";n.push(` <${o.module}:${p}`)}for(const o of c.classes){let p=` ${o.name}`;o.superClass&&(p+=`:${o.superClass}`),p+=` ${o.startLine}-${o.endLine}`,o.description&&(p+=` ${o.description}`),n.push(p);for(const l of o.methods){const A=l.static?" +":" .",_=l.kind==="get"?"get:":l.kind==="set"?"set:":"";let v=`${A}${_}${l.name}(${l.params}) ${l.line}`;l.description&&(v+=` ${l.description}`);const N=`${o.name}.${l.name}`,G=((s=c.callGraph)==null?void 0:s[N])??((i=c.callGraph)==null?void 0:i[l.name]);Array.isArray(G)&&G.length>0&&(v+=` →${G.join(",")}`),n.push(v)}}for(const o of c.functions){let p=` ${o.name}(${o.params}) ${o.startLine}-${o.endLine}`;o.description&&(p+=` ${o.description}`);const l=(f=c.callGraph)==null?void 0:f[o.name];Array.isArray(l)&&l.length>0&&(p+=` →${l.join(",")}`),n.push(p)}for(const o of c.constants){let p=` $${o.name} ${o.line}`;o.description&&(p+=` ${o.description}`),n.push(p)}if(c.exports&&c.exports.length>0){const o=[];for(const p of c.exports)p.kind==="default"?o.push(p.localName?`default:${p.localName}`:"default"):p.kind==="type"?o.push(`type:${p.name}`):o.push(p.name);n.push(` >${o.join(",")}`)}}return n.push("@FNMAP"),n.join(`
|
|
35
|
+
`)}function rt(e,t){const n=["flowchart TD"],s=o=>"id_"+o.replace(/[^a-zA-Z0-9]/g,p=>`_${p.charCodeAt(0)}_`),i=o=>o.replace(/"/g,"#quot;"),f=t.functions.map(o=>o.name),$=[];for(const o of t.classes)for(const p of o.methods)$.push(`${o.name}.${p.name}`);const c=[...f,...$];if(c.length===0)return null;const m=E.basename(e,E.extname(e));n.push(` subgraph ${s(m)}["${m}"]`);for(const o of c)n.push(` ${s(o)}["${i(o)}"]`);n.push(" end");const g=t.callGraph??{};for(const[o,p]of Object.entries(g))if(Array.isArray(p)){for(const l of p)if(c.includes(l)||l.includes(".")){const A=c.includes(l)?l:l.split(".").pop();(c.includes(l)||c.some(_=>_.endsWith(A)))&&n.push(` ${s(o)} --> ${s(l)}`)}}return n.join(`
|
|
36
|
+
`)}function it(e,t){const n=["flowchart TD"],s=m=>"id_"+m.replace(/[^a-zA-Z0-9]/g,g=>`_${g.charCodeAt(0)}_`),i=m=>m.replace(/"/g,"#quot;"),f=new Map,$=[];for(const{relativePath:m,info:g}of t){const o=E.basename(m,E.extname(m)),p=g.functions.map(v=>v.name),l=[];for(const v of g.classes)for(const N of v.methods)l.push(`${v.name}.${N.name}`);const A=[...p,...l];f.set(m,{fileName:o,functions:A});const _=g.callGraph??{};for(const[v,N]of Object.entries(_))if(Array.isArray(N))for(const G of N)$.push({file:m,fileName:o,caller:v,callee:G})}for(const[,{fileName:m,functions:g}]of f)if(g.length!==0){n.push(` subgraph ${s(m)}["${i(m)}"]`);for(const o of g)n.push(` ${s(m)}_${s(o)}["${i(o)}"]`);n.push(" end")}const c=new Set;for(const{fileName:m,caller:g,callee:o}of $){const p=`${s(m)}_${s(g)}`;let l=null;for(const[,{fileName:A,functions:_}]of f)if(_.includes(o)){l=`${s(A)}_${s(o)}`;break}if(!l){const A=[...f.keys()].find(_=>{var v;return((v=f.get(_))==null?void 0:v.fileName)===m});if(A){const _=f.get(A);_!=null&&_.functions.includes(o)&&(l=`${s(m)}_${s(o)}`)}}if(l){const A=`${p}-->${l}`;c.has(A)||(n.push(` ${p} --> ${l}`),c.add(A))}}return n.join(`
|
|
37
|
+
`)}function Nt(e,t){const n=(t==null?void 0:t.filePath)??null;try{const s=ze(e,n);return s?Ke(s)?{success:!1,error:s.parseError,errorType:s.errorType,loc:s.loc}:{success:!0,info:s}:{success:!1,error:"Analysis returned null / 分析返回空值",errorType:U.PARSE_ERROR}}catch(s){return{success:!1,error:`Failed to process code / 处理代码失败: ${s.message}`,errorType:U.PARSE_ERROR}}}function at(e){const t=et(e);if(!t.valid)return{success:!1,error:t.error,errorType:t.errorType??U.VALIDATION_ERROR};try{const n=b.readFileSync(e,"utf-8"),s=ze(n,e);return s?Ke(s)?{success:!1,error:s.parseError,errorType:s.errorType,loc:s.loc}:{success:!0,info:s}:{success:!1,error:"Analysis returned null / 分析返回空值",errorType:U.PARSE_ERROR}}catch(n){const s=n;return{success:!1,error:be(U.FILE_READ_ERROR,"Failed to read or process file / 读取或处理文件失败",{file:e,suggestion:s.message}),errorType:U.FILE_READ_ERROR}}}function Lt(e){const t=E.join(e,"package.json");if(!b.existsSync(t))return null;try{return JSON.parse(b.readFileSync(t,"utf-8"))}catch{return null}}function jt(e){return e?new Set([...Object.keys(e.dependencies||{}),...Object.keys(e.devDependencies||{})]):new Set}function wt(e,t){for(const n of t)if(n.endsWith("*")){const s=n.slice(0,-1);try{const i=b.readdirSync(e).filter(f=>f.startsWith(s));if(i.length>0)return i[0]??null}catch{}}else if(b.existsSync(E.join(e,n)))return n;return null}function Dt(e,t){var n,s;return e?(n=e.devDependencies)!=null&&n[t]?"devDependencies":(s=e.dependencies)!=null&&s[t]?"dependencies":"":""}const Pt=[{name:"typescript",depNames:["typescript"],configPatterns:["tsconfig.json"],level:"block"},{name:"eslint",depNames:["eslint"],configPatterns:[".eslintrc*","eslint.config.*"],level:"warn"},{name:"biome",depNames:["@biomejs/biome"],configPatterns:["biome.json","biome.jsonc"],level:"warn"},{name:"prettier",depNames:["prettier"],configPatterns:[".prettierrc*","prettier.config.*"],level:"warn"},{name:"vitest",depNames:["vitest"],configPatterns:[],level:"block"},{name:"jest",depNames:["jest"],configPatterns:["jest.config.*"],level:"block"},{name:"mocha",depNames:["mocha"],configPatterns:[".mocharc*"],level:"block"}],Mt={typescript:`# TypeScript 类型检查
|
|
38
38
|
TS_OUTPUT=$(npx tsc --noEmit 2>&1)
|
|
39
39
|
if [ $? -ne 0 ]; then
|
|
40
40
|
TS_ERRORS=$(echo "$TS_OUTPUT" | head -30)
|
|
@@ -69,7 +69,7 @@ TEST_OUTPUT=$(npx mocha 2>&1)
|
|
|
69
69
|
if [ $? -ne 0 ]; then
|
|
70
70
|
TEST_ERRORS=$(echo "$TEST_OUTPUT" | tail -30)
|
|
71
71
|
BLOCK_ERRORS="$BLOCK_ERRORS\\n[测试失败]\\n$TEST_ERRORS"
|
|
72
|
-
fi`};function
|
|
72
|
+
fi`};function ct(e){return`#!/bin/bash
|
|
73
73
|
# Auto-generated by fnmap --hooks
|
|
74
74
|
# 自动代码质量检查脚本 - 由 fnmap 生成,勿手动编辑
|
|
75
75
|
|
|
@@ -88,7 +88,7 @@ WARN_MESSAGES=""
|
|
|
88
88
|
# fnmap 索引更新
|
|
89
89
|
fnmap --changed 2>/dev/null || true
|
|
90
90
|
|
|
91
|
-
${e.filter(s=>s.detected).map(s=>
|
|
91
|
+
${e.filter(s=>s.detected).map(s=>Mt[s.name]).filter(Boolean).join(`
|
|
92
92
|
|
|
93
93
|
`)}
|
|
94
94
|
|
|
@@ -104,30 +104,61 @@ elif [ -n "$WARN_MESSAGES" ]; then
|
|
|
104
104
|
ESCAPED=$(echo -e "$WARN_MESSAGES" | escape_json)
|
|
105
105
|
echo "{\\"systemMessage\\":$ESCAPED}"
|
|
106
106
|
fi
|
|
107
|
-
`}const
|
|
107
|
+
`}const Ut="检查 .fnmap 文件保护...",Gt="quality-check.sh",qt=`node -e "const j=JSON.parse(require('fs').readFileSync(0,'utf8'));const f=j.tool_input?.file_path||'';if(f.endsWith('.fnmap')){console.log(JSON.stringify({hookSpecificOutput:{hookEventName:'PreToolUse',permissionDecision:'deny',permissionDecisionReason:'.fnmap 文件由脚本自动维护,禁止手动修改。请使用 fnmap --changed 命令更新。'}}));}"`;function lt(e,t){const n=E.join(e,".claude"),s=E.join(n,"hooks"),i=E.join(n,"settings.json"),f=E.join(s,"quality-check.sh");b.mkdirSync(s,{recursive:!0});const $=ct(t);b.writeFileSync(f,$);let c={};if(b.existsSync(i))try{c=JSON.parse(b.readFileSync(i,"utf-8"))}catch{c={}}c.hooks||(c.hooks={}),c.hooks.PreToolUse||(c.hooks.PreToolUse=[]),c.hooks.PreToolUse=c.hooks.PreToolUse.filter(m=>{var g;return!((g=m.hooks)!=null&&g.some(o=>{var p;return(p=o.statusMessage)==null?void 0:p.includes("fnmap")}))}),c.hooks.PreToolUse.push({matcher:"Edit|Write",hooks:[{type:"command",command:qt,statusMessage:Ut}]}),c.hooks.Stop||(c.hooks.Stop=[]),c.hooks.Stop=c.hooks.Stop.filter(m=>{var g;return!((g=m.hooks)!=null&&g.some(o=>{var p;return(p=o.command)==null?void 0:p.includes(Gt)}))}),c.hooks.Stop.push({matcher:"",hooks:[{type:"command",command:"bash .claude/hooks/quality-check.sh",timeout:120,statusMessage:"代码质量检查中..."}]}),b.writeFileSync(i,JSON.stringify(c,null,2))}function Wt(e,t){return new Promise(n=>{e.question(t,s=>{n(s.trim())})})}async function Qe(e,t){const n=!t;t||(t=Ze.createInterface({input:process.stdin,output:process.stdout}));try{console.log(`
|
|
108
108
|
${y.bold}fnmap - Claude Code Hooks Setup${y.reset}`),console.log("=".repeat(50)),console.log(`Detecting project tools...
|
|
109
|
-
`);const s=
|
|
110
|
-
Hooks to install:`),console.log(` 1. ${y.bold}[protect]${y.reset} Block AI from editing .fnmap files (PreToolUse)`),console.log(` 2. ${y.bold}[fnmap]${y.reset} Auto-update fnmap index on stop (Stop)`);let f=3;for(const c of i){const m=c.level==="block"?"block on errors":"warn on issues";console.log(` ${f}. ${y.bold}[${c.name}]${y.reset}${" ".repeat(Math.max(1,10-c.name.length))}${c.name} check - ${m} (Stop)`),f++}if((await
|
|
111
|
-
Install these hooks to .claude/settings.json? (Y/n): `)).toLowerCase()==="n"){console.log("Skipped hooks installation.");return}
|
|
112
|
-
${y.green}✓${y.reset} Created .claude/hooks/quality-check.sh`),console.log(`${y.green}✓${y.reset} Updated .claude/settings.json`),console.log(`${y.green}✓${y.reset} Hooks installed! Restart Claude Code session to activate.`)}finally{n&&t&&t.close()}}function
|
|
109
|
+
`);const s=ft(e);for(const c of s)c.detected?console.log(` ${y.green}✓${y.reset} ${c.name} (${c.source})`):console.log(` ${y.gray}✗ ${c.name} (not found)${y.reset}`);const i=s.filter(c=>c.detected);console.log(`
|
|
110
|
+
Hooks to install:`),console.log(` 1. ${y.bold}[protect]${y.reset} Block AI from editing .fnmap files (PreToolUse)`),console.log(` 2. ${y.bold}[fnmap]${y.reset} Auto-update fnmap index on stop (Stop)`);let f=3;for(const c of i){const m=c.level==="block"?"block on errors":"warn on issues";console.log(` ${f}. ${y.bold}[${c.name}]${y.reset}${" ".repeat(Math.max(1,10-c.name.length))}${c.name} check - ${m} (Stop)`),f++}if((await Wt(t,`
|
|
111
|
+
Install these hooks to .claude/settings.json? (Y/n): `)).toLowerCase()==="n"){console.log("Skipped hooks installation.");return}lt(e,i),console.log(`
|
|
112
|
+
${y.green}✓${y.reset} Created .claude/hooks/quality-check.sh`),console.log(`${y.green}✓${y.reset} Updated .claude/settings.json`),console.log(`${y.green}✓${y.reset} Hooks installed! Restart Claude Code session to activate.`)}finally{n&&t&&t.close()}}function ft(e){const t=Lt(e),n=jt(t);return Pt.map(s=>{const i=s.depNames.find($=>n.has($));if(i){const $=Dt(t,i);return{name:s.name,detected:!0,source:$||"dependencies",level:s.level}}const f=wt(e,s.configPatterns);return f?{name:s.name,detected:!0,source:f,level:s.level}:{name:s.name,detected:!1,source:"",level:s.level}})}const dt="<!-- fnmap:start -->",Be="<!-- fnmap:end -->",De=`
|
|
113
|
+
${dt}
|
|
114
|
+
|
|
115
|
+
## .fnmap Code Index Format
|
|
116
|
+
|
|
117
|
+
The \`.fnmap\` file provides a structured code index for quick navigation. Read it before exploring code to locate target files and function line numbers.
|
|
118
|
+
|
|
119
|
+
**Format Reference:**
|
|
120
|
+
|
|
121
|
+
- \`#filename.js\` - Filename followed by file description
|
|
122
|
+
- \`<module:members\` - Imported module and its members
|
|
123
|
+
- \`funcName(params) 10-20 description →callee1,callee2\` - Function signature, line range, description, call graph
|
|
124
|
+
- \`ClassName:SuperClass 30-100\` - Class definition with inheritance
|
|
125
|
+
- \` .method(params) 35 →callee\` - Instance method (\`.\` prefix)
|
|
126
|
+
- \` +staticMethod(params) 40\` - Static method (\`+\` prefix)
|
|
127
|
+
- \`$constName 5\` - Constant definition (\`$\` prefix)
|
|
128
|
+
- \`>export1,export2,default\` - Exports (\`>\` prefix, supports \`default\`, \`type:Name\`)
|
|
129
|
+
|
|
130
|
+
**Call Graph:** The \`→\` at the end of function/method lines indicates which functions are called (both local and imported), helping you understand code execution flow.
|
|
131
|
+
|
|
132
|
+
## .fnmap File Protection
|
|
133
|
+
|
|
134
|
+
\`.fnmap\` files are **auto-generated** by the fnmap tool. **DO NOT** edit, create, rename, or delete any \`.fnmap\` or \`*.fnmap\` files directly. Only read them for code navigation. Updates are handled automatically by hooks running \`fnmap --changed\`.
|
|
135
|
+
|
|
136
|
+
## Code Comment Guidelines
|
|
137
|
+
|
|
138
|
+
1. Every global variable, function, class, and file module must have a **concise comment describing its purpose or functionality** - avoid describing anything else
|
|
139
|
+
2. When updating code, always update related comments to reflect the changes
|
|
140
|
+
3. Prefer encapsulating logic in functions rather than writing flat, sequential code
|
|
141
|
+
|
|
142
|
+
${Be}
|
|
143
|
+
`,Ye=`
|
|
113
144
|
# fnmap generated files
|
|
114
145
|
.fnmap
|
|
115
146
|
*.fnmap
|
|
116
147
|
*.mermaid
|
|
117
148
|
.fnmap.mermaid
|
|
118
|
-
`;function Oe(e,t){return new Promise(n=>{e.question(t,s=>{n(s.trim())})})}function
|
|
119
|
-
`);console.log(`${y.green}✓${y.reset} Added fnmap rules to .gitignore`)}function
|
|
120
|
-
`)
|
|
121
|
-
${y.bold}fnmap - Interactive Setup${y.reset}`),console.log("=".repeat(50));try{const n
|
|
122
|
-
Add fnmap rules to .gitignore? (Y/n): `)).toLowerCase()!=="n"&&
|
|
123
|
-
${y.yellow}!${y.reset} No CLAUDE.md or AGENTS.md found in project.`),(await Oe(t,"Create CLAUDE.md with fnmap documentation? (Y/n): ")).toLowerCase()!=="n"&&
|
|
149
|
+
`;function Oe(e,t){return new Promise(n=>{e.question(t,s=>{n(s.trim())})})}function pt(e,t){let n=0;const s=["node_modules",".git","dist","build",".next","coverage"];if(!b.existsSync(e))return x.warn(`Directory does not exist: ${e}`),0;const i=b.readdirSync(e,{withFileTypes:!0});for(const f of i){const $=E.join(e,f.name);if(f.isDirectory()){if(s.includes(f.name))continue;n+=pt($,t)}else if(f.isFile()){const c=f.name;if(c===".fnmap"||c.endsWith(".fnmap")||c.endsWith(".mermaid"))try{b.unlinkSync($),x.success(`Deleted: ${E.relative(t,$)}`),n++}catch(m){const g=m;x.error(`Failed to delete ${E.relative(t,$)}: ${g.message}`)}}}return n}function Bt(e,t){x.title("fnmap - Clear Generated Files"),x.info("=".repeat(50));const n=t?E.resolve(e,t):e,s=pt(n,e);x.info("=".repeat(50)),s>0?x.success(`Cleared ${s} generated file(s)`):x.info("No generated files found")}function Kt(e){const t=E.join(e,".gitignore");if(b.existsSync(t)){const n=b.readFileSync(t,"utf-8");if(n.includes("fnmap generated files")||n.includes("*.fnmap")){console.log(`${y.yellow}!${y.reset} .gitignore already contains fnmap rules`);return}b.appendFileSync(t,Ye)}else b.writeFileSync(t,Ye.trim()+`
|
|
150
|
+
`);console.log(`${y.green}✓${y.reset} Added fnmap rules to .gitignore`)}function Pe(e,t){const n=E.dirname(e);if(b.existsSync(n)||b.mkdirSync(n,{recursive:!0}),b.existsSync(e)){const s=b.readFileSync(e,"utf-8"),i=s.indexOf(dt),f=s.indexOf(Be);if(i!==-1&&f!==-1){const $=s.substring(0,i)+De.trim()+s.substring(f+Be.length);b.writeFileSync(e,$),console.log(`${y.green}✓${y.reset} Updated fnmap documentation in ${t}`)}else s.includes(".fnmap Code Index Format")?console.log(`${y.yellow}!${y.reset} ${t} contains legacy fnmap docs without markers, please remove old fnmap sections manually and re-run`):(b.appendFileSync(e,De),console.log(`${y.green}✓${y.reset} Added fnmap documentation to ${t}`))}else b.writeFileSync(e,De.trim()+`
|
|
151
|
+
`),console.log(`${y.green}✓${y.reset} Added fnmap documentation to ${t}`)}async function Vt(e){const t=Ze.createInterface({input:process.stdin,output:process.stdout});console.log(`
|
|
152
|
+
${y.bold}fnmap - Interactive Setup${y.reset}`),console.log("=".repeat(50));try{const n=E.join(e,".fnmaprc");if(b.existsSync(n))console.log(`${y.yellow}!${y.reset} Config file already exists: .fnmaprc`);else{const l={enable:!0,include:["src/**/*.js","src/**/*.ts","src/**/*.jsx","src/**/*.tsx"],exclude:["node_modules","dist","build",".next","coverage","__pycache__",".cache"]};b.writeFileSync(n,JSON.stringify(l,null,2)),console.log(`${y.green}✓${y.reset} Created config file: .fnmaprc`)}(await Oe(t,`
|
|
153
|
+
Add fnmap rules to .gitignore? (Y/n): `)).toLowerCase()!=="n"&&Kt(e);const i=E.join(e,"CLAUDE.md"),f=E.join(e,"AGENTS.md"),$=E.join(ht.homedir(),".claude","CLAUDE.md"),c=b.existsSync(i),m=b.existsSync(f),g=b.existsSync($);if(!(c||m))console.log(`
|
|
154
|
+
${y.yellow}!${y.reset} No CLAUDE.md or AGENTS.md found in project.`),(await Oe(t,"Create CLAUDE.md with fnmap documentation? (Y/n): ")).toLowerCase()!=="n"&&Pe(i,"CLAUDE.md");else{console.log(`
|
|
124
155
|
${y.bold}Select files to add fnmap documentation:${y.reset}`),console.log(`(Enter numbers separated by comma, e.g., 1,2)
|
|
125
|
-
`);const l=[];let
|
|
126
|
-
`);const N=(await Oe(t,"Your choice: ")).split(",").map(G=>G.trim()).filter(Boolean);if(N.includes("0")||N.length===0)console.log("Skipped adding documentation to files.");else for(const G of N)if(G===_){const H=await Oe(t,"Enter custom file path: ");if(H){const d
|
|
127
|
-
Setup Claude Code hooks for auto quality checks? (Y/n): `)).toLowerCase()!=="n"&&await
|
|
156
|
+
`);const l=[];let A=1;c&&l.push({key:String(A++),label:"Project CLAUDE.md",path:i,exists:!0}),l.push({key:String(A++),label:"User CLAUDE.md (~/.claude/CLAUDE.md)",path:$,exists:g}),m&&l.push({key:String(A++),label:"AGENTS.md",path:f,exists:!0});const _=String(A);for(const G of l){const H=G.exists?`${y.green}[exists]${y.reset}`:`${y.gray}[new]${y.reset}`;console.log(` ${G.key}. ${G.label} ${H}`)}console.log(` ${_}. Custom file path`),console.log(` 0. Skip
|
|
157
|
+
`);const N=(await Oe(t,"Your choice: ")).split(",").map(G=>G.trim()).filter(Boolean);if(N.includes("0")||N.length===0)console.log("Skipped adding documentation to files.");else for(const G of N)if(G===_){const H=await Oe(t,"Enter custom file path: ");if(H){const d=E.isAbsolute(H)?H:E.resolve(e,H);Pe(d,H)}}else{const H=l.find(d=>d.key===G);H&&Pe(H.path,H.label)}}(await Oe(t,`
|
|
158
|
+
Setup Claude Code hooks for auto quality checks? (Y/n): `)).toLowerCase()!=="n"&&await Qe(e,t),console.log(`
|
|
128
159
|
`+"=".repeat(50)),console.log(`${y.green}✓${y.reset} Setup complete!`),console.log(`
|
|
129
|
-
Run ${y.bold}fnmap${y.reset} or ${y.bold}fnmap --dir src${y.reset} to generate code index.`)}finally{t.close()}}async function
|
|
130
|
-
Analyzing: ${p}`);const l=
|
|
131
|
-
Generating .fnmap index...`),t.merge)for(const[o,p]of g)try{const l=
|
|
132
|
-
Generating Mermaid call graphs...`),t.mermaid==="file"||t.mermaid===!0)for(const[o,p]of g)for(const{relativePath:l,info:
|
|
133
|
-
`+"=".repeat(50)),x.stats(`Complete! Analyzed: ${y.green}${
|
|
160
|
+
Run ${y.bold}fnmap${y.reset} or ${y.bold}fnmap --dir src${y.reset} to generate code index.`)}finally{t.close()}}async function mt(){const e=He();e.parse(process.argv);const t=e.opts(),n=e.args;t.log&&Se(!1);const s=E.resolve(t.project);if(t.clear){const o=Fe();Se(!1),Bt(s,t.dir),Se(o);return}if(t.hooks){const o=Fe();Se(!1),await Qe(s),Se(o);return}if(t.init){const o=Fe();Se(!1),await Vt(s),Se(o);return}const i=[...t.files??[],...n.map(Ae)].filter(o=>b.existsSync(o));let f=[];if(t.changed||t.staged){const o=ot(s,t.staged);if(o.length===0){x.info("No git changed code files detected");return}const p=new Set;for(const l of o)p.add(E.dirname(l));for(const l of p){const A=It(l);f.push(...A)}}else if(i.length>0)f=i.map(o=>E.isAbsolute(o)?o:E.resolve(s,o));else if(t.dir){const o=E.resolve(s,t.dir);f=Ne(o,s).map(l=>E.join(s,l))}else{const{config:o,source:p}=nt(s);if(o){if(x.info(`Using config: ${p}`),o.enable===!1){x.info("Config file has enable set to false, skipping processing");return}const l=st(o),A=[...Ve,...l.exclude];if(l.include&&l.include.length>0){const _=new Set;for(const v of l.include){const N=v.replace(/\/\*\*\/.*$/,"").replace(/\*\*\/.*$/,"").replace(/\/\*\..*$/,"").replace(/\*\..*$/,"");N&&_.add(N)}for(const v of _){const N=E.resolve(s,v);if(b.existsSync(N)){const G=Ne(N,s,A);f.push(...G.map(H=>E.join(s,H)))}}}}else{x.warn("No config file found. Use fnmap init to create config, or use --dir/--files to specify scope"),x.info(""),x.info("Supported config files: .fnmaprc, .fnmaprc.json, package.json#fnmap");return}}if(f.length===0){x.info("No files found to process");return}f=[...new Set(f)],x.info("=".repeat(50)),x.title("fnmap - AI Code Indexing Tool"),x.info("=".repeat(50));let $=0,c=0;const m=[],g=new Map;for(const o of f){const p=E.relative(s,o);x.info(`
|
|
161
|
+
Analyzing: ${p}`);const l=at(o);if(l.success){$++;const A=l.info;if(A.isPureType){x.info("Skipped (pure type file) / 跳过纯类型文件");continue}if(!(A.functions.length>0||A.classes.length>0||A.constants.length>0||A.exports&&A.exports.length>0)){x.info("Skipped (empty file) / 跳过空文件");continue}x.success(`Imports: ${A.imports.length}, Functions: ${A.functions.length}, Classes: ${A.classes.length}, Constants: ${A.constants.length}`);const v=E.dirname(o);g.has(v)||g.set(v,[]),g.get(v).push({relativePath:p,info:A})}else c++,m.push({file:p,reason:l.error}),x.error(l.error)}if(g.size>0)if(x.info(`
|
|
162
|
+
Generating .fnmap index...`),t.merge)for(const[o,p]of g)try{const l=We(o,p),A=E.join(o,".fnmap");b.writeFileSync(A,l),x.success(E.relative(s,A))}catch(l){const A=l;x.error(`Failed to generate .fnmap for ${E.relative(s,o)}: ${A.message}`)}else for(const[o,p]of g)for(const{relativePath:l,info:A}of p)try{const _=We(o,[{relativePath:l,info:A}]),v=E.basename(l,E.extname(l)),N=E.join(o,`${v}.fnmap`);b.writeFileSync(N,_),x.success(E.relative(s,N))}catch(_){const v=_;x.error(`Failed to generate .fnmap for ${l}: ${v.message}`)}if(t.mermaid&&g.size>0){if(x.info(`
|
|
163
|
+
Generating Mermaid call graphs...`),t.mermaid==="file"||t.mermaid===!0)for(const[o,p]of g)for(const{relativePath:l,info:A}of p)try{const _=rt(l,A);if(_){const v=E.basename(l,E.extname(l)),N=E.join(o,`${v}.mermaid`);b.writeFileSync(N,_),x.success(E.relative(s,N))}}catch(_){const v=_;x.error(`Failed to generate mermaid for ${l}: ${v.message}`)}else if(t.mermaid==="project")try{const o=[];for(const[,A]of g)o.push(...A);const p=it(s,o),l=E.join(s,".fnmap.mermaid");b.writeFileSync(l,p),x.success(E.relative(s,l))}catch(o){const p=o;x.error(`Failed to generate project mermaid: ${p.message}`)}}if(x.info(`
|
|
164
|
+
`+"=".repeat(50)),x.stats(`Complete! Analyzed: ${y.green}${$}${y.reset}, Failed: ${c>0?y.red:""}${c}${y.reset}`),m.length>0)for(const{file:o,reason:p}of m)x.stats(` ${y.red}✗${y.reset} ${o}: ${p}`);x.info("=".repeat(50))}require.main===module&&mt().catch(e=>{console.error(e),process.exit(1)});exports.COLORS=y;exports.DEFAULT_CONFIG=Ge;exports.DEFAULT_EXCLUDES=Ve;exports.ErrorTypes=U;exports.MAX_DIR_DEPTH=Ue;exports.MAX_FILE_SIZE=Me;exports.SUPPORTED_EXTENSIONS=Le;exports.analyzeFile=ze;exports.detectTools=ft;exports.executeHooksSetup=Qe;exports.extractJSDocDescription=oe;exports.formatError=be;exports.generateAiMap=We;exports.generateFileMermaid=rt;exports.generateHeader=kt;exports.generateProjectMermaid=it;exports.generateQualityScript=ct;exports.getGitChangedFiles=ot;exports.getVersion=tt;exports.installHooks=lt;exports.isParseError=Ke;exports.isProcessFailure=St;exports.isProcessSuccess=Et;exports.isQuietMode=Fe;exports.isValidationFailure=xt;exports.isValidationSuccess=Rt;exports.loadConfig=nt;exports.logger=x;exports.main=mt;exports.mergeConfig=st;exports.normalizePath=Ae;exports.normalizePaths=Ct;exports.processCode=Nt;exports.processFile=at;exports.program=At;exports.removeExistingHeaders=Ft;exports.scanDirectory=Ne;exports.setQuietMode=Se;exports.setupCLI=He;exports.validateConfig=qe;exports.validateFilePath=et;
|
package/dist/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AA+SA;;GAEG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CA2Q1C"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@didnhdj/fnmap",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "AI code indexing tool for analyzing JS/TS code structure and generating structured code maps to help AI understand code quickly",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|