@didnhdj/fnmap 0.1.1 → 0.1.2
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 +0 -1
- package/package.json +1 -1
- package/dist/index.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -33,4 +33,3 @@ Analyzing: ${s}`);const m=he(c);if(m.success){p++;const d=m.info;E.success(`Impo
|
|
|
33
33
|
Generating .fnmap index...`);for(const[c,s]of u){const m=ue(c,s),d=I.join(c,".fnmap");v.writeFileSync(d,m),E.success(I.relative(t,d))}}if(a.mermaid&&u.size>0){if(E.info(`
|
|
34
34
|
Generating Mermaid call graphs...`),a.mermaid==="file"||a.mermaid===!0)for(const[c,s]of u)for(const{relativePath:m,info:d}of s){const F=me(m,d);if(F){const f=I.basename(m,I.extname(m)),n=I.join(c,`${f}.mermaid`);v.writeFileSync(n,F),E.success(I.relative(t,n))}}else if(a.mermaid==="project"){const c=[];for(const[,d]of u)c.push(...d);const s=ge(t,c),m=I.join(t,".fnmap.mermaid");v.writeFileSync(m,s),E.success(I.relative(t,m))}}E.info(`
|
|
35
35
|
`+"=".repeat(50)),E.info(`Complete! Analyzed: ${C.green}${p}${C.reset}, Failed: ${l>0?C.red:""}${l}${C.reset}`),E.info("=".repeat(50))}if(require.main===module){const{main:e}=require("./main");e()}exports.COLORS=C;exports.DEFAULT_CONFIG=H;exports.DEFAULT_EXCLUDES=K;exports.ErrorTypes=O;exports.MAX_DIR_DEPTH=X;exports.MAX_FILE_SIZE=W;exports.SUPPORTED_EXTENSIONS=Z;exports.analyzeFile=pe;exports.extractJSDocDescription=k;exports.formatError=q;exports.generateAiMap=ue;exports.generateFileMermaid=me;exports.generateHeader=be;exports.generateProjectMermaid=ge;exports.getGitChangedFiles=de;exports.getVersion=ce;exports.isParseError=oe;exports.isProcessFailure=Fe;exports.isProcessSuccess=Se;exports.isQuietMode=Ce;exports.isValidationFailure=ve;exports.isValidationSuccess=_e;exports.loadConfig=le;exports.logger=E;exports.main=Ae;exports.mergeConfig=fe;exports.processFile=he;exports.program=Oe;exports.removeExistingHeaders=xe;exports.scanDirectory=z;exports.setQuietMode=ae;exports.setupCLI=Y;exports.validateConfig=Q;exports.validateFilePath=ie;
|
|
36
|
-
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@didnhdj/fnmap",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
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",
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/types/index.ts","../src/constants/index.ts","../src/validation/index.ts","../src/cli/index.ts","../src/config/index.ts","../src/scanner/index.ts","../src/analyzer/jsdoc.ts","../src/analyzer/index.ts","../src/generator/header.ts","../src/generator/fnmap.ts","../src/generator/mermaid.ts","../src/processor/index.ts","../src/main.ts","../src/index.ts"],"sourcesContent":["// ============== 错误类型 ==============\n\nexport const ErrorTypes = {\n FILE_NOT_FOUND: 'FILE_NOT_FOUND',\n FILE_READ_ERROR: 'FILE_READ_ERROR',\n PARSE_ERROR: 'PARSE_ERROR',\n CONFIG_ERROR: 'CONFIG_ERROR',\n VALIDATION_ERROR: 'VALIDATION_ERROR',\n PERMISSION_ERROR: 'PERMISSION_ERROR',\n FILE_TOO_LARGE: 'FILE_TOO_LARGE'\n} as const;\n\nexport type ErrorType = (typeof ErrorTypes)[keyof typeof ErrorTypes];\n\n// ============== 验证结果类型 ==============\n\nexport interface ValidationSuccess {\n valid: true;\n}\n\nexport interface ValidationFailure {\n valid: false;\n error: string;\n errorType?: ErrorType;\n}\n\nexport type ValidationResult = ValidationSuccess | ValidationFailure;\n\n// ============== 配置类型 ==============\n\nexport interface FnmapConfig {\n enable?: boolean;\n include?: string[];\n exclude?: string[];\n}\n\nexport interface LoadedConfig {\n config: FnmapConfig | null;\n source: string | null;\n}\n\n// ============== 代码分析结果类型 ==============\n\nexport interface ImportInfo {\n module: string;\n members: string[];\n usedIn: string[];\n}\n\nexport interface FunctionInfo {\n name: string;\n params: string;\n startLine: number;\n endLine: number;\n description: string;\n}\n\nexport interface MethodInfo {\n name: string;\n params: string;\n line: number;\n static: boolean;\n kind: 'method' | 'get' | 'set' | 'constructor';\n description: string;\n}\n\nexport interface ClassInfo {\n name: string;\n superClass: string | null;\n startLine: number;\n endLine: number;\n methods: MethodInfo[];\n description: string;\n}\n\nexport interface ConstantInfo {\n name: string;\n line: number;\n description: string;\n}\n\nexport type CallGraph = Record<string, string[]>;\n\nexport interface FileInfo {\n description: string;\n imports: ImportInfo[];\n functions: FunctionInfo[];\n classes: ClassInfo[];\n constants: ConstantInfo[];\n callGraph: CallGraph;\n}\n\nexport interface ParseErrorResult {\n parseError: string;\n errorType: ErrorType;\n loc?: { line: number; column: number };\n}\n\nexport type AnalyzeResult = FileInfo | ParseErrorResult;\n\n// ============== 处理结果类型 ==============\n\nexport interface ProcessSuccess {\n success: true;\n info: FileInfo;\n}\n\nexport interface ProcessFailure {\n success: false;\n error: string;\n errorType: ErrorType;\n loc?: { line: number; column: number };\n}\n\nexport type ProcessResult = ProcessSuccess | ProcessFailure;\n\n// ============== CLI 类型 ==============\n\nexport interface CLIOptions {\n files?: string[];\n dir?: string;\n project: string;\n changed?: boolean;\n staged?: boolean;\n mermaid?: boolean | 'file' | 'project';\n quiet?: boolean;\n init?: boolean;\n}\n\n// ============== 错误格式化上下文 ==============\n\nexport interface ErrorContext {\n file?: string;\n line?: number;\n column?: number;\n suggestion?: string;\n}\n\n// ============== 文件信息映射 ==============\n\nexport interface FileInfoEntry {\n relativePath: string;\n info: FileInfo;\n}\n\n// ============== 类型守卫 ==============\n\nexport function isParseError(result: AnalyzeResult): result is ParseErrorResult {\n return 'parseError' in result;\n}\n\nexport function isProcessSuccess(result: ProcessResult): result is ProcessSuccess {\n return result.success === true;\n}\n\nexport function isProcessFailure(result: ProcessResult): result is ProcessFailure {\n return result.success === false;\n}\n\nexport function isValidationSuccess(result: ValidationResult): result is ValidationSuccess {\n return result.valid === true;\n}\n\nexport function isValidationFailure(result: ValidationResult): result is ValidationFailure {\n return result.valid === false;\n}\n","import type { FnmapConfig } from '../types';\n\n// ANSI颜色常量\nexport const COLORS = {\n reset: '\\x1b[0m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n gray: '\\x1b[90m',\n bold: '\\x1b[1m'\n} as const;\n\n// 文件大小限制 (10MB)\nexport const MAX_FILE_SIZE = 10 * 1024 * 1024;\n\n// 最大目录深度限制\nexport const MAX_DIR_DEPTH = 50;\n\n// 默认支持的文件扩展名\nexport const SUPPORTED_EXTENSIONS = ['.js', '.ts', '.jsx', '.tsx', '.mjs'] as const;\nexport type SupportedExtension = (typeof SUPPORTED_EXTENSIONS)[number];\n\n// 默认排除的目录\nexport const DEFAULT_EXCLUDES = [\n 'node_modules',\n '.git',\n 'dist',\n 'build',\n '.next',\n 'coverage',\n '__pycache__',\n '.cache'\n] as const;\n\n// 默认配置\nexport const DEFAULT_CONFIG: Required<FnmapConfig> = {\n enable: true,\n include: ['**/*.js', '**/*.ts', '**/*.jsx', '**/*.tsx', '**/*.mjs'],\n exclude: []\n};\n","import fs from 'fs';\nimport type { ValidationResult, ErrorContext, FnmapConfig, ErrorType } from '../types';\nimport { ErrorTypes } from '../types';\nimport { MAX_FILE_SIZE } from '../constants';\n\n/**\n * 验证文件路径\n */\nexport function validateFilePath(filePath: unknown): ValidationResult {\n if (!filePath || typeof filePath !== 'string') {\n return {\n valid: false,\n error: 'File path is required and must be a string / 文件路径必须是字符串',\n errorType: ErrorTypes.VALIDATION_ERROR\n };\n }\n\n if (!fs.existsSync(filePath)) {\n return {\n valid: false,\n error: `File not found: ${filePath} / 文件不存在: ${filePath}`,\n errorType: ErrorTypes.FILE_NOT_FOUND\n };\n }\n\n try {\n const stats = fs.statSync(filePath);\n\n if (!stats.isFile()) {\n return {\n valid: false,\n error: `Path is not a file: ${filePath} / 路径不是文件: ${filePath}`,\n errorType: ErrorTypes.VALIDATION_ERROR\n };\n }\n\n if (stats.size > MAX_FILE_SIZE) {\n return {\n valid: false,\n error: `File too large (${(stats.size / 1024 / 1024).toFixed(2)}MB > ${MAX_FILE_SIZE / 1024 / 1024}MB): ${filePath} / 文件过大`,\n errorType: ErrorTypes.FILE_TOO_LARGE\n };\n }\n } catch (e) {\n const error = e as Error;\n return {\n valid: false,\n error: `Cannot access file: ${filePath}. Reason: ${error.message} / 无法访问文件`,\n errorType: ErrorTypes.PERMISSION_ERROR\n };\n }\n\n return { valid: true };\n}\n\n/**\n * 验证配置对象\n */\nexport function validateConfig(config: unknown): ValidationResult {\n if (!config || typeof config !== 'object') {\n return {\n valid: false,\n error: 'Config must be an object / 配置必须是对象'\n };\n }\n\n const cfg = config as Partial<FnmapConfig>;\n\n if (cfg.enable !== undefined && typeof cfg.enable !== 'boolean') {\n return {\n valid: false,\n error: 'Config.enable must be a boolean / enable 字段必须是布尔值'\n };\n }\n\n if (cfg.include !== undefined && !Array.isArray(cfg.include)) {\n return {\n valid: false,\n error: 'Config.include must be an array / include 字段必须是数组'\n };\n }\n\n if (cfg.exclude !== undefined && !Array.isArray(cfg.exclude)) {\n return {\n valid: false,\n error: 'Config.exclude must be an array / exclude 字段必须是数组'\n };\n }\n\n return { valid: true };\n}\n\n/**\n * 格式化错误信息\n */\nexport function formatError(\n _errorType: ErrorType | string,\n message: string,\n context: ErrorContext = {}\n): string {\n const parts: string[] = [message];\n\n if (context.file) {\n parts.push(`File: ${context.file}`);\n }\n\n if (context.line !== undefined && context.column !== undefined) {\n parts.push(`Location: Line ${context.line}, Column ${context.column}`);\n }\n\n if (context.suggestion) {\n parts.push(`Suggestion: ${context.suggestion}`);\n }\n\n return parts.join('\\n ');\n}\n","import { Command } from 'commander';\nimport { COLORS } from '../constants';\n\n// 日志工具\nlet quietMode = false;\n\n// 使用模块级变量存储 program 实例\nlet _program: Command | null = null;\n\nexport const logger = {\n error: (msg: string): void => {\n if (!quietMode) console.error(`${COLORS.red}✗${COLORS.reset} ${msg}`);\n },\n success: (msg: string): void => {\n if (!quietMode) console.log(`${COLORS.green}✓${COLORS.reset} ${msg}`);\n },\n info: (msg: string): void => {\n if (!quietMode) console.log(msg);\n },\n warn: (msg: string): void => {\n if (!quietMode) console.warn(`${COLORS.yellow}!${COLORS.reset} ${msg}`);\n },\n title: (msg: string): void => {\n if (!quietMode) console.log(`${COLORS.bold}${msg}${COLORS.reset}`);\n }\n};\n\nexport function setQuietMode(quiet: boolean): void {\n quietMode = quiet;\n}\n\nexport function isQuietMode(): boolean {\n return quietMode;\n}\n\n/**\n * 获取package.json中的版本号\n */\nexport function getVersion(): string {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const pkg = require('../../package.json') as { version: string };\n return pkg.version;\n } catch {\n return '0.1.0';\n }\n}\n\n/**\n * 配置CLI命令\n */\nexport function setupCLI(): Command {\n // 每次创建新的 Command 实例以支持测试\n _program = new Command();\n\n _program\n .name('fnmap')\n .description('AI code indexing tool - Analyzes JS/TS code structure and generates structured code maps')\n .version(getVersion(), '-v, --version', 'Show version number')\n .option('-f, --files <files>', 'Process specified files (comma-separated)', (val: string) =>\n val\n .split(',')\n .map((f) => f.trim())\n .filter(Boolean)\n )\n .option('-d, --dir <dir>', 'Process all code files in directory')\n .option('-p, --project <dir>', 'Specify project root directory', process.env.CLAUDE_PROJECT_DIR ?? process.cwd())\n .option('-c, --changed', 'Process only git changed files (staged + modified + untracked)')\n .option('-s, --staged', 'Process only git staged files (for pre-commit hook)')\n .option('-m, --mermaid [mode]', 'Generate Mermaid call graph (file=file-level, project=project-level)')\n .option('-q, --quiet', 'Quiet mode')\n .option('--init', 'Create default config file .fnmaprc')\n .argument('[files...]', 'Directly specify file paths')\n .allowUnknownOption(false)\n .addHelpText(\n 'after',\n `\nConfiguration files (by priority):\n .fnmaprc JSON config file\n .fnmaprc.json JSON config file\n package.json#fnmap fnmap field in package.json\n\nOutput:\n .fnmap Code index file (imports, functions, classes, constants, call graph)\n *.mermaid Mermaid call graph (when using --mermaid file)\n .fnmap.mermaid Project-level Mermaid call graph (when using --mermaid project)\n\nExamples:\n $ fnmap --dir src Process src directory\n $ fnmap --files a.js,b.js Process specified files\n $ fnmap --changed Process git changed files\n $ fnmap --staged -q For pre-commit hook usage\n $ fnmap --mermaid file --dir src Generate file-level call graphs\n $ fnmap --mermaid project Generate project-level call graph\n $ fnmap --init Create config file\n`\n );\n\n return _program;\n}\n\n// 导出 program getter\nexport function getProgram(): Command {\n if (!_program) {\n return setupCLI();\n }\n return _program;\n}\n\n// 为了兼容性,导出 program 为 getter\nexport const program = {\n get opts() {\n return getProgram().opts.bind(getProgram());\n },\n get args() {\n return getProgram().args;\n },\n get parse() {\n return getProgram().parse.bind(getProgram());\n }\n};\n","import fs from 'fs';\nimport path from 'path';\nimport type { FnmapConfig, LoadedConfig } from '../types';\nimport { ErrorTypes } from '../types';\nimport { DEFAULT_CONFIG } from '../constants';\nimport { validateConfig, formatError } from '../validation';\nimport { logger } from '../cli';\n\n/**\n * 加载配置文件\n * 优先级: .fnmaprc > .fnmaprc.json > package.json#fnmap > 默认配置\n */\nexport function loadConfig(projectDir: string): LoadedConfig {\n const configFiles = ['.fnmaprc', '.fnmaprc.json'];\n\n for (const file of configFiles) {\n const configPath = path.join(projectDir, file);\n if (fs.existsSync(configPath)) {\n try {\n const content = fs.readFileSync(configPath, 'utf-8');\n\n // 检查是否为空文件\n if (!content.trim()) {\n logger.warn(`Config file is empty: ${file}. Using default config / 配置文件为空,使用默认配置`);\n continue;\n }\n\n let config: unknown;\n try {\n config = JSON.parse(content);\n } catch (parseError) {\n const pe = parseError as Error & { lineNumber?: number; columnNumber?: number };\n const errorMsg = formatError(\n ErrorTypes.CONFIG_ERROR,\n `Failed to parse config file: ${file} / 配置文件解析失败`,\n {\n file: configPath,\n line: pe.lineNumber,\n column: pe.columnNumber,\n suggestion: 'Check JSON syntax, ensure proper quotes and commas / 检查 JSON 语法,确保引号和逗号正确'\n }\n );\n logger.warn(errorMsg);\n continue;\n }\n\n // 验证配置\n const validation = validateConfig(config);\n if (!validation.valid) {\n logger.warn(`Invalid config in ${file}: ${validation.error}`);\n continue;\n }\n\n return { config: config as FnmapConfig, source: file };\n } catch (e) {\n const error = e as Error;\n const errorMsg = formatError(\n ErrorTypes.FILE_READ_ERROR,\n `Failed to read config file: ${file} / 配置文件读取失败`,\n {\n file: configPath,\n suggestion: error.message\n }\n );\n logger.warn(errorMsg);\n }\n }\n }\n\n // 检查 package.json 中的 fnmap 字段\n const pkgPath = path.join(projectDir, 'package.json');\n if (fs.existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as { fnmap?: unknown };\n if (pkg.fnmap) {\n const validation = validateConfig(pkg.fnmap);\n if (!validation.valid) {\n logger.warn(`Invalid fnmap config in package.json: ${validation.error}`);\n } else {\n return { config: pkg.fnmap as FnmapConfig, source: 'package.json#fnmap' };\n }\n }\n } catch {\n // ignore package.json parse errors\n }\n }\n\n return { config: null, source: null };\n}\n\n/**\n * 合并配置\n */\nexport function mergeConfig(userConfig: FnmapConfig | null): Required<FnmapConfig> {\n if (!userConfig) return DEFAULT_CONFIG;\n return {\n ...DEFAULT_CONFIG,\n ...userConfig,\n exclude: [...(userConfig.exclude ?? [])]\n };\n}\n","import fs from 'fs';\nimport path from 'path';\nimport child_process from 'child_process';\nimport { SUPPORTED_EXTENSIONS, DEFAULT_EXCLUDES, MAX_DIR_DEPTH } from '../constants';\nimport { logger } from '../cli';\n\n/**\n * 获取 git 改动的文件列表\n */\nexport function getGitChangedFiles(projectDir: string, stagedOnly = false): string[] {\n const files: string[] = [];\n\n try {\n let output: string;\n if (stagedOnly) {\n // 只获取 staged 文件\n output = child_process.execSync('git diff --cached --name-only --diff-filter=ACMR', {\n cwd: projectDir,\n encoding: 'utf-8'\n });\n } else {\n // 获取所有改动文件(包括 staged、modified、untracked)\n const staged = child_process.execSync('git diff --cached --name-only --diff-filter=ACMR', {\n cwd: projectDir,\n encoding: 'utf-8'\n });\n const modified = child_process.execSync('git diff --name-only --diff-filter=ACMR', {\n cwd: projectDir,\n encoding: 'utf-8'\n });\n const untracked = child_process.execSync('git ls-files --others --exclude-standard', {\n cwd: projectDir,\n encoding: 'utf-8'\n });\n output = `${staged}\\n${modified}\\n${untracked}`;\n }\n\n const changedFiles = output\n .split('\\n')\n .map((f) => f.trim())\n .filter(Boolean)\n .filter((f) => {\n const ext = path.extname(f);\n return (SUPPORTED_EXTENSIONS as readonly string[]).includes(ext);\n });\n\n // 去重并转换为绝对路径\n const uniqueFiles = [...new Set(changedFiles)];\n for (const f of uniqueFiles) {\n const fullPath = path.resolve(projectDir, f);\n if (fs.existsSync(fullPath)) {\n files.push(fullPath);\n }\n }\n } catch {\n // 不是 git 仓库或其他错误\n return [];\n }\n\n return files;\n}\n\n/**\n * 递归扫描目录获取所有代码文件\n */\nexport function scanDirectory(\n dir: string,\n baseDir: string = dir,\n excludes: readonly string[] = DEFAULT_EXCLUDES,\n depth = 0,\n visited: Set<string> = new Set()\n): string[] {\n const files: string[] = [];\n\n if (!fs.existsSync(dir)) {\n logger.warn(`Directory does not exist: ${dir} / 目录不存在`);\n return files;\n }\n\n // 检查深度限制\n if (depth > MAX_DIR_DEPTH) {\n logger.warn(`Max directory depth (${MAX_DIR_DEPTH}) exceeded: ${dir} / 超过最大目录深度`);\n return files;\n }\n\n // 获取规范化的真实路径,处理符号链接\n let realPath: string;\n try {\n realPath = fs.realpathSync(dir);\n } catch (e) {\n const error = e as Error;\n logger.warn(`Cannot resolve real path: ${dir}. Reason: ${error.message} / 无法解析真实路径`);\n return files;\n }\n\n // 检测循环引用\n if (visited.has(realPath)) {\n logger.warn(`Circular reference detected, skipping: ${dir} / 检测到循环引用`);\n return files;\n }\n visited.add(realPath);\n\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch (e) {\n const error = e as NodeJS.ErrnoException;\n if (error.code === 'EACCES' || error.code === 'EPERM') {\n logger.warn(`Permission denied: ${dir} / 权限不足`);\n } else {\n logger.warn(`Failed to read directory: ${dir}. Reason: ${error.message} / 读取目录失败`);\n }\n return files;\n }\n\n for (const entry of entries) {\n try {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n if (!excludes.includes(entry.name)) {\n files.push(...scanDirectory(fullPath, baseDir, excludes, depth + 1, visited));\n }\n } else if (entry.isFile()) {\n const ext = path.extname(entry.name);\n if ((SUPPORTED_EXTENSIONS as readonly string[]).includes(ext)) {\n files.push(path.relative(baseDir, fullPath));\n }\n }\n // 忽略符号链接、设备文件等其他类型\n } catch (e) {\n const error = e as Error;\n logger.warn(`Error processing entry: ${entry.name}. Reason: ${error.message} / 处理条目出错`);\n }\n }\n\n return files;\n}\n","import type { Comment } from '@babel/types';\n\n/**\n * 从JSDoc注释中提取描述\n */\nexport function extractJSDocDescription(comment: Comment | null | undefined): string {\n if (!comment) return '';\n\n const text = comment.value;\n const lines = text.split('\\n').map((l) => l.replace(/^\\s*\\*\\s?/, '').trim());\n\n // 优先查找 @description 标签\n for (const line of lines) {\n if (line.startsWith('@description ')) {\n return line.slice(13).trim().slice(0, 60);\n }\n }\n\n // 否则取第一行非空非标签内容\n for (const line of lines) {\n if (line && !line.startsWith('@') && !line.startsWith('/')) {\n return line.slice(0, 60);\n }\n }\n\n return '';\n}\n","import parser from '@babel/parser';\nimport _traverse from '@babel/traverse';\nimport type { NodePath } from '@babel/traverse';\nimport type * as t from '@babel/types';\nimport type {\n FileInfo,\n AnalyzeResult,\n ImportInfo,\n FunctionInfo,\n ClassInfo,\n MethodInfo,\n ConstantInfo\n} from '../types';\nimport { ErrorTypes } from '../types';\nimport { formatError } from '../validation';\nimport { extractJSDocDescription } from './jsdoc';\n\n// 处理 ESM/CJS 兼容性\nconst traverse = typeof _traverse === 'function' ? _traverse : (_traverse as { default: typeof _traverse }).default;\n\n/**\n * 分析JS/TS文件,提取结构信息\n */\nexport function analyzeFile(code: unknown, filePath: string | null): AnalyzeResult {\n // 输入验证\n if (code === null || code === undefined) {\n return {\n parseError: 'Code content is null or undefined / 代码内容为空',\n errorType: ErrorTypes.VALIDATION_ERROR\n };\n }\n\n if (typeof code !== 'string') {\n return {\n parseError: 'Code must be a string / 代码必须是字符串类型',\n errorType: ErrorTypes.VALIDATION_ERROR\n };\n }\n\n // 检查空文件\n if (!code.trim()) {\n return {\n description: '',\n imports: [],\n functions: [],\n classes: [],\n constants: [],\n callGraph: {}\n };\n }\n\n const info: FileInfo = {\n description: '',\n imports: [],\n functions: [],\n classes: [],\n constants: [],\n callGraph: {}\n };\n\n // 提取现有的文件描述注释\n const existingCommentMatch = code.match(/^\\/\\*\\*[\\s\\S]*?\\*\\//);\n if (existingCommentMatch) {\n const commentText = existingCommentMatch[0];\n const lines = commentText\n .split('\\n')\n .map((l) => l.replace(/^\\s*\\*\\s?/, '').trim())\n .filter((l) => l && !l.startsWith('/') && !l.startsWith('@ai'));\n\n for (const line of lines) {\n if (line.startsWith('@description ')) {\n info.description = line.slice(13).trim();\n break;\n }\n }\n if (!info.description && lines.length > 0) {\n const firstLine = lines.find((l) => !l.startsWith('@'));\n if (firstLine) info.description = firstLine;\n }\n }\n\n let ast: t.File;\n try {\n const isTS = filePath && (filePath.endsWith('.ts') || filePath.endsWith('.tsx'));\n ast = parser.parse(code, {\n sourceType: 'unambiguous',\n plugins: ['jsx', 'classPrivateProperties', 'classPrivateMethods', ...(isTS ? (['typescript'] as const) : [])]\n });\n } catch (e) {\n const error = e as Error & { loc?: { line: number; column: number } };\n const errorMsg = formatError(ErrorTypes.PARSE_ERROR, `Syntax error: ${error.message} / 语法错误`, {\n file: filePath ?? undefined,\n line: error.loc?.line,\n column: error.loc?.column,\n suggestion: 'Check syntax errors in the file / 检查文件中的语法错误'\n });\n return {\n parseError: errorMsg,\n loc: error.loc,\n errorType: ErrorTypes.PARSE_ERROR\n };\n }\n\n // 收集导入信息\n const importsMap = new Map<string, Set<string>>();\n const localToModule = new Map<string, string>();\n const usageMap = new Map<string, Set<string>>();\n\n // 辅助函数:获取当前所在的函数/方法名\n function getEnclosingFunctionName(nodePath: NodePath): string | null {\n let current: NodePath | null = nodePath;\n while (current) {\n if (current.node.type === 'FunctionDeclaration') {\n const funcNode = current.node as t.FunctionDeclaration;\n if (funcNode.id) {\n return funcNode.id.name;\n }\n }\n if (current.node.type === 'ClassMethod') {\n const methodNode = current.node as t.ClassMethod;\n const classPath = current.parentPath?.parentPath;\n const classNode = classPath?.node as t.ClassDeclaration | undefined;\n const className = classNode?.id?.name ?? '';\n const methodName = (methodNode.key as t.Identifier)?.name ?? '';\n return className ? `${className}.${methodName}` : methodName;\n }\n if (current.node.type === 'ArrowFunctionExpression' || current.node.type === 'FunctionExpression') {\n const parent = current.parent as t.Node;\n if (parent?.type === 'VariableDeclarator') {\n const varDecl = parent as t.VariableDeclarator;\n const id = varDecl.id as t.Identifier;\n if (id?.name) return id.name;\n }\n }\n current = current.parentPath;\n }\n return null;\n }\n\n // 第一遍:收集导入信息\n traverse(ast, {\n VariableDeclarator(nodePath: NodePath<t.VariableDeclarator>) {\n const node = nodePath.node;\n if (\n node.init?.type === 'CallExpression' &&\n node.init.callee?.type === 'Identifier' &&\n node.init.callee.name === 'require' &&\n node.init.arguments?.[0]?.type === 'StringLiteral'\n ) {\n const moduleName = node.init.arguments[0].value;\n if (!importsMap.has(moduleName)) {\n importsMap.set(moduleName, new Set());\n }\n\n if (node.id.type === 'Identifier') {\n const localName = node.id.name;\n importsMap.get(moduleName)!.add(localName);\n localToModule.set(localName, moduleName);\n usageMap.set(localName, new Set());\n } else if (node.id.type === 'ObjectPattern') {\n for (const prop of node.id.properties) {\n if (prop.type === 'ObjectProperty' && prop.key.type === 'Identifier') {\n const localName = prop.value.type === 'Identifier' ? prop.value.name : prop.key.name;\n importsMap.get(moduleName)!.add(prop.key.name);\n localToModule.set(localName, moduleName);\n usageMap.set(localName, new Set());\n }\n }\n }\n }\n },\n\n CallExpression(nodePath: NodePath<t.CallExpression>) {\n const node = nodePath.node;\n if (\n node.callee?.type === 'Identifier' &&\n node.callee.name === 'require' &&\n node.arguments?.[0]?.type === 'StringLiteral'\n ) {\n const parent = nodePath.parent;\n if (parent?.type === 'MemberExpression' && parent.property?.type === 'Identifier') {\n const moduleName = node.arguments[0].value;\n if (!importsMap.has(moduleName)) {\n importsMap.set(moduleName, new Set());\n }\n importsMap.get(moduleName)!.add(parent.property.name);\n const grandParent = nodePath.parentPath?.parent;\n if (grandParent?.type === 'VariableDeclarator') {\n const varDecl = grandParent as t.VariableDeclarator;\n if (varDecl.id?.type === 'Identifier') {\n localToModule.set(varDecl.id.name, moduleName);\n usageMap.set(varDecl.id.name, new Set());\n }\n }\n }\n }\n },\n\n ImportDeclaration(nodePath: NodePath<t.ImportDeclaration>) {\n const node = nodePath.node;\n const moduleName = node.source.value;\n if (!importsMap.has(moduleName)) {\n importsMap.set(moduleName, new Set());\n }\n\n for (const specifier of node.specifiers) {\n let importedName: string | undefined;\n let localName: string | undefined;\n if (specifier.type === 'ImportDefaultSpecifier') {\n importedName = 'default';\n localName = specifier.local.name;\n } else if (specifier.type === 'ImportNamespaceSpecifier') {\n importedName = '*';\n localName = specifier.local.name;\n } else if (specifier.type === 'ImportSpecifier') {\n const imported = specifier.imported;\n importedName = imported.type === 'Identifier' ? imported.name : imported.value;\n localName = specifier.local.name;\n }\n if (importedName && localName) {\n importsMap.get(moduleName)!.add(importedName);\n localToModule.set(localName, moduleName);\n usageMap.set(localName, new Set());\n }\n }\n }\n });\n\n // 第二遍:收集函数/类信息,并追踪导入使用\n traverse(ast, {\n Identifier(nodePath: NodePath<t.Identifier>) {\n const name = nodePath.node.name;\n if (usageMap.has(name)) {\n const parent = nodePath.parent;\n if (parent?.type === 'VariableDeclarator' && (parent as t.VariableDeclarator).id === nodePath.node) return;\n if (parent?.type === 'ImportSpecifier' || parent?.type === 'ImportDefaultSpecifier') return;\n const enclosing = getEnclosingFunctionName(nodePath);\n if (enclosing) {\n usageMap.get(name)!.add(enclosing);\n }\n }\n },\n\n FunctionDeclaration(nodePath: NodePath<t.FunctionDeclaration>) {\n const node = nodePath.node;\n const name = node.id?.name ?? '[anonymous]';\n const params = node.params.map((p) => {\n if (p.type === 'Identifier') return p.name;\n if (p.type === 'AssignmentPattern' && p.left?.type === 'Identifier') return p.left.name + '?';\n if (p.type === 'RestElement' && p.argument?.type === 'Identifier') return '...' + p.argument.name;\n return '?';\n });\n const startLine = node.loc?.start?.line ?? 0;\n const endLine = node.loc?.end?.line ?? 0;\n\n let desc = '';\n const comments = node.leadingComments;\n if (comments && comments.length > 0) {\n desc = extractJSDocDescription(comments[comments.length - 1]);\n }\n\n info.functions.push({\n name,\n params: params.join(','),\n startLine,\n endLine,\n description: desc\n } as FunctionInfo);\n },\n\n ClassDeclaration(nodePath: NodePath<t.ClassDeclaration>) {\n const node = nodePath.node;\n const name = node.id?.name ?? '[anonymous]';\n const startLine = node.loc?.start?.line ?? 0;\n const endLine = node.loc?.end?.line ?? 0;\n const superClass = node.superClass?.type === 'Identifier' ? node.superClass.name : null;\n\n let desc = '';\n const comments = node.leadingComments;\n if (comments && comments.length > 0) {\n desc = extractJSDocDescription(comments[comments.length - 1]);\n }\n\n const methods: MethodInfo[] = [];\n if (node.body?.body) {\n for (const member of node.body.body) {\n if (member.type === 'ClassMethod') {\n const methodName = member.key?.type === 'Identifier' ? member.key.name : '[computed]';\n const methodParams = member.params.map((p) => {\n if (p.type === 'Identifier') return p.name;\n if (p.type === 'AssignmentPattern' && p.left?.type === 'Identifier') return p.left.name + '?';\n return '?';\n });\n const methodLine = member.loc?.start?.line ?? 0;\n\n let methodDesc = '';\n const methodComments = member.leadingComments;\n if (methodComments && methodComments.length > 0) {\n methodDesc = extractJSDocDescription(methodComments[methodComments.length - 1]);\n }\n\n methods.push({\n name: methodName,\n params: methodParams.join(','),\n line: methodLine,\n static: member.static,\n kind: member.kind as MethodInfo['kind'],\n description: methodDesc\n });\n }\n }\n }\n\n info.classes.push({\n name,\n superClass,\n startLine,\n endLine,\n methods,\n description: desc\n } as ClassInfo);\n },\n\n VariableDeclaration(nodePath: NodePath<t.VariableDeclaration>) {\n if (nodePath.parent.type !== 'Program') return;\n\n const node = nodePath.node;\n if (node.kind === 'const') {\n let desc = '';\n const comments = node.leadingComments;\n if (comments && comments.length > 0) {\n desc = extractJSDocDescription(comments[comments.length - 1]);\n }\n\n for (const decl of node.declarations) {\n const name = decl.id?.type === 'Identifier' ? decl.id.name : undefined;\n if (name && name === name.toUpperCase() && name.length > 2) {\n const startLine = node.loc?.start?.line ?? 0;\n info.constants.push({\n name,\n line: startLine,\n description: desc\n } as ConstantInfo);\n }\n }\n }\n }\n });\n\n // 转换导入信息\n for (const [moduleName, members] of importsMap) {\n const usedIn = new Set<string>();\n for (const localName of localToModule.keys()) {\n if (localToModule.get(localName) === moduleName && usageMap.has(localName)) {\n for (const fn of usageMap.get(localName)!) {\n usedIn.add(fn);\n }\n }\n }\n info.imports.push({\n module: moduleName,\n members: Array.from(members),\n usedIn: Array.from(usedIn)\n } as ImportInfo);\n }\n\n // 第三遍:构建函数调用图\n const definedFunctions = new Set<string>();\n for (const fn of info.functions) {\n definedFunctions.add(fn.name);\n }\n for (const cls of info.classes) {\n for (const method of cls.methods) {\n definedFunctions.add(method.name);\n definedFunctions.add(`${cls.name}.${method.name}`);\n }\n }\n\n // 收集所有导入的标识符\n const importedNames = new Set(localToModule.keys());\n\n const callGraph = new Map<string, Set<string>>();\n\n traverse(ast, {\n CallExpression(nodePath: NodePath<t.CallExpression>) {\n const node = nodePath.node;\n let calleeName: string | null = null;\n\n // 直接函数调用: funcName()\n if (node.callee.type === 'Identifier') {\n calleeName = node.callee.name;\n }\n // 方法调用: this.method() 或 obj.method()\n else if (node.callee.type === 'MemberExpression' && node.callee.property?.type === 'Identifier') {\n const objName = node.callee.object?.type === 'Identifier' ? node.callee.object.name : undefined;\n const propName = node.callee.property.name;\n // 导入对象的方法调用: fs.readFileSync()\n if (objName && importedNames.has(objName)) {\n calleeName = `${objName}.${propName}`;\n } else {\n calleeName = propName;\n }\n }\n\n if (calleeName) {\n const caller = getEnclosingFunctionName(nodePath);\n if (caller && caller !== calleeName) {\n // 文件内定义的函数 或 导入的函数\n const isDefinedFunc = definedFunctions.has(calleeName);\n const isImportedFunc =\n importedNames.has(calleeName) ||\n (calleeName.includes('.') && importedNames.has(calleeName.split('.')[0]!));\n\n if (isDefinedFunc || isImportedFunc) {\n if (!callGraph.has(caller)) callGraph.set(caller, new Set());\n callGraph.get(caller)!.add(calleeName);\n }\n }\n }\n }\n });\n\n // 转换调用图为对象格式\n info.callGraph = {};\n for (const [caller, callees] of callGraph) {\n info.callGraph[caller] = Array.from(callees);\n }\n\n return info;\n}\n\nexport { extractJSDocDescription };\n","import type { FileInfo } from '../types';\n\n/**\n * 生成紧凑格式AI注释头\n */\nexport function generateHeader(info: FileInfo, fileName: string): string {\n const lines: string[] = [];\n\n let headerLine = `/*@AI ${fileName}`;\n if (info.description) {\n headerLine += ` - ${info.description.slice(0, 50)}`;\n }\n lines.push(headerLine);\n\n // 导入信息\n for (const imp of info.imports) {\n const members = imp.members.join(',');\n let line = `<${imp.module}:${members}`;\n if (imp.usedIn?.length > 0) {\n line += ` ->${imp.usedIn.join(',')}`;\n }\n lines.push(line);\n }\n\n // 类信息\n for (const cls of info.classes) {\n let clsLine = cls.name;\n if (cls.superClass) clsLine += `:${cls.superClass}`;\n clsLine += ` ${cls.startLine}-${cls.endLine}`;\n if (cls.description) clsLine += ` ${cls.description}`;\n lines.push(clsLine);\n\n for (const method of cls.methods) {\n const prefix = method.static ? ' +' : ' .';\n const kindMark = method.kind === 'get' ? 'get:' : method.kind === 'set' ? 'set:' : '';\n let methodLine = `${prefix}${kindMark}${method.name}(${method.params}) ${method.line}`;\n if (method.description) methodLine += ` ${method.description}`;\n lines.push(methodLine);\n }\n }\n\n // 函数信息\n for (const fn of info.functions) {\n let fnLine = `${fn.name}(${fn.params}) ${fn.startLine}-${fn.endLine}`;\n if (fn.description) fnLine += ` ${fn.description}`;\n lines.push(fnLine);\n }\n\n // 常量信息\n for (const c of info.constants) {\n let constLine = `${c.name} ${c.line}`;\n if (c.description) constLine += ` ${c.description}`;\n lines.push(constLine);\n }\n\n lines.push('@AI*/');\n return lines.join('\\n');\n}\n\n/**\n * 移除现有的AI注释头\n */\nexport function removeExistingHeaders(code: string): string {\n let result = code;\n result = result.replace(/\\/\\*@AI[\\s\\S]*?@AI\\*\\/\\s*/g, '');\n result = result.replace(/\\/\\*\\*[\\s\\S]*?@ai-context-end[\\s\\S]*?\\*\\/\\s*/g, '');\n result = result.replace(/^\\/\\*\\*[\\s\\S]*?\\*\\/\\s*\\n?/, '');\n return result;\n}\n","import path from 'path';\nimport type { FileInfoEntry } from '../types';\n\n/**\n * 生成目录级 .fnmap 索引文件(包含完整信息)\n */\nexport function generateAiMap(dirPath: string, filesInfo: FileInfoEntry[]): string {\n const lines: string[] = [`@FNMAP ${path.basename(dirPath)}/`];\n\n for (const { relativePath, info } of filesInfo) {\n const fileName = path.basename(relativePath);\n let fileLine = `#${fileName}`;\n if (info.description) {\n fileLine += ` ${info.description.slice(0, 50)}`;\n }\n lines.push(fileLine);\n\n // 添加导入信息(不含使用位置,由函数行的调用图提供)\n for (const imp of info.imports) {\n const members = imp.members.join(',');\n lines.push(` <${imp.module}:${members}`);\n }\n\n // 添加类信息\n for (const cls of info.classes) {\n let clsLine = ` ${cls.name}`;\n if (cls.superClass) clsLine += `:${cls.superClass}`;\n clsLine += ` ${cls.startLine}-${cls.endLine}`;\n if (cls.description) clsLine += ` ${cls.description}`;\n lines.push(clsLine);\n\n // 类方法\n for (const method of cls.methods) {\n const prefix = method.static ? ' +' : ' .';\n const kindMark = method.kind === 'get' ? 'get:' : method.kind === 'set' ? 'set:' : '';\n let methodLine = `${prefix}${kindMark}${method.name}(${method.params}) ${method.line}`;\n if (method.description) methodLine += ` ${method.description}`;\n // 追加调用信息\n const methodKey = `${cls.name}.${method.name}`;\n const calls = info.callGraph?.[methodKey] ?? info.callGraph?.[method.name];\n if (calls && calls.length > 0) methodLine += ` →${calls.join(',')}`;\n lines.push(methodLine);\n }\n }\n\n // 添加函数信息\n for (const fn of info.functions) {\n let fnLine = ` ${fn.name}(${fn.params}) ${fn.startLine}-${fn.endLine}`;\n if (fn.description) fnLine += ` ${fn.description}`;\n // 追加调用信息\n const calls = info.callGraph?.[fn.name];\n if (calls && calls.length > 0) fnLine += ` →${calls.join(',')}`;\n lines.push(fnLine);\n }\n\n // 添加常量信息\n for (const c of info.constants) {\n let constLine = ` ${c.name} ${c.line}`;\n if (c.description) constLine += ` ${c.description}`;\n lines.push(constLine);\n }\n }\n\n lines.push('@FNMAP');\n return lines.join('\\n');\n}\n","import path from 'path';\nimport type { FileInfo, FileInfoEntry } from '../types';\n\n/**\n * 生成单文件的mermaid调用图\n */\nexport function generateFileMermaid(fileName: string, info: FileInfo): string | null {\n const lines: string[] = ['flowchart TD'];\n // 使用更安全的ID生成策略以避免冲突\n const safeId = (name: string): string =>\n 'id_' +\n name.replace(/[^a-zA-Z0-9]/g, (c) => `_${c.charCodeAt(0)}_`);\n const escapeLabel = (text: string): string => text.replace(/\"/g, '#quot;');\n\n // 收集所有函数节点\n const functions = info.functions.map((fn) => fn.name);\n const classMethods: string[] = [];\n for (const cls of info.classes) {\n for (const method of cls.methods) {\n classMethods.push(`${cls.name}.${method.name}`);\n }\n }\n const allFunctions = [...functions, ...classMethods];\n\n if (allFunctions.length === 0) {\n return null; // 没有函数,跳过\n }\n\n // 添加子图标题\n const baseName = path.basename(fileName, path.extname(fileName));\n lines.push(` subgraph ${safeId(baseName)}[\"${baseName}\"]`);\n\n // 添加函数节点\n for (const fn of allFunctions) {\n lines.push(` ${safeId(fn)}[\"${escapeLabel(fn)}\"]`);\n }\n lines.push(' end');\n\n // 添加调用关系边\n const callGraph = info.callGraph ?? {};\n for (const [caller, callees] of Object.entries(callGraph)) {\n for (const callee of callees) {\n // 只显示文件内部的调用关系\n if (allFunctions.includes(callee) || callee.includes('.')) {\n const calleeName = allFunctions.includes(callee) ? callee : callee.split('.').pop()!;\n if (allFunctions.includes(callee) || allFunctions.some((f) => f.endsWith(calleeName))) {\n lines.push(` ${safeId(caller)} --> ${safeId(callee)}`);\n }\n }\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * 生成项目级mermaid调用图\n */\nexport function generateProjectMermaid(_projectDir: string, allFilesInfo: FileInfoEntry[]): string {\n const lines: string[] = ['flowchart TD'];\n\n const safeId = (name: string): string =>\n 'id_' +\n name.replace(/[^a-zA-Z0-9]/g, (c) => `_${c.charCodeAt(0)}_`);\n const escapeLabel = (text: string): string => text.replace(/\"/g, '#quot;');\n\n // 收集所有文件的函数和它们的调用关系\n const fileToFunctions = new Map<string, { fileName: string; functions: string[] }>();\n const allCallEdges: Array<{ file: string; fileName: string; caller: string; callee: string }> = [];\n\n for (const { relativePath, info } of allFilesInfo) {\n const fileName = path.basename(relativePath, path.extname(relativePath));\n const functions = info.functions.map((fn) => fn.name);\n const classMethods: string[] = [];\n for (const cls of info.classes) {\n for (const method of cls.methods) {\n classMethods.push(`${cls.name}.${method.name}`);\n }\n }\n const allFunctions = [...functions, ...classMethods];\n fileToFunctions.set(relativePath, { fileName, functions: allFunctions });\n\n // 收集调用边\n const callGraph = info.callGraph ?? {};\n for (const [caller, callees] of Object.entries(callGraph)) {\n for (const callee of callees) {\n allCallEdges.push({\n file: relativePath,\n fileName,\n caller,\n callee\n });\n }\n }\n }\n\n // 按文件生成子图\n for (const [, { fileName, functions }] of fileToFunctions) {\n if (functions.length === 0) continue;\n\n lines.push(` subgraph ${safeId(fileName)}[\"${escapeLabel(fileName)}\"]`);\n for (const fn of functions) {\n lines.push(` ${safeId(fileName)}_${safeId(fn)}[\"${escapeLabel(fn)}\"]`);\n }\n lines.push(' end');\n }\n\n // 添加调用关系边\n const addedEdges = new Set<string>();\n for (const { fileName, caller, callee } of allCallEdges) {\n const callerId = `${safeId(fileName)}_${safeId(caller)}`;\n\n // 查找callee所在的文件\n let calleeId: string | null = null;\n for (const [, { fileName: fn, functions }] of fileToFunctions) {\n if (functions.includes(callee)) {\n calleeId = `${safeId(fn)}_${safeId(callee)}`;\n break;\n }\n }\n\n // 如果没找到,可能是同文件内调用或外部调用\n if (!calleeId) {\n const matchingKey = [...fileToFunctions.keys()].find((k) => fileToFunctions.get(k)?.fileName === fileName);\n if (matchingKey) {\n const fileData = fileToFunctions.get(matchingKey);\n if (fileData?.functions.includes(callee)) {\n calleeId = `${safeId(fileName)}_${safeId(callee)}`;\n }\n }\n }\n\n if (calleeId) {\n const edgeKey = `${callerId}-->${calleeId}`;\n if (!addedEdges.has(edgeKey)) {\n lines.push(` ${callerId} --> ${calleeId}`);\n addedEdges.add(edgeKey);\n }\n }\n }\n\n return lines.join('\\n');\n}\n","import fs from 'fs';\nimport type { ProcessResult } from '../types';\nimport { ErrorTypes, isParseError } from '../types';\nimport { validateFilePath, formatError } from '../validation';\nimport { analyzeFile } from '../analyzer';\n\n/**\n * 处理单个文件(只分析,不修改文件)\n */\nexport function processFile(filePath: string): ProcessResult {\n // 使用验证函数\n const validation = validateFilePath(filePath);\n if (!validation.valid) {\n return {\n success: false,\n error: validation.error,\n errorType: validation.errorType ?? ErrorTypes.VALIDATION_ERROR\n };\n }\n\n try {\n const code = fs.readFileSync(filePath, 'utf-8');\n const result = analyzeFile(code, filePath);\n\n if (!result) {\n return {\n success: false,\n error: 'Analysis returned null / 分析返回空值',\n errorType: ErrorTypes.PARSE_ERROR\n };\n }\n\n // 检查是否有解析错误\n if (isParseError(result)) {\n return {\n success: false,\n error: result.parseError,\n errorType: result.errorType,\n loc: result.loc\n };\n }\n\n return { success: true, info: result };\n } catch (e) {\n const error = e as Error;\n // 捕获文件读取错误\n const errorMsg = formatError(ErrorTypes.FILE_READ_ERROR, `Failed to read or process file / 读取或处理文件失败`, {\n file: filePath,\n suggestion: error.message\n });\n return {\n success: false,\n error: errorMsg,\n errorType: ErrorTypes.FILE_READ_ERROR\n };\n }\n}\n","import fs from 'fs';\nimport path from 'path';\nimport type { CLIOptions, FileInfoEntry } from './types';\nimport { COLORS, DEFAULT_EXCLUDES } from './constants';\nimport { logger, setupCLI, setQuietMode } from './cli';\nimport { loadConfig, mergeConfig } from './config';\nimport { scanDirectory, getGitChangedFiles } from './scanner';\nimport { processFile } from './processor';\nimport { generateAiMap, generateFileMermaid, generateProjectMermaid } from './generator';\n\n/**\n * 主函数\n */\nexport function main(): void {\n // 配置并解析CLI\n const program = setupCLI();\n program.parse(process.argv);\n\n const options = program.opts<CLIOptions>();\n const args = program.args;\n\n // 设置静默模式\n if (options.quiet) {\n setQuietMode(true);\n }\n\n const projectDir = path.resolve(options.project);\n\n // init命令:创建默认配置文件\n if (options.init) {\n const configPath = path.join(projectDir, '.fnmaprc');\n if (fs.existsSync(configPath)) {\n console.log(`${COLORS.yellow}!${COLORS.reset} Config file already exists: .fnmaprc`);\n return;\n }\n\n const defaultConfig = {\n enable: true,\n include: ['src/**/*.js', 'src/**/*.ts', 'src/**/*.jsx', 'src/**/*.tsx'],\n exclude: ['node_modules', 'dist', 'build', '.next', 'coverage', '__pycache__', '.cache']\n };\n\n fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2));\n console.log(`${COLORS.green}✓${COLORS.reset} Created config file: .fnmaprc`);\n return;\n }\n\n // 合并文件参数\n const fileArgs = [...(options.files ?? []), ...args].filter((f) => fs.existsSync(f));\n\n // 确定要处理的文件列表\n let filesToProcess: string[] = [];\n\n if (options.changed || options.staged) {\n // 基于git改动\n filesToProcess = getGitChangedFiles(projectDir, options.staged);\n if (filesToProcess.length === 0) {\n logger.info('No git changed code files detected');\n return;\n }\n } else if (fileArgs.length > 0) {\n // 指定的文件\n filesToProcess = fileArgs.map((f) => (path.isAbsolute(f) ? f : path.resolve(projectDir, f)));\n } else if (options.dir) {\n // 扫描指定目录\n const targetDir = path.resolve(projectDir, options.dir);\n const relFiles = scanDirectory(targetDir, projectDir);\n filesToProcess = relFiles.map((f) => path.join(projectDir, f));\n } else {\n // 检查项目配置文件\n const { config, source } = loadConfig(projectDir);\n\n if (config) {\n logger.info(`Using config: ${source}`);\n\n // 检查是否启用\n if (config.enable === false) {\n logger.info('Config file has enable set to false, skipping processing');\n return;\n }\n\n // 合并配置\n const mergedConfig = mergeConfig(config);\n const excludes = [...DEFAULT_EXCLUDES, ...mergedConfig.exclude];\n\n if (mergedConfig.include) {\n for (const pattern of mergedConfig.include) {\n const dir = pattern.replace(/\\/\\*\\*\\/.*$/, '').replace(/\\*\\*\\/.*$/, '');\n const targetDir = dir ? path.resolve(projectDir, dir) : projectDir;\n if (fs.existsSync(targetDir)) {\n const relFiles = scanDirectory(targetDir, projectDir, excludes);\n filesToProcess.push(...relFiles.map((f) => path.join(projectDir, f)));\n }\n }\n }\n } else {\n logger.warn('No config file found. Use fnmap init to create config, or use --dir/--files to specify scope');\n logger.info('');\n logger.info('Supported config files: .fnmaprc, .fnmaprc.json, package.json#fnmap');\n return;\n }\n }\n\n if (filesToProcess.length === 0) {\n logger.info('No files found to process');\n return;\n }\n\n // 去重\n filesToProcess = [...new Set(filesToProcess)];\n\n logger.info('='.repeat(50));\n logger.title('fnmap - AI Code Indexing Tool');\n logger.info('='.repeat(50));\n\n let processed = 0;\n let failed = 0;\n const dirFilesMap = new Map<string, FileInfoEntry[]>();\n\n for (const filePath of filesToProcess) {\n const relativePath = path.relative(projectDir, filePath);\n logger.info(`\\nAnalyzing: ${relativePath}`);\n\n const result = processFile(filePath);\n\n if (result.success) {\n processed++;\n const info = result.info;\n logger.success(\n `Imports: ${info.imports.length}, Functions: ${info.functions.length}, Classes: ${info.classes.length}, Constants: ${info.constants.length}`\n );\n\n // 收集目录信息\n const dir = path.dirname(filePath);\n if (!dirFilesMap.has(dir)) {\n dirFilesMap.set(dir, []);\n }\n dirFilesMap.get(dir)!.push({ relativePath, info });\n } else {\n failed++;\n logger.error(result.error);\n }\n }\n\n // 生成.fnmap索引文件\n if (dirFilesMap.size > 0) {\n logger.info('\\nGenerating .fnmap index...');\n for (const [dir, filesInfo] of dirFilesMap) {\n const mapContent = generateAiMap(dir, filesInfo);\n const mapPath = path.join(dir, '.fnmap');\n fs.writeFileSync(mapPath, mapContent);\n logger.success(path.relative(projectDir, mapPath));\n }\n }\n\n // 生成Mermaid调用图\n if (options.mermaid && dirFilesMap.size > 0) {\n logger.info('\\nGenerating Mermaid call graphs...');\n\n if (options.mermaid === 'file' || options.mermaid === true) {\n // 文件级:每个文件生成一个mermaid图\n for (const [dir, filesInfo] of dirFilesMap) {\n for (const { relativePath, info } of filesInfo) {\n const mermaidContent = generateFileMermaid(relativePath, info);\n if (mermaidContent) {\n const baseName = path.basename(relativePath, path.extname(relativePath));\n const mermaidPath = path.join(dir, `${baseName}.mermaid`);\n fs.writeFileSync(mermaidPath, mermaidContent);\n logger.success(path.relative(projectDir, mermaidPath));\n }\n }\n }\n } else if (options.mermaid === 'project') {\n // 项目级:生成一个包含所有文件的mermaid图\n const allFilesInfo: FileInfoEntry[] = [];\n for (const [, filesInfo] of dirFilesMap) {\n allFilesInfo.push(...filesInfo);\n }\n const mermaidContent = generateProjectMermaid(projectDir, allFilesInfo);\n const mermaidPath = path.join(projectDir, '.fnmap.mermaid');\n fs.writeFileSync(mermaidPath, mermaidContent);\n logger.success(path.relative(projectDir, mermaidPath));\n }\n }\n\n logger.info('\\n' + '='.repeat(50));\n logger.info(\n `Complete! Analyzed: ${COLORS.green}${processed}${COLORS.reset}, Failed: ${failed > 0 ? COLORS.red : ''}${failed}${COLORS.reset}`\n );\n logger.info('='.repeat(50));\n}\n","#!/usr/bin/env node\n/**\n * fnmap - AI Code Indexing Tool\n * Analyzes JS/TS code structure and generates structured code maps to help AI understand code quickly\n */\n\n// 导出类型\nexport type {\n ErrorType,\n ValidationResult,\n ValidationSuccess,\n ValidationFailure,\n FnmapConfig,\n LoadedConfig,\n ImportInfo,\n FunctionInfo,\n MethodInfo,\n ClassInfo,\n ConstantInfo,\n CallGraph,\n FileInfo,\n ParseErrorResult,\n AnalyzeResult,\n ProcessResult,\n ProcessSuccess,\n ProcessFailure,\n CLIOptions,\n ErrorContext,\n FileInfoEntry\n} from './types';\n\n// 导出类型守卫\nexport { ErrorTypes, isParseError, isProcessSuccess, isProcessFailure, isValidationSuccess, isValidationFailure } from './types';\n\n// 导出常量\nexport { COLORS, SUPPORTED_EXTENSIONS, DEFAULT_EXCLUDES, DEFAULT_CONFIG, MAX_FILE_SIZE, MAX_DIR_DEPTH } from './constants';\n\n// 导出验证函数\nexport { validateFilePath, validateConfig, formatError } from './validation';\n\n// 导出配置函数\nexport { loadConfig, mergeConfig } from './config';\n\n// 导出 CLI\nexport { setupCLI, getVersion, logger, setQuietMode, isQuietMode, program } from './cli';\n\n// 导出扫描器\nexport { scanDirectory, getGitChangedFiles } from './scanner';\n\n// 导出分析器\nexport { analyzeFile, extractJSDocDescription } from './analyzer';\n\n// 导出生成器\nexport { generateHeader, removeExistingHeaders, generateAiMap, generateFileMermaid, generateProjectMermaid } from './generator';\n\n// 导出处理器\nexport { processFile } from './processor';\n\n// 导出主函数\nexport { main } from './main';\n\n// CLI 入口\nif (require.main === module) {\n const { main } = require('./main');\n main();\n}\n"],"names":["ErrorTypes","isParseError","result","isProcessSuccess","isProcessFailure","isValidationSuccess","isValidationFailure","COLORS","MAX_FILE_SIZE","MAX_DIR_DEPTH","SUPPORTED_EXTENSIONS","DEFAULT_EXCLUDES","DEFAULT_CONFIG","validateFilePath","filePath","fs","stats","e","validateConfig","config","cfg","formatError","_errorType","message","context","parts","quietMode","_program","logger","msg","setQuietMode","quiet","isQuietMode","getVersion","setupCLI","Command","val","f","getProgram","program","loadConfig","projectDir","configFiles","file","configPath","path","content","parseError","pe","errorMsg","validation","error","pkgPath","pkg","mergeConfig","userConfig","getGitChangedFiles","stagedOnly","files","output","child_process","staged","modified","untracked","changedFiles","ext","uniqueFiles","fullPath","scanDirectory","dir","baseDir","excludes","depth","visited","realPath","entries","entry","extractJSDocDescription","comment","lines","l","line","traverse","_traverse","analyzeFile","code","info","existingCommentMatch","firstLine","ast","isTS","parser","_a","_b","importsMap","localToModule","usageMap","getEnclosingFunctionName","nodePath","current","funcNode","methodNode","classPath","classNode","className","methodName","_c","parent","id","node","_d","moduleName","localName","prop","grandParent","_e","varDecl","_f","specifier","importedName","imported","name","enclosing","params","p","startLine","endLine","desc","comments","superClass","methods","_g","member","_h","methodParams","methodLine","_j","_i","methodDesc","methodComments","decl","members","usedIn","fn","definedFunctions","cls","method","importedNames","callGraph","calleeName","objName","propName","caller","isDefinedFunc","isImportedFunc","callees","generateHeader","fileName","headerLine","imp","clsLine","prefix","kindMark","fnLine","c","constLine","removeExistingHeaders","generateAiMap","dirPath","filesInfo","relativePath","fileLine","methodKey","calls","generateFileMermaid","safeId","escapeLabel","text","functions","classMethods","allFunctions","baseName","callee","generateProjectMermaid","_projectDir","allFilesInfo","fileToFunctions","allCallEdges","addedEdges","callerId","calleeId","matchingKey","k","fileData","edgeKey","processFile","main","options","args","defaultConfig","fileArgs","filesToProcess","targetDir","source","mergedConfig","pattern","relFiles","processed","failed","dirFilesMap","mapContent","mapPath","mermaidContent","mermaidPath"],"mappings":"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"}
|